]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2159 The total classes used in complexity distribution is different than the...
authorsimonbrandhof <simon.brandhof@gmail.com>
Tue, 1 Feb 2011 09:57:21 +0000 (10:57 +0100)
committersimonbrandhof <simon.brandhof@gmail.com>
Tue, 1 Feb 2011 09:57:28 +0000 (10:57 +0100)
15 files changed:
plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidExecutor.java
plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/SquidPlugin.java
plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/bridges/CopyBasicMeasuresBridge.java
plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/bridges/ResourceIndex.java
plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/decorators/ClassesDecorator.java [new file with mode: 0644]
plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/decorators/FunctionsDecorator.java [new file with mode: 0644]
plugins/sonar-squid-java-plugin/src/test/java/org/sonar/plugins/squid/SquidPluginTest.java
sonar-squid/src/main/java/org/sonar/squid/api/SourceCode.java
sonar-squid/src/test/java/org/sonar/squid/api/SourceCodeTest.java
tests/integration/tests/maven-projects/java-complexity/src/main/java/foo/AnonymousClass.java [new file with mode: 0644]
tests/integration/tests/maven-projects/java-complexity/src/main/java/foo/ContainsInnerClasses.java
tests/integration/tests/maven-projects/java-complexity/src/main/java/foo/Helloworld.java
tests/integration/tests/maven-projects/java-complexity/src/main/java/foo/ZeroComplexity.java [new file with mode: 0644]
tests/integration/tests/src/test/java/org/sonar/tests/integration/JavaComplexityIT.java
tests/integration/tests/src/test/java/org/sonar/tests/integration/Struts139IT.java

