]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8745 add rule activation date (q profile) into analysis report
authorDaniel Schwarz <daniel.schwarz@sonarsource.com>
Fri, 3 Feb 2017 13:47:11 +0000 (14:47 +0100)
committerDaniel Schwarz <bartfastiel@users.noreply.github.com>
Fri, 10 Feb 2017 07:57:34 +0000 (08:57 +0100)
20 files changed:
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/qualityprofile/ActiveRule.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadQualityProfilesStep.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/ActiveRuleCompleter.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/CommentDensityRuleTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/CommonRuleTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/CoverageRuleTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/DuplicatedBlockRuleTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/SkippedTestRuleTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/commonrule/TestErrorRuleTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualityprofile/ActiveRulesHolderImplTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/ActiveRule.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultActiveRule.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewActiveRule.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ActiveRulesPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRulesLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/LoadedActiveRule.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java
sonar-scanner-protocol/src/main/protobuf/scanner_report.proto
sonar-ws/src/main/protobuf/ws-rules.proto

index e8c5f97c05696ba9dcd2cb3cfd5c08ac3deee4dc..c21cd58f7b373275d3d8932d64109b6e24fbd4d2 100644 (file)
@@ -29,11 +29,13 @@ public class ActiveRule {
   private final RuleKey ruleKey;
   private final String severity;
   private final Map<String, String> params;
+  private final long createdAt;
 
-  public ActiveRule(RuleKey ruleKey, String severity, Map<String, String> params) {
+  public ActiveRule(RuleKey ruleKey, String severity, Map<String, String> params, long createdAt) {
     this.ruleKey = ruleKey;
     this.severity = severity;
     this.params = ImmutableMap.copyOf(params);
+    this.createdAt = createdAt;
   }
 
   public RuleKey getRuleKey() {
@@ -47,4 +49,8 @@ public class ActiveRule {
   public Map<String, String> getParams() {
     return params;
   }
+
+  public long getCreatedAt() {
+    return createdAt;
+  }
 }
index d406db99305b5afd41baf2437822c0795d71c4cf..ce21d2c27a192e5de7b0cef1bbe52249fdf7a2cf 100644 (file)
@@ -81,6 +81,6 @@ public class LoadQualityProfilesStep implements ComputationStep {
   private static ActiveRule convert(ScannerReport.ActiveRule input) {
     RuleKey key = RuleKey.of(input.getRuleRepository(), input.getRuleKey());
     Map<String, String> params = new HashMap<>(input.getParamsByKey());
-    return new ActiveRule(key, input.getSeverity().name(), params);
+    return new ActiveRule(key, input.getSeverity().name(), params, input.getCreatedAt());
   }
 }
index 496a1aee2b7352922e3d10cc643161f48860efa8..ed6459780baf570586102eb4f49a73afe53726be 100644 (file)
@@ -35,6 +35,7 @@ import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.db.DbClient;
@@ -162,6 +163,7 @@ public class ActiveRuleCompleter {
     String inheritance = activeRule.getInheritance();
     activeRuleResponse.setInherit(inheritance != null ? inheritance : ActiveRule.Inheritance.NONE.name());
     activeRuleResponse.setSeverity(activeRule.getSeverityString());
+    activeRuleResponse.setCreatedAt(DateUtils.formatDateTime(activeRule.getCreatedAt()));
     Rules.Active.Param.Builder paramBuilder = Rules.Active.Param.newBuilder();
     for (ActiveRuleParamDto parameter : parameters) {
       activeRuleResponse.addParams(paramBuilder.clear()
index fc482f87de220f769182c3d277c3fc7b058ae90d..7a520d787c398cb035a122191477125ea689c532 100644 (file)
@@ -71,7 +71,7 @@ public class CommentDensityRuleTest {
 
   @Test
   public void no_issues_if_enough_comments() {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "25")));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "25"), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(90.0, 1));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
@@ -81,7 +81,7 @@ public class CommentDensityRuleTest {
 
   @Test
   public void issue_if_not_enough_comments() {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "25")));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "25"), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(10.0, 1));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_KEY, Measure.newMeasureBuilder().create(40));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.NCLOC_KEY, Measure.newMeasureBuilder().create(360));
