]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5389 Allow to find an active rule by internal key
authorJulien HENRY <julien.henry@sonarsource.com>
Tue, 22 Jul 2014 13:09:38 +0000 (15:09 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Tue, 22 Jul 2014 13:21:40 +0000 (15:21 +0200)
sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/XooPlugin.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/CreateIssueByInternalKeySensor.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/ActiveRules.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultActiveRules.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/ActiveRulesBuilderTest.java

index 545bacaa0050fe1e0872f207c1c365838f070f3f..0c2c4a6356acc76d3a61cc503dfe1b1d0419d04b 100644 (file)
@@ -24,6 +24,7 @@ import org.apache.commons.lang.StringUtils;
 import org.picocontainer.injectors.ProviderAdapter;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.DefaultActiveRules;
 import org.sonar.api.config.Settings;
 import org.sonar.api.profiles.RulesProfile;
 import org.sonar.api.rules.ActiveRule;
@@ -76,7 +77,7 @@ public class RulesProfileProvider extends ProviderAdapter {
     // TODO deprecatedProfile.setVersion(qProfile.version());
     deprecatedProfile.setName(qProfile.getName());
     deprecatedProfile.setLanguage(qProfile.getLanguage());
-    for (org.sonar.api.batch.rule.ActiveRule activeRule : activeRules.findByLanguage(qProfile.getLanguage())) {
+    for (org.sonar.api.batch.rule.ActiveRule activeRule : ((DefaultActiveRules) activeRules).findByLanguage(qProfile.getLanguage())) {
       Rule rule = ruleFinder.findByKey(activeRule.ruleKey());
       ActiveRule deprecatedActiveRule = deprecatedProfile.activateRule(rule, RulePriority.valueOf(activeRule.severity()));
       for (Map.Entry<String, String> param : activeRule.params().entrySet()) {
index e0536f66d43b60f54af0e2900b0c4eb226d44813..3fec3ccb251f3cd2418e36c1cada5319c658ffd8 100644 (file)
@@ -45,7 +45,7 @@ public class IssuesMediumTest {
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way")
-    .activateRule(new ActiveRule("xoo", "OneIssuePerLine", "MAJOR", "xoo", "xoo"))
+    .activateRule(new ActiveRule("xoo", "OneIssuePerLine", "MAJOR", "OneIssuePerLine.internal", "xoo"))
     .bootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor"))
     .build();
 
@@ -70,6 +70,18 @@ public class IssuesMediumTest {
     assertThat(result.issues()).hasSize(24);
   }
 
+  @Test
+  public void findActiveRuleByInternalKey() throws Exception {
+    File projectDir = new File(IssuesMediumTest.class.getResource("/mediumtest/xoo/sample").toURI());
+
+    TaskResult result = tester
+      .newScanTask(new File(projectDir, "sonar-project.properties"))
+      .property("sonar.xoo.internalKey", "OneIssuePerLine.internal")
+      .start();
+
+    assertThat(result.issues()).hasSize(24 /* 24 lines */+ 3 /* 3 files */);
+  }
+
   @Test
   public void testOverrideQProfileSeverity() throws Exception {
     File projectDir = new File(IssuesMediumTest.class.getResource("/mediumtest/xoo/sample").toURI());
index 37abfffed295e0f41985255f6b03e38076f8cacd..f281ea09899433f603af22b027e0c5056f819cd9 100644 (file)
@@ -23,6 +23,7 @@ import org.sonar.api.SonarPlugin;
 import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
 import org.sonar.batch.mediumtest.xoo.plugin.lang.MeasureSensor;
 import org.sonar.batch.mediumtest.xoo.plugin.lang.ScmActivitySensor;
+import org.sonar.batch.mediumtest.xoo.plugin.rule.CreateIssueByInternalKeySensor;
 import org.sonar.batch.mediumtest.xoo.plugin.rule.OneIssueOnDirPerFileSensor;
 import org.sonar.batch.mediumtest.xoo.plugin.rule.OneIssuePerLineSensor;
 
@@ -39,9 +40,10 @@ public final class XooPlugin extends SonarPlugin {
       ScmActivitySensor.class,
       Xoo.class,
 
-      // rules
+      // sensors
       OneIssuePerLineSensor.class,
-      OneIssueOnDirPerFileSensor.class
+      OneIssueOnDirPerFileSensor.class,
+      CreateIssueByInternalKeySensor.class
       );
   }
 }
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/CreateIssueByInternalKeySensor.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/CreateIssueByInternalKeySensor.java
new file mode 100644 (file)
index 0000000..1ee150a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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.mediumtest.xoo.plugin.rule;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.rule.ActiveRule;
+import org.sonar.api.batch.sensor.Sensor;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
+import org.sonar.batch.mediumtest.xoo.plugin.base.XooConstants;
+
+public class CreateIssueByInternalKeySensor implements Sensor {
+
+  private static final String INTERNAL_KEY_PROPERTY = "sonar.xoo.internalKey";
+
+  @Override
+  public void describe(SensorDescriptor descriptor) {
+    descriptor
+      .name("CreateIssueByInternalKeySensor")
+      .workOnLanguages(Xoo.KEY)
+      .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST);
+  }
+
+  @Override
+  public void execute(SensorContext context) {
+    for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) {
+      createIssues(file, context);
+    }
+  }
+
+  private void createIssues(InputFile file, SensorContext context) {
+    ActiveRule rule = context.activeRules().findByInternalKey(XooConstants.REPOSITORY_KEY,
+      context.settings().getString(INTERNAL_KEY_PROPERTY));
+    if (rule != null) {
+      context.addIssue(context.issueBuilder()
+        .ruleKey(rule.ruleKey())
+        .onFile(file)
+        .message("This issue is generated on each file")
+        .build());
+    }
+  }
+}
index 17a885f0677b6b151f456381e71fa03c177e17fc..20a2fb19a4e928c8b80c753570d6879ff5de6cce 100644 (file)
@@ -23,6 +23,7 @@ import org.sonar.api.BatchComponent;
 import org.sonar.api.rule.RuleKey;
 
 import javax.annotation.CheckForNull;
+
 import java.util.Collection;
 
 /**
@@ -56,7 +57,17 @@ public interface ActiveRules extends BatchComponent {
 
   /**
    * The active rules for a given language, like <code>java</code>
+   * @deprecated since 4.5 Not sure rules will continue to be linked to a language
    */
+  @Deprecated
   Collection<ActiveRule> findByLanguage(String language);
 
+  /**
+   * Find a {@link ActiveRule} by the associated internal key. <code>null</code>
+   * is returned if the rule does not exist or if the rule is not activated
+   * on any Quality profile associated with the module.
+   */
+  @CheckForNull
+  ActiveRule findByInternalKey(String repository, String internalKey);
+
 }
index 86807ff737f8be1b878d80315dcc70e95545d5dc..91b5cafda55f99b2f119826eb51116b14c099207 100644 (file)
@@ -21,20 +21,23 @@ package org.sonar.api.batch.rule.internal;
 
 import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ListMultimap;
-import org.apache.commons.lang.StringUtils;
 import org.sonar.api.batch.rule.ActiveRule;
 import org.sonar.api.batch.rule.ActiveRules;
 import org.sonar.api.rule.RuleKey;
 
 import javax.annotation.concurrent.Immutable;
+
 import java.util.Collection;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
 
 @Immutable
-class DefaultActiveRules implements ActiveRules {
+public class DefaultActiveRules implements ActiveRules {
 
   // TODO use disk-backed cache (persistit) instead of full in-memory cache ?
   private final ListMultimap<String, ActiveRule> activeRulesByRepository;
+  private final Map<String, Map<String, ActiveRule>> activeRulesByRepositoryAndKey = new HashMap<String, Map<String, ActiveRule>>();
+  private final Map<String, Map<String, ActiveRule>> activeRulesByRepositoryAndInternalKey = new HashMap<String, Map<String, ActiveRule>>();
   private final ListMultimap<String, ActiveRule> activeRulesByLanguage;
 
   public DefaultActiveRules(Collection<NewActiveRule> newActiveRules) {
@@ -43,9 +46,18 @@ class DefaultActiveRules implements ActiveRules {
     for (NewActiveRule newAR : newActiveRules) {
       DefaultActiveRule ar = new DefaultActiveRule(newAR);
       repoBuilder.put(ar.ruleKey().repository(), ar);
-      if (ar.language()!=null) {
+      if (ar.language() != null) {
         langBuilder.put(ar.language(), ar);
       }
+      if (!activeRulesByRepositoryAndKey.containsKey(ar.ruleKey().repository())) {
+        activeRulesByRepositoryAndKey.put(ar.ruleKey().repository(), new HashMap<String, ActiveRule>());
+        activeRulesByRepositoryAndInternalKey.put(ar.ruleKey().repository(), new HashMap<String, ActiveRule>());
+      }
+      activeRulesByRepositoryAndKey.get(ar.ruleKey().repository()).put(ar.ruleKey().rule(), ar);
+      String internalKey = ar.internalKey();
+      if (internalKey != null) {
+        activeRulesByRepositoryAndInternalKey.get(ar.ruleKey().repository()).put(internalKey, ar);
+      }
     }
     activeRulesByRepository = repoBuilder.build();
     activeRulesByLanguage = langBuilder.build();
@@ -53,13 +65,7 @@ class DefaultActiveRules implements ActiveRules {
 
   @Override
   public ActiveRule find(RuleKey ruleKey) {
-    List<ActiveRule> rules = activeRulesByRepository.get(ruleKey.repository());
-    for (ActiveRule rule : rules) {
-      if (StringUtils.equals(rule.ruleKey().rule(), ruleKey.rule())) {
-        return rule;
-      }
-    }
-    return null;
+    return activeRulesByRepositoryAndKey.containsKey(ruleKey.repository()) ? activeRulesByRepositoryAndKey.get(ruleKey.repository()).get(ruleKey.rule()) : null;
   }
 
   @Override
@@ -76,4 +82,9 @@ class DefaultActiveRules implements ActiveRules {
   public Collection<ActiveRule> findByLanguage(String language) {
     return activeRulesByLanguage.get(language);
   }
+
+  @Override
+  public ActiveRule findByInternalKey(String repository, String internalKey) {
+    return activeRulesByRepositoryAndInternalKey.containsKey(repository) ? activeRulesByRepositoryAndInternalKey.get(repository).get(internalKey) : null;
+  }
 }
index c308024616f31268f7660d2a6d3a69764d64605f..584b1ea7663cc24de13fbb82721a6cf2f082a446 100644 (file)
@@ -52,6 +52,7 @@ public class ActiveRulesBuilderTest {
     assertThat(activeRules.findAll()).hasSize(3);
     assertThat(activeRules.findByRepository("squid")).hasSize(2);
     assertThat(activeRules.findByRepository("findbugs")).hasSize(1);
+    assertThat(activeRules.findByInternalKey("squid", "__S0001__")).isNotNull();
     assertThat(activeRules.findByRepository("unknown")).isEmpty();
 
     ActiveRule squid1 = activeRules.find(RuleKey.of("squid", "S0001"));