diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2014-06-19 14:48:07 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2014-06-19 14:48:47 +0200 |
commit | e6a79a3f8da7bd3351aade2e9fb8a4f57c9fabe6 (patch) | |
tree | 6b590a32cc284372ef50bee6c1354b394ba3c60f /sonar-batch | |
parent | 059c65d520fc80ac85616e98d789b4b67cac9019 (diff) | |
download | sonarqube-e6a79a3f8da7bd3351aade2e9fb8a4f57c9fabe6.tar.gz sonarqube-e6a79a3f8da7bd3351aade2e9fb8a4f57c9fabe6.zip |
SONAR-5389 Analyzer optimizer
Diffstat (limited to 'sonar-batch')
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(); + } +} |