diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-02-09 16:37:56 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-02-10 10:19:53 +0100 |
commit | 7afdd2432c308f95d97d06ac45865d67d5040682 (patch) | |
tree | 3735bd0a5900bf0eaba893a28ff2e6ad6ba5748f | |
parent | 968bd79f0d5e57a03dd09b7c1c40514b323c30fb (diff) | |
download | sonarqube-7afdd2432c308f95d97d06ac45865d67d5040682.tar.gz sonarqube-7afdd2432c308f95d97d06ac45865d67d5040682.zip |
SONAR-8760 Define 'Cognitive Complexity' metric
14 files changed, 143 insertions, 6 deletions
diff --git a/it/it-projects/shared/xoo-multi-modules-sample/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo.measures b/it/it-projects/shared/xoo-multi-modules-sample/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo.measures index 7812e4167fb..f3953ccd0fe 100644 --- a/it/it-projects/shared/xoo-multi-modules-sample/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo.measures +++ b/it/it-projects/shared/xoo-multi-modules-sample/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo.measures @@ -1,2 +1,4 @@ ncloc:12 classes:1 +complexity:3 +cognitive_complexity:4 diff --git a/it/it-projects/shared/xoo-multi-modules-sample/module_a/module_a2/src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo.measures b/it/it-projects/shared/xoo-multi-modules-sample/module_a/module_a2/src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo.measures index 63df5add6d4..a23e10d8ab4 100644 --- a/it/it-projects/shared/xoo-multi-modules-sample/module_a/module_a2/src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo.measures +++ b/it/it-projects/shared/xoo-multi-modules-sample/module_a/module_a2/src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo.measures @@ -1,2 +1,5 @@ ncloc:15 classes:1 +complexity:4 +cognitive_complexity:5 + diff --git a/it/it-projects/shared/xoo-multi-modules-sample/module_b/module_b1/src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo.measures b/it/it-projects/shared/xoo-multi-modules-sample/module_b/module_b1/src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo.measures index 3947d3bdbff..f3953ccd0fe 100644 --- a/it/it-projects/shared/xoo-multi-modules-sample/module_b/module_b1/src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo.measures +++ b/it/it-projects/shared/xoo-multi-modules-sample/module_b/module_b1/src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo.measures @@ -1,2 +1,4 @@ ncloc:12 -classes:1
\ No newline at end of file +classes:1 +complexity:3 +cognitive_complexity:4 diff --git a/it/it-projects/shared/xoo-multi-modules-sample/module_b/module_b2/src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo.measures b/it/it-projects/shared/xoo-multi-modules-sample/module_b/module_b2/src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo.measures index 3947d3bdbff..f3953ccd0fe 100644 --- a/it/it-projects/shared/xoo-multi-modules-sample/module_b/module_b2/src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo.measures +++ b/it/it-projects/shared/xoo-multi-modules-sample/module_b/module_b2/src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo.measures @@ -1,2 +1,4 @@ ncloc:12 -classes:1
\ No newline at end of file +classes:1 +complexity:3 +cognitive_complexity:4 diff --git a/it/it-projects/shared/xoo-sample/src/main/xoo/sample/Sample.xoo.measures b/it/it-projects/shared/xoo-sample/src/main/xoo/sample/Sample.xoo.measures index 641332a5013..06c9b6c2f38 100644 --- a/it/it-projects/shared/xoo-sample/src/main/xoo/sample/Sample.xoo.measures +++ b/it/it-projects/shared/xoo-sample/src/main/xoo/sample/Sample.xoo.measures @@ -2,6 +2,7 @@ ncloc:13 #Used by dashboard/widgets tests complexity:3 complexity_in_classes:3 +cognitive_complexity:4 classes:1 comment_lines:3 public_api:5 diff --git a/it/it-tests/src/test/java/it/Category1Suite.java b/it/it-tests/src/test/java/it/Category1Suite.java index 7190c2f5f9e..643b706757e 100644 --- a/it/it-tests/src/test/java/it/Category1Suite.java +++ b/it/it-tests/src/test/java/it/Category1Suite.java @@ -26,6 +26,7 @@ import it.authorisation.IssuePermissionTest; import it.authorisation.PermissionSearchTest; import it.authorisation.ProvisioningPermissionTest; import it.authorisation.QualityProfileAdminPermissionTest; +import it.complexity.ComplexityMeasuresTest; import it.customMeasure.CustomMeasuresTest; import it.i18n.I18nTest; import it.measure.MeasuresWsTest; @@ -98,7 +99,9 @@ import static util.ItUtils.xooPlugin; // source code EncodingTest.class, HighlightingTest.class, - ProjectCodeTest.class + ProjectCodeTest.class, + // complexity + ComplexityMeasuresTest.class }) public class Category1Suite { diff --git a/it/it-tests/src/test/java/it/complexity/ComplexityMeasuresTest.java b/it/it-tests/src/test/java/it/complexity/ComplexityMeasuresTest.java new file mode 100644 index 00000000000..03962332b21 --- /dev/null +++ b/it/it-tests/src/test/java/it/complexity/ComplexityMeasuresTest.java @@ -0,0 +1,90 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package it.complexity; + +import com.sonar.orchestrator.Orchestrator; +import com.sonar.orchestrator.build.SonarScanner; +import it.Category1Suite; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Java6Assertions.entry; +import static util.ItUtils.getMeasuresAsDoubleByMetricKey; +import static util.ItUtils.projectDir; + +// TODO complete the test with other complexity metrics +public class ComplexityMeasuresTest { + + private static final String PROJECT = "com.sonarsource.it.samples:multi-modules-sample"; + private static final String MODULE = "com.sonarsource.it.samples:multi-modules-sample:module_a"; + private static final String SUB_MODULE = "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1"; + private static final String DIRECTORY = "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1"; + private static final String FILE = "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo"; + + private static final String COMPLEXITY_METRIC = "complexity"; + private static final String COGNITIVE_COMPLEXITY_METRIC = "cognitive_complexity"; + + @ClassRule + public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; + + @BeforeClass + public static void inspectProject() { + orchestrator.resetData(); + orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-multi-modules-sample"))); + } + + @Test + public void compute_complexity_metrics_on_file() { + assertThat(getMeasuresAsDoubleByMetricKey(orchestrator, FILE, COMPLEXITY_METRIC, COGNITIVE_COMPLEXITY_METRIC)).containsOnly( + entry(COMPLEXITY_METRIC, 3d), + entry(COGNITIVE_COMPLEXITY_METRIC, 4d)); + } + + @Test + public void compute_complexity_metrics_on_directory() { + assertThat(getMeasuresAsDoubleByMetricKey(orchestrator, DIRECTORY, COMPLEXITY_METRIC, COGNITIVE_COMPLEXITY_METRIC)).containsOnly( + entry(COMPLEXITY_METRIC, 3d), + entry(COGNITIVE_COMPLEXITY_METRIC, 4d)); + } + + @Test + public void compute_complexity_metrics_on_sub_module() { + assertThat(getMeasuresAsDoubleByMetricKey(orchestrator, SUB_MODULE, COMPLEXITY_METRIC, COGNITIVE_COMPLEXITY_METRIC)).containsOnly( + entry(COMPLEXITY_METRIC, 3d), + entry(COGNITIVE_COMPLEXITY_METRIC, 4d)); + } + + @Test + public void compute_complexity_metrics_on_module() { + assertThat(getMeasuresAsDoubleByMetricKey(orchestrator, MODULE, COMPLEXITY_METRIC, COGNITIVE_COMPLEXITY_METRIC)).containsOnly( + entry(COMPLEXITY_METRIC, 7d), + entry(COGNITIVE_COMPLEXITY_METRIC, 9d)); + } + + @Test + public void compute_complexity_metrics_on_project() { + assertThat(getMeasuresAsDoubleByMetricKey(orchestrator, PROJECT, COMPLEXITY_METRIC, COGNITIVE_COMPLEXITY_METRIC)).containsOnly( + entry(COMPLEXITY_METRIC, 13d), + entry(COGNITIVE_COMPLEXITY_METRIC, 17d)); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ComplexityMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ComplexityMeasuresStep.java index f710ad91051..2cc7ea7f578 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ComplexityMeasuresStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ComplexityMeasuresStep.java @@ -33,6 +33,7 @@ import org.sonar.server.computation.task.step.ComputationStep; import static org.sonar.api.measures.CoreMetrics.CLASSES_KEY; import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY; import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_KEY; +import static org.sonar.api.measures.CoreMetrics.COGNITIVE_COMPLEXITY_KEY; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_CLASSES_KEY; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_KEY; @@ -53,6 +54,7 @@ public class ComplexityMeasuresStep implements ComputationStep { createIntSumFormula(COMPLEXITY_KEY), createIntSumFormula(COMPLEXITY_IN_CLASSES_KEY), createIntSumFormula(COMPLEXITY_IN_FUNCTIONS_KEY), + createIntSumFormula(COGNITIVE_COMPLEXITY_KEY), new DistributionFormula(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY), new DistributionFormula(FILE_COMPLEXITY_DISTRIBUTION_KEY), new DistributionFormula(CLASS_COMPLEXITY_DISTRIBUTION_KEY), diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ReportComplexityMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ReportComplexityMeasuresStepTest.java index 67d4bc666fb..fff37cc9a03 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ReportComplexityMeasuresStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ReportComplexityMeasuresStepTest.java @@ -35,6 +35,8 @@ import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY; import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION; import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY; import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_KEY; +import static org.sonar.api.measures.CoreMetrics.COGNITIVE_COMPLEXITY; +import static org.sonar.api.measures.CoreMetrics.COGNITIVE_COMPLEXITY_KEY; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_CLASSES; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_CLASSES_KEY; @@ -102,7 +104,9 @@ public class ReportComplexityMeasuresStepTest { .add(CLASS_COMPLEXITY) .add(CLASSES) .add(FUNCTION_COMPLEXITY) - .add(FUNCTIONS); + .add(FUNCTIONS) + .add(COGNITIVE_COMPLEXITY); + @Rule public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); @@ -123,6 +127,11 @@ public class ReportComplexityMeasuresStepTest { verify_sum_aggregation(COMPLEXITY_IN_FUNCTIONS_KEY); } + @Test + public void aggregate_cognitive_complexity() throws Exception { + verify_sum_aggregation(COGNITIVE_COMPLEXITY_KEY); + } + private void verify_sum_aggregation(String metricKey) { measureRepository.addRawMeasure(FILE_1_REF, metricKey, newMeasureBuilder().create(10)); measureRepository.addRawMeasure(FILE_2_REF, metricKey, newMeasureBuilder().create(40)); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ViewsComplexityMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ViewsComplexityMeasuresStepTest.java index 9a1ee04a03b..1cb49d6cff2 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ViewsComplexityMeasuresStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ViewsComplexityMeasuresStepTest.java @@ -35,6 +35,8 @@ import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY; import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION; import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY; import static org.sonar.api.measures.CoreMetrics.CLASS_COMPLEXITY_KEY; +import static org.sonar.api.measures.CoreMetrics.COGNITIVE_COMPLEXITY; +import static org.sonar.api.measures.CoreMetrics.COGNITIVE_COMPLEXITY_KEY; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_CLASSES; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_CLASSES_KEY; @@ -101,7 +103,9 @@ public class ViewsComplexityMeasuresStepTest { .add(CLASS_COMPLEXITY) .add(CLASSES) .add(FUNCTION_COMPLEXITY) - .add(FUNCTIONS); + .add(FUNCTIONS) + .add(COGNITIVE_COMPLEXITY); + @Rule public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); @@ -122,6 +126,11 @@ public class ViewsComplexityMeasuresStepTest { verify_sum_aggregation(COMPLEXITY_IN_FUNCTIONS_KEY); } + @Test + public void aggregate_cognitive_complexity_in_functions() throws Exception { + verify_sum_aggregation(COGNITIVE_COMPLEXITY_KEY); + } + private void verify_sum_aggregation(String metricKey) { addRawMeasureValue(PROJECT_VIEW_1_REF, metricKey, 10); addRawMeasureValue(PROJECT_VIEW_2_REF, metricKey, 40); diff --git a/sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java b/sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java index 295cd8416d9..9d9596cd57f 100644 --- a/sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java +++ b/sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java @@ -31,6 +31,7 @@ import org.sonar.api.measures.Metrics; import static org.sonar.api.measures.CoreMetrics.ACCESSORS; import static org.sonar.api.measures.CoreMetrics.CLASSES; +import static org.sonar.api.measures.CoreMetrics.COGNITIVE_COMPLEXITY; import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES; import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_DATA; import static org.sonar.api.measures.CoreMetrics.COMPLEXITY; @@ -95,6 +96,7 @@ public class ScannerMetrics { COMPLEXITY, COMPLEXITY_IN_CLASSES, COMPLEXITY_IN_FUNCTIONS, + COGNITIVE_COMPLEXITY, FILE_COMPLEXITY_DISTRIBUTION, FUNCTION_COMPLEXITY_DISTRIBUTION, 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 317f5048d52..2d59b3c72cf 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1930,6 +1930,8 @@ metric.class_complexity_distribution.description=Classes distribution /complexit metric.class_complexity_distribution.name=Class Distribution / Complexity metric.code_smells.description=Code Smells metric.code_smells.name=Code Smells +metric.cognitive_complexity.description=Cognitive complexity +metric.cognitive_complexity.name=Cognitive Complexity metric.commented_out_code_lines.description=Commented lines of code metric.commented_out_code_lines.name=Commented-Out LOC metric.comment_blank_lines.description=Comments that do not contain comments diff --git a/sonar-core/src/test/java/org/sonar/core/metric/ScannerMetricsTest.java b/sonar-core/src/test/java/org/sonar/core/metric/ScannerMetricsTest.java index fc44410de8d..80c9231b2c1 100644 --- a/sonar-core/src/test/java/org/sonar/core/metric/ScannerMetricsTest.java +++ b/sonar-core/src/test/java/org/sonar/core/metric/ScannerMetricsTest.java @@ -36,7 +36,7 @@ public class ScannerMetricsTest { @Test public void check_number_of_allowed_core_metrics() throws Exception { - assertThat(SENSOR_METRICS_WITHOUT_METRIC_PLUGIN.getMetrics()).hasSize(33); + assertThat(SENSOR_METRICS_WITHOUT_METRIC_PLUGIN.getMetrics()).hasSize(34); } @Test 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 dbcafc7e600..a2e7a526ed6 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 @@ -467,6 +467,16 @@ public final class CoreMetrics { .setDomain(DOMAIN_COMPLEXITY) .create(); + public static final String COGNITIVE_COMPLEXITY_KEY = "cognitive_complexity"; + public static final Metric<Integer> COGNITIVE_COMPLEXITY = new Metric.Builder(COGNITIVE_COMPLEXITY_KEY, "Cognitive Complexity", Metric.ValueType.INT) + .setDescription("Cognitive complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(DOMAIN_COMPLEXITY) + .setBestValue(0.0) + .setOptimizedBestValue(true) + .create(); + // -------------------------------------------------------------------------------------------------------------------- // // UNIT TESTS |