@@ -98,7 +98,7 @@ public class CommentDensityRuleTest {
 
   @Test
   public void issue_if_not_enough_comments__test_ceil() {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "25")));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "25"), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(0.0, 1));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_KEY, Measure.newMeasureBuilder().create(0));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.NCLOC_KEY, Measure.newMeasureBuilder().create(1));
@@ -120,7 +120,7 @@ public class CommentDensityRuleTest {
     thrown.expect(IllegalStateException.class);
     thrown.expectMessage("Minimum density of rule [common-java:InsufficientCommentDensity] is incorrect. Got [100] but must be strictly less than 100.");
 
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "100")));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "100"), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(0.0, 1));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_KEY, Measure.newMeasureBuilder().create(0));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.NCLOC_KEY, Measure.newMeasureBuilder().create(1));
index 2d7eee461ff3c943b111a58f072cafbc6b66621b..c8d75e20f4ac1fcde57627800fa08d6cbdb2b15b 100644 (file)
@@ -36,7 +36,7 @@ public class CommonRuleTest {
 
   @Test
   public void test_getMinDensityParam() throws Exception {
-    ActiveRule activeRule = new ActiveRule(RuleTesting.XOO_X1, Severity.MAJOR, ImmutableMap.of("minDensity", "30.5"));
+    ActiveRule activeRule = new ActiveRule(RuleTesting.XOO_X1, Severity.MAJOR, ImmutableMap.of("minDensity", "30.5"), 1_000L);
     double minDensity = CommonRule.getMinDensityParam(activeRule, "minDensity");
 
     assertThat(minDensity).isEqualTo(30.5);
@@ -47,7 +47,7 @@ public class CommonRuleTest {
     thrown.expect(IllegalStateException.class);
     thrown.expectMessage("Required parameter [minDensity] is missing on rule [xoo:x1]");
 
-    ActiveRule activeRule = new ActiveRule(RuleTesting.XOO_X1, Severity.MAJOR, ImmutableMap.<String, String>of());
+    ActiveRule activeRule = new ActiveRule(RuleTesting.XOO_X1, Severity.MAJOR, ImmutableMap.<String, String>of(), 1_000L);
     CommonRule.getMinDensityParam(activeRule, "minDensity");
   }
 
@@ -56,7 +56,7 @@ public class CommonRuleTest {
     thrown.expect(IllegalStateException.class);
     thrown.expectMessage("Minimum density of rule [xoo:x1] is incorrect. Got [-30.5] but must be between 0 and 100.");
 
-    ActiveRule activeRule = new ActiveRule(RuleTesting.XOO_X1, Severity.MAJOR, ImmutableMap.of("minDensity", "-30.5"));
+    ActiveRule activeRule = new ActiveRule(RuleTesting.XOO_X1, Severity.MAJOR, ImmutableMap.of("minDensity", "-30.5"), 1_000L);
     CommonRule.getMinDensityParam(activeRule, "minDensity");
   }
 
@@ -65,7 +65,7 @@ public class CommonRuleTest {
     thrown.expect(IllegalStateException.class);
     thrown.expectMessage("Minimum density of rule [xoo:x1] is incorrect. Got [305] but must be between 0 and 100.");
 
-    ActiveRule activeRule = new ActiveRule(RuleTesting.XOO_X1, Severity.MAJOR, ImmutableMap.of("minDensity", "305"));
+    ActiveRule activeRule = new ActiveRule(RuleTesting.XOO_X1, Severity.MAJOR, ImmutableMap.of("minDensity", "305"), 1_000L);
     CommonRule.getMinDensityParam(activeRule, "minDensity");
   }
 }
index e6caaed3a0567b1e0598544a2489af6b4a88ee30..7556d06e3c3716e35871e0b1a264ca40dde3c3fc 100644 (file)
@@ -85,7 +85,7 @@ public abstract class CoverageRuleTest {
 
   @Test
   public void no_issue_if_enough_coverage() {
-    activeRuleHolder.put(new ActiveRule(getRuleKey(), Severity.CRITICAL, ImmutableMap.of(getMinPropertyKey(), "65")));
+    activeRuleHolder.put(new ActiveRule(getRuleKey(), Severity.CRITICAL, ImmutableMap.of(getMinPropertyKey(), "65"), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getCoverageMetricKey(), Measure.newMeasureBuilder().create(90.0, 1));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
@@ -95,7 +95,7 @@ public abstract class CoverageRuleTest {
 
   @Test
   public void issue_if_coverage_is_too_low() {
-    activeRuleHolder.put(new ActiveRule(getRuleKey(), Severity.CRITICAL, ImmutableMap.of(getMinPropertyKey(), "65")));
+    activeRuleHolder.put(new ActiveRule(getRuleKey(), Severity.CRITICAL, ImmutableMap.of(getMinPropertyKey(), "65"), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getCoverageMetricKey(), Measure.newMeasureBuilder().create(20.0, 1));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getUncoveredMetricKey(), Measure.newMeasureBuilder().create(40));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getToCoverMetricKey(), Measure.newMeasureBuilder().create(50));
@@ -113,7 +113,7 @@ public abstract class CoverageRuleTest {
 
   @Test
   public void no_issue_if_coverage_is_not_set() {
-    activeRuleHolder.put(new ActiveRule(getRuleKey(), Severity.CRITICAL, ImmutableMap.of(getMinPropertyKey(), "65")));
+    activeRuleHolder.put(new ActiveRule(getRuleKey(), Severity.CRITICAL, ImmutableMap.of(getMinPropertyKey(), "65"), 1_000L));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
 
index 013acccfc21dc2458024eac8d8b9fdfff2203f9d..07239e4217b1654f4976a315267fdcfedddcbbff 100644 (file)
@@ -65,7 +65,7 @@ public class DuplicatedBlockRuleTest {
 
   @Test
   public void no_issue_if_no_duplicated_blocks() throws Exception {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap()));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap(), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.DUPLICATED_BLOCKS_KEY, Measure.newMeasureBuilder().create(0));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
@@ -75,7 +75,7 @@ public class DuplicatedBlockRuleTest {
 
   @Test
   public void issue_if_duplicated_blocks() throws Exception {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap()));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap(), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.DUPLICATED_BLOCKS_KEY, Measure.newMeasureBuilder().create(3));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
index 3a8d5daa7c05f6eff7bc4908ea42c60e17d594fb..b3b7de070edc78a6cb217b9419dc1be882aa2283 100644 (file)
@@ -66,7 +66,7 @@ public class SkippedTestRuleTest {
 
   @Test
   public void issue_if_skipped_tests() throws Exception {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap()));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap(), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.SKIPPED_TESTS_KEY, Measure.newMeasureBuilder().create(2));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
@@ -79,7 +79,7 @@ public class SkippedTestRuleTest {
 
   @Test
   public void no_issues_if_zero_skipped_tests() throws Exception {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap()));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap(), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.SKIPPED_TESTS_KEY, Measure.newMeasureBuilder().create(0));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
@@ -89,7 +89,7 @@ public class SkippedTestRuleTest {
 
   @Test
   public void no_issues_if_measure_is_absent() throws Exception {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap()));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap(), 1_000L));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
 
index 4ea1147c4a78b3d8ac6cfbc520e48e7679476c1a..4738271083f30f9a92656150449d90cc706b3e0c 100644 (file)
@@ -67,7 +67,7 @@ public class TestErrorRuleTest {
 
   @Test
   public void issue_if_errors_or_failures() throws Exception {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap()));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap(), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.TEST_ERRORS_KEY, Measure.newMeasureBuilder().create(2));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.TEST_FAILURES_KEY, Measure.newMeasureBuilder().create(1));
 
