diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-02-06 15:09:57 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-02-06 15:09:57 +0100 |
commit | 7bc3f415b7eece1a7c48278f6b788b15660f865a (patch) | |
tree | 55a5cedaf10a7c60fc9aa814ceea92961b158bc0 /plugins/sonar-core-plugin/src | |
parent | ef5cc2f5d7bebc31dd7b67fc4ed693b947155f36 (diff) | |
download | sonarqube-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')
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()); |