diff options
author | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2013-09-20 14:10:14 +0200 |
---|---|---|
committer | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2013-09-23 08:28:04 +0200 |
commit | 501e92cfd1292455f5d93d91a86bfa0cf69fc73c (patch) | |
tree | e7c158f28997efd59a0d8b36bba85bef6b761977 /plugins | |
parent | 0ac32549b3b249d266376efa3bc7ad0e188c2447 (diff) | |
download | sonarqube-501e92cfd1292455f5d93d91a86bfa0cf69fc73c.tar.gz sonarqube-501e92cfd1292455f5d93d91a86bfa0cf69fc73c.zip |
SONAR-4679 Separate pattern matching at filter time from pattern initialization at scan time
Diffstat (limited to 'plugins')
13 files changed, 279 insertions, 183 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilter.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilter.java index 7691df8bb59..362a7331d1b 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilter.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilter.java @@ -25,27 +25,23 @@ import org.slf4j.LoggerFactory; import org.sonar.api.issue.Issue; import org.sonar.api.issue.IssueFilter; import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; -import org.sonar.plugins.core.issue.ignore.pattern.PatternsInitializer; - -import java.util.List; +import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; public final class IgnoreIssuesFilter implements IssueFilter { private static final Logger LOG = LoggerFactory.getLogger(IgnoreIssuesFilter.class); - private PatternsInitializer patternsInitializer; + private PatternMatcher patternMatcher; - public IgnoreIssuesFilter(PatternsInitializer patternsInitializer) { - this.patternsInitializer = patternsInitializer; + public IgnoreIssuesFilter(PatternMatcher patternMatcher) { + this.patternMatcher = patternMatcher; } public boolean accept(Issue issue) { - List<IssuePattern> patterns = patternsInitializer.getPatternsForComponent(issue.componentKey()); - for (IssuePattern pattern : patterns) { - if (pattern.match(issue)) { - logExclusion(issue, pattern); - return false; - } + IssuePattern pattern = patternMatcher.getMatchingPattern(issue); + if (pattern != null) { + logExclusion(issue, pattern); + return false; } return true; } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPlugin.java index 9054563223b..e083d44aab2 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPlugin.java @@ -20,6 +20,8 @@ package org.sonar.plugins.core.issue.ignore; +import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; + import com.google.common.collect.ImmutableList; import org.sonar.plugins.core.issue.ignore.pattern.PatternsInitializer; import org.sonar.plugins.core.issue.ignore.scanner.RegexpScanner; @@ -39,6 +41,7 @@ public final class IgnoreIssuesPlugin { extensions.addAll(IgnoreIssuesConfiguration.getPropertyDefinitions()); extensions.add( PatternsInitializer.class, + PatternMatcher.class, RegexpScanner.class, SourceScanner.class, IgnoreIssuesFilter.class); diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePattern.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePattern.java index 458292a6e80..f4e80ac86cf 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePattern.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePattern.java @@ -143,7 +143,7 @@ public class IssuePattern { return false; } - boolean matchRule(RuleKey rule) { + public boolean matchRule(RuleKey rule) { if (rule == null) { return false; } @@ -152,7 +152,7 @@ public class IssuePattern { return rulePattern.match(key); } - boolean matchResource(String resource) { + public boolean matchResource(String resource) { return resource != null && resourcePattern.match(resource); } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcher.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcher.java new file mode 100644 index 00000000000..40b923d75e3 --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcher.java @@ -0,0 +1,65 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; +import org.sonar.api.BatchExtension; +import org.sonar.api.issue.Issue; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +public class PatternMatcher implements BatchExtension { + + private Multimap<String, IssuePattern> patternByComponent = LinkedHashMultimap.create(); + + public IssuePattern getMatchingPattern(Issue issue) { + IssuePattern matchingPattern = null; + Iterator<IssuePattern> patternIterator = getPatternsForComponent(issue.componentKey()).iterator(); + while(matchingPattern == null && patternIterator.hasNext()) { + IssuePattern nextPattern = patternIterator.next(); + if (nextPattern.match(issue)) { + matchingPattern = nextPattern; + } + } + return matchingPattern; + } + + @VisibleForTesting + Collection<IssuePattern> getPatternsForComponent(String componentKey) { + return patternByComponent.get(componentKey); + } + + public void addPatternForComponent(String component, IssuePattern pattern) { + patternByComponent.put(component, pattern.forResource(component)); + } + + public void addPatternToExcludeResource(String resource) { + addPatternForComponent(resource, new IssuePattern(resource, "*").setCheckLines(false)); + } + + public void addPatternToExcludeLines(String resource, Set<LineRange> lineRanges) { + addPatternForComponent(resource, new IssuePattern(resource, "*", lineRanges).setCheckLines(true)); + } + +} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializer.java index 5be21f823d2..d942d45db95 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializer.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializer.java @@ -21,17 +21,13 @@ package org.sonar.plugins.core.issue.ignore.pattern; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import org.apache.commons.lang.StringUtils; import org.sonar.api.BatchExtension; import org.sonar.api.config.Settings; import org.sonar.plugins.core.issue.ignore.IgnoreIssuesConfiguration; import java.util.List; -import java.util.Map; -import java.util.Set; import static com.google.common.base.Objects.firstNonNull; import static com.google.common.base.Strings.nullToEmpty; @@ -43,7 +39,6 @@ public class PatternsInitializer implements BatchExtension { private List<IssuePattern> multicriteriaPatterns; private List<IssuePattern> blockPatterns; private List<IssuePattern> allFilePatterns; - private Map<String, List<IssuePattern>> patternByComponent = Maps.newHashMap(); public PatternsInitializer(Settings settings) { this.settings = settings; @@ -120,36 +115,4 @@ public class PatternsInitializer implements BatchExtension { allFilePatterns.add(pattern); } } - - public void addPatternToExcludeResource(String resource) { - addPatternForComponent(resource, new IssuePattern(resource, "*").setCheckLines(false)); - } - - public void addPatternToExcludeLines(String resource, Set<LineRange> lineRanges) { - addPatternForComponent(resource, new IssuePattern(resource, "*", lineRanges).setCheckLines(true)); - } - - public void configurePatternsForComponent(String componentKey, String path) { - for (IssuePattern pattern: multicriteriaPatterns) { - if (pattern.matchResource(path)) { - addPatternForComponent(componentKey, pattern); - } - } - } - - public List<IssuePattern> getPatternsForComponent(String componentKey) { - if (patternByComponent.containsKey(componentKey)) { - return patternByComponent.get(componentKey); - } else { - return ImmutableList.of(); - } - } - - private void addPatternForComponent(String component, IssuePattern pattern) { - if (!patternByComponent.containsKey(component)) { - List<IssuePattern> newList = Lists.newArrayList(); - patternByComponent.put(component, newList); - } - patternByComponent.get(component).add(pattern.forResource(component)); - } } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/RegexpScanner.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/RegexpScanner.java index 93af123e7cb..3001337abc8 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/RegexpScanner.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/RegexpScanner.java @@ -20,8 +20,9 @@ package org.sonar.plugins.core.issue.ignore.scanner; -import org.apache.commons.lang.StringUtils; +import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; +import org.apache.commons.lang.StringUtils; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.apache.commons.io.FileUtils; @@ -42,7 +43,7 @@ public class RegexpScanner implements BatchExtension { private static final Logger LOG = LoggerFactory.getLogger(RegexpScanner.class); - private PatternsInitializer patternsInitializer; + private PatternMatcher patternMatcher; private List<java.util.regex.Pattern> allFilePatterns; private List<DoubleRegexpMatcher> blockMatchers; @@ -52,17 +53,17 @@ public class RegexpScanner implements BatchExtension { private List<LineExclusion> lineExclusions; private LineExclusion currentLineExclusion; - public RegexpScanner(PatternsInitializer patternsInitializer) { - this.patternsInitializer = patternsInitializer; + public RegexpScanner(PatternsInitializer patternsInitializer, PatternMatcher patternMatcher) { + this.patternMatcher = patternMatcher; lineExclusions = Lists.newArrayList(); allFilePatterns = Lists.newArrayList(); blockMatchers = Lists.newArrayList(); - for (IssuePattern pattern : this.patternsInitializer.getAllFilePatterns()) { + for (IssuePattern pattern : patternsInitializer.getAllFilePatterns()) { allFilePatterns.add(java.util.regex.Pattern.compile(pattern.getAllFileRegexp())); } - for (IssuePattern pattern : this.patternsInitializer.getBlockPatterns()) { + for (IssuePattern pattern : patternsInitializer.getBlockPatterns()) { blockMatchers.add(new DoubleRegexpMatcher( java.util.regex.Pattern.compile(pattern.getBeginBlockRegexp()), java.util.regex.Pattern.compile(pattern.getEndBlockRegexp()))); @@ -93,7 +94,7 @@ public class RegexpScanner implements BatchExtension { // first check the single regexp patterns that can be used to totally exclude a file for (java.util.regex.Pattern pattern : allFilePatterns) { if (pattern.matcher(line).find()) { - patternsInitializer.addPatternToExcludeResource(resource); + patternMatcher.addPatternToExcludeResource(resource); // nothing more to do on this file LOG.debug("- Exclusion pattern '{}': every violation in this file will be ignored.", pattern); return; @@ -114,7 +115,7 @@ public class RegexpScanner implements BatchExtension { if (!lineExclusions.isEmpty()) { Set<LineRange> lineRanges = convertLineExclusionsToLineRanges(); LOG.debug("- Line exclusions found: {}", lineRanges); - patternsInitializer.addPatternToExcludeLines(resource, lineRanges); + patternMatcher.addPatternToExcludeLines(resource, lineRanges); } } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScanner.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScanner.java index b6c097e1b3f..8fc73aac95f 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScanner.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScanner.java @@ -20,6 +20,9 @@ package org.sonar.plugins.core.issue.ignore.scanner; +import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; + +import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; import org.sonar.api.batch.Phase; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; @@ -43,12 +46,14 @@ public final class SourceScanner implements Sensor { private final RegexpScanner regexpScanner; private final PatternsInitializer patternsInitializer; + private final PatternMatcher patternMatcher; private final ModuleFileSystem fileSystem; private final PathResolver pathResolver; - public SourceScanner(RegexpScanner regexpScanner, PatternsInitializer patternsInitializer, ModuleFileSystem fileSystem) { + public SourceScanner(RegexpScanner regexpScanner, PatternsInitializer patternsInitializer, PatternMatcher patternMatcher, ModuleFileSystem fileSystem) { this.regexpScanner = regexpScanner; this.patternsInitializer = patternsInitializer; + this.patternMatcher = patternMatcher; this.fileSystem = fileSystem; this.pathResolver = new PathResolver(); } @@ -82,8 +87,13 @@ public final class SourceScanner implements Sensor { try { String componentKey = resolveComponent(inputFile, dirs, project, isTest); if (componentKey != null) { + String relativePath = pathResolver.relativePath(dirs, inputFile).path(); - patternsInitializer.configurePatternsForComponent(componentKey, relativePath); + for (IssuePattern pattern: patternsInitializer.getMulticriteriaPatterns()) { + if (pattern.matchResource(relativePath)) { + patternMatcher.addPatternForComponent(componentKey, pattern); + } + } if (patternsInitializer.hasFileContentPattern()) { regexpScanner.scan(componentKey, inputFile, sourcesEncoding); } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilterTest.java index fb229d2114a..c4b4022dff4 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilterTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilterTest.java @@ -23,15 +23,8 @@ package org.sonar.plugins.core.issue.ignore; import org.junit.Before; import org.junit.Test; import org.sonar.api.issue.Issue; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rules.Rule; import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; -import org.sonar.plugins.core.issue.ignore.pattern.PatternDecoder; -import org.sonar.plugins.core.issue.ignore.pattern.PatternsInitializer; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; +import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -39,66 +32,29 @@ import static org.mockito.Mockito.when; public class IgnoreIssuesFilterTest { - public static final Rule CHECKSTYLE_RULE = Rule.create("checkstyle", "MagicNumber", ""); - public static final String JAVA_FILE = "org.foo.Hello"; - - private PatternsInitializer patternsInitializer; + private PatternMatcher patternMatcher; private IgnoreIssuesFilter filter; + private Issue issue; @Before public void init() { - patternsInitializer = mock(PatternsInitializer.class); - when(patternsInitializer.getMulticriteriaPatterns()).thenReturn(Collections.<IssuePattern> emptyList()); - - filter = new IgnoreIssuesFilter(patternsInitializer); - } - - @Test - public void shouldBeDeactivatedWhenPropertyIsMissing() { - assertThat(filter.accept(create(CHECKSTYLE_RULE, JAVA_FILE, null))).isTrue(); - } - - @Test - public void shouldBeIgnoredWithStandardPatterns() throws IOException { - when(patternsInitializer.getPatternsForComponent(JAVA_FILE)).thenReturn(createPatterns("org.foo.Hello;checkstyle:MagicNumber;[15-200]")); + patternMatcher = mock(PatternMatcher.class); + issue = mock(Issue.class); - assertThat(filter.accept(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isFalse(); + filter = new IgnoreIssuesFilter(patternMatcher); } @Test - public void shouldNotBeIgnoredWithStandardPatterns() throws IOException { - when(patternsInitializer.getPatternsForComponent(JAVA_FILE)).thenReturn(createPatterns("org.foo.Hello;checkstyle:MagicNumber;[15-200]")); + public void shouldAcceptIfMatcherHasNoPatternForIssue() { + when(patternMatcher.getMatchingPattern(issue)).thenReturn(null); - assertThat(filter.accept(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isTrue(); + assertThat(filter.accept(issue)).isTrue(); } @Test - public void shouldBeIgnoredWithExtraPattern() throws IOException { - when(patternsInitializer.getPatternsForComponent(JAVA_FILE)).thenReturn(createPatterns("org.foo.Hello;*;[15-200]")); - - assertThat(filter.accept(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isFalse(); - } - - @Test - public void shouldNotBeIgnoredWithExtraPattern() throws IOException { - when(patternsInitializer.getPatternsForComponent(JAVA_FILE)).thenReturn(createPatterns("org.foo.Hello;*;[15-200]")); - - assertThat(filter.accept(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isTrue(); - } - - private Issue create(Rule rule, String component, Integer line) { - Issue mockIssue = mock(Issue.class); - RuleKey ruleKey = null; - if (rule != null) { - ruleKey = rule.ruleKey(); - } - when(mockIssue.ruleKey()).thenReturn(ruleKey); - when(mockIssue.componentKey()).thenReturn(component); - when(mockIssue.line()).thenReturn(line); - return mockIssue; - } + public void shouldNotAcceptIfMatcherHasPatternForIssue() { + when(patternMatcher.getMatchingPattern(issue)).thenReturn(mock(IssuePattern.class)); - private List<IssuePattern> createPatterns(String line) { - return new PatternDecoder().decode(line); + assertThat(filter.accept(issue)).isFalse(); } } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPluginTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPluginTest.java index 4c5395a0b06..ca2b2dcf0b5 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPluginTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPluginTest.java @@ -27,6 +27,6 @@ import static org.fest.assertions.Assertions.assertThat; public class IgnoreIssuesPluginTest { @Test public void justForCoverage() { - assertThat(IgnoreIssuesPlugin.getExtensions()).hasSize(3 /* properties */ + 4 /* extensions */); + assertThat(IgnoreIssuesPlugin.getExtensions()).hasSize(3 /* properties */ + 5 /* extensions */); } } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcherTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcherTest.java new file mode 100644 index 00000000000..af7f97e9f0e --- /dev/null +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcherTest.java @@ -0,0 +1,120 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; + +import com.google.common.collect.Sets; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.issue.Issue; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rules.Rule; + +import java.io.IOException; +import java.util.Set; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class PatternMatcherTest { + + public static final Rule CHECKSTYLE_RULE = Rule.create("checkstyle", "MagicNumber", ""); + public static final String JAVA_FILE = "org.foo.Hello"; + + private PatternMatcher patternMatcher; + + @Before + public void setUp() { + patternMatcher = new PatternMatcher(); + } + + @Test + public void shouldReturnExtraPatternForResource() { + String file = "foo"; + patternMatcher.addPatternToExcludeResource(file); + + IssuePattern extraPattern = patternMatcher.getPatternsForComponent(file).iterator().next(); + assertThat(extraPattern.matchResource(file)).isTrue(); + assertThat(extraPattern.isCheckLines()).isFalse(); + } + + @Test + public void shouldReturnExtraPatternForLinesOfResource() { + String file = "foo"; + Set<LineRange> lineRanges = Sets.newHashSet(); + lineRanges.add(new LineRange(25, 28)); + patternMatcher.addPatternToExcludeLines(file, lineRanges); + + IssuePattern extraPattern = patternMatcher.getPatternsForComponent(file).iterator().next(); + assertThat(extraPattern.matchResource(file)).isTrue(); + assertThat(extraPattern.getAllLines()).isEqualTo(Sets.newHashSet(25, 26, 27, 28)); + } + + @Test + public void shouldHaveNoMatcherIfNoneDefined() { + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, null))).isNull(); + } + + @Test + public void shouldMatchWithStandardPatterns() throws IOException { + patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;checkstyle:MagicNumber;[15-200]")); + + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isNotNull(); + } + + @Test + public void shouldNotMatchWithStandardPatterns() throws IOException { + patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;checkstyle:MagicNumber;[15-200]")); + + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isNull(); + } + + @Test + public void shouldMatchWithExtraPattern() throws IOException { + patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;*;[15-200]")); + + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isNotNull(); + } + + @Test + public void shouldNotMatchWithExtraPattern() throws IOException { + patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;*;[15-200]")); + + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isNull(); + } + + private Issue create(Rule rule, String component, Integer line) { + Issue mockIssue = mock(Issue.class); + RuleKey ruleKey = null; + if (rule != null) { + ruleKey = rule.ruleKey(); + } + when(mockIssue.ruleKey()).thenReturn(ruleKey); + when(mockIssue.componentKey()).thenReturn(component); + when(mockIssue.line()).thenReturn(line); + return mockIssue; + } + + private IssuePattern createPattern(String line) { + return new PatternDecoder().decode(line).get(0); + } + +} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializerTest.java index 4abb5358747..aec0ea0d1de 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializerTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializerTest.java @@ -20,8 +20,6 @@ package org.sonar.plugins.core.issue.ignore.pattern; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; import org.sonar.api.config.PropertyDefinitions; @@ -29,11 +27,7 @@ import org.sonar.api.config.Settings; import org.sonar.api.utils.SonarException; import org.sonar.plugins.core.issue.ignore.IgnoreIssuesConfiguration; -import java.util.Set; - import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class PatternsInitializerTest { @@ -55,28 +49,6 @@ public class PatternsInitializerTest { } @Test - public void shouldReturnExtraPatternForResource() { - String file = "foo"; - patternsInitializer.addPatternToExcludeResource(file); - - IssuePattern extraPattern = patternsInitializer.getPatternsForComponent(file).get(0); - assertThat(extraPattern.matchResource(file)).isTrue(); - assertThat(extraPattern.isCheckLines()).isFalse(); - } - - @Test - public void shouldReturnExtraPatternForLinesOfResource() { - String file = "foo"; - Set<LineRange> lineRanges = Sets.newHashSet(); - lineRanges.add(new LineRange(25, 28)); - patternsInitializer.addPatternToExcludeLines(file, lineRanges); - - IssuePattern extraPattern = patternsInitializer.getPatternsForComponent(file).get(0); - assertThat(extraPattern.matchResource(file)).isTrue(); - assertThat(extraPattern.getAllLines()).isEqualTo(Sets.newHashSet(25, 26, 27, 28)); - } - - @Test public void shouldReturnMulticriteriaPattern() { settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_KEY, "1,2"); settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_KEY + ".1." + IgnoreIssuesConfiguration.RESOURCE_KEY, "org/foo/Bar.java"); @@ -170,25 +142,4 @@ public class PatternsInitializerTest { settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_ALLFILE_KEY + ".1." + IgnoreIssuesConfiguration.FILE_REGEXP, ""); patternsInitializer.initPatterns(); } - - @Test - public void shouldConfigurePatternsForComponents() { - String componentKey = "groupId:artifactId:org.foo.Bar"; - String path = "org/foo/Bar.java"; - - IssuePattern matching1, matching2, notMatching; - matching1 = mock(IssuePattern.class); - when(matching1.matchResource(path)).thenReturn(true); - matching2 = mock(IssuePattern.class); - when(matching2.matchResource(path)).thenReturn(true); - notMatching = mock(IssuePattern.class); - when(notMatching.matchResource(path)).thenReturn(false); - - patternsInitializer.initPatterns(); - patternsInitializer.getMulticriteriaPatterns().addAll(Lists.newArrayList(matching1, matching2, notMatching)); - patternsInitializer.configurePatternsForComponent(componentKey, path); - - assertThat(patternsInitializer.getPatternsForComponent(componentKey).size()).isEqualTo(2); - assertThat(patternsInitializer.getPatternsForComponent("other").size()).isEqualTo(0); - } } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/RegexpScannerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/RegexpScannerTest.java index 109de97e31d..fe7bc1973f9 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/RegexpScannerTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/RegexpScannerTest.java @@ -20,6 +20,8 @@ package org.sonar.plugins.core.issue.ignore.scanner; +import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; + import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; @@ -48,6 +50,8 @@ public class RegexpScannerTest { @Mock private PatternsInitializer patternsInitializer; @Mock + private PatternMatcher patternMatcher; + @Mock private IssuePattern allFilePattern; @Mock private IssuePattern blockPattern1; @@ -66,7 +70,7 @@ public class RegexpScannerTest { when(patternsInitializer.getAllFilePatterns()).thenReturn(Arrays.asList(allFilePattern)); when(patternsInitializer.getBlockPatterns()).thenReturn(Arrays.asList(blockPattern1, blockPattern2)); - regexpScanner = new RegexpScanner(patternsInitializer); + regexpScanner = new RegexpScanner(patternsInitializer, patternMatcher); verify(patternsInitializer, times(1)).getAllFilePatterns(); verify(patternsInitializer, times(1)).getBlockPatterns(); @@ -84,7 +88,7 @@ public class RegexpScannerTest { public void shouldAddPatternToExcludeFile() throws IOException { regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-single-regexp.txt"), UTF_8); - verify(patternsInitializer, times(1)).addPatternToExcludeResource(javaFile); + verify(patternMatcher, times(1)).addPatternToExcludeResource(javaFile); verifyNoMoreInteractions(patternsInitializer); } @@ -92,7 +96,7 @@ public class RegexpScannerTest { public void shouldAddPatternToExcludeFileEvenIfAlsoDoubleRegexps() throws IOException { regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-single-regexp-and-double-regexp.txt"), UTF_8); - verify(patternsInitializer, times(1)).addPatternToExcludeResource(javaFile); + verify(patternMatcher, times(1)).addPatternToExcludeResource(javaFile); verifyNoMoreInteractions(patternsInitializer); } @@ -102,7 +106,7 @@ public class RegexpScannerTest { Set<LineRange> lineRanges = Sets.newHashSet(); lineRanges.add(new LineRange(21, 25)); - verify(patternsInitializer, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); verifyNoMoreInteractions(patternsInitializer); } @@ -112,7 +116,7 @@ public class RegexpScannerTest { Set<LineRange> lineRanges = Sets.newHashSet(); lineRanges.add(new LineRange(21, 34)); - verify(patternsInitializer, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); verifyNoMoreInteractions(patternsInitializer); } @@ -123,7 +127,7 @@ public class RegexpScannerTest { Set<LineRange> lineRanges = Sets.newHashSet(); lineRanges.add(new LineRange(21, 25)); lineRanges.add(new LineRange(29, 33)); - verify(patternsInitializer, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); verifyNoMoreInteractions(patternsInitializer); } @@ -133,7 +137,7 @@ public class RegexpScannerTest { Set<LineRange> lineRanges = Sets.newHashSet(); lineRanges.add(new LineRange(25, 35)); - verify(patternsInitializer, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); verifyNoMoreInteractions(patternsInitializer); } @@ -143,7 +147,7 @@ public class RegexpScannerTest { Set<LineRange> lineRanges = Sets.newHashSet(); lineRanges.add(new LineRange(21, 29)); - verify(patternsInitializer, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); verifyNoMoreInteractions(patternsInitializer); } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScannerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScannerTest.java index bbcff4d25a9..24860050ee3 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScannerTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScannerTest.java @@ -33,6 +33,7 @@ import org.sonar.api.scan.filesystem.FileQuery; import org.sonar.api.scan.filesystem.ModuleFileSystem; import org.sonar.api.utils.SonarException; import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; +import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; import org.sonar.plugins.core.issue.ignore.pattern.PatternsInitializer; import java.io.File; @@ -44,9 +45,11 @@ import java.util.List; import static com.google.common.base.Charsets.UTF_8; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; public class SourceScannerTest { @@ -58,6 +61,8 @@ public class SourceScannerTest { @Mock private PatternsInitializer patternsInitializer; @Mock + private PatternMatcher patternMatcher; + @Mock private ModuleFileSystem fileSystem; private Project project; @@ -74,7 +79,7 @@ public class SourceScannerTest { Mockito.doReturn("java").when(project).getLanguageKey(); when(fileSystem.sourceCharset()).thenReturn(UTF_8); - scanner = new SourceScanner(regexpScanner, patternsInitializer, fileSystem); + scanner = new SourceScanner(regexpScanner, patternsInitializer, patternMatcher, fileSystem); } @Test @@ -106,8 +111,6 @@ public class SourceScannerTest { scanner.analyse(project, null); - verify(patternsInitializer).configurePatternsForComponent("polop:[default].Foo", "Foo.java"); - verify(patternsInitializer).configurePatternsForComponent("polop:[default].FooTest", "FooTest.java"); verify(regexpScanner).scan("polop:[default].Foo", sourceFile, UTF_8); verify(regexpScanner).scan("polop:[default].FooTest", testFile, UTF_8); } @@ -127,12 +130,39 @@ public class SourceScannerTest { scanner.analyse(project, null); - verify(patternsInitializer).configurePatternsForComponent("polop:[default].Foo", "Foo.java"); - verify(patternsInitializer).configurePatternsForComponent("polop:[default].FooTest", "FooTest.java"); verifyNoMoreInteractions(regexpScanner); } @Test + public void shouldAddExclusionsForMulticriteriaPatterns() throws IOException { + File sourceFile = new File("src/main/java/Foo.java"); + File testFile = new File("src/test/java/FooTest.java"); + + when(project.getLanguageKey()).thenReturn("java"); + when(fileSystem.files(Mockito.isA(FileQuery.class))) + .thenReturn(Arrays.asList(sourceFile)) + .thenReturn(Arrays.asList(testFile)); + when(fileSystem.sourceDirs()).thenReturn(Arrays.asList(new File("src/main/java"))); + when(fileSystem.testDirs()).thenReturn(Arrays.asList(new File("src/test/java"))); + + IssuePattern pattern1 = mock(IssuePattern.class); + when(pattern1.matchResource("Foo.java")).thenReturn(true); + when(pattern1.matchResource("FooTest.java")).thenReturn(false); + IssuePattern pattern2 = mock(IssuePattern.class); + when(pattern2.matchResource("Foo.java")).thenReturn(false); + when(pattern2.matchResource("FooTest.java")).thenReturn(true); + + Mockito.doReturn(ImmutableList.of(pattern1, pattern2)).when(patternsInitializer).getMulticriteriaPatterns(); + when(patternsInitializer.hasFileContentPattern()).thenReturn(false); + + scanner.analyse(project, null); + + verify(patternMatcher).addPatternForComponent("polop:[default].Foo", pattern1); + verify(patternMatcher).addPatternForComponent("polop:[default].FooTest", pattern2); + verifyZeroInteractions(regexpScanner); + } + + @Test public void shouldAnalyseOtherProject() throws IOException { File sourceFile = new File("Foo.php"); File testFile = new File("FooTest.php"); @@ -147,8 +177,6 @@ public class SourceScannerTest { scanner.analyse(project, null); - verify(patternsInitializer).configurePatternsForComponent("polop:Foo.php", "Foo.php"); - verify(patternsInitializer).configurePatternsForComponent("polop:FooTest.php", "FooTest.php"); verify(regexpScanner).scan("polop:Foo.php", sourceFile, UTF_8); verify(regexpScanner).scan("polop:FooTest.php", testFile, UTF_8); } @@ -197,7 +225,6 @@ public class SourceScannerTest { when(project.getLanguageKey()).thenReturn("php"); when(fileSystem.files(Mockito.isA(FileQuery.class))).thenReturn(Arrays.asList(sourceFile)); List<IssuePattern> empty = ImmutableList.of(); - when(patternsInitializer.getPatternsForComponent("Foo.php")).thenReturn(empty); doThrow(new IOException("BUG")).when(regexpScanner).scan("polop:Foo.php", sourceFile, UTF_8); thrown.expect(SonarException.class); |