@@ -81,7 +81,7 @@ public class TestErrorRuleTest {
 
   @Test
   public void no_issues_if_zero_errors_and_failures() throws Exception {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap()));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap(), 1_000L));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.TEST_ERRORS_KEY, Measure.newMeasureBuilder().create(0));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.TEST_FAILURES_KEY, Measure.newMeasureBuilder().create(0));
 
@@ -92,7 +92,7 @@ public class TestErrorRuleTest {
 
   @Test
   public void no_issues_if_test_measures_are_absent() throws Exception {
-    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap()));
+    activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, Collections.<String, String>emptyMap(), 1_000L));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
 
index abf5a88b8fe3e49a8c90662cefb8a425fe59ceef..71d018544889bdc0574a8c9573c028db3a343c4f 100644 (file)
@@ -32,6 +32,8 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 public class ActiveRulesHolderImplTest {
 
+  private static final long SOME_DATE = 1_000L;
+
   static final RuleKey RULE_KEY = RuleKey.of("java", "S001");
 
   @Rule
@@ -48,7 +50,7 @@ public class ActiveRulesHolderImplTest {
 
   @Test
   public void get_active_rule() throws Exception {
-    underTest.set(asList(new ActiveRule(RULE_KEY, Severity.BLOCKER, Collections.<String, String>emptyMap())));
+    underTest.set(asList(new ActiveRule(RULE_KEY, Severity.BLOCKER, Collections.<String, String>emptyMap(), SOME_DATE)));
 
     Optional<ActiveRule> activeRule = underTest.get(RULE_KEY);
     assertThat(activeRule.isPresent()).isTrue();
@@ -61,7 +63,7 @@ public class ActiveRulesHolderImplTest {
     thrown.expect(IllegalStateException.class);
     thrown.expectMessage("Active rules have already been initialized");
 
-    underTest.set(asList(new ActiveRule(RULE_KEY, Severity.BLOCKER, Collections.<String, String>emptyMap())));
+    underTest.set(asList(new ActiveRule(RULE_KEY, Severity.BLOCKER, Collections.<String, String>emptyMap(), 1_000L)));
     underTest.set(Collections.<ActiveRule>emptyList());
 
   }
@@ -80,8 +82,7 @@ public class ActiveRulesHolderImplTest {
     thrown.expectMessage("Active rule must not be declared multiple times: java:S001");
 
     underTest.set(asList(
-      new ActiveRule(RULE_KEY, Severity.BLOCKER, Collections.<String, String>emptyMap()),
-      new ActiveRule(RULE_KEY, Severity.MAJOR, Collections.<String, String>emptyMap())
-      ));
+      new ActiveRule(RULE_KEY, Severity.BLOCKER, Collections.<String, String>emptyMap(), 1_000L),
+      new ActiveRule(RULE_KEY, Severity.MAJOR, Collections.<String, String>emptyMap(), 1_000L)));
   }
 }
