aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/sonar-core-plugin/src
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2015-02-06 15:09:57 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2015-02-06 15:09:57 +0100
commit7bc3f415b7eece1a7c48278f6b788b15660f865a (patch)
tree55a5cedaf10a7c60fc9aa814ceea92961b158bc0 /plugins/sonar-core-plugin/src
parentef5cc2f5d7bebc31dd7b67fc4ed693b947155f36 (diff)
downloadsonarqube-7bc3f415b7eece1a7c48278f6b788b15660f865a.tar.gz
sonarqube-7bc3f415b7eece1a7c48278f6b788b15660f865a.zip
Revert "SONAR-6044 Stop storing distribution of issue-related measures by rule"
This reverts commit 217d3d5d39aa5a06828743d11b5a7fab0e10d8f0. Conflicts: server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
Diffstat (limited to 'plugins/sonar-core-plugin/src')
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecorator.java107
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SeverityUtils.java60
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecoratorTest.java44
3 files changed, 165 insertions, 46 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecorator.java
index 1b2758732f9..d775ba8ec4c 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecorator.java
@@ -30,16 +30,14 @@ import org.sonar.api.measures.*;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
-import org.sonar.api.rule.Severity;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RulePriority;
import org.sonar.batch.components.Period;
import org.sonar.batch.components.TimeMachineConfiguration;
import javax.annotation.Nullable;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
/**
* Computes metrics related to number of issues.
@@ -90,15 +88,18 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
Collection<Issue> issues = issuable.issues();
boolean shouldSaveNewMetrics = shouldSaveNewMetrics(context);
- Multiset<String> severityBag = HashMultiset.create();
- ListMultimap<String, Issue> issuesPerSeverity = ArrayListMultimap.create();
+ Multiset<RulePriority> severityBag = HashMultiset.create();
+ Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity = Maps.newHashMap();
+ ListMultimap<RulePriority, Issue> issuesPerSeverity = ArrayListMultimap.create();
int countOpen = 0;
int countReopened = 0;
int countConfirmed = 0;
for (Issue issue : issues) {
- severityBag.add(issue.severity());
- issuesPerSeverity.put(issue.severity(), issue);
+ severityBag.add(RulePriority.valueOf(issue.severity()));
+ Multiset<RuleKey> rulesBag = initRules(rulesPerSeverity, RulePriority.valueOf(issue.severity()));
+ rulesBag.add(issue.ruleKey());
+ issuesPerSeverity.put(RulePriority.valueOf(issue.severity()), issue);
if (Issue.STATUS_OPEN.equals(issue.status())) {
countOpen++;
@@ -109,9 +110,11 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
}
}
- for (String severity : Severity.ALL) {
- saveIssuesForSeverity(context, severity, severityBag);
- saveNewIssuesForSeverity(context, severity, issuesPerSeverity, shouldSaveNewMetrics);
+ for (RulePriority ruleSeverity : RulePriority.values()) {
+ saveIssuesForSeverity(context, ruleSeverity, severityBag);
+ saveIssuesPerRules(context, ruleSeverity, rulesPerSeverity);
+ saveNewIssuesForSeverity(context, ruleSeverity, issuesPerSeverity, shouldSaveNewMetrics);
+ saveNewIssuesPerRule(context, ruleSeverity, issues, shouldSaveNewMetrics);
}
saveTotalIssues(context, issues);
@@ -138,16 +141,16 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
}
}
- private void saveIssuesForSeverity(DecoratorContext context, String severity, Multiset<String> severitiesBag) {
- Metric metric = SeverityUtils.severityToIssueMetric(severity);
+ private void saveIssuesForSeverity(DecoratorContext context, RulePriority ruleSeverity, Multiset<RulePriority> severitiesBag) {
+ Metric metric = SeverityUtils.severityToIssueMetric(ruleSeverity);
if (context.getMeasure(metric) == null) {
Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.metric(metric));
- int sum = MeasureUtils.sum(true, children).intValue() + severitiesBag.count(severity);
+ int sum = MeasureUtils.sum(true, children).intValue() + severitiesBag.count(ruleSeverity);
context.saveMeasure(metric, (double) sum);
}
}
- private void saveNewIssuesForSeverity(DecoratorContext context, String severity, ListMultimap<String, Issue> issuesPerSeverities, boolean shouldSaveNewMetrics) {
+ private void saveNewIssuesForSeverity(DecoratorContext context, RulePriority severity, ListMultimap<RulePriority, Issue> issuesPerSeverities, boolean shouldSaveNewMetrics) {
if (shouldSaveNewMetrics) {
Metric metric = SeverityUtils.severityToNewMetricIssue(severity);
Measure measure = new Measure(metric);
@@ -155,6 +158,66 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
}
}
+ private void saveIssuesPerRules(DecoratorContext context, RulePriority severity, Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity) {
+ Metric metric = SeverityUtils.severityToIssueMetric(severity);
+
+ Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.rules(metric));
+ for (Measure child : children) {
+ RuleMeasure childRuleMeasure = (RuleMeasure) child;
+ RuleKey ruleKey = childRuleMeasure.ruleKey();
+ if (ruleKey != null && MeasureUtils.hasValue(childRuleMeasure)) {
+ Multiset<RuleKey> rulesBag = initRules(rulesPerSeverity, severity);
+ rulesBag.add(ruleKey, childRuleMeasure.getIntValue());
+ }
+ }
+
+ Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
+ if (rulesBag != null) {
+ for (Multiset.Entry<RuleKey> entry : rulesBag.entrySet()) {
+ RuleMeasure measure = RuleMeasure.createForRule(metric, entry.getElement(), (double) entry.getCount());
+ measure.setSeverity(severity);
+ context.saveMeasure(measure);
+ }
+ }
+ }
+
+ private void saveNewIssuesPerRule(DecoratorContext context, RulePriority severity, Collection<Issue> issues, boolean shouldSaveNewMetrics) {
+ if (shouldSaveNewMetrics) {
+ Metric metric = SeverityUtils.severityToNewMetricIssue(severity);
+ ListMultimap<RuleKey, Measure> childMeasuresPerRuleKeys = ArrayListMultimap.create();
+ ListMultimap<RuleKey, Issue> issuesPerRuleKeys = ArrayListMultimap.create();
+ Set<RuleKey> ruleKeys = Sets.newHashSet();
+
+ Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.rules(metric));
+ for (Measure child : children) {
+ RuleMeasure childRuleMeasure = (RuleMeasure) child;
+ RuleKey ruleKey = childRuleMeasure.ruleKey();
+ if (ruleKey != null) {
+ childMeasuresPerRuleKeys.put(ruleKey, childRuleMeasure);
+ ruleKeys.add(ruleKey);
+ }
+ }
+
+ for (Issue issue : issues) {
+ if (RulePriority.valueOf(issue.severity()).equals(severity)) {
+ ruleKeys.add(issue.ruleKey());
+ issuesPerRuleKeys.put(issue.ruleKey(), issue);
+ }
+ }
+
+ for (RuleKey ruleKey : ruleKeys) {
+ RuleMeasure measure = RuleMeasure.createForRule(metric, ruleKey, null);
+ measure.setSeverity(severity);
+ for (Period period : timeMachineConfiguration.periods()) {
+ int variationIndex = period.getIndex();
+ double sum = MeasureUtils.sumOnVariation(true, variationIndex, childMeasuresPerRuleKeys.get(ruleKey)) + countIssues(issuesPerRuleKeys.get(ruleKey), period);
+ measure.setVariation(variationIndex, sum);
+ }
+ context.saveMeasure(measure);
+ }
+ }
+ }
+
private void saveNewIssues(DecoratorContext context, Measure measure, Collection<Issue> issues) {
for (Period period : timeMachineConfiguration.periods()) {
int variationIndex = period.getIndex();
@@ -177,6 +240,15 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
return sum;
}
+ private Multiset<RuleKey> initRules(Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity, RulePriority severity) {
+ Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
+ if (rulesBag == null) {
+ rulesBag = HashMultiset.create();
+ rulesPerSeverity.put(severity, rulesBag);
+ }
+ return rulesBag;
+ }
+
private int countIssues(Collection<Issue> issues, Period period) {
// SONAR-3647 Use real snapshot date and not target date in order to stay consistent with other measure variations
Date datePlusOneSecond = period.getDate() != null ? DateUtils.addSeconds(period.getDate(), 1) : null;
@@ -185,6 +257,9 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
@VisibleForTesting
int countIssuesAfterDate(Collection<Issue> issues, @Nullable Date date) {
+ if (issues == null) {
+ return 0;
+ }
int count = 0;
for (Issue issue : issues) {
if (isAfter(issue, date)) {
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SeverityUtils.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SeverityUtils.java
index ed6b9551e16..e1a1d5ba19c 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SeverityUtils.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SeverityUtils.java
@@ -21,44 +21,46 @@ package org.sonar.plugins.core.issue;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
-import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RulePriority;
final class SeverityUtils {
private SeverityUtils() {
// only static methods
}
- static Metric severityToIssueMetric(String severity) {
- switch (severity) {
- case Severity.BLOCKER:
- return CoreMetrics.BLOCKER_VIOLATIONS;
- case Severity.CRITICAL:
- return CoreMetrics.CRITICAL_VIOLATIONS;
- case Severity.MAJOR:
- return CoreMetrics.MAJOR_VIOLATIONS;
- case Severity.MINOR:
- return CoreMetrics.MINOR_VIOLATIONS;
- case Severity.INFO:
- return CoreMetrics.INFO_VIOLATIONS;
- default:
- throw new IllegalArgumentException("Unsupported severity: " + severity);
+ static Metric severityToIssueMetric(RulePriority severity) {
+ Metric metric;
+ if (severity.equals(RulePriority.BLOCKER)) {
+ metric = CoreMetrics.BLOCKER_VIOLATIONS;
+ } else if (severity.equals(RulePriority.CRITICAL)) {
+ metric = CoreMetrics.CRITICAL_VIOLATIONS;
+ } else if (severity.equals(RulePriority.MAJOR)) {
+ metric = CoreMetrics.MAJOR_VIOLATIONS;
+ } else if (severity.equals(RulePriority.MINOR)) {
+ metric = CoreMetrics.MINOR_VIOLATIONS;
+ } else if (severity.equals(RulePriority.INFO)) {
+ metric = CoreMetrics.INFO_VIOLATIONS;
+ } else {
+ throw new IllegalArgumentException("Unsupported severity: " + severity);
}
+ return metric;
}
- static Metric severityToNewMetricIssue(String severity) {
- switch (severity) {
- case Severity.BLOCKER:
- return CoreMetrics.NEW_BLOCKER_VIOLATIONS;
- case Severity.CRITICAL:
- return CoreMetrics.NEW_CRITICAL_VIOLATIONS;
- case Severity.MAJOR:
- return CoreMetrics.NEW_MAJOR_VIOLATIONS;
- case Severity.MINOR:
- return CoreMetrics.NEW_MINOR_VIOLATIONS;
- case Severity.INFO:
- return CoreMetrics.NEW_INFO_VIOLATIONS;
- default:
- throw new IllegalArgumentException("Unsupported severity: " + severity);
+ static Metric severityToNewMetricIssue(RulePriority severity) {
+ Metric metric;
+ if (severity.equals(RulePriority.BLOCKER)) {
+ metric = CoreMetrics.NEW_BLOCKER_VIOLATIONS;
+ } else if (severity.equals(RulePriority.CRITICAL)) {
+ metric = CoreMetrics.NEW_CRITICAL_VIOLATIONS;
+ } else if (severity.equals(RulePriority.MAJOR)) {
+ metric = CoreMetrics.NEW_MAJOR_VIOLATIONS;
+ } else if (severity.equals(RulePriority.MINOR)) {
+ metric = CoreMetrics.NEW_MINOR_VIOLATIONS;
+ } else if (severity.equals(RulePriority.INFO)) {
+ metric = CoreMetrics.NEW_INFO_VIOLATIONS;
+ } else {
+ throw new IllegalArgumentException("Unsupported severity: " + severity);
}
+ return metric;
}
}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecoratorTest.java
index 054f2b5f02f..be9b8ae586c 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecoratorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecoratorTest.java
@@ -39,6 +39,7 @@ import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RulePriority;
+import org.sonar.api.test.IsRuleMeasure;
import org.sonar.batch.components.Period;
import org.sonar.batch.components.TimeMachineConfiguration;
@@ -185,10 +186,39 @@ public class CountUnresolvedIssuesDecoratorTest {
}
@Test
+ public void should_count_issues_per_rule() {
+ List<Issue> issues = newArrayList();
+ issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()));
+ issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()));
+ issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name()));
+ when(issuable.issues()).thenReturn(issues);
+
+ decorator.decorate(resource, context);
+
+ verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0)));
+ verify(context, never()).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA1, 0.0)));
+ verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA2, 1.0)));
+ }
+
+ @Test
+ public void same_rule_should_have_different_severities() {
+ List<Issue> issues = newArrayList();
+ issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()));
+ issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()));
+ issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.MINOR.name()));
+ when(issuable.issues()).thenReturn(issues);
+
+ decorator.decorate(resource, context);
+
+ verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0)));
+ verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MINOR_VIOLATIONS, ruleA1, 1.0)));
+ }
+
+ @Test
public void should_count_issues_after_date() {
List<Issue> issues = createIssuesForNewMetrics();
- assertThat(decorator.countIssuesAfterDate(Collections.<Issue>emptyList(), fiveDaysAgo)).isEqualTo(0);
+ assertThat(decorator.countIssuesAfterDate(null, fiveDaysAgo)).isEqualTo(0);
assertThat(decorator.countIssuesAfterDate(issues, fiveDaysAgo)).isEqualTo(1); // 1 rightNow
assertThat(decorator.countIssuesAfterDate(issues, tenDaysAgo)).isEqualTo(3); // 1 rightNow + 2 fiveDaysAgo
assertThat(decorator.countIssuesAfterDate(issues, sameSecond)).isEqualTo(0); // 0
@@ -222,6 +252,18 @@ public class CountUnresolvedIssuesDecoratorTest {
}
@Test
+ public void should_save_rule_new_issues() {
+ when(issuable.issues()).thenReturn(createIssuesForNewMetrics());
+
+ decorator.decorate(resource, context);
+
+ // remember : period1 is 5daysAgo, period2 is 10daysAgo
+ verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, ruleA1, 1.0, 1.0)));
+ verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, ruleA2, 0.0, 1.0)));
+ verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, ruleB1, 0.0, 1.0)));
+ }
+
+ @Test
public void should_not_save_new_issues_if_measure_already_computed() {
when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(new Measure());
when(issuable.issues()).thenReturn(createIssuesForNewMetrics());