]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3644 Break compatibility with plugin configuration
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Fri, 6 Sep 2013 09:37:19 +0000 (11:37 +0200)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Fri, 6 Sep 2013 09:37:19 +0000 (11:37 +0200)
Use relative paths rather than component keys for filter definition
Add utility to compute component key based on underlying file path
Enhance coverage and compliance

16 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesConfiguration.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilter.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPlugin.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/Pattern.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternDecoder.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializer.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScanner.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilterTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPluginTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternDecoderTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternsInitializerTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/SourceScannerTest.java
sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/component/ComponentKeysTest.java [new file with mode: 0644]

index 045425c5d76c3df42f895f5875300899adb2bd22..e09370c404f40b711d657aaa8abbd6cccd10fbf0 100644 (file)
@@ -1,4 +1,3 @@
-// POLOP_IS_GREAT
 /*
  * SonarQube, open source software quality management tool.
  * Copyright (C) 2008-2013 SonarSource
@@ -31,8 +30,9 @@ import org.sonar.api.config.PropertyDefinition;
 
 import java.util.List;
 
-public class IgnoreIssuesConfiguration {
+public final class IgnoreIssuesConfiguration {
 
+  private IgnoreIssuesConfiguration() {}
 
   static final int LARGE_SIZE = 20;
   static final int SMALL_SIZE = 10;
index c60b9b71672ce202634945e599175912f5d78234..ea342e36a1f449ccca54e2b1f4221e23ca71e7b3 100644 (file)
@@ -40,14 +40,7 @@ public final class IgnoreIssuesFilter implements IssueFilter {
   }
 
   public boolean accept(Issue issue) {
-    Pattern extraPattern = patternsInitializer.getExtraPattern(issue.componentKey());
-    LOG.debug("Extra pattern for resource {}: {}", issue.componentKey(), extraPattern);
-    if (extraPattern != null && extraPattern.match(issue)) {
-      logExclusion(issue, extraPattern);
-      return false;
-    }
-
-    List<Pattern> patterns = patternsInitializer.getMulticriteriaPatterns();
+    List<Pattern> patterns = patternsInitializer.getPatternsForComponent(issue.componentKey());
     for (Pattern pattern : patterns) {
       if (pattern.match(issue)) {
         logExclusion(issue, pattern);
index 29d0048c50a2ed49d0bc67a2e350905cfd616259..ea929d517bdb7676d48e0ae948f287dcc1ee6e6f 100644 (file)
@@ -29,6 +29,8 @@ import java.util.List;
 
 public final class IgnoreIssuesPlugin {
 
+  private IgnoreIssuesPlugin() {}
+
   public static List<?> getExtensions() {
     ImmutableList.Builder<Object> extensions = ImmutableList.builder();
 
index ae3a8ebc91b4a737439f349be5038b9a2ad69d05..40e5855ecfadea8746ae2bb2fb75118532f84571 100644 (file)
@@ -116,7 +116,8 @@ public class Pattern {
   }
 
   public boolean match(Issue violation) {
-    boolean match = matchResource(violation.componentKey()) && matchRule(violation.ruleKey());
+    boolean match = violation.componentKey() != null
+      && matchRule(violation.ruleKey());
     if (checkLines && violation.line() != null) {
       match = match && matchLine(violation.line());
     }
@@ -138,7 +139,6 @@ public class Pattern {
   }
 
   boolean matchRule(RuleKey rule) {
-    System.out.printf("Matching rule {} against pattern {}", rule, rulePattern);
     if (rule == null) {
       return false;
     }
@@ -148,7 +148,6 @@ public class Pattern {
   }
 
   boolean matchResource(String resource) {
-    System.out.printf("Matching resource {} against pattern {}", resource, resourcePattern);
     return resource != null && resourcePattern.match(resource);
   }
 
index d40388b9a28bb89b216de5cda0ff6719b94e6e5e..b31ecdc0555f6426b9ddb915f201fa782c64ccc4 100644 (file)
@@ -22,12 +22,9 @@ package org.sonar.plugins.core.issue.ignore.pattern;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Lists;
-import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.utils.SonarException;
 
-import java.io.File;
-import java.io.IOException;
 import java.util.List;
 
 public class PatternDecoder {
@@ -47,23 +44,6 @@ public class PatternDecoder {
     return patterns;
   }
 
-  public List<Pattern> decode(File file) {
-    try {
-      List<String> lines = FileUtils.readLines(file);
-      List<Pattern> patterns = Lists.newLinkedList();
-      for (String line : lines) {
-        Pattern pattern = decodeLine(line);
-        if (pattern != null) {
-          patterns.add(pattern);
-        }
-      }
-      return patterns;
-
-    } catch (IOException e) {
-      throw new SonarException("Fail to load the file: " + file.getAbsolutePath(), e);
-    }
-  }
-
   /**
    * Main method that decodes a line which defines a pattern
    */