index 51032004300d172fe69c264e1a9593c09d7951f7..e91453287505e8812f187a47e8a543f42880e340 100644 (file)
  */
 package org.sonar.api.batch.rule;
 
-import org.sonar.api.rule.RuleKey;
-
-import javax.annotation.CheckForNull;
-
 import java.util.Map;
+import javax.annotation.CheckForNull;
+import org.sonar.api.rule.RuleKey;
 
 /**
  * Configuration of a rule activated on a Quality profile
index e2bb7cfd67a370c87e8de8fc0b9f526183746f1d..cc95d9c2867b6a442d7ec8c0c6c2ddfcb0a8d192 100644 (file)
 package org.sonar.api.batch.rule.internal;
 
 import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import javax.annotation.concurrent.Immutable;
 import org.sonar.api.batch.rule.ActiveRule;
 import org.sonar.api.rule.RuleKey;
 
-import javax.annotation.concurrent.Immutable;
-
-import java.util.Map;
-
 @Immutable
 public class DefaultActiveRule implements ActiveRule {
   private final RuleKey ruleKey;
@@ -35,6 +33,7 @@ public class DefaultActiveRule implements ActiveRule {
   private final String language;
   private final String templateRuleKey;
   private final Map<String, String> params;
+  private final long createdAt;
 
   DefaultActiveRule(NewActiveRule newActiveRule) {
     this.severity = newActiveRule.severity;
@@ -43,6 +42,7 @@ public class DefaultActiveRule implements ActiveRule {
     this.ruleKey = newActiveRule.ruleKey;
     this.params = ImmutableMap.copyOf(newActiveRule.params);
     this.language = newActiveRule.language;
+    this.createdAt = newActiveRule.createdAt;
   }
 
   @Override
@@ -80,4 +80,8 @@ public class DefaultActiveRule implements ActiveRule {
   public String templateRuleKey() {
     return templateRuleKey;
   }
+
+  public long createdAt() {
+    return createdAt;
+  }
 }
index 9bc995c72815b1db1c809c786afeb117535d0873..173e2e51faa456e9318b6675b36ba967c3506ad4 100644 (file)
  */
 package org.sonar.api.batch.rule.internal;
 
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 
-import javax.annotation.Nullable;
-
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * @since 4.2
  */