index a2736b7c755d0269f92d47467fe29d258e40c04b..46ffd2412974d4c5be0f5e28c7e1a2fff3601e72 100644 (file)
@@ -53,7 +53,7 @@ public final class SquidExecutor {
   private CheckFactory checkFactory;
 
   public SquidExecutor(boolean analyzePropertyAccessors, String fieldNamesToExcludeFromLcom4Computation, CheckFactory checkFactory,
-      Charset sourcesCharset) {
+                       Charset sourcesCharset) {
     JavaSquidConfiguration conf = createJavaSquidConfiguration(analyzePropertyAccessors, fieldNamesToExcludeFromLcom4Computation,
         sourcesCharset);
     squid = new Squid(conf);
@@ -61,13 +61,13 @@ public final class SquidExecutor {
   }
 
   private JavaSquidConfiguration createJavaSquidConfiguration(boolean analyzePropertyAccessors,
-      String fieldNamesToExcludeFromLcom4Computation,
-      Charset sourcesCharset) {
+                                                              String fieldNamesToExcludeFromLcom4Computation,
+                                                              Charset sourcesCharset) {
     JavaSquidConfiguration conf = new JavaSquidConfiguration(analyzePropertyAccessors, sourcesCharset);
 
-    if ( !StringUtils.isBlank(fieldNamesToExcludeFromLcom4Computation)) {
+    if (!StringUtils.isBlank(fieldNamesToExcludeFromLcom4Computation)) {
       for (String fieldName : fieldNamesToExcludeFromLcom4Computation.split(",")) {
-        if ( !StringUtils.isBlank(fieldName)) {
+        if (!StringUtils.isBlank(fieldName)) {
           conf.addFieldToExcludeFromLcom4Calculation(fieldName);
         }
       }
@@ -136,8 +136,11 @@ public final class SquidExecutor {
     Collection<SourceCode> squidClasses = squid.search(new QueryByType(SourceClass.class));
     for (SourceCode squidClass : squidClasses) {
       Resource sonarClass = resourceIndex.get(squidClass);
-      for (Bridge bridge : bridges) {
-        bridge.onClass((SourceClass) squidClass, (JavaClass)sonarClass);
+      // can be null with anonymous classes
+      if (sonarClass != null) {
+        for (Bridge bridge : bridges) {
+          bridge.onClass((SourceClass) squidClass, (JavaClass) sonarClass);
+        }
       }
     }
   }
@@ -145,9 +148,11 @@ public final class SquidExecutor {
   private void saveMethods(ResourceIndex resourceIndex, List<Bridge> bridges) {
     Collection<SourceCode> squidMethods = squid.search(new QueryByType(SourceMethod.class));
     for (SourceCode squidMethod : squidMethods) {
-      JavaMethod sonarMethod = (JavaMethod)resourceIndex.get(squidMethod);
-      for (Bridge bridge : bridges) {
-        bridge.onMethod((SourceMethod) squidMethod, sonarMethod);
+      JavaMethod sonarMethod = (JavaMethod) resourceIndex.get(squidMethod);
+      if (sonarMethod != null) {
+        for (Bridge bridge : bridges) {
+          bridge.onMethod((SourceMethod) squidMethod, sonarMethod);
+        }
       }
     }
   }
index ea18236faef7c548f0a71a16d0f6c1c8ad491d1b..6fed2b2c84c104107bd23802e014eacb24ca7d71 100644 (file)
@@ -24,7 +24,9 @@ import org.sonar.api.Plugin;
 import org.sonar.api.Properties;
 import org.sonar.api.Property;
 import org.sonar.plugins.squid.decorators.ClassComplexityDistributionBuilder;
+import org.sonar.plugins.squid.decorators.ClassesDecorator;
 import org.sonar.plugins.squid.decorators.FunctionComplexityDistributionBuilder;
+import org.sonar.plugins.squid.decorators.FunctionsDecorator;
 
 import java.util.Arrays;
 import java.util.List;
@@ -61,7 +63,8 @@ public class SquidPlugin implements Plugin {
 
   public List getExtensions() {
     return Arrays.asList(SquidSearchProxy.class, SquidSensor.class, SquidRuleRepository.class, JavaSourceImporter.class,
-        ClassComplexityDistributionBuilder.class, FunctionComplexityDistributionBuilder.class);
+        ClassComplexityDistributionBuilder.class, FunctionComplexityDistributionBuilder.class, ClassesDecorator.class,
+        FunctionsDecorator.class);
   }
 
   @Override
index 94f7b3bdd65225f9687319181d6de0383b0ffcb4..a783141cc75fc3c619e2c70ca5927f3d93a92e3b 100644 (file)
@@ -39,7 +39,6 @@ public final class CopyBasicMeasuresBridge extends Bridge {
   @Override
   public void onFile(SourceFile squidFile, Resource sonarResource) {
     copyStandard(squidFile, sonarResource);
-    copy(squidFile, sonarResource, Metric.CLASSES, CoreMetrics.CLASSES);
     copy(squidFile, sonarResource, Metric.FILES, CoreMetrics.FILES);
     context.saveMeasure(sonarResource, CoreMetrics.PUBLIC_DOCUMENTED_API_DENSITY, ParsingUtils.scaleValue(squidFile.getDouble(Metric.PUBLIC_DOCUMENTED_API_DENSITY) * 100, 2));
   }
@@ -58,12 +57,13 @@ public final class CopyBasicMeasuresBridge extends Bridge {
     copy(squidCode, sonarResource, Metric.LINES_OF_CODE, CoreMetrics.NCLOC);
     copy(squidCode, sonarResource, Metric.LINES, CoreMetrics.LINES);
     copy(squidCode, sonarResource, Metric.COMMENT_LINES_WITHOUT_HEADER, CoreMetrics.COMMENT_LINES);
-    copy(squidCode, sonarResource, Metric.METHODS, CoreMetrics.FUNCTIONS);
     copy(squidCode, sonarResource, Metric.ACCESSORS, CoreMetrics.ACCESSORS);
     copy(squidCode, sonarResource, Metric.PUBLIC_API, CoreMetrics.PUBLIC_API);
     copy(squidCode, sonarResource, Metric.COMPLEXITY, CoreMetrics.COMPLEXITY);
     copy(squidCode, sonarResource, Metric.STATEMENTS, CoreMetrics.STATEMENTS);
     copy(squidCode, sonarResource, Metric.COMMENTED_OUT_CODE_LINES, CoreMetrics.COMMENTED_OUT_CODE_LINES);
+
+
   }
 
   private void copy(SourceCode squidResource, Resource sonarResource, Metric squidMetric, org.sonar.api.measures.Metric sonarMetric) {
index 105a33e6b2d9285a92f0c0e608e64825cf51fecd..b9c5819b9943522769b775b97fef5a9940a48f70 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.java.api.JavaClass;
 import org.sonar.java.api.JavaMethod;
 import org.sonar.squid.Squid;
 import org.sonar.squid.api.*;
+import org.sonar.squid.indexer.QueryByMeasure;
 import org.sonar.squid.indexer.QueryByType;
 import org.sonar.squid.measures.Metric;
 
@@ -38,7 +39,7 @@ import java.util.HashMap;
 
 public final class ResourceIndex extends HashMap<SourceCode, Resource> {
 
-  public ResourceIndex    loadSquidResources(Squid squid, SensorContext context, Project project) {
+  public ResourceIndex loadSquidResources(Squid squid, SensorContext context, Project project) {
     loadSquidProject(squid, project);
     loadSquidPackages(squid, context);
     loadSquidFiles(squid, context);
@@ -64,16 +65,16 @@ public final class ResourceIndex extends HashMap<SourceCode, Resource> {
     Collection<SourceCode> files = squid.search(new QueryByType(SourceFile.class));
     for (SourceCode squidFile : files) {
       JavaFile sonarFile = SquidUtils.convertJavaFileKeyFromSquidFormat(squidFile.getKey());
-      JavaPackage sonarPackage = (JavaPackage)get(squidFile.getParent(SourcePackage.class));
+      JavaPackage sonarPackage = (JavaPackage) get(squidFile.getParent(SourcePackage.class));
       context.index(sonarFile, sonarPackage);
       put(squidFile, context.getResource(sonarFile)); // resource is reloaded to get the id
     }
   }
 
   private void loadSquidClasses(Squid squid, SensorContext context) {
-    Collection<SourceCode> classes = squid.search(new QueryByType(SourceClass.class));
+    Collection<SourceCode> classes = squid.search(new QueryByType(SourceClass.class), new QueryByMeasure(Metric.CLASSES, QueryByMeasure.Operator.GREATER_THAN_EQUALS, 1));
     for (SourceCode squidClass : classes) {
-      JavaFile sonarFile = (JavaFile)get(squidClass.getParent(SourceFile.class));
+      JavaFile sonarFile = (JavaFile) get(squidClass.getParent(SourceFile.class));
       JavaClass sonarClass = new JavaClass.Builder()
           .setName(convertClassKey(squidClass.getKey()))
           .setFromLine(squidClass.getStartAtLine())
@@ -88,17 +89,19 @@ public final class ResourceIndex extends HashMap<SourceCode, Resource> {
     Collection<SourceCode> methods = squid.search(new QueryByType(SourceMethod.class));
     for (SourceCode squidMethod : methods) {
       SourceClass squidClass = squidMethod.getParent(SourceClass.class);
-      JavaClass sonarClass = (JavaClass)get(squidClass);
-      JavaMethod sonarMethod = new JavaMethod.Builder()
-          .setClass(sonarClass)
-          .setSignature(squidMethod.getName())
-          .setFromLine(squidMethod.getStartAtLine())
-          .setToLine(squidMethod.getEndAtLine())
-          .setAccessor(squidMethod.getInt(Metric.ACCESSORS)>0)
-          .create();
+      JavaClass sonarClass = (JavaClass) get(squidClass);
+      if (sonarClass != null) {
+        JavaMethod sonarMethod = new JavaMethod.Builder()
+            .setClass(sonarClass)
+            .setSignature(squidMethod.getName())
+            .setFromLine(squidMethod.getStartAtLine())
+            .setToLine(squidMethod.getEndAtLine())
+            .setAccessor(squidMethod.getInt(Metric.ACCESSORS) > 0)
+            .create();
 
-      context.index(sonarMethod, sonarClass);
-      put(squidMethod, sonarMethod);
+        context.index(sonarMethod, sonarClass);
+        put(squidMethod, sonarMethod);
+      }
     }
   }
 
diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/decorators/ClassesDecorator.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/decorators/ClassesDecorator.java
new file mode 100644 (file)
index 0000000..aa605bd
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.squid.decorators;
+
+import org.sonar.api.batch.Decorator;
+import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.Java;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.Scopes;
+
+public final class ClassesDecorator implements Decorator {
+
+  public void decorate(Resource resource, DecoratorContext context) {
+    if (Scopes.isFile(resource)) {
+      int classes = 0;
+      for (DecoratorContext child : context.getChildren()) {
+        if (Scopes.isType(child.getResource())) {
+          classes++;
+        }
+      }
+      context.saveMeasure(new Measure(CoreMetrics.CLASSES, (double) classes));
+    }
+  }
+
+  public boolean shouldExecuteOnProject(Project project) {
+    return Java.KEY.equals(project.getLanguageKey());
+  }
+}
diff --git a/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/decorators/FunctionsDecorator.java b/plugins/sonar-squid-java-plugin/src/main/java/org/sonar/plugins/squid/decorators/FunctionsDecorator.java
new file mode 100644 (file)
index 0000000..3bd9e65
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.squid.decorators;
+
+import org.sonar.api.batch.Decorator;
+import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.Java;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.Scopes;
+import org.sonar.java.api.JavaMethod;
+
+public final class FunctionsDecorator implements Decorator {
+
+  public void decorate(Resource resource, DecoratorContext context) {
+    if (Scopes.isType(resource)) {
+      int methods=0;
+      for (DecoratorContext child : context.getChildren()) {
+        if (child.getResource() instanceof JavaMethod && !((JavaMethod)child.getResource()).isAccessor()) {
+          methods++;
+        }
+      }
+      context.saveMeasure(new Measure(CoreMetrics.FUNCTIONS, (double)methods));
+    }
+  }
+
+  public boolean shouldExecuteOnProject(Project project) {
+    return Java.KEY.equals(project.getLanguageKey());
+  }
+}
index 0387b5010951aef725212d649dd109dfa03d69d2..4bf33ac016f39c8e05992f70e005e51a9f17b404 100644 (file)
@@ -31,6 +31,6 @@ public class SquidPluginTest {
   @Test
   public void coverageForFun() {
     assertThat(new SquidPlugin().getKey(), not(nullValue()));
-    assertThat(new SquidPlugin().getExtensions().size(), is(6));
+    assertThat(new SquidPlugin().getExtensions().size(), is(8));
   }
 }
index a38d2613258a0c7bf7427fb15bcb7f30dabecfb1..cbadf4d6a052f6c66399663b3f4b5f08ecf465fa 100644 (file)
 
 package org.sonar.squid.api;
 
-import java.util.HashSet;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
 import org.sonar.squid.measures.Measurable;
 import org.sonar.squid.measures.Measures;
 import org.sonar.squid.measures.Metric;
 import org.sonar.squid.measures.MetricDef;
 
+import java.util.HashSet;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
 public abstract class SourceCode implements Measurable, Comparable<SourceCode> {
 
   private final String name;
@@ -212,6 +212,17 @@ public abstract class SourceCode implements Measurable, Comparable<SourceCode> {
     return parent.getParent(sourceCode);
   }
 
+  public <SOURCECODE extends SourceCode> SOURCECODE getAncestor(Class<SOURCECODE> withClass) {
+    SOURCECODE ancestor = getParent(withClass);
+    if (ancestor!=null) {
+      SOURCECODE parentAncestor = ancestor.getAncestor(withClass);
+      if (parentAncestor!=null) {
+        ancestor = parentAncestor;
+      }
+    }
+    return ancestor;
+  }
+
   public void log(CheckMessage message) {
     message.setSourceCode(this);
     getCheckMessages().add(message);
index 37011a6c95dda749cde0d6f314276adeaaab0ff8..9e71cf712f03c4b0815058d5e6a936c0f84f9ecd 100644 (file)
@@ -94,6 +94,24 @@ public class SourceCodeTest {
     assertEquals(pacFrom, classFrom.getParent(SourcePackage.class));
   }
 
+  @Test
+  public void testGetAncestorByType() {
+    SourceFile file = new SourceFile("org.from.From.java", "From.java");
+    SourceClass class1 = new SourceClass("org.from.From", "From");
+    SourceClass class2 = new SourceClass("org.from.From$Foo", "From$Foo");
+    SourceMethod method = new SourceMethod(class2, "foo()", 10);
+    file.addChild(class1);
+    class1.addChild(class2);
+    class2.addChild(method);
+
+    assertEquals(file, class1.getAncestor(SourceFile.class));
+    assertEquals(class1, class2.getAncestor(SourceClass.class));
+    assertEquals(file, class2.getAncestor(SourceFile.class));
+    assertEquals(class1, method.getAncestor(SourceClass.class));
+    assertEquals(file, method.getAncestor(SourceFile.class));
+  }
+
+
   @Test
   public void testHasAmongParents() {
     assertTrue(cla.hasAmongParents(prj));
diff --git a/tests/integration/tests/maven-projects/java-complexity/src/main/java/foo/AnonymousClass.java b/tests/integration/tests/maven-projects/java-complexity/src/main/java/foo/AnonymousClass.java
new file mode 100644 (file)
index 0000000..a7572a6
--- /dev/null
@@ -0,0 +1,26 @@
+package foo;
+
+import java.io.Serializable;
+import java.lang.Runnable;
+
+// class complexity: 4
+public class AnonymousClass {
+
+  // method complexity: 3
+  public void anonymousClassWithComplexity() {
+    Runnable runnable = new Runnable() {
+      public void run() {
+        if (true) {
+          System.out.println("true");
+        }
+      }
+    };
+  }
+
+  // method complexity: 1
+  public void anonymousClassWithZeroComplexity() {
+    Serializable serializable = new Serializable() {
+
+    };
+  }
+}
\ No newline at end of file
index 9ed05abd6261e4ef7f8bd66a0406002d9b1051ed..900e5e5eac123504e353f3bd694fb89443a9c7ea 100644 (file)
@@ -1,23 +1,23 @@
 package foo;
 
-
+// class complexity: 5
 public class ContainsInnerClasses {
 
-  // complexity: 1
+  // method complexity: 1
   public ContainsInnerClasses() {
 
   }
 
-  // complexity: 3
+  // class complexity: 3
   public static class InnerClass {
     private String field;
 
-    // complexity: 1
+    // method complexity: 1
     public InnerClass() {
 
     }
 
-    // complexity: 2
+    // method complexity: 2
     public InnerClass(String s) {
       if (s != null) {
         field = s;
@@ -26,11 +26,11 @@ public class ContainsInnerClasses {
   }
 }
 
-// complexity: 1
+// class complexity: 1
 class PackageClass {
     private String field;
 
-    // complexity: 1
+    // method complexity: 1
     public PackageClass() {
 
     }
index 37fae842697e65f381038ebad55ecf766a1527d2..ded87d618489d9e1ddcfa1087646493b31f81f19 100644 (file)
@@ -1,11 +1,11 @@
 package foo;
 
-// complexity: 6
+// class complexity: 6
 public class Helloworld {
 
   private String field = null;
 
-  // this is considered as a method
+  // this is considered as a method (bug http://jira.codehaus.org/browse/SONAR-2152)
   // complexity: 2
   static {
     int i = 0;
@@ -14,7 +14,7 @@ public class Helloworld {
     }
   }
 
-  // complexity: 1
+  // method complexity: 1
   public Helloworld(String s) {
     this.field = s;
   }
@@ -31,7 +31,7 @@ public class Helloworld {
     this.field = s;
   }
 
-  // complexity: 3
+  // method complexity: 3
   public void sayHello() {
     for (int i = 0; i < 5; i++) {
       if (field != null) {
diff --git a/tests/integration/tests/maven-projects/java-complexity/src/main/java/foo/ZeroComplexity.java b/tests/integration/tests/maven-projects/java-complexity/src/main/java/foo/ZeroComplexity.java
new file mode 100644 (file)
index 0000000..ee6b3eb
--- /dev/null
@@ -0,0 +1,6 @@
+package foo;
+
+// complexity: 0
+public class ZeroComplexity {
+  
+}
index e3e3ad1f157c4ea1e9aaeded95fd62afd0e97ff8..96af69d950a7b5f70c9183772f31e58145942b3a 100644 (file)
@@ -38,6 +38,21 @@ public class JavaComplexityIT {
     sonar = ITUtils.createSonarWsClient();
   }
 
+  @Test
+  public void testClasses() {
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo.AnonymousClass", CoreMetrics.CLASSES_KEY).getIntValue(), is(1));
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo.ZeroComplexity", CoreMetrics.CLASSES_KEY).getIntValue(), is(1));
+    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.CLASSES_KEY).getIntValue(), is(6));
+  }
+
+  @Test
+  public void testMethods() {
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo.AnonymousClass", CoreMetrics.FUNCTIONS_KEY).getIntValue(), is(2));
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo.ZeroComplexity", CoreMetrics.FUNCTIONS_KEY).getIntValue(), is(0));
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo.ContainsInnerClasses", CoreMetrics.FUNCTIONS_KEY).getIntValue(), is(4));
+    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.FUNCTIONS_KEY).getIntValue(), is(8));
+  }
+
   @Test
   public void testFileComplexity() {
     assertThat(getMeasure("org.sonar.tests:java-complexity:foo.Helloworld", CoreMetrics.COMPLEXITY_KEY).getIntValue(), is(6));
@@ -46,12 +61,12 @@ public class JavaComplexityIT {
 
   @Test
   public void testPackageComplexity() {
-    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.COMPLEXITY_KEY).getIntValue(), is(11));
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.COMPLEXITY_KEY).getIntValue(), is(15));
   }
 
   @Test
   public void testProjectComplexity() {
-    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.COMPLEXITY_KEY).getIntValue(), is(11));
+    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.COMPLEXITY_KEY).getIntValue(), is(15));
   }
 
   @Test
@@ -64,9 +79,17 @@ public class JavaComplexityIT {
     // complexity 5 / 4 methods. Real value is 1.25 but round up to 1.3
     assertThat(getMeasure("org.sonar.tests:java-complexity:foo.ContainsInnerClasses", CoreMetrics.FUNCTION_COMPLEXITY_KEY).getValue(), is(1.3));
 
-    // 3.0 * 2 + 1.25 * 4 = 11 for 6 methods
-    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.FUNCTION_COMPLEXITY_KEY).getValue(), is(1.8));
-    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.FUNCTION_COMPLEXITY_KEY).getValue(), is(1.8));
+    // (1 + 3) / 2 = 2
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo.AnonymousClass", CoreMetrics.FUNCTION_COMPLEXITY_KEY).getValue(), is(2.0));
+
+    // ContainsInnerClasses: 5/4
+    // Helloworld: 6/2
+    // AnonymousClass: 4/2
+    // => 15/8=1.875
+    // BUG http://jira.codehaus.org/browse/SONAR-2152
+    // Should use sum of method complexity, not class complexity.
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.FUNCTION_COMPLEXITY_KEY).getValue(), is(1.9));
+    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.FUNCTION_COMPLEXITY_KEY).getValue(), is(1.9));
   }
 
   @Test
@@ -76,23 +99,24 @@ public class JavaComplexityIT {
     // 1 + 1 + 3 => complexity 5/3
     assertThat(getMeasure("org.sonar.tests:java-complexity:foo.ContainsInnerClasses", CoreMetrics.CLASS_COMPLEXITY_KEY).getValue(), is(1.7));
 
-    // 1 + 1 + 3 + 6 => 11/4 = 2.75
-    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.CLASS_COMPLEXITY_KEY).getValue(), is(2.8));
+    // 1 + 1 + 3 + 6 + 0 + 4 => 15/6 = 2.5
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.CLASS_COMPLEXITY_KEY).getValue(), is(2.5));
   }
 
   @Test
   public void testDistributionOfClassComplexity() {
-    // 1 + 1 + 3 + 6 => 3 in range [0,5[ and 1 in range [5,10[
-    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY).getData(), is("0=3;5=1;10=0;20=0;30=0;60=0;90=0"));
-    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY).getData(), is("0=3;5=1;10=0;20=0;30=0;60=0;90=0"));
+    // 1 + 1 + 3 + 6 + 0 + 4 => 5 in range [0,5[ and 1 in range [5,10[
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY).getData(), is("0=5;5=1;10=0;20=0;30=0;60=0;90=0"));
+    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION_KEY).getData(), is("0=5;5=1;10=0;20=0;30=0;60=0;90=0"));
   }
 
   @Test
   public void testDistributionOfMethodComplexity() {
     // ContainsInnerClasses: 1+ 1 + 2 + 1
     // Helloworld: 1 + 3 (static block is not a method)
-    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY).getData(), is("1=4;2=2;4=0;6=0;8=0;10=0;12=0"));
-    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY).getData(), is("1=4;2=2;4=0;6=0;8=0;10=0;12=0"));
+    // Anonymous class : 1 + 3
+    assertThat(getMeasure("org.sonar.tests:java-complexity:foo", CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY).getData(), is("1=5;2=3;4=0;6=0;8=0;10=0;12=0"));
+    assertThat(getMeasure("org.sonar.tests:java-complexity", CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY).getData(), is("1=5;2=3;4=0;6=0;8=0;10=0;12=0"));
   }
 
   @Test
