From 08f6ba94574e741aa85acf5cca0b1b612f28c27e Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Mon, 29 Feb 2016 14:32:25 +0100 Subject: [PATCH] SONAR-7338 SONAR-7339 SONAR-7340 new metrics to count issues by type --- .../src/test/java/it/dbCleaner/PurgeTest.java | 16 +- .../computation/issue/IssueCounter.java | 63 ++++- .../computation/issue/IssueCounterTest.java | 79 +++++- .../resources/org/sonar/l10n/core.properties | 24 +- .../org/sonar/api/measures/CoreMetrics.java | 232 ++++++++++++++---- 5 files changed, 332 insertions(+), 82 deletions(-) diff --git a/it/it-tests/src/test/java/it/dbCleaner/PurgeTest.java b/it/it-tests/src/test/java/it/dbCleaner/PurgeTest.java index 936d17517cf..91edeef92db 100644 --- a/it/it-tests/src/test/java/it/dbCleaner/PurgeTest.java +++ b/it/it-tests/src/test/java/it/dbCleaner/PurgeTest.java @@ -76,10 +76,10 @@ public class PurgeTest { collector.checkThat("Wrong number of files", count("projects where qualifier in ('FIL')"), equalTo(4)); collector.checkThat("Wrong number of unit test files", count("projects where qualifier in ('UTS')"), equalTo(0)); - int measuresOnTrk = 37; - int measuresOnBrc = 174; - int measuresOnDir = 109; - int measuresOnFil = 61; + int measuresOnTrk = 40; + int measuresOnBrc = 192; + int measuresOnDir = 121; + int measuresOnFil = 65; // count measures  assertMeasuresCountForQualifier("TRK", measuresOnTrk); @@ -105,9 +105,9 @@ public class PurgeTest { // must be a different date, else a single snapshot is kept per day scan(PROJECT_SAMPLE_PATH, DateFormatUtils.ISO_DATE_FORMAT.format(today)); - int newMeasuresOnTrk = 43; - int newMeasuresOnBrc = 214; - int newMeasuresOnDir = 32; + int newMeasuresOnTrk = 49; + int newMeasuresOnBrc = 250; + int newMeasuresOnDir = 44; int newMeasuresOnFil = 0; assertMeasuresCountForQualifier("TRK", measuresOnTrk + newMeasuresOnTrk); @@ -119,7 +119,7 @@ public class PurgeTest { collector.checkThat( "Wrong number of measure of new_ metrics", count("project_measures, metrics where metrics.id = project_measures.metric_id and metrics.name like 'new_%'"), - equalTo(88)); + equalTo(121)); // added measures relate to project and new_* metrics expectedMeasures += newMeasuresOnTrk + newMeasuresOnBrc + newMeasuresOnDir + newMeasuresOnFil; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java index 49452586779..75925943942 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java @@ -19,6 +19,7 @@ */ package org.sonar.server.computation.issue; +import com.google.common.collect.EnumMultiset; import com.google.common.collect.HashMultiset; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Multiset; @@ -26,7 +27,9 @@ import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; import org.sonar.api.issue.Issue; +import org.sonar.api.measures.CoreMetrics; import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.issue.IssueType; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.measure.Measure; import org.sonar.server.computation.measure.MeasureRepository; @@ -64,11 +67,12 @@ import static org.sonar.api.rule.Severity.MINOR; /** * For each component, computes the measures related to number of issues: * * For each value, the variation on configured periods is also computed. */ @@ -90,6 +94,17 @@ public class IssueCounter extends IssueVisitor { INFO, NEW_INFO_VIOLATIONS_KEY ); + private static final Map TYPE_TO_METRIC_KEY = ImmutableMap.builder() + .put(IssueType.CODE_SMELL, CoreMetrics.CODE_SMELLS_KEY) + .put(IssueType.BUG, CoreMetrics.BUGS_KEY) + .put(IssueType.VULNERABILITY, CoreMetrics.VULNERABILITIES_KEY) + .build(); + private static final Map TYPE_TO_NEW_METRIC_KEY = ImmutableMap.builder() + .put(IssueType.CODE_SMELL, CoreMetrics.NEW_CODE_SMELLS_KEY) + .put(IssueType.BUG, CoreMetrics.NEW_BUGS_KEY) + .put(IssueType.VULNERABILITY, CoreMetrics.NEW_VULNERABILITIES_KEY) + .build(); + private final PeriodsHolder periodsHolder; private final MetricRepository metricRepository; private final MeasureRepository measureRepository; @@ -131,8 +146,9 @@ public class IssueCounter extends IssueVisitor { @Override public void afterComponent(Component component) { - addMeasuresByStatus(component); addMeasuresBySeverity(component); + addMeasuresByStatus(component); + addMeasuresByType(component); addMeasuresByPeriod(component); currentCounters = null; } @@ -153,6 +169,12 @@ public class IssueCounter extends IssueVisitor { addMeasure(component, FALSE_POSITIVE_ISSUES_KEY, currentCounters.counter().falsePositives); } + private void addMeasuresByType(Component component) { + for (Map.Entry entry : TYPE_TO_METRIC_KEY.entrySet()) { + addMeasure(component, entry.getValue(), currentCounters.counter().typeBag.count(entry.getKey())); + } + } + private void addMeasure(Component component, String metricKey, int value) { Metric metric = metricRepository.getByKey(metricKey); measureRepository.add(component, metric, Measure.newMeasureBuilder().create(value)); @@ -174,7 +196,23 @@ public class IssueCounter extends IssueVisitor { Double[] variations = new Double[PeriodsHolder.MAX_NUMBER_OF_PERIODS]; for (Period period : periodsHolder.getPeriods()) { Multiset bag = currentCounters.counterForPeriod(period.getIndex()).severityBag; - variations[period.getIndex() - 1] = new Double(bag.count(severity)); + variations[period.getIndex() - 1] = (double) bag.count(severity); + } + Metric metric = metricRepository.getByKey(metricKey); + measureRepository.add(component, metric, Measure.newMeasureBuilder() + .setVariations(new MeasureVariations(variations)) + .createNoValue()); + } + + // waiting for Java 8 lambda in order to factor this loop with the previous one + // (see call currentCounters.counterForPeriod(period.getIndex()).xxx with xxx as severityBag or typeBag) + for (Map.Entry entry : TYPE_TO_NEW_METRIC_KEY.entrySet()) { + IssueType type = entry.getKey(); + String metricKey = entry.getValue(); + Double[] variations = new Double[PeriodsHolder.MAX_NUMBER_OF_PERIODS]; + for (Period period : periodsHolder.getPeriods()) { + Multiset bag = currentCounters.counterForPeriod(period.getIndex()).typeBag; + variations[period.getIndex() - 1] = (double) bag.count(type); } Metric metric = metricRepository.getByKey(metricKey); measureRepository.add(component, metric, Measure.newMeasureBuilder() @@ -193,7 +231,8 @@ public class IssueCounter extends IssueVisitor { private int reopened = 0; private int confirmed = 0; private int falsePositives = 0; - private Multiset severityBag = HashMultiset.create(); + private final Multiset severityBag = HashMultiset.create(); + private final EnumMultiset typeBag = EnumMultiset.create(IssueType.class); void add(Counter counter) { unresolved += counter.unresolved; @@ -202,11 +241,13 @@ public class IssueCounter extends IssueVisitor { confirmed += counter.confirmed; falsePositives += counter.falsePositives; severityBag.addAll(counter.severityBag); + typeBag.addAll(counter.typeBag); } - void add(Issue issue) { + void add(DefaultIssue issue) { if (issue.resolution() == null) { unresolved++; + typeBag.add(issue.type()); severityBag.add(issue.severity()); } else if (Issue.RESOLUTION_FALSE_POSITIVE.equals(issue.resolution())) { falsePositives++; @@ -248,11 +289,11 @@ public class IssueCounter extends IssueVisitor { } } - void addOnPeriod(Issue issue, int periodIndex) { + void addOnPeriod(DefaultIssue issue, int periodIndex) { array[periodIndex].add(issue); } - void add(Issue issue) { + void add(DefaultIssue issue) { array[0].add(issue); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueCounterTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueCounterTest.java index 19086ea06b3..776499638ef 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueCounterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueCounterTest.java @@ -25,7 +25,9 @@ import org.assertj.core.data.Offset; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.sonar.api.measures.CoreMetrics; import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.issue.IssueType; import org.sonar.db.rule.RuleTesting; import org.sonar.server.computation.batch.BatchReportReaderRule; import org.sonar.server.computation.batch.TreeRootHolderRule; @@ -90,6 +92,12 @@ public class IssueCounterTest { static final Metric NEW_MINOR_ISSUES_METRIC = new MetricImpl(14, NEW_MINOR_VIOLATIONS_KEY, NEW_MINOR_VIOLATIONS_KEY, INT); static final Metric NEW_INFO_ISSUES_METRIC = new MetricImpl(15, NEW_INFO_VIOLATIONS_KEY, NEW_INFO_VIOLATIONS_KEY, INT); static final Metric FALSE_POSITIVE_ISSUES_METRIC = new MetricImpl(16, FALSE_POSITIVE_ISSUES_KEY, FALSE_POSITIVE_ISSUES_KEY, INT); + static final Metric CODE_SMELLS_METRIC = new MetricImpl(17, CoreMetrics.CODE_SMELLS_KEY, CoreMetrics.CODE_SMELLS_KEY, INT); + static final Metric BUGS_METRIC = new MetricImpl(18, CoreMetrics.BUGS_KEY, CoreMetrics.BUGS_KEY, INT); + static final Metric VULNERABILITIES_METRIC = new MetricImpl(19, CoreMetrics.VULNERABILITIES_KEY, CoreMetrics.VULNERABILITIES_KEY, INT); + static final Metric NEW_CODE_SMELLS_METRIC = new MetricImpl(20, CoreMetrics.NEW_CODE_SMELLS_KEY, CoreMetrics.NEW_CODE_SMELLS_KEY, INT); + static final Metric NEW_BUGS_METRIC = new MetricImpl(21, CoreMetrics.NEW_BUGS_KEY, CoreMetrics.NEW_BUGS_KEY, INT); + static final Metric NEW_VULNERABILITIES_METRIC = new MetricImpl(22, CoreMetrics.NEW_VULNERABILITIES_KEY, CoreMetrics.NEW_VULNERABILITIES_KEY, INT); @Rule public BatchReportReaderRule reportReader = new BatchReportReaderRule(); @@ -117,7 +125,13 @@ public class IssueCounterTest { .add(NEW_MAJOR_ISSUES_METRIC) .add(NEW_MINOR_ISSUES_METRIC) .add(NEW_INFO_ISSUES_METRIC) - .add(FALSE_POSITIVE_ISSUES_METRIC); + .add(FALSE_POSITIVE_ISSUES_METRIC) + .add(CODE_SMELLS_METRIC) + .add(BUGS_METRIC) + .add(VULNERABILITIES_METRIC) + .add(NEW_CODE_SMELLS_METRIC) + .add(NEW_BUGS_METRIC) + .add(NEW_VULNERABILITIES_METRIC); @Rule public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); @@ -202,19 +216,52 @@ public class IssueCounterTest { assertThat(measureRepository.getRawMeasure(PROJECT, MAJOR_ISSUES_METRIC).get().getIntValue()).isEqualTo(1); } + @Test + public void count_unresolved_issues_by_type() { + periodsHolder.setPeriods(); + + // bottom-up traversal -> from files to project + // file1 : one open code smell, one closed code smell (which will be excluded from metric) + underTest.beforeComponent(FILE1); + underTest.onIssue(FILE1, createIssue(null, STATUS_OPEN, BLOCKER).setType(IssueType.CODE_SMELL)); + underTest.onIssue(FILE1, createIssue(RESOLUTION_FIXED, STATUS_CLOSED, MAJOR).setType(IssueType.CODE_SMELL)); + underTest.afterComponent(FILE1); + + // file2 : one bug + underTest.beforeComponent(FILE2); + underTest.onIssue(FILE2, createIssue(null, STATUS_CONFIRMED, BLOCKER).setType(IssueType.BUG)); + underTest.afterComponent(FILE2); + + underTest.beforeComponent(PROJECT); + underTest.afterComponent(PROJECT); + + assertThat(measureRepository.getRawMeasure(FILE1, CODE_SMELLS_METRIC).get().getIntValue()).isEqualTo(1); + assertThat(measureRepository.getRawMeasure(FILE1, BUGS_METRIC).get().getIntValue()).isEqualTo(0); + assertThat(measureRepository.getRawMeasure(FILE1, VULNERABILITIES_METRIC).get().getIntValue()).isEqualTo(0); + + assertThat(measureRepository.getRawMeasure(FILE2, CODE_SMELLS_METRIC).get().getIntValue()).isEqualTo(0); + assertThat(measureRepository.getRawMeasure(FILE2, BUGS_METRIC).get().getIntValue()).isEqualTo(1); + assertThat(measureRepository.getRawMeasure(FILE2, VULNERABILITIES_METRIC).get().getIntValue()).isEqualTo(0); + + assertThat(measureRepository.getRawMeasure(PROJECT, CODE_SMELLS_METRIC).get().getIntValue()).isEqualTo(1); + assertThat(measureRepository.getRawMeasure(PROJECT, BUGS_METRIC).get().getIntValue()).isEqualTo(1); + assertThat(measureRepository.getRawMeasure(PROJECT, VULNERABILITIES_METRIC).get().getIntValue()).isEqualTo(0); + } + @Test public void count_new_issues() { Period period = newPeriod(3, 1500000000000L); periodsHolder.setPeriods(period); underTest.beforeComponent(FILE1); - // created before -> existing issues - underTest.onIssue(FILE1, createIssueAt(null, STATUS_OPEN, BLOCKER, period.getSnapshotDate() - 1000000L)); - // created during the first analysis starting the period -> existing issues - underTest.onIssue(FILE1, createIssueAt(null, STATUS_OPEN, BLOCKER, period.getSnapshotDate())); - // created after -> new issues - underTest.onIssue(FILE1, createIssueAt(null, STATUS_OPEN, CRITICAL, period.getSnapshotDate() + 100000L)); - underTest.onIssue(FILE1, createIssueAt(RESOLUTION_FIXED, STATUS_CLOSED, MAJOR, period.getSnapshotDate() + 200000L)); + // created before -> existing issues (so ignored) + underTest.onIssue(FILE1, createIssueAt(null, STATUS_OPEN, BLOCKER, period.getSnapshotDate() - 1000000L).setType(IssueType.CODE_SMELL)); + // created during the first analysis starting the period -> existing issues (so ignored) + underTest.onIssue(FILE1, createIssueAt(null, STATUS_OPEN, BLOCKER, period.getSnapshotDate()).setType(IssueType.BUG)); + // created after -> 3 new issues but 1 is closed + underTest.onIssue(FILE1, createIssueAt(null, STATUS_OPEN, CRITICAL, period.getSnapshotDate() + 100000L).setType(IssueType.CODE_SMELL)); + underTest.onIssue(FILE1, createIssueAt(null, STATUS_OPEN, CRITICAL, period.getSnapshotDate() + 100000L).setType(IssueType.BUG)); + underTest.onIssue(FILE1, createIssueAt(RESOLUTION_FIXED, STATUS_CLOSED, MAJOR, period.getSnapshotDate() + 200000L).setType(IssueType.BUG)); underTest.afterComponent(FILE1); underTest.beforeComponent(FILE2); @@ -223,15 +270,21 @@ public class IssueCounterTest { underTest.beforeComponent(PROJECT); underTest.afterComponent(PROJECT); - assertVariation(FILE1, NEW_ISSUES_METRIC, period.getIndex(), 1); - assertVariation(FILE1, NEW_CRITICAL_ISSUES_METRIC, period.getIndex(), 1); + assertVariation(FILE1, NEW_ISSUES_METRIC, period.getIndex(), 2); + assertVariation(FILE1, NEW_CRITICAL_ISSUES_METRIC, period.getIndex(), 2); assertVariation(FILE1, NEW_BLOCKER_ISSUES_METRIC, period.getIndex(), 0); assertVariation(FILE1, NEW_MAJOR_ISSUES_METRIC, period.getIndex(), 0); + assertVariation(FILE1, NEW_CODE_SMELLS_METRIC, period.getIndex(), 1); + assertVariation(FILE1, NEW_BUGS_METRIC, period.getIndex(), 1); + assertVariation(FILE1, NEW_VULNERABILITIES_METRIC, period.getIndex(), 0); - assertVariation(PROJECT, NEW_ISSUES_METRIC, period.getIndex(), 1); - assertVariation(PROJECT, NEW_CRITICAL_ISSUES_METRIC, period.getIndex(), 1); + assertVariation(PROJECT, NEW_ISSUES_METRIC, period.getIndex(), 2); + assertVariation(PROJECT, NEW_CRITICAL_ISSUES_METRIC, period.getIndex(), 2); assertVariation(PROJECT, NEW_BLOCKER_ISSUES_METRIC, period.getIndex(), 0); assertVariation(PROJECT, NEW_MAJOR_ISSUES_METRIC, period.getIndex(), 0); + assertVariation(PROJECT, NEW_CODE_SMELLS_METRIC, period.getIndex(), 1); + assertVariation(PROJECT, NEW_BUGS_METRIC, period.getIndex(), 1); + assertVariation(PROJECT, NEW_VULNERABILITIES_METRIC, period.getIndex(), 0); } private void assertVariation(Component component, Metric metric, int periodIndex, int expectedVariation) { @@ -243,6 +296,7 @@ public class IssueCounterTest { return new DefaultIssue() .setResolution(resolution).setStatus(status) .setSeverity(severity).setRuleKey(RuleTesting.XOO_X1) + .setType(IssueType.CODE_SMELL) .setCreationDate(new Date()); } @@ -250,6 +304,7 @@ public class IssueCounterTest { return new DefaultIssue() .setResolution(resolution).setStatus(status) .setSeverity(severity).setRuleKey(RuleTesting.XOO_X1) + .setType(IssueType.CODE_SMELL) .setCreationDate(new Date(creationDate)); } diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 3f1fc6a41af..562b3c9026f 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2268,8 +2268,9 @@ metric_domain.General=General metric_domain.Duplication=Duplication metric_domain.Design=Design metric_domain.SCM=SCM -metric_domain.Management=Management -metric_domain.Reviews=Reviews +metric_domain.Maintainability=Maintainability +metric_domain.Reliability=Reliability +metric_domain.Security=Security #------------------------------------------------------------------------------ @@ -2665,6 +2666,25 @@ metric.new_minor_violations.description=New Minor issues metric.new_info_violations.name=New Info issues metric.new_info_violations.description=New Info issues +metric.code_smells.name=Code Smells +metric.code_smells.description=Code Smells + +metric.new_code_smells.name=New Code Smells +metric.new_code_smells.description=New Code Smells + +metric.bugs.name=Bugs +metric.bugs.description=Bugs + +metric.new_bugs.name=New Bugs +metric.new_bugs.description=New Bugs + +metric.vulnerabilities.name=Vulnerabilities +metric.vulnerabilities.description=Vulnerabilities + +metric.new_vulnerabilities.name=New Vulnerabilities +metric.new_vulnerabilities.description=New Vulnerabilities + + #-------------------------------------------------------------------------------------------------------------------- # # DESIGN diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java index 796c66d1a15..4a93c6bdae3 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java @@ -42,12 +42,29 @@ public final class CoreMetrics { public static String DOMAIN_COMPLEXITY = "Complexity"; public static String DOMAIN_DOCUMENTATION = "Documentation"; public static String DOMAIN_SCM = "SCM"; - public static String DOMAIN_ISSUES = "Issues"; public static String DOMAIN_GENERAL = "General"; public static String DOMAIN_DUPLICATION = "Duplication"; public static String DOMAIN_DESIGN = "Design"; + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static String DOMAIN_MAINTAINABILITY = "Maintainability"; + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static String DOMAIN_RELIABILITY = "Reliability"; + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static String DOMAIN_SECURITY = "Security"; + /** * @since 4.0 */ @@ -365,21 +382,21 @@ public final class CoreMetrics { @Deprecated public static final Metric CLASS_COMPLEXITY_DISTRIBUTION = new Metric.Builder(CLASS_COMPLEXITY_DISTRIBUTION_KEY, "Classes distribution /complexity", Metric.ValueType.DISTRIB) - .setDescription("Classes distribution /complexity") - .setDirection(Metric.DIRECTION_NONE) - .setQualitative(true) - .setDomain(DOMAIN_COMPLEXITY) - .setHidden(true) - .create(); + .setDescription("Classes distribution /complexity") + .setDirection(Metric.DIRECTION_NONE) + .setQualitative(true) + .setDomain(DOMAIN_COMPLEXITY) + .setHidden(true) + .create(); public static final String FUNCTION_COMPLEXITY_DISTRIBUTION_KEY = "function_complexity_distribution"; public static final Metric FUNCTION_COMPLEXITY_DISTRIBUTION = new Metric.Builder(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, "Functions distribution /complexity", Metric.ValueType.DISTRIB) - .setDescription("Functions distribution /complexity") - .setDirection(Metric.DIRECTION_NONE) - .setQualitative(true) - .setDomain(DOMAIN_COMPLEXITY) - .create(); + .setDescription("Functions distribution /complexity") + .setDirection(Metric.DIRECTION_NONE) + .setQualitative(true) + .setDomain(DOMAIN_COMPLEXITY) + .create(); public static final String FILE_COMPLEXITY_DISTRIBUTION_KEY = "file_complexity_distribution"; public static final Metric FILE_COMPLEXITY_DISTRIBUTION = new Metric.Builder(FILE_COMPLEXITY_DISTRIBUTION_KEY, "Files distribution /complexity", Metric.ValueType.DISTRIB) @@ -886,12 +903,12 @@ public final class CoreMetrics { */ public static final Metric NEW_IT_UNCOVERED_CONDITIONS = new Metric.Builder(NEW_IT_UNCOVERED_CONDITIONS_KEY, "Uncovered branches by IT on new code", Metric.ValueType.INT) - .setDescription("Uncovered branches by Integration Tests on new code") - .setDirection(Metric.DIRECTION_WORST) - .setDomain(DOMAIN_INTEGRATION_TESTS) - .setBestValue(0.0) - .setDeleteHistoricalData(true) - .create(); + .setDescription("Uncovered branches by Integration Tests on new code") + .setDirection(Metric.DIRECTION_WORST) + .setDomain(DOMAIN_INTEGRATION_TESTS) + .setBestValue(0.0) + .setDeleteHistoricalData(true) + .create(); /** * @since 2.12 @@ -1113,12 +1130,12 @@ public final class CoreMetrics { @Deprecated public static final Metric OVERALL_COVERAGE_LINE_HITS_DATA = new Metric.Builder(OVERALL_COVERAGE_LINE_HITS_DATA_KEY, "Overall coverage hits by line", Metric.ValueType.DATA) - .setDescription("Coverage hits by all tests and by line") - .setDirection(Metric.DIRECTION_NONE) - .setQualitative(false) - .setDomain(DOMAIN_OVERALL_TESTS) - .setDeleteHistoricalData(true) - .create(); + .setDescription("Coverage hits by all tests and by line") + .setDirection(Metric.DIRECTION_NONE) + .setQualitative(false) + .setDomain(DOMAIN_OVERALL_TESTS) + .setDeleteHistoricalData(true) + .create(); /** * @since 3.3 @@ -1146,11 +1163,11 @@ public final class CoreMetrics { */ public static final Metric NEW_OVERALL_CONDITIONS_TO_COVER = new Metric.Builder(NEW_OVERALL_CONDITIONS_TO_COVER_KEY, "Overall branches to cover on new code", Metric.ValueType.INT) - .setDescription("New branches to cover by all tests") - .setDomain(DOMAIN_OVERALL_TESTS) - .setDeleteHistoricalData(true) - .setHidden(true) - .create(); + .setDescription("New branches to cover by all tests") + .setDomain(DOMAIN_OVERALL_TESTS) + .setDeleteHistoricalData(true) + .setHidden(true) + .create(); /** * @since 3.3 @@ -1176,12 +1193,12 @@ public final class CoreMetrics { */ public static final Metric NEW_OVERALL_UNCOVERED_CONDITIONS = new Metric.Builder(NEW_OVERALL_UNCOVERED_CONDITIONS_KEY, "Overall uncovered branches on new code", Metric.ValueType.INT) - .setDescription("New branches that are not covered by any test") - .setDirection(Metric.DIRECTION_WORST) - .setDomain(DOMAIN_OVERALL_TESTS) - .setBestValue(0.0) - .setDeleteHistoricalData(true) - .create(); + .setDescription("New branches that are not covered by any test") + .setDirection(Metric.DIRECTION_WORST) + .setDomain(DOMAIN_OVERALL_TESTS) + .setBestValue(0.0) + .setDeleteHistoricalData(true) + .create(); /** * @since 3.3 @@ -1210,14 +1227,14 @@ public final class CoreMetrics { */ public static final Metric NEW_OVERALL_BRANCH_COVERAGE = new Metric.Builder(NEW_OVERALL_BRANCH_COVERAGE_KEY, "Overall condition coverage on new code", Metric.ValueType.PERCENT) - .setDescription("Condition coverage of new/changed code by all tests") - .setDirection(Metric.DIRECTION_BETTER) - .setQualitative(true) - .setDomain(DOMAIN_OVERALL_TESTS) - .setWorstValue(0.0) - .setBestValue(100.0) - .setDeleteHistoricalData(true) - .create(); + .setDescription("Condition coverage of new/changed code by all tests") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(true) + .setDomain(DOMAIN_OVERALL_TESTS) + .setWorstValue(0.0) + .setBestValue(100.0) + .setDeleteHistoricalData(true) + .create(); /** * @since 3.3 @@ -1251,10 +1268,10 @@ public final class CoreMetrics { @Deprecated public static final Metric OVERALL_COVERED_CONDITIONS_BY_LINE = new Metric.Builder(OVERALL_COVERED_CONDITIONS_BY_LINE_KEY, "Overall covered branches by line", Metric.ValueType.DATA) - .setDescription("Overall covered branches by all tests and by line") - .setDomain(DOMAIN_OVERALL_TESTS) - .setDeleteHistoricalData(true) - .create(); + .setDescription("Overall covered branches by all tests and by line") + .setDomain(DOMAIN_OVERALL_TESTS) + .setDeleteHistoricalData(true) + .create(); // -------------------------------------------------------------------------------------------------------------------- // @@ -1539,6 +1556,123 @@ public final class CoreMetrics { .setOptimizedBestValue(true) .create(); + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final String CODE_SMELLS_KEY = "code_smells"; + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final Metric CODE_SMELLS = new Metric.Builder(CODE_SMELLS_KEY, "Code Smells", Metric.ValueType.INT) + .setDescription("Code Smells") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(DOMAIN_MAINTAINABILITY) + .setBestValue(0.0) + .setOptimizedBestValue(true) + .create(); + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final String NEW_CODE_SMELLS_KEY = "new_code_smells"; + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final Metric NEW_CODE_SMELLS = new Metric.Builder(NEW_CODE_SMELLS_KEY, "New code smells", Metric.ValueType.INT) + .setDescription("New Code Smells") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(true) + .setDomain(DOMAIN_MAINTAINABILITY) + .setBestValue(0.0) + .setOptimizedBestValue(true) + .setDeleteHistoricalData(true) + .create(); + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final String BUGS_KEY = "bugs"; + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final Metric BUGS = new Metric.Builder(BUGS_KEY, "Bugs", Metric.ValueType.INT) + .setDescription("Bugs") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(DOMAIN_RELIABILITY) + .setBestValue(0.0) + .setOptimizedBestValue(true) + .create(); + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final String NEW_BUGS_KEY = "new_bugs"; + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final Metric NEW_BUGS = new Metric.Builder(NEW_BUGS_KEY, "New Bugs", Metric.ValueType.INT) + .setDescription("New Bugs") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(true) + .setDomain(DOMAIN_RELIABILITY) + .setBestValue(0.0) + .setOptimizedBestValue(true) + .setDeleteHistoricalData(true) + .create(); + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final String VULNERABILITIES_KEY = "vulnerabilities"; + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final Metric VULNERABILITIES = new Metric.Builder(VULNERABILITIES_KEY, "Vulnerabilities", Metric.ValueType.INT) + .setDescription("Vulnerabilities") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(DOMAIN_SECURITY) + .setBestValue(0.0) + .setOptimizedBestValue(true) + .create(); + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final String NEW_VULNERABILITIES_KEY = "new_vulnerabilities"; + + /** + * SonarQube Quality Model + * @since 5.5 + */ + public static final Metric NEW_VULNERABILITIES = new Metric.Builder(NEW_VULNERABILITIES_KEY, "New Vulnerabilities", Metric.ValueType.INT) + .setDescription("New Vulnerabilities") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(true) + .setDomain(DOMAIN_SECURITY) + .setBestValue(0.0) + .setOptimizedBestValue(true) + .setDeleteHistoricalData(true) + .create(); + // -------------------------------------------------------------------------------------------------------------------- // // DESIGN @@ -2003,8 +2137,8 @@ public final class CoreMetrics { @Deprecated public static final transient Metric SCM_LAST_COMMIT_DATETIMES_BY_LINE = new Metric.Builder(SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY, "Last commit dates by line", Metric.ValueType.DATA) - .setDomain(DOMAIN_SCM) - .create(); + .setDomain(DOMAIN_SCM) + .create(); // -------------------------------------------------------------------------------------------------------------------- // -- 2.39.5