@@ -36,6 +34,7 @@ public class NewActiveRule {
   String name;
   String severity = Severity.defaultSeverity();
   Map<String, String> params = new HashMap<>();
+  long createdAt;
   String internalKey;
   String language;
   String templateRuleKey;
@@ -85,6 +84,14 @@ public class NewActiveRule {
     return params;
   }
 
+  public long getCreatedAt() {
+    return createdAt;
+  }
+
+  public void setCreatedAt(long createdAt) {
+    this.createdAt = createdAt;
+  }
+
   public ActiveRulesBuilder activate() {
     builder.activate(this);
     return builder;
index 2a751aa04b42db24891d4a48e9ce3334374f5928..ddc70b43b625404c890ac23da89ca0d983ae125f 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.scanner.report;
 
 import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.DefaultActiveRule;
 import org.sonar.scanner.protocol.Constants;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
@@ -38,11 +39,13 @@ public class ActiveRulesPublisher implements ReportPublisherStep {
   public void publish(ScannerReportWriter writer) {
     final ScannerReport.ActiveRule.Builder builder = ScannerReport.ActiveRule.newBuilder();
     writer.writeActiveRules(activeRules.findAll().stream()
+      .map(DefaultActiveRule.class::cast)
       .map(input -> {
         builder.clear();
         builder.setRuleRepository(input.ruleKey().repository());
         builder.setRuleKey(input.ruleKey().rule());
         builder.setSeverity(Constants.Severity.valueOf(input.severity()));
+        builder.setCreatedAt(input.createdAt());
         builder.getMutableParamsByKey().putAll(input.params());
         return builder.build();
       }).collect(toList()));
index 42df46a0a3de3a93aa422b9fe2b58ad9dd6d8525..6e0564b513d8f5b895089a116d1e930ad126c3ae 100644 (file)
@@ -82,6 +82,7 @@ public class ActiveRulesProvider extends ProviderAdapter {
       NewActiveRule newActiveRule = builder.create(activeRule.getRuleKey());
       newActiveRule.setName(activeRule.getName());
       newActiveRule.setSeverity(activeRule.getSeverity());
+      newActiveRule.setCreatedAt(activeRule.getCreatedAt());
       newActiveRule.setLanguage(activeRule.getLanguage());
       newActiveRule.setInternalKey(activeRule.getInternalKey());
       newActiveRule.setTemplateRuleKey(activeRule.getTemplateRuleKey());
index 2f8b518cb0461a2225c2de7b08f208509d4d64b6..5bc38c82a0f140012a68a132c7d837655603ffa9 100644 (file)
@@ -37,8 +37,11 @@ import org.sonarqube.ws.Rules.Rule;
 import org.sonarqube.ws.Rules.SearchResponse;
 import org.sonarqube.ws.client.GetRequest;
 
+import static org.sonar.api.utils.DateUtils.dateToLong;
+import static org.sonar.api.utils.DateUtils.parseDateTime;
+
 public class DefaultActiveRulesLoader implements ActiveRulesLoader {
-  private static final String RULES_SEARCH_URL = "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives&activation=true";
+  private static final String RULES_SEARCH_URL = "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives,createdAt&activation=true";
 
   private final ScannerWsClient wsClient;
 
@@ -103,6 +106,7 @@ public class DefaultActiveRulesLoader implements ActiveRulesLoader {
       loadedRule.setRuleKey(RuleKey.parse(r.getKey()));
       loadedRule.setName(r.getName());
       loadedRule.setSeverity(active.getSeverity());
+      loadedRule.setCreatedAt(dateToLong(parseDateTime(active.getCreatedAt())));
       loadedRule.setLanguage(r.getLang());
       loadedRule.setInternalKey(r.getInternalKey());
       if (r.hasTemplateKey()) {
index 72ec6f5f26600475cf893eb5b5908540049f3031..d329518735f803cec829f8a7f897db59418119b8 100644 (file)
@@ -30,6 +30,7 @@ public class LoadedActiveRule {
   private String name;
   private String language;
   private Map<String, String> params;
+  private long createdAt;
   private String templateRuleKey;
   private String internalKey;
 
@@ -73,6 +74,14 @@ public class LoadedActiveRule {
     this.params = params;
   }
 
+  public long getCreatedAt() {
+    return createdAt;
+  }
+
+  public void setCreatedAt(long createdAt) {
+    this.createdAt = createdAt;
+  }
+
   @CheckForNull
   public String getTemplateRuleKey() {
     return templateRuleKey;
index 1b373162db7dec56f7861365f2f7f1e4ccc870ac..e29a30194bc4672b343d18d9c2a0f2f4609ba92d 100644 (file)
@@ -87,7 +87,7 @@ public class DefaultActiveRulesLoaderTest {
   }
 
   private String urlOfPage(int page) {
-    return "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives&activation=true&qprofile=c%2B-test_c%2B-values-17445&p=" + page
+    return "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives,createdAt&activation=true&qprofile=c%2B-test_c%2B-values-17445&p=" + page
       + "&ps=500";
   }
 
@@ -95,7 +95,7 @@ public class DefaultActiveRulesLoaderTest {
    * Generates an imaginary protobuf result.
    *
    * @param numberOfRules the number of rules, that the response should contain
-   * @param total TODO
+   * @param total the number of results on all pages
    * @return the binary stream
    */
   private InputStream responseOfSize(int numberOfRules, int total) {
@@ -111,6 +111,7 @@ public class DefaultActiveRulesLoaderTest {
         rules.addRules(ruleBuilder);
 
         Active.Builder activeBuilder = Active.newBuilder();
+        activeBuilder.setCreatedAt("2014-05-27T15:50:45+0100");
         if (EXAMPLE_KEY.equals(key)) {
           activeBuilder.addParams(Rules.Active.Param.newBuilder().setKey(FORMAT_KEY).setValue(FORMAT_VALUE));
           activeBuilder.setSeverity(SEVERITY_VALUE);
index 0bfdff21c152e3dfc20a59816fb1d40c833c1a2f..7033c31ce75c5f4862f16ebb8e72e23273a17487 100644 (file)
@@ -56,6 +56,7 @@ message ActiveRule {
   string rule_key = 2;
   Severity severity = 3;
   map<string,string> params_by_key = 4;
+  int64 createdAt = 5;
 }
 
 message ComponentLink {
index 4b4b2f697c074cee5cf2e04507966763dcbf335e..d3dfe2cd826f8ae2ce8560fd90c76672c79f3d8e 100644 (file)
@@ -157,6 +157,7 @@ message Active {
   // Unused since 5.6, it has been removed because it was never used and costly to compute
   optional string unusedParent = 4;
   repeated Param params = 5;
+  optional string createdAt = 6;
 
   message Param {
     optional string key = 1;