index 2724b24db7f84e169c6749d5353551ed13905101..d608b39bfd8b08314e0b0cb80fb36ea7ee9ec5df 100644 (file)
@@ -99,7 +99,7 @@ public class Struts139IT {
   public void sizeMetrics() {
     assertThat(getProjectMeasure("lines").getIntValue(), is(114621));
     assertThat(getProjectMeasure("ncloc").getIntValue(), is(50080));
-    assertThat(getProjectMeasure("functions").getIntValue(), is(4292));
+    assertThat(getProjectMeasure("functions").getIntValue(), is(4234));
     assertThat(getProjectMeasure("accessors").getIntValue(), is(1133));
     assertThat(getProjectMeasure("classes").getIntValue(), is(518));
     assertThat(getProjectMeasure("packages").getIntValue(), is(49));
@@ -134,8 +134,8 @@ public class Struts139IT {
   @Test
   public void classComplexityDistribution() throws Exception {
     assertThat(sonar.find(ResourceQuery.createForMetrics("org.apache.struts:struts-core:org.apache.struts.config", "class_complexity_distribution")).getMeasure("class_complexity_distribution").getData(), is("0=10;5=3;10=2;20=1;30=4;60=4;90=1"));
-    assertThat(getCoreModuleMeasure("class_complexity_distribution").getData(), is("0=49;5=26;10=24;20=14;30=18;60=9;90=10"));
-    assertThat(getProjectMeasure("class_complexity_distribution").getData(), is("0=173;5=90;10=86;20=55;30=69;60=34;90=17"));
+    assertThat(getCoreModuleMeasure("class_complexity_distribution").getData(), is("0=47;5=26;10=24;20=12;30=18;60=9;90=10"));
+    assertThat(getProjectMeasure("class_complexity_distribution").getData(), is("0=171;5=90;10=84;20=53;30=69;60=34;90=17"));
   }
 
   @Test