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() {
public Map<String, String> getParams() {
return params;
}
+
+ public long getCreatedAt() {
+ return createdAt;
+ }
}
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());
}
}
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;
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()
@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");
@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));
@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));
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));
@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);
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");
}
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");
}
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");
}
}
@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");
@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));
@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");
@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");
@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");
@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");
@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");
@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");
@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));
@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));
@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");
public class ActiveRulesHolderImplTest {
+ private static final long SOME_DATE = 1_000L;
+
static final RuleKey RULE_KEY = RuleKey.of("java", "S001");
@Rule
@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();
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());
}
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)));
}
}
*/
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
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;
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;
this.ruleKey = newActiveRule.ruleKey;
this.params = ImmutableMap.copyOf(newActiveRule.params);
this.language = newActiveRule.language;
+ this.createdAt = newActiveRule.createdAt;
}
@Override
public String templateRuleKey() {
return templateRuleKey;
}
+
+ public long createdAt() {
+ return createdAt;
+ }
}
*/
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
*/
String name;
String severity = Severity.defaultSeverity();
Map<String, String> params = new HashMap<>();
+ long createdAt;
String internalKey;
String language;
String templateRuleKey;
return params;
}
+ public long getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(long createdAt) {
+ this.createdAt = createdAt;
+ }
+
public ActiveRulesBuilder activate() {
builder.activate(this);
return builder;
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;
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()));
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());
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;
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()) {
private String name;
private String language;
private Map<String, String> params;
+ private long createdAt;
private String templateRuleKey;
private String internalKey;
this.params = params;
}
+ public long getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(long createdAt) {
+ this.createdAt = createdAt;
+ }
+
@CheckForNull
public String getTemplateRuleKey() {
return templateRuleKey;
}
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";
}
* 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) {
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);
string rule_key = 2;
Severity severity = 3;
map<string,string> params_by_key = 4;
+ int64 createdAt = 5;
}
message ComponentLink {
// 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;