aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-06-19 14:48:07 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2014-06-19 14:48:47 +0200
commite6a79a3f8da7bd3351aade2e9fb8a4f57c9fabe6 (patch)
tree6b590a32cc284372ef50bee6c1354b394ba3c60f /sonar-batch
parent059c65d520fc80ac85616e98d789b4b67cac9019 (diff)
downloadsonarqube-e6a79a3f8da7bd3351aade2e9fb8a4f57c9fabe6.tar.gz
sonarqube-e6a79a3f8da7bd3351aade2e9fb8a4f57c9fabe6.zip
SONAR-5389 Analyzer optimizer
Diffstat (limited to 'sonar-batch')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerOptimizer.java45
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan2/AnalyzerOptimizerTest.java117
3 files changed, 156 insertions, 13 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java
index 1f5408c2002..701233abbef 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java
@@ -19,8 +19,6 @@
*/
package org.sonar.batch.scan;
-import org.sonar.api.batch.measure.Metric;
-
import org.sonar.api.batch.DependedUpon;
import org.sonar.api.batch.DependsUpon;
import org.sonar.api.batch.Sensor;
@@ -29,6 +27,7 @@ import org.sonar.api.batch.analyzer.Analyzer;
import org.sonar.api.batch.analyzer.AnalyzerContext;
import org.sonar.api.batch.analyzer.internal.DefaultAnalyzerDescriptor;
import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.measure.Metric;
import org.sonar.api.resources.Project;
import org.sonar.batch.scan2.AnalyzerOptimizer;
@@ -53,12 +52,12 @@ public class SensorWrapper implements Sensor {
}
@DependedUpon
- public List<Metric<?>> provides() {
+ public List<Metric> provides() {
return Arrays.asList(descriptor.provides());
}
@DependsUpon
- public List<Metric<?>> depends() {
+ public List<Metric> depends() {
return Arrays.asList(descriptor.dependsOn());
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerOptimizer.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerOptimizer.java
index 3ad0a29aa76..0e875360743 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerOptimizer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerOptimizer.java
@@ -23,27 +23,54 @@ 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;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.rule.ActiveRules;
public class AnalyzerOptimizer implements BatchComponent {
- private FileSystem fs;
+ private final FileSystem fs;
+ private final ActiveRules activeRules;
- public AnalyzerOptimizer(FileSystem fs) {
+ public AnalyzerOptimizer(FileSystem fs, ActiveRules activeRules) {
this.fs = fs;
+ this.activeRules = activeRules;
}
/**
* 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()));
+ // FS Conditions
+ boolean fsCondition = fsCondition(descriptor);
+ boolean activeRulesCondition = activeRulesCondition(descriptor);
+ return fsCondition && activeRulesCondition;
+ }
+
+ private boolean activeRulesCondition(DefaultAnalyzerDescriptor descriptor) {
+ if (!descriptor.ruleRepositories().isEmpty()) {
+ for (String repoKey : descriptor.ruleRepositories()) {
+ if (!activeRules.findByRepository(repoKey).isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private boolean fsCondition(DefaultAnalyzerDescriptor descriptor) {
+ if (!descriptor.languages().isEmpty() || !descriptor.types().isEmpty()) {
+ FilePredicate langPredicate = descriptor.languages().isEmpty() ? fs.predicates().all() : fs.predicates().hasLanguages(descriptor.languages());
+
+ FilePredicate typePredicate = descriptor.types().isEmpty() ? fs.predicates().all() : fs.predicates().none();
+ for (InputFile.Type type : descriptor.types()) {
+ typePredicate = fs.predicates().or(
+ typePredicate,
+ fs.predicates().hasType(type));
+ }
+ return fs.hasFiles(fs.predicates().and(langPredicate, typePredicate));
}
- return fs.hasFiles(predicate);
+ return true;
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan2/AnalyzerOptimizerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan2/AnalyzerOptimizerTest.java
new file mode 100644
index 00000000000..1384950b99d
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan2/AnalyzerOptimizerTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.analyzer.internal.DefaultAnalyzerDescriptor;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.rule.RuleKey;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class AnalyzerOptimizerTest {
+
+ DefaultFileSystem fs = new DefaultFileSystem();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+ private AnalyzerOptimizer optimizer;
+
+ @Before
+ public void prepare() {
+ optimizer = new AnalyzerOptimizer(fs, new ActiveRulesBuilder().build());
+ }
+
+ @Test
+ public void should_run_analyzer_with_no_metadata() throws Exception {
+ DefaultAnalyzerDescriptor descriptor = new DefaultAnalyzerDescriptor();
+
+ assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+ }
+
+ @Test
+ public void should_optimize_on_language() throws Exception {
+ DefaultAnalyzerDescriptor descriptor = new DefaultAnalyzerDescriptor()
+ .workOnLanguages("java", "php");
+ assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+ fs.add(new DefaultInputFile("src/Foo.java").setLanguage("java"));
+ assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+ }
+
+ @Test
+ public void should_optimize_on_type() throws Exception {
+ DefaultAnalyzerDescriptor descriptor = new DefaultAnalyzerDescriptor()
+ .workOnFileTypes(InputFile.Type.MAIN);
+ assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+ fs.add(new DefaultInputFile("tests/FooTest.java").setType(InputFile.Type.TEST));
+ assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+ fs.add(new DefaultInputFile("src/Foo.java").setType(InputFile.Type.MAIN));
+ assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+ }
+
+ @Test
+ public void should_optimize_on_both_type_and_language() throws Exception {
+ DefaultAnalyzerDescriptor descriptor = new DefaultAnalyzerDescriptor()
+ .workOnLanguages("java", "php")
+ .workOnFileTypes(InputFile.Type.MAIN);
+ assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+ fs.add(new DefaultInputFile("tests/FooTest.java").setLanguage("java").setType(InputFile.Type.TEST));
+ fs.add(new DefaultInputFile("src/Foo.cbl").setLanguage("cobol").setType(InputFile.Type.MAIN));
+ assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+ fs.add(new DefaultInputFile("src/Foo.java").setLanguage("java").setType(InputFile.Type.MAIN));
+ assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+ }
+
+ @Test
+ public void should_optimize_on_repository() throws Exception {
+ DefaultAnalyzerDescriptor descriptor = new DefaultAnalyzerDescriptor()
+ .createIssuesForRuleRepositories("squid");
+ assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+ ActiveRules activeRules = new ActiveRulesBuilder()
+ .activate(RuleKey.of("repo1", "foo"))
+ .end()
+ .build();
+ optimizer = new AnalyzerOptimizer(fs, activeRules);
+
+ assertThat(optimizer.shouldExecute(descriptor)).isFalse();
+
+ activeRules = new ActiveRulesBuilder()
+ .activate(RuleKey.of("repo1", "foo"))
+ .end()
+ .activate(RuleKey.of("squid", "rule"))
+ .end()
+ .build();
+ optimizer = new AnalyzerOptimizer(fs, activeRules);
+ assertThat(optimizer.shouldExecute(descriptor)).isTrue();
+ }
+}