]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3900 Add new metrics "complexity in classes" and "complexity in methods" to...
authorJulien Lancelot <julien.lancelot@gmail.com>
Thu, 21 Mar 2013 13:10:42 +0000 (14:10 +0100)
committerJulien Lancelot <julien.lancelot@gmail.com>
Thu, 21 Mar 2013 13:10:42 +0000 (14:10 +0100)
sonar-plugin-api/src/main/java/org/sonar/api/measures/AverageFormula.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
sonar-plugin-api/src/test/java/org/sonar/api/measures/AverageFormulaTest.java

index d9f04ee3604e74165bf809e6b1c0f6775ef7b3e4..c42d62ebc6460ca1f1b8106d6676fe8ef5169f6d 100644 (file)
@@ -36,6 +36,7 @@ public class AverageFormula implements Formula {
 
   private Metric mainMetric;
   private Metric byMetric;
+  private Metric fallbackMetric;
 
   /**
    * This method should be private but it kep package-protected because of AverageComplexityFormula.
@@ -55,6 +56,16 @@ public class AverageFormula implements Formula {
     return new AverageFormula(main, by);
   }
 
+  /**
+   * Set a fallback metric if no measures found for the main metric.
+   *
+   * @param fallbackMetric The fallback metric
+   */
+  public AverageFormula setFallbackForMainMetric(Metric fallbackMetric) {
+    this.fallbackMetric = fallbackMetric;
+    return this;
+  }
+
   /**
    * {@inheritDoc}
    */
@@ -87,8 +98,9 @@ public class AverageFormula implements Formula {
     boolean hasApplicableChildren = false;
 
     for (FormulaData childrenData : data.getChildren()) {
+      Double fallbackMeasure = fallbackMetric != null ? MeasureUtils.getValue(childrenData.getMeasure(fallbackMetric), null) : null;
       Double childrenByMeasure = MeasureUtils.getValue(childrenData.getMeasure(byMetric), null);
-      Double childrenMainMeasure = MeasureUtils.getValue(childrenData.getMeasure(mainMetric), null);
+      Double childrenMainMeasure = MeasureUtils.getValue(childrenData.getMeasure(mainMetric), fallbackMeasure);
       if (childrenMainMeasure != null && childrenByMeasure != null && childrenByMeasure > 0.0) {
         totalByMeasure += childrenByMeasure;
         totalMainMeasure += childrenMainMeasure;
@@ -104,8 +116,9 @@ public class AverageFormula implements Formula {
   private Measure calculateForFile(FormulaData data, FormulaContext context) {
     Measure result = null;
 
+    Double fallbackMeasure = fallbackMetric != null ? MeasureUtils.getValue(data.getMeasure(fallbackMetric), null) : null;
     Double byMeasure = MeasureUtils.getValue(data.getMeasure(byMetric), null);
-    Double mainMeasure = MeasureUtils.getValue(data.getMeasure(mainMetric), null);
+    Double mainMeasure = MeasureUtils.getValue(data.getMeasure(mainMetric), fallbackMeasure);
     if (mainMeasure != null && byMeasure != null && byMeasure > 0.0) {
       result = new Measure(context.getTargetMetric(), (mainMeasure / byMeasure));
     }
index aa8f3bf5e675c48bb1b0b4e9b3d766b116b20952..682848a7bd4a65ff90ca5f839b75ef6014702e48 100644 (file)
@@ -275,33 +275,52 @@ public final class CoreMetrics {
       .setFormula(new SumChildValuesFormula(false))
       .create();
 
+  public static final String FILE_COMPLEXITY_KEY = "file_complexity";
+  public static final Metric FILE_COMPLEXITY = new Metric.Builder(FILE_COMPLEXITY_KEY, "Complexity /file", Metric.ValueType.FLOAT)
+      .setDescription("Complexity average by file")
+      .setDirection(Metric.DIRECTION_WORST)
+      .setQualitative(true)
+      .setDomain(DOMAIN_COMPLEXITY)
+      .setFormula(AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FILES))
+      .create();
+
+  public static final String COMPLEXITY_IN_CLASSES_KEY = "complexity_in_classes";
+  public static final Metric COMPLEXITY_IN_CLASSES = new Metric.Builder(COMPLEXITY_IN_CLASSES_KEY, "Complexity in classes", Metric.ValueType.INT)
+      .setDescription("Cyclomatic complexity in classes")
+      .setDirection(Metric.DIRECTION_WORST)
+      .setQualitative(false)
+      .setDomain(DOMAIN_COMPLEXITY)
+      .setFormula(new SumChildValuesFormula(false))
+      .create();
+
   public static final String CLASS_COMPLEXITY_KEY = "class_complexity";
   public static final Metric CLASS_COMPLEXITY = new Metric.Builder(CLASS_COMPLEXITY_KEY, "Complexity /class", Metric.ValueType.FLOAT)
       .setDescription("Complexity average by class")
       .setDirection(Metric.DIRECTION_WORST)
       .setQualitative(true)
       .setDomain(DOMAIN_COMPLEXITY)
-      .setFormula(AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.CLASSES))
+      .setFormula(AverageFormula.create(CoreMetrics.COMPLEXITY_IN_CLASSES, CoreMetrics.CLASSES).setFallbackForMainMetric(CoreMetrics.COMPLEXITY))
       .create();
 
-  public static final String FUNCTION_COMPLEXITY_KEY = "function_complexity";
-  public static final Metric FUNCTION_COMPLEXITY = new Metric.Builder(FUNCTION_COMPLEXITY_KEY, "Complexity /method", Metric.ValueType.FLOAT)
-      .setDescription("Complexity average by method")
+  public static final String COMPLEXITY_IN_FUNCTIONS_KEY = "complexity_in_functions";
+  public static final Metric COMPLEXITY_IN_FUNCTIONS = new Metric.Builder(COMPLEXITY_IN_FUNCTIONS_KEY, "Complexity in functions", Metric.ValueType.INT)
+      .setDescription("Cyclomatic complexity in methods")
       .setDirection(Metric.DIRECTION_WORST)
-      .setQualitative(true)
+      .setQualitative(false)
       .setDomain(DOMAIN_COMPLEXITY)
-      .setFormula(AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS))
+      .setFormula(new SumChildValuesFormula(false))
       .create();
 
-  public static final String FILE_COMPLEXITY_KEY = "file_complexity";
-  public static final Metric FILE_COMPLEXITY = new Metric.Builder(FILE_COMPLEXITY_KEY, "Complexity /file", Metric.ValueType.FLOAT)
-      .setDescription("Complexity average by file")
+  public static final String FUNCTION_COMPLEXITY_KEY = "function_complexity";
+  public static final Metric FUNCTION_COMPLEXITY = new Metric.Builder(FUNCTION_COMPLEXITY_KEY, "Complexity /method", Metric.ValueType.FLOAT)
+      .setDescription("Complexity average by method")
       .setDirection(Metric.DIRECTION_WORST)
       .setQualitative(true)
       .setDomain(DOMAIN_COMPLEXITY)
-      .setFormula(AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FILES))
+      .setFormula(AverageFormula.create(CoreMetrics.COMPLEXITY_IN_FUNCTIONS, CoreMetrics.FUNCTIONS).setFallbackForMainMetric(CoreMetrics.COMPLEXITY))
       .create();
 
+
   /**
    * @deprecated in 3.0 - see SONAR-3289
    */
index c8e9b09ca156e8e054b71a956f3af6c6c38077a2..ae9767b4ef11e0aa75322f27d829730aaca89f25 100644 (file)
  */
 package org.sonar.api.measures;
 
-import com.google.common.collect.Lists;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.resources.JavaFile;
 
 import java.util.List;
 
+import static com.google.common.collect.Lists.newArrayList;
 import static junit.framework.Assert.assertNull;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.Matchers.hasItems;
@@ -46,14 +46,14 @@ public class AverageFormulaTest {
   }
 
   @Test
-  public void testDependsUponMetrics() throws Exception {
+  public void test_depends_upon_metrics() throws Exception {
     AverageFormula formula = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS);
     assertThat(formula.dependsUponMetrics(), hasItems(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS));
   }
 
   @Test
-  public void testAverageCalculation() {
-    List<FormulaData> childrenData = Lists.newArrayList();
+  public void test_average_calculation() {
+    List<FormulaData> childrenData = newArrayList();
     FormulaData data1 = mock(FormulaData.class);
     childrenData.add(data1);
     when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
@@ -72,23 +72,23 @@ public class AverageFormulaTest {
   }
 
   @Test
-  public void shouldNotComputeIfNotTargetMetric() {
+  public void should_not_compute_if_not_target_metric() {
     when(data.getMeasure(CoreMetrics.FUNCTION_COMPLEXITY)).thenReturn(new Measure(CoreMetrics.FUNCTION_COMPLEXITY, 2.0));
     Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
     assertNull(measure);
   }
 
   @Test
-  public void testWhenNoChildrenMesaures() {
-    List<FormulaData> childrenData = Lists.newArrayList();
+  public void test_when_no_children_mesaures() {
+    List<FormulaData> childrenData = newArrayList();
     when(data.getChildren()).thenReturn(childrenData);
     Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
     assertNull(measure);
   }
 
   @Test
-  public void testWhenNoComplexityMesaures() {
-    List<FormulaData> childrenData = Lists.newArrayList();
+  public void test_when_no_complexity_mesaures() {
+    List<FormulaData> childrenData = newArrayList();
     FormulaData data1 = mock(FormulaData.class);
     childrenData.add(data1);
     when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
@@ -100,8 +100,8 @@ public class AverageFormulaTest {
   }
 
   @Test
-  public void testWhenNoByMetricMesaures() {
-    List<FormulaData> childrenData = Lists.newArrayList();
+  public void test_when_no_by_metric_mesaures() {
+    List<FormulaData> childrenData = newArrayList();
     FormulaData data1 = mock(FormulaData.class);
     childrenData.add(data1);
     when(data1.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 43.0));
@@ -113,17 +113,17 @@ public class AverageFormulaTest {
   }
 
   @Test
-  public void testWhenMixedMetrics() {
-    List<FormulaData> childrenData = Lists.newArrayList();
+  public void test_when_mixed_metrics() {
+    List<FormulaData> childrenData = newArrayList();
     FormulaData data1 = mock(FormulaData.class);
     childrenData.add(data1);
     when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
-    when(data1.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 107.0));
+    when(data1.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 107.0));
 
     FormulaData data2 = mock(FormulaData.class);
     childrenData.add(data2);
     when(data2.getMeasure(CoreMetrics.STATEMENTS)).thenReturn(new Measure(CoreMetrics.STATEMENTS, 127.0));
-    when(data2.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 233.0));
+    when(data2.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 233.0));
 
     when(data.getChildren()).thenReturn(childrenData);
 
@@ -133,7 +133,7 @@ public class AverageFormulaTest {
   }
 
   @Test
-  public void testCalculationForFIle() {
+  public void test_calculation_for_file() {
     when(data.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 60.0));
     when(data.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 20.0));
     when(context.getResource()).thenReturn(new JavaFile("foo"));
@@ -141,4 +141,49 @@ public class AverageFormulaTest {
     Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
     assertThat(measure.getValue(), is(3.0));
   }
+
+  @Test
+  public void should_use_fallback_metric_when_no_data_on_main_metric_for_file() {
+    when(data.getMeasure(CoreMetrics.COMPLEXITY_IN_FUNCTIONS)).thenReturn(null);
+    when(data.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 60.0));
+    when(data.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 20.0));
+    when(context.getResource()).thenReturn(new JavaFile("foo"));
+
+    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY_IN_FUNCTIONS, CoreMetrics.FUNCTIONS)
+        .setFallbackForMainMetric(CoreMetrics.COMPLEXITY)
+        .calculate(data, context);
+    assertThat(measure.getValue(), is(3.0));
+  }
+
+  @Test
+  public void should_use_main_metric_even_if_fallback_metric_provided() {
+    when(data.getMeasure(CoreMetrics.COMPLEXITY_IN_FUNCTIONS)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 60.0));
+    when(data.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 42.0));
+    when(data.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 20.0));
+    when(context.getResource()).thenReturn(new JavaFile("foo"));
+
+    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY_IN_FUNCTIONS, CoreMetrics.FUNCTIONS)
+        .setFallbackForMainMetric(CoreMetrics.COMPLEXITY)
+        .calculate(data, context);
+    assertThat(measure.getValue(), is(3.0));
+  }
+
+  @Test
+  public void should_use_fallback_metric_when_no_data_on_main_metric_for_children() {
+    List<FormulaData> childrenData = newArrayList();
+    FormulaData data1 = mock(FormulaData.class);
+    childrenData.add(data1);
+    when(data1.getMeasure(CoreMetrics.COMPLEXITY_IN_FUNCTIONS)).thenReturn(null);
+    when(data1.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 107.0));
+    when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
+
+    when(data.getChildren()).thenReturn(childrenData);
+
+    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY_IN_FUNCTIONS, CoreMetrics.FUNCTIONS)
+        .setFallbackForMainMetric(CoreMetrics.COMPLEXITY)
+        .calculate(data, context);
+
+    assertThat(measure.getValue(), is(2.5));
+  }
+
 }