diff --git a/1 b/1 deleted file mode 100644 index e69de29bb..000000000 diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetricKey.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetricKey.java index 211f2824d..544af3663 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetricKey.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetricKey.java @@ -6,7 +6,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.metrics.impl.AtfdMetric.AtfdClassMetric; -import net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric.CycloClassMetric; import net.sourceforge.pmd.lang.java.metrics.impl.LocMetric.LocClassMetric; import net.sourceforge.pmd.lang.java.metrics.impl.NcssMetric.NcssClassMetric; import net.sourceforge.pmd.lang.java.metrics.impl.WmcMetric; @@ -31,13 +30,6 @@ public enum JavaClassMetricKey implements MetricKey { */ WMC(new WmcMetric()), - /** - * Cyclomatic complexity. - * - * @see net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric - */ - CYCLO(new CycloClassMetric()), - /** * Non Commenting Source Statements. * diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetricKey.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetricKey.java index a6236e6cd..152a3bf4d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetricKey.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetricKey.java @@ -6,7 +6,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.metrics.impl.AtfdMetric.AtfdOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric.CycloOperationMetric; +import net.sourceforge.pmd.lang.java.metrics.impl.CycloMetric; import net.sourceforge.pmd.lang.java.metrics.impl.LocMetric.LocOperationMetric; import net.sourceforge.pmd.lang.java.metrics.impl.NcssMetric.NcssOperationMetric; import net.sourceforge.pmd.lang.java.metrics.impl.NpathMetric; @@ -27,9 +27,9 @@ public enum JavaOperationMetricKey implements MetricKey VERSION_MAP; @@ -54,26 +49,23 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { "cycloVersion", "Choose a variant of Cyclo or the standard", VERSION_MAP, Version.STANDARD, MetricVersion.class, 3.0f); - private int reportLevel; - private boolean reportClasses = true; - private boolean reportMethods = true; + private int methodReportLevel; + private int classReportLevel; private MetricVersion cycloVersion = Version.STANDARD; public CyclomaticComplexityRule() { - definePropertyDescriptor(REPORT_LEVEL_DESCRIPTOR); - definePropertyDescriptor(REPORT_CLASSES_DESCRIPTOR); - definePropertyDescriptor(REPORT_METHODS_DESCRIPTOR); + definePropertyDescriptor(CLASS_LEVEL_DESCRIPTOR); + definePropertyDescriptor(METHOD_LEVEL_DESCRIPTOR); definePropertyDescriptor(CYCLO_VERSION_DESCRIPTOR); } @Override public Object visit(ASTCompilationUnit node, Object data) { - reportLevel = getProperty(REPORT_LEVEL_DESCRIPTOR); + methodReportLevel = getProperty(METHOD_LEVEL_DESCRIPTOR); + classReportLevel = getProperty(CLASS_LEVEL_DESCRIPTOR); cycloVersion = getProperty(CYCLO_VERSION_DESCRIPTOR); - reportClasses = getProperty(REPORT_CLASSES_DESCRIPTOR); - reportMethods = getProperty(REPORT_METHODS_DESCRIPTOR); super.visit(node, data); return data; @@ -85,14 +77,16 @@ public Object visit(ASTAnyTypeDeclaration node, Object data) { super.visit(node, data); - if (reportClasses && JavaClassMetricKey.CYCLO.supports(node)) { - int classCyclo = (int) JavaMetrics.get(JavaClassMetricKey.CYCLO, node, cycloVersion); - int classHighest = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, node, cycloVersion, ResultOption.HIGHEST); + if (JavaClassMetricKey.WMC.supports(node)) { + int classWmc = (int) JavaMetrics.get(JavaClassMetricKey.WMC, node, cycloVersion); + + if (classWmc >= classReportLevel) { + int classHighest = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, node, cycloVersion, ResultOption.HIGHEST); - if (classCyclo >= reportLevel || classHighest >= reportLevel) { String[] messageParams = {node.getTypeKind().name().toLowerCase(), node.getImage(), - classCyclo + " (Highest = " + classHighest + ")", }; + " total", + classWmc + " (highest " + classHighest + ")", }; addViolation(data, node, messageParams); } @@ -104,13 +98,14 @@ public Object visit(ASTAnyTypeDeclaration node, Object data) { @Override public final Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - if (reportMethods) { - int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, node, cycloVersion); - if (cyclo >= reportLevel) { - addViolation(data, node, new String[] {node instanceof ASTMethodDeclaration ? "method" : "constructor", - node.getQualifiedName().getOperation(), "" + cyclo, }); - } + int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, node, cycloVersion); + if (cyclo >= methodReportLevel) { + addViolation(data, node, new String[] {node instanceof ASTMethodDeclaration ? "method" : "constructor", + node.getQualifiedName().getOperation(), + "", + "" + cyclo, }); } + return data; } diff --git a/pmd-java/src/main/resources/rulesets/java/metrics.xml b/pmd-java/src/main/resources/rulesets/java/metrics.xml index 5a35fb5bb..5a7961176 100644 --- a/pmd-java/src/main/resources/rulesets/java/metrics.xml +++ b/pmd-java/src/main/resources/rulesets/java/metrics.xml @@ -10,7 +10,7 @@ = 10. + Additionnally, classes with many methods of moderate complexity get reported as well once the total of their + methods' complexities reaches 80, even if none of the methods was directly reported. Reported methods should be broken down into several smaller methods. Reported classes should probably be broken down into subcomponents.]]> diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java index fa3ece822..8024c3fc0 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java @@ -20,7 +20,7 @@ public class CycloTestRule extends AbstractMetricTestRule { @Override protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.CYCLO; + return null; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml index e7302c2c1..689d89ca5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml @@ -66,21 +66,19 @@ Complicated method - Standard - 3 + 2 - '.Complicated' has value 13 highest 21. '.Complicated#exception()' has value 4. - '.Complicated#example()' has value 21. + '.Complicated#example()' has value 23. Complicated method - Ignore boolean path version - 3 + 2 ignoreBooleanPaths - '.Complicated' has value 10 highest 14. '.Complicated#exception()' has value 4. '.Complicated#example()' has value 14. @@ -103,21 +101,6 @@ - - Empty class should count 0 - 1 - - '.Foo' has value 0 highest 0. - - - - - - - - #984 Cyclomatic complexity should treat constructors like methods - + #984 Cyclomatic complexity should treat constructors like methods false 1 @@ -201,25 +183,19 @@ - Interfaces are not supported - 0 - - - - - - - Avoid division by 0 when averaging a metric over no operations - -1 + Ternary expression counts 1 + boolean complexity 1 - '.Foo' has value NaN. + + '.Foo#bar()' has value 3. + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/metrics/xml/CyclomaticComplexity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/metrics/xml/CyclomaticComplexity.xml index 98288e590..e134bd68c 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/metrics/xml/CyclomaticComplexity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/metrics/xml/CyclomaticComplexity.xml @@ -1,7 +1,7 @@ - + Simple method - 1 + 1 + 1 2 - The class 'Foo' has a Cyclomatic Complexity of 2 (Highest = 1). - The method 'foo()' has a Cyclomatic Complexity of 1. + The class 'Foo' has a total cyclomatic complexity of 1 (highest 1). + The method 'foo()' has a cyclomatic complexity of 1. testLessComplicatedThanReportLevel - 10 0 Complicated method - 10 - 2 + 1 - The class 'Complicated' has a Cyclomatic Complexity of 18 (Highest = 17). - The method 'example()' has a Cyclomatic Complexity of 17. + The method 'example()' has a cyclomatic complexity of 17. - + Complicated method (ignoreBooleanPath) - 10 ignoreBooleanPaths - 2 + 1 - The class 'Complicated' has a Cyclomatic Complexity of 11 (Highest = 10). - The method 'example()' has a Cyclomatic Complexity of 10. + The method 'example()' has a cyclomatic complexity of 10. - + Constructor - 1 - 2 + 1 + 1 - The class 'Foo' has a Cyclomatic Complexity of 2 (Highest = 1). - The constructor 'Foo()' has a Cyclomatic Complexity of 1. + The constructor 'Foo()' has a cyclomatic complexity of 1. - Testing new parameter showClassMethods - false + Test class report level + 17 + 999 1 - + - Testing new parameter showMethodsMethods - false + Test method report level + 999 + 17 1 - - - - - Testing default value of showClassMethods and reportClasses - 2 - + @@ -152,29 +143,22 @@ - #984 Cyclomatic complexity should treat constructors like methods: 1 - reportMethods=true - - false - true - 1 + #984 Cyclomatic complexity should treat constructors like methods: 1 - reportMethods=true + 1 1 - #984 Cyclomatic complexity should treat constructors like methods: 2 - - reportMethods=false - - false - false - 1 + #984 Cyclomatic complexity should treat constructors like methods: 2 -reportMethods=false + 999 0 #985 Suppressed methods shouldn't affect avg CyclomaticComplexity - 2 + 2 0 Standard Cyclo should count empty switch labels too - false - true - 2 + 2 1 - The method 'switchCase()' has a Cyclomatic Complexity of 3. + The method 'switchCase()' has a cyclomatic complexity of 3. IgnoreBooleanPaths Cyclo should not count empty switch labels - false - true ignoreBooleanPaths - 2 + 2 1 - The method 'switchCase()' has a Cyclomatic Complexity of 2. + The method 'switchCase()' has a cyclomatic complexity of 2. @@ -253,37 +233,222 @@ Standard Cyclo should count boolean paths - false - 2 + 2 1 - The method 'foo()' has a Cyclomatic Complexity of 8. + The method 'foo()' has a cyclomatic complexity of 8. IgnoreBooleanPaths Cyclo should not count boolean paths - false ignoreBooleanPaths - 2 + 2 1 - The method 'foo()' has a Cyclomatic Complexity of 4. + The method 'foo()' has a cyclomatic complexity of 4. + + + + - Avoid division by 0 when averaging a metric over no operations - -1 + + Test many unreported methods 1 - - - - + + The class 'Complicated' has a total cyclomatic complexity of 80 (highest 8). + + diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index d301c0083..0fc7526c0 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -167,4 +167,5 @@ All existing rules have been updated to reflect these changes. If you have custo * [#545](https://github.com/pmd/pmd/pull/545): \[apex] Apex metrics framework - [Clément Fournier](https://github.com/oowekyala) * [#548](https://github.com/pmd/pmd/pull/548): \[java] Metrics documentation - [Clément Fournier](https://github.com/oowekyala) * [#550](https://github.com/pmd/pmd/pull/550): \[java] Add basic resolution to type inference - [Bendegúz Nagy](https://github.com/WinterGrascph) +* [#555](https://github.com/pmd/pmd/pull/555): \[java] Changed metrics/CyclomaticComplexityRule to use WMC when reporting classes - [Clément Fournier](https://github.com/oowekyala)