@@ -29,6 +29,7 @@ import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.platform.ComponentContainer; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.batch.scan.SensorWrapper; | |||
import org.sonar.batch.scan2.AnalyzerOptimizer; | |||
import javax.annotation.Nullable; | |||
@@ -42,11 +43,13 @@ public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensio | |||
private FileSystem fs; | |||
private AnalyzerContext context; | |||
private AnalyzerOptimizer analyzerOptimizer; | |||
public BatchExtensionDictionnary(ComponentContainer componentContainer, FileSystem fs, AnalyzerContext context) { | |||
public BatchExtensionDictionnary(ComponentContainer componentContainer, FileSystem fs, AnalyzerContext context, AnalyzerOptimizer analyzerOptimizer) { | |||
super(componentContainer); | |||
this.fs = fs; | |||
this.context = context; | |||
this.analyzerOptimizer = analyzerOptimizer; | |||
} | |||
public <T> Collection<T> select(Class<T> type, @Nullable Project project, boolean sort, @Nullable ExtensionMatcher matcher) { | |||
@@ -61,7 +64,7 @@ public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensio | |||
List<T> result = Lists.newArrayList(); | |||
for (Object extension : getExtensions(type)) { | |||
if (type == Sensor.class && extension instanceof Analyzer) { | |||
extension = new SensorWrapper((Analyzer) extension, context, fs); | |||
extension = new SensorWrapper((Analyzer) extension, context, fs, analyzerOptimizer); | |||
} | |||
if (shouldKeep(type, extension, project, matcher)) { | |||
result.add((T) extension); |
@@ -81,6 +81,7 @@ import org.sonar.batch.scan.filesystem.PreviousFileHashLoader; | |||
import org.sonar.batch.scan.filesystem.ProjectFileSystemAdapter; | |||
import org.sonar.batch.scan.filesystem.StatusDetectionFactory; | |||
import org.sonar.batch.scan.report.JsonReport; | |||
import org.sonar.batch.scan2.AnalyzerOptimizer; | |||
import org.sonar.core.component.ScanPerspectives; | |||
import org.sonar.core.measure.MeasurementFilters; | |||
@@ -137,6 +138,8 @@ public class ModuleScanContainer extends ComponentContainer { | |||
ProjectFileSystemAdapter.class, | |||
QProfileVerifier.class, | |||
AnalyzerOptimizer.class, | |||
// the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor) | |||
getComponentByType(ResourcePersister.class).getSnapshot(module), | |||
@@ -29,6 +29,7 @@ import org.sonar.api.batch.analyzer.internal.DefaultAnalyzerDescriptor; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.batch.measures.Metric; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.batch.scan2.AnalyzerOptimizer; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
@@ -39,9 +40,11 @@ public class SensorWrapper implements Sensor { | |||
private AnalyzerContext adaptor; | |||
private FileSystem fs; | |||
private DefaultAnalyzerDescriptor descriptor; | |||
private AnalyzerOptimizer optimizer; | |||
public SensorWrapper(Analyzer analyzer, AnalyzerContext adaptor, FileSystem fs) { | |||
public SensorWrapper(Analyzer analyzer, AnalyzerContext adaptor, FileSystem fs, AnalyzerOptimizer optimizer) { | |||
this.analyzer = analyzer; | |||
this.optimizer = optimizer; | |||
descriptor = new DefaultAnalyzerDescriptor(); | |||
analyzer.describe(descriptor); | |||
this.adaptor = adaptor; | |||
@@ -60,19 +63,7 @@ public class SensorWrapper implements Sensor { | |||
@Override | |||
public boolean shouldExecuteOnProject(Project project) { | |||
if (!descriptor.languages().isEmpty()) { | |||
if (project.getLanguageKey() != null && !descriptor.languages().contains(project.getLanguageKey())) { | |||
return false; | |||
} | |||
boolean hasFile = false; | |||
for (String languageKey : descriptor.languages()) { | |||
hasFile |= fs.hasFiles(fs.predicates().hasLanguage(languageKey)); | |||
} | |||
if (!hasFile) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
return optimizer.shouldExecute(descriptor); | |||
} | |||
@Override |
@@ -0,0 +1,49 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan2; | |||
import org.sonar.api.BatchComponent; | |||
import org.sonar.api.batch.analyzer.internal.DefaultAnalyzerDescriptor; | |||
import org.sonar.api.batch.fs.FilePredicate; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
public class AnalyzerOptimizer implements BatchComponent { | |||
private FileSystem fs; | |||
public AnalyzerOptimizer(FileSystem fs) { | |||
this.fs = fs; | |||
} | |||
/** | |||
* Decide if the given Analyzer should be executed. | |||
*/ | |||
public boolean shouldExecute(DefaultAnalyzerDescriptor descriptor) { | |||
FilePredicate predicate = fs.predicates().hasLanguages(descriptor.languages()); | |||
if (descriptor.types().size() == 1) { | |||
// Size = 0 or Size = 2 means both main and test type | |||
predicate = fs.predicates().and( | |||
predicate, | |||
fs.predicates().hasType(descriptor.types().iterator().next())); | |||
} | |||
return fs.hasFiles(predicate); | |||
} | |||
} |
@@ -34,9 +34,11 @@ public class AnalyzersExecutor implements BatchComponent { | |||
private static final Logger LOG = LoggerFactory.getLogger(AnalyzersExecutor.class); | |||
private BatchExtensionDictionnary selector; | |||
private AnalyzerOptimizer optimizer; | |||
public AnalyzersExecutor(BatchExtensionDictionnary selector) { | |||
public AnalyzersExecutor(BatchExtensionDictionnary selector, AnalyzerOptimizer optimizer) { | |||
this.selector = selector; | |||
this.optimizer = optimizer; | |||
} | |||
public void execute(AnalyzerContext context) { | |||
@@ -47,6 +49,11 @@ public class AnalyzersExecutor implements BatchComponent { | |||
DefaultAnalyzerDescriptor descriptor = new DefaultAnalyzerDescriptor(); | |||
analyzer.describe(descriptor); | |||
if (!optimizer.shouldExecute(descriptor)) { | |||
LOG.debug("Analyzer skipped: " + descriptor.name()); | |||
continue; | |||
} | |||
LOG.info("Execute analyzer: " + descriptor.name()); | |||
executeSensor(context, analyzer); |
@@ -98,6 +98,8 @@ public class ModuleScanContainer extends ComponentContainer { | |||
ModuleFileSystemInitializer.class, | |||
QProfileVerifier.class, | |||
AnalyzerOptimizer.class, | |||
DefaultAnalyzerContext.class, | |||
BatchExtensionDictionnary.class, | |||
IssueFilters.class, |
@@ -19,15 +19,15 @@ | |||
*/ | |||
package org.sonar.batch.bootstrap; | |||
import org.sonar.api.batch.analyzer.AnalyzerContext; | |||
import org.junit.Test; | |||
import org.sonar.api.BatchExtension; | |||
import org.sonar.api.batch.Sensor; | |||
import org.sonar.api.batch.SensorContext; | |||
import org.sonar.api.batch.analyzer.AnalyzerContext; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.platform.ComponentContainer; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.batch.scan2.AnalyzerOptimizer; | |||
import java.util.Collection; | |||
@@ -43,7 +43,7 @@ public class BatchExtensionDictionnaryTest { | |||
for (BatchExtension extension : extensions) { | |||
iocContainer.addSingleton(extension); | |||
} | |||
return new BatchExtensionDictionnary(iocContainer, mock(FileSystem.class), mock(AnalyzerContext.class)); | |||
return new BatchExtensionDictionnary(iocContainer, mock(FileSystem.class), mock(AnalyzerContext.class), mock(AnalyzerOptimizer.class)); | |||
} | |||
@Test |
@@ -50,8 +50,8 @@ public class DefaultAnalyzerDescriptor implements AnalyzerDescriptor { | |||
return Arrays.asList(languages); | |||
} | |||
public InputFile.Type[] types() { | |||
return types; | |||
public Collection<InputFile.Type> types() { | |||
return Arrays.asList(types); | |||
} | |||
@Override |