@@ -138,7 +118,7 @@ public class PatternDecoder {
 
   @VisibleForTesting
   boolean isBlankOrComment(String line) {
-    return StringUtils.isBlank(line) || StringUtils.startsWith(line, "#");
+    return StringUtils.isBlank(line) ^ StringUtils.startsWith(line, "#");
   }
 
   @VisibleForTesting
index bfc3bdbe377b98bc245ebb308a3f70c7ba6b0aac..e310a265c378de52ce59893785375491207ad404 100644 (file)
@@ -21,6 +21,7 @@
 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;
@@ -42,7 +43,7 @@ public class PatternsInitializer implements BatchExtension {
   private List<Pattern> multicriteriaPatterns;
   private List<Pattern> blockPatterns;
   private List<Pattern> allFilePatterns;
-  private Map<String, Pattern> extraPatternByResource = Maps.newHashMap();
+  private Map<String, List<Pattern>> patternByComponent = Maps.newHashMap();
 
   public PatternsInitializer(Settings settings) {
     this.settings = settings;
@@ -61,8 +62,16 @@ public class PatternsInitializer implements BatchExtension {
     return allFilePatterns;
   }
 
-  public Pattern getExtraPattern(String resource) {
-    return extraPatternByResource.get(resource.substring(resource.lastIndexOf(":") + 1));
+  public boolean hasFileContentPattern() {
+    return ! (blockPatterns.isEmpty() && allFilePatterns.isEmpty());
+  }
+
+  public boolean hasMulticriteriaPatterns() {
+    return ! multicriteriaPatterns.isEmpty();
+  }
+
+  public boolean hasConfiguredPatterns() {
+    return hasFileContentPattern() || hasMulticriteriaPatterns();
   }
 
   @VisibleForTesting
@@ -108,11 +117,34 @@ public class PatternsInitializer implements BatchExtension {
   }
 
   public void addPatternToExcludeResource(String resource) {
-    extraPatternByResource.put(resource, new Pattern(resource, "*").setCheckLines(false));
+    addPatternForComponent(resource, new Pattern(resource, "*").setCheckLines(false));
   }
 
   public void addPatternToExcludeLines(String resource, Set<LineRange> lineRanges) {
-    extraPatternByResource.put(resource, new Pattern(resource, "*", lineRanges));
+    addPatternForComponent(resource, new Pattern(resource, "*", lineRanges));
+  }
+
+  public void configurePatternsForComponent(String componentKey, String path) {
+    for (Pattern pattern: multicriteriaPatterns) {
+      if (pattern.matchResource(path)) {
+        addPatternForComponent(componentKey, pattern);
+      }
+    }
+  }
+
+  public List<Pattern> getPatternsForComponent(String componentKey) {
+    if (patternByComponent.containsKey(componentKey)) {
+      return patternByComponent.get(componentKey);
+    } else {
+      return ImmutableList.of();
+    }
   }
 
+  private void addPatternForComponent(String component, Pattern pattern) {
+    if (!patternByComponent.containsKey(component)) {
+      List<Pattern> newList = Lists.newArrayList();
+      patternByComponent.put(component, newList);
+    }
+    patternByComponent.get(component).add(pattern);
+  }
 }
index 55fec5877c91f10576030546893c0a950fdca9ab..cc721a156934139bf5efc330f9a3915478ddf128 100644 (file)
@@ -26,9 +26,12 @@ import org.sonar.api.batch.SensorContext;
 import org.sonar.api.resources.Java;
 import org.sonar.api.resources.JavaFile;
 import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
 import org.sonar.api.scan.filesystem.FileQuery;
 import org.sonar.api.scan.filesystem.ModuleFileSystem;
+import org.sonar.api.scan.filesystem.PathResolver;
 import org.sonar.api.utils.SonarException;
+import org.sonar.core.component.ComponentKeys;
 import org.sonar.plugins.core.issue.ignore.pattern.PatternsInitializer;
 
 import java.io.File;
@@ -41,15 +44,17 @@ public final class SourceScanner implements Sensor {
   private final RegexpScanner regexpScanner;
   private final PatternsInitializer patternsInitializer;
   private final ModuleFileSystem fileSystem;
+  private final PathResolver pathResolver;
 
   public SourceScanner(RegexpScanner regexpScanner, PatternsInitializer patternsInitializer, ModuleFileSystem fileSystem) {
     this.regexpScanner = regexpScanner;
     this.patternsInitializer = patternsInitializer;
     this.fileSystem = fileSystem;
+    this.pathResolver = new PathResolver();
   }
 
   public boolean shouldExecuteOnProject(Project project) {
-    return patternsInitializer.getAllFilePatterns().size() > 0 || patternsInitializer.getBlockPatterns().size() > 0;
+    return patternsInitializer.hasConfiguredPatterns();
   }
 
   /**
@@ -64,17 +69,24 @@ public final class SourceScanner implements Sensor {
     Charset sourcesEncoding = fileSystem.sourceCharset();
 
     List<File> files;
+    List<File> dirs;
     if (isTest) {
       files = fileSystem.files(FileQuery.onTest().onLanguage(project.getLanguageKey()));
+      dirs = fileSystem.testDirs();
     } else {
       files = fileSystem.files(FileQuery.onSource().onLanguage(project.getLanguageKey()));
+      dirs = fileSystem.sourceDirs();
     }
 
     for (File inputFile : files) {
       try {
-        String resource = defineResource(inputFile, fileSystem, project, isTest);
-        if (resource != null) {
-          regexpScanner.scan(resource, inputFile, sourcesEncoding);
+        String componentKey = resolveComponent(inputFile, fileSystem, project, isTest);
+        if (componentKey != null) {
+          String relativePath = pathResolver.relativePath(dirs, inputFile).path();
+          patternsInitializer.configurePatternsForComponent(componentKey, relativePath);
+          if (patternsInitializer.hasFileContentPattern()) {
+            regexpScanner.scan(componentKey, inputFile, sourcesEncoding);
+          }
         }
       } catch (Exception e) {
         throw new SonarException("Unable to read the source file : '" + inputFile.getAbsolutePath() + "' with the charset : '"
@@ -86,7 +98,8 @@ public final class SourceScanner implements Sensor {
   /*
    * This method is necessary because Java resources are not treated as every other resource...
    */
-  private String defineResource(File inputFile, ModuleFileSystem fileSystem, Project project, boolean isTest) {
+  private String resolveComponent(File inputFile, ModuleFileSystem fileSystem, Project project, boolean isTest) {
+    Resource<?> resource = null;
     if (Java.KEY.equals(project.getLanguageKey()) && Java.isJavaFile(inputFile)) {
       List<File> sourceDirs = null;
       if (isTest) {
@@ -94,19 +107,21 @@ public final class SourceScanner implements Sensor {
       } else {
         sourceDirs = fileSystem.sourceDirs();
       }
-      JavaFile file = JavaFile.fromIOFile(inputFile, sourceDirs, isTest);
-      if (file == null) {
-        return null;
-      } else {
-        return file.getKey();
-      }
+      resource = JavaFile.fromIOFile(inputFile, sourceDirs, isTest);
+    } else {
+      resource = new org.sonar.api.resources.File(inputFile.getPath());
+    }
+
+    if (resource == null) {
+      return null;
+    } else {
+      return ComponentKeys.createKey(project, resource);
     }
-    return inputFile.getPath();
   }
 
   @Override
   public String toString() {
-    return "Ignore Issues - Source Scanner";
+    return "Issues Exclusions - Source Scanner";
   }
 
 }
index 0a37fc7132cec20f16b63aaecb22c18e580303f4..2808d578252fce93ec6ad116a5c300dbd7052468 100644 (file)
@@ -60,28 +60,28 @@ public class IgnoreIssuesFilterTest {
 
   @Test
   public void shouldBeIgnoredWithStandardPatterns() throws IOException {
-    when(patternsInitializer.getMulticriteriaPatterns()).thenReturn(createPatterns("org.foo.Bar;*;*\norg.foo.Hello;checkstyle:MagicNumber;[15-200]"));
+    when(patternsInitializer.getPatternsForComponent(JAVA_FILE)).thenReturn(createPatterns("org.foo.Hello;checkstyle:MagicNumber;[15-200]"));
 
     assertThat(filter.accept(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isFalse();
   }
 
   @Test
   public void shouldNotBeIgnoredWithStandardPatterns() throws IOException {
-    when(patternsInitializer.getMulticriteriaPatterns()).thenReturn(createPatterns("org.foo.Bar;*;*\norg.foo.Hello;checkstyle:MagicNumber;[15-200]"));
+    when(patternsInitializer.getPatternsForComponent(JAVA_FILE)).thenReturn(createPatterns("org.foo.Hello;checkstyle:MagicNumber;[15-200]"));
 
     assertThat(filter.accept(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isTrue();
   }
 
   @Test
   public void shouldBeIgnoredWithExtraPattern() throws IOException {
-    when(patternsInitializer.getExtraPattern(JAVA_FILE)).thenReturn(createPatterns("org.foo.Hello;*;[15-200]").get(0));
+    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.getExtraPattern(JAVA_FILE)).thenReturn(createPatterns("org.foo.Hello;*;[15-200]").get(0));
+    when(patternsInitializer.getPatternsForComponent(JAVA_FILE)).thenReturn(createPatterns("org.foo.Hello;*;[15-200]"));
 
     assertThat(filter.accept(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isTrue();
   }
index c478e714efe2a276cfdb1703d35d568a6a5e1307..4c5395a0b064baf00f73fe80881c6018a6d0d2d5 100644 (file)
@@ -27,6 +27,6 @@ import static org.fest.assertions.Assertions.assertThat;
 public class IgnoreIssuesPluginTest {
   @Test
   public void justForCoverage() {
-    assertThat(new IgnoreIssuesPlugin().getExtensions()).hasSize(3 /* properties */ + 4 /* extensions */);
+    assertThat(IgnoreIssuesPlugin.getExtensions()).hasSize(3 /* properties */ + 4 /* extensions */);
   }
 }
index 3d904b43ec523d4dc287ffbb36b625bc5d465c96..c527412a5d695ef15c011c9205f78b93bb3c7db1 100644 (file)
@@ -25,7 +25,6 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.SonarException;
 
-import java.io.File;
 import java.util.List;
 
 import static org.fest.assertions.Assertions.assertThat;
@@ -138,14 +137,6 @@ public class PatternDecoderTest {
     assertThat(pattern.getAllFileRegexp()).isEqualTo("SONAR-ALL-OFF");
   }
 
-  @Test
-  public void shouldFailIfUnexistingFile() {
-    thrown.expect(SonarException.class);
-    thrown.expectMessage("Fail to load the file");
-
-    decoder.decode(new File("foo"));
-  }
-
   @Test
   public void shouldFailToReadUncorrectLine1() {
     thrown.expect(SonarException.class);
index ec6a6529255a8aa9cf50acb032231c043a995ba2..09ad7fe348262877e01ae351f619ed23621de2cc 100644 (file)
 
 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;
 import org.sonar.api.config.Settings;
 import org.sonar.plugins.core.issue.ignore.Constants;
-import org.sonar.plugins.core.issue.ignore.IgnoreIssuesPlugin;
+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 {
 
@@ -40,13 +43,14 @@ public class PatternsInitializerTest {
 
   @Before
   public void init() {
-    settings = new Settings(new PropertyDefinitions(new IgnoreIssuesPlugin()));
+    settings = new Settings(new PropertyDefinitions(IgnoreIssuesConfiguration.getPropertyDefinitions()));
     patternsInitializer = new PatternsInitializer(settings);
   }
 
   @Test
   public void testNoConfiguration() {
     patternsInitializer.initPatterns();
+    assertThat(patternsInitializer.hasConfiguredPatterns()).isFalse();
     assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0);
   }
 
@@ -55,7 +59,7 @@ public class PatternsInitializerTest {
     String file = "foo";
     patternsInitializer.addPatternToExcludeResource(file);
 
-    Pattern extraPattern = patternsInitializer.getExtraPattern(file);
+    Pattern extraPattern = patternsInitializer.getPatternsForComponent(file).get(0);
     assertThat(extraPattern.matchResource(file)).isTrue();
     assertThat(extraPattern.isCheckLines()).isFalse();
   }
@@ -67,7 +71,7 @@ public class PatternsInitializerTest {
     lineRanges.add(new LineRange(25, 28));
     patternsInitializer.addPatternToExcludeLines(file, lineRanges);
 
-    Pattern extraPattern = patternsInitializer.getExtraPattern(file);
+    Pattern extraPattern = patternsInitializer.getPatternsForComponent(file).get(0);
     assertThat(extraPattern.matchResource(file)).isTrue();
     assertThat(extraPattern.getAllLines()).isEqualTo(Sets.newHashSet(25, 26, 27, 28));
   }
@@ -75,14 +79,17 @@ public class PatternsInitializerTest {
   @Test
   public void shouldReturnMulticriteriaPattern() {
     settings.setProperty(Constants.PATTERNS_MULTICRITERIA_KEY, "1,2");
-    settings.setProperty(Constants.PATTERNS_MULTICRITERIA_KEY + ".1." + Constants.RESOURCE_KEY, "org.foo.Bar");
+    settings.setProperty(Constants.PATTERNS_MULTICRITERIA_KEY + ".1." + Constants.RESOURCE_KEY, "org/foo/Bar.java");
     settings.setProperty(Constants.PATTERNS_MULTICRITERIA_KEY + ".1." + Constants.RULE_KEY, "*");
     settings.setProperty(Constants.PATTERNS_MULTICRITERIA_KEY + ".1." + Constants.RESOURCE_KEY, "*");
-    settings.setProperty(Constants.PATTERNS_MULTICRITERIA_KEY + ".2." + Constants.LINE_RANGE_KEY, "org.foo.Hello");
+    settings.setProperty(Constants.PATTERNS_MULTICRITERIA_KEY + ".2." + Constants.LINE_RANGE_KEY, "org/foo/Hello.java");
     settings.setProperty(Constants.PATTERNS_MULTICRITERIA_KEY + ".2." + Constants.RULE_KEY, "checkstyle:MagicNumber");
     settings.setProperty(Constants.PATTERNS_MULTICRITERIA_KEY + ".2." + Constants.LINE_RANGE_KEY, "[15-200]");
     patternsInitializer.initPatterns();
 
+    assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue();
+    assertThat(patternsInitializer.hasFileContentPattern()).isFalse();
+    assertThat(patternsInitializer.hasMulticriteriaPatterns()).isTrue();
     assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(2);
     assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(0);
     assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(0);
@@ -97,6 +104,9 @@ public class PatternsInitializerTest {
     settings.setProperty(Constants.PATTERNS_BLOCK_KEY + ".2." + Constants.END_BLOCK_REGEXP, "// FOO-ON");
     patternsInitializer.initPatterns();
 
+    assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue();
+    assertThat(patternsInitializer.hasFileContentPattern()).isTrue();
+    assertThat(patternsInitializer.hasMulticriteriaPatterns()).isFalse();
     assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0);
     assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(2);
     assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(0);
@@ -109,8 +119,32 @@ public class PatternsInitializerTest {
     settings.setProperty(Constants.PATTERNS_ALLFILE_KEY + ".2." + Constants.FILE_REGEXP, "//FOO-IGNORE-ALL");
     patternsInitializer.initPatterns();
 
+    assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue();
+    assertThat(patternsInitializer.hasFileContentPattern()).isTrue();
+    assertThat(patternsInitializer.hasMulticriteriaPatterns()).isFalse();
     assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0);
     assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(0);
     assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(2);
   }
+
+  @Test
+  public void shouldConfigurePatternsForComponents() {
+    String componentKey = "groupId:artifactId:org.foo.Bar";
+    String path = "org/foo/Bar.java";
+
+    Pattern matching1, matching2, notMatching;
+    matching1 = mock(Pattern.class);
+    when(matching1.matchResource(path)).thenReturn(true);
+    matching2 = mock(Pattern.class);
+    when(matching2.matchResource(path)).thenReturn(true);
+    notMatching = mock(Pattern.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);
+  }
 }
index 954512edf8c67138bb3e32dab3ffc8962883d9e2..4cd9954ef70963ae6eb24a0c6ddcdf2792462702 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.sonar.plugins.core.issue.ignore.scanner;
 
+import com.google.common.collect.ImmutableList;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -40,13 +41,12 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
 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.never;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 public class SourceScannerTest {
@@ -58,10 +58,10 @@ public class SourceScannerTest {
   @Mock
   private PatternsInitializer patternsInitializer;
   @Mock
-  private Project project;
-  @Mock
   private ModuleFileSystem fileSystem;
 
+  private Project project;
+
   @Rule
   public ExpectedException thrown = ExpectedException.none();
 
@@ -69,6 +69,9 @@ public class SourceScannerTest {
   public void init() {
     MockitoAnnotations.initMocks(this);
 
+    Project realProject = new Project("polop");
+    project = Mockito.spy(realProject);
+    Mockito.doReturn("java").when(project).getLanguageKey();
     when(fileSystem.sourceCharset()).thenReturn(UTF_8);
 
     scanner = new SourceScanner(regexpScanner, patternsInitializer, fileSystem);
@@ -76,20 +79,15 @@ public class SourceScannerTest {
 
   @Test
   public void testToString() throws Exception {
-    assertThat(scanner.toString()).isEqualTo("Ignore Issues - Source Scanner");
+    assertThat(scanner.toString()).isEqualTo("Issues Exclusions - Source Scanner");
   }
 
   @Test
   public void shouldExecute() throws IOException {
-    when(patternsInitializer.getAllFilePatterns()).thenReturn(Arrays.asList(new Pattern(), new Pattern()));
+    when(patternsInitializer.hasConfiguredPatterns()).thenReturn(true);
     assertThat(scanner.shouldExecuteOnProject(null)).isTrue();
 
-    when(patternsInitializer.getAllFilePatterns()).thenReturn(Collections.<Pattern>emptyList());
-    when(patternsInitializer.getBlockPatterns()).thenReturn(Arrays.asList(new Pattern(), new Pattern()));
-    assertThat(scanner.shouldExecuteOnProject(null)).isTrue();
-
-    when(patternsInitializer.getAllFilePatterns()).thenReturn(Collections.<Pattern>emptyList());
-    when(patternsInitializer.getBlockPatterns()).thenReturn(Collections.<Pattern>emptyList());
+    when(patternsInitializer.hasConfiguredPatterns()).thenReturn(false);
     assertThat(scanner.shouldExecuteOnProject(null)).isFalse();
   }
 
@@ -104,11 +102,34 @@ public class SourceScannerTest {
       .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")));
+    when(patternsInitializer.hasFileContentPattern()).thenReturn(true);
 
     scanner.analyse(project, null);
 
-    verify(regexpScanner).scan("[default].Foo", sourceFile, UTF_8);
-    verify(regexpScanner).scan("[default].FooTest", testFile, UTF_8);
+    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);
+  }
+
+  @Test
+  public void shouldAnalyseFilesOnlyWhenRegexConfigured() 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")));
+    when(patternsInitializer.hasFileContentPattern()).thenReturn(false);
+
+    scanner.analyse(project, null);
+
+    verify(patternsInitializer).configurePatternsForComponent("polop:[default].Foo", "Foo.java");
+    verify(patternsInitializer).configurePatternsForComponent("polop:[default].FooTest", "FooTest.java");
+    verifyNoMoreInteractions(regexpScanner);
   }
 
   @Test
@@ -120,11 +141,16 @@ public class SourceScannerTest {
     when(fileSystem.files(Mockito.isA(FileQuery.class)))
       .thenReturn(Arrays.asList(sourceFile))
       .thenReturn(Arrays.asList(testFile));
+    when(fileSystem.sourceDirs()).thenReturn(ImmutableList.of(new File("")));
+    when(fileSystem.testDirs()).thenReturn(ImmutableList.of(new File("")));
+    when(patternsInitializer.hasFileContentPattern()).thenReturn(true);
 
     scanner.analyse(project, null);
 
-    verify(regexpScanner).scan("Foo.php", sourceFile, UTF_8);
-    verify(regexpScanner).scan("FooTest.php", testFile, UTF_8);
+    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);
   }
 
   @Test
@@ -137,8 +163,9 @@ public class SourceScannerTest {
     when(fileSystem.files(Mockito.isA(FileQuery.class)))
       .thenReturn(Arrays.asList(sourceFile, otherFile))
       .thenReturn(empty);
-    when(fileSystem.sourceDirs()).thenReturn(Arrays.asList(new File("src/main/java")));
-    when(fileSystem.testDirs()).thenReturn(Arrays.asList(new File("src/test/java")));
+    when(fileSystem.sourceDirs()).thenReturn(ImmutableList.of(new File("src/main/java"), new File("")));
+    when(fileSystem.testDirs()).thenReturn(ImmutableList.of(new File("src/test/java")));
+    when(patternsInitializer.hasFileContentPattern()).thenReturn(true);
 
     scanner.analyse(project, null);
 
@@ -156,6 +183,7 @@ public class SourceScannerTest {
       .thenReturn(empty);
     when(fileSystem.sourceDirs()).thenReturn(Arrays.asList(new File("src/main/java")));
     when(fileSystem.testDirs()).thenReturn(Arrays.asList(new File("src/test/java")));
+    when(patternsInitializer.hasFileContentPattern()).thenReturn(true);
 
     scanner.analyse(project, null);
 
@@ -168,7 +196,9 @@ public class SourceScannerTest {
 
     when(project.getLanguageKey()).thenReturn("php");
     when(fileSystem.files(Mockito.isA(FileQuery.class))).thenReturn(Arrays.asList(sourceFile));
-    doThrow(new IOException("BUG")).when(regexpScanner).scan("Foo.php", sourceFile, UTF_8);
+    List<Pattern> 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);
     thrown.expectMessage("Unable to read the source file");
index 308b9f02eb5f94918857494877b7e9579217651e..caa4a98b0b22f187023801820254a6488a525def 100644 (file)
@@ -28,11 +28,19 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.Event;
 import org.sonar.api.batch.SonarIndex;
-import org.sonar.api.database.model.ResourceModel;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.design.Dependency;
-import org.sonar.api.measures.*;
-import org.sonar.api.resources.*;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasuresFilter;
+import org.sonar.api.measures.MeasuresFilters;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.ProjectLink;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.ResourceUtils;
+import org.sonar.api.resources.Scopes;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.Violation;
 import org.sonar.api.utils.SonarException;
@@ -42,9 +50,17 @@ import org.sonar.batch.ProjectTree;
 import org.sonar.batch.ResourceFilters;
 import org.sonar.batch.issue.DeprecatedViolations;
 import org.sonar.batch.issue.ScanIssues;
+import org.sonar.core.component.ComponentKeys;
 import org.sonar.core.component.ScanGraph;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 public class DefaultIndex extends SonarIndex {
 
@@ -444,19 +460,6 @@ public class DefaultIndex extends SonarIndex {
     return null;
   }
 
-  static String createUID(Project project, Resource resource) {
-    String uid = resource.getKey();
-    if (!StringUtils.equals(Scopes.PROJECT, resource.getScope())) {
-      // not a project nor a library
-      uid = new StringBuilder(ResourceModel.KEY_SIZE)
-        .append(project.getKey())
-        .append(':')
-        .append(resource.getKey())
-        .toString();
-    }
-    return uid;
-  }
-
   private boolean checkExclusion(Resource resource, Bucket parent) {
     boolean excluded = (parent != null && parent.isExcluded()) || (resourceFilters != null && resourceFilters.isExcluded(resource));
     resource.setExcluded(excluded);
@@ -529,7 +532,7 @@ public class DefaultIndex extends SonarIndex {
       return null;
     }
 
-    resource.setEffectiveKey(createUID(currentProject, resource));
+    resource.setEffectiveKey(ComponentKeys.createKey(currentProject, resource));
     bucket = new Bucket(resource).setParent(parentBucket);
     buckets.put(resource, bucket);
 
index be5cc3c4540a54f15a991c310c93d4d3676a86ce..e3f2e17300a98549f180d925f20b77cb58aea303 100644 (file)
@@ -81,18 +81,6 @@ public class DefaultIndexTest {
     index.doStart(project);
   }
 
-  @Test
-  public void shouldCreateUID() {
-    Project project = new Project("my_project");
-    assertThat(DefaultIndex.createUID(project, project)).isEqualTo("my_project");
-
-    JavaPackage javaPackage = new JavaPackage("org.foo");
-    assertThat(DefaultIndex.createUID(project, javaPackage)).isEqualTo("my_project:org.foo");
-
-    Library library = new Library("junit:junit", "4.7");
-    assertThat(DefaultIndex.createUID(project, library)).isEqualTo("junit:junit");
-  }
-
   @Test
   public void shouldIndexParentOfDeprecatedFiles() {
     File file = new File("org/foo/Bar.java");
diff --git a/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java b/sonar-core/src/main/java/org/sonar/core/component/ComponentKeys.java
new file mode 100644 (file)
index 0000000..6d1c0ef
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.core.component;
+
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.database.model.ResourceModel;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.Scopes;
+
+public final class ComponentKeys {
+
+  private ComponentKeys() {}
+
+  public static String createKey(Project project, Resource<?> resource) {
+    String key = resource.getKey();
+    if (!StringUtils.equals(Scopes.PROJECT, resource.getScope())) {
+      // not a project nor a library
+      key = new StringBuilder(ResourceModel.KEY_SIZE)
+        .append(project.getKey())
+        .append(':')
+        .append(resource.getKey())
+        .toString();
+    }
+    return key;
+  }
+
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/component/ComponentKeysTest.java b/sonar-core/src/test/java/org/sonar/core/component/ComponentKeysTest.java
new file mode 100644 (file)
index 0000000..9287ea6
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.core.component;
+
+import org.junit.Test;
+import org.sonar.api.resources.JavaPackage;
+import org.sonar.api.resources.Library;
+import org.sonar.api.resources.Project;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class ComponentKeysTest {
+
+  @Test
+  public void shouldCreateUID() {
+    Project project = new Project("my_project");
+    assertThat(ComponentKeys.createKey(project, project)).isEqualTo("my_project");
+
+    JavaPackage javaPackage = new JavaPackage("org.foo");
+    assertThat(ComponentKeys.createKey(project, javaPackage)).isEqualTo("my_project:org.foo");
+
+    Library library = new Library("junit:junit", "4.7");
+    assertThat(ComponentKeys.createKey(project, library)).isEqualTo("junit:junit");
+  }
+
+}