From 08544a7539624689f235042892ee7e17105deb1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 20 Jan 2020 21:45:08 +0100 Subject: [PATCH] Throw on metric not supported --- .../pmd/lang/apex/metrics/ApexMetrics.java | 8 +-- .../rule/design/CyclomaticComplexityRule.java | 20 +++--- .../impl/AbstractApexMetricTestRule.java | 5 +- .../pmd/lang/metrics/MetricsUtil.java | 51 +++++++++++++-- .../pmd/lang/java/metrics/JavaMetrics.java | 8 +-- .../rule/design/CyclomaticComplexityRule.java | 27 ++++---- .../lang/java/rule/design/DataClassRule.java | 28 ++++++--- .../lang/java/rule/design/GodClassRule.java | 15 +++-- .../java/rule/design/NPathComplexityRule.java | 12 ++-- .../lang/java/rule/design/NcssCountRule.java | 62 +++++++++---------- .../pmd/lang/java/xpath/MetricFunction.java | 9 ++- 11 files changed, 156 insertions(+), 89 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java index 8ac1fe2bb9..d8dd2ec984 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java @@ -55,7 +55,7 @@ public final class ApexMetrics { * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed */ public static double get(MetricKey> key, ASTUserClass node) { - return MetricsUtil.computeMetric(key, node, MetricOptions.emptyOptions()); + return get(key, node, MetricOptions.emptyOptions()); } @@ -70,7 +70,7 @@ public final class ApexMetrics { * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed */ public static double get(MetricKey> key, ASTUserClass node, MetricOptions options) { - return MetricsUtil.computeMetric(key, node, options); + return MetricsUtil.computeMetricOrNaN(key, node, options); } @@ -83,7 +83,7 @@ public final class ApexMetrics { * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed */ public static double get(MetricKey key, ASTMethod node) { - return MetricsUtil.computeMetric(key, node, MetricOptions.emptyOptions()); + return get(key, node, MetricOptions.emptyOptions()); } @@ -98,7 +98,7 @@ public final class ApexMetrics { * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed */ public static double get(MetricKey key, ASTMethod node, MetricOptions options) { - return MetricsUtil.computeMetric(key, node, options); + return MetricsUtil.computeMetricOrNaN(key, node, options); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityRule.java index a10676b530..c742a7e7f4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityRule.java @@ -90,16 +90,18 @@ public class CyclomaticComplexityRule extends AbstractApexRule { @Override public final Object visit(ASTMethod node, Object data) { - int cyclo = (int) MetricsUtil.computeMetric(ApexOperationMetricKey.CYCLO, node); - if (cyclo >= getProperty(METHOD_LEVEL_DESCRIPTOR)) { - String opType = inTrigger ? "trigger" - : node.getImage().equals(classNames.peek()) ? "constructor" - : "method"; + if (ApexOperationMetricKey.CYCLO.supports(node)) { + int cyclo = (int) MetricsUtil.computeMetric(ApexOperationMetricKey.CYCLO, node); + if (cyclo >= getProperty(METHOD_LEVEL_DESCRIPTOR)) { + String opType = inTrigger ? "trigger" + : node.getImage().equals(classNames.peek()) ? "constructor" + : "method"; - addViolation(data, node, new String[]{opType, - node.getQualifiedName().getOperation(), - "", - "" + cyclo, }); + addViolation(data, node, new String[] {opType, + node.getQualifiedName().getOperation(), + "", + "" + cyclo, }); + } } return data; diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java index 290ffa897e..e63478a0df 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java @@ -16,6 +16,7 @@ import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.lang.metrics.MetricOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.lang.metrics.ResultOption; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -134,7 +135,7 @@ public abstract class AbstractApexMetricTestRule extends AbstractApexRule { } if (classKey != null && reportClasses && classKey.supports(node)) { - int classValue = (int) ApexMetrics.get(classKey, node, metricOptions); + int classValue = (int) MetricsUtil.computeMetric(classKey, node, metricOptions); String valueReport = String.valueOf(classValue); @@ -153,7 +154,7 @@ public abstract class AbstractApexMetricTestRule extends AbstractApexRule { @Override public Object visit(ASTMethod node, Object data) { if (opKey != null && reportMethods && opKey.supports(node)) { - int methodValue = (int) ApexMetrics.get(opKey, node, metricOptions); + int methodValue = (int) MetricsUtil.computeMetric(opKey, node, metricOptions); if (methodValue >= reportLevel) { addViolation(data, node, new String[] {node.getQualifiedName().toString(), "" + methodValue}); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsUtil.java index 65db7403ab..39c108721a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsUtil.java @@ -23,6 +23,15 @@ public final class MetricsUtil { // util class } + public static boolean supportsAll(N node, MetricKey... metrics) { + for (MetricKey metric : metrics) { + if (!metric.supports(node)) { + return false; + } + } + return true; + } + public static double computeAggregate(MetricKey key, Iterable ops, ResultOption resultOption) { return computeAggregate(key, ops, MetricOptions.emptyOptions(), resultOption); } @@ -50,9 +59,7 @@ public final class MetricsUtil { for (O op : ops) { if (key.supports(op)) { double val = computeMetric(key, op, options); - if (!Double.isNaN(val)) { - values.add(val); - } + values.add(val); } } @@ -65,7 +72,7 @@ public final class MetricsUtil { case AVERAGE: return average(values); default: - return Double.NaN; + throw new IllegalArgumentException("Unknown result option " + resultOption); } } @@ -90,6 +97,33 @@ public final class MetricsUtil { * @param options The options of the metric * * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed + * + * @deprecated This is provided for compatibility with pre 6.21.0 + * behavior. Users of a metric should always check beforehand if + * the metric supports the argument. + */ + @Deprecated + public static double computeMetricOrNaN(MetricKey key, N node, MetricOptions options) { + if (!key.supports(node)) { + return Double.NaN; + } + return computeMetric(key, node, options, false); + } + + /** + * Computes a metric identified by its code on a node, possibly + * selecting a variant with the {@code options} parameter. + * + *

Note that contrary to the previous behaviour, this method + * throws an exception if the metric does not support the node. + * + * @param key The key identifying the metric to be computed + * @param node The node on which to compute the metric + * @param options The options of the metric + * + * @return The value of the metric + * + * @throws IllegalArgumentException If the metric does not support the given node */ public static double computeMetric(MetricKey key, N node, MetricOptions options) { return computeMetric(key, node, options, false); @@ -99,12 +133,17 @@ public final class MetricsUtil { * Computes a metric identified by its code on a node, possibly * selecting a variant with the {@code options} parameter. * + *

Note that contrary to the previous behaviour, this method + * throws an exception if the metric does not support the node. + * * @param key The key identifying the metric to be computed * @param node The node on which to compute the metric * @param options The options of the metric * @param forceRecompute Force recomputation of the result * - * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed + * @return The value of the metric + * + * @throws IllegalArgumentException If the metric does not support the given node */ public static double computeMetric(MetricKey key, N node, MetricOptions options, boolean forceRecompute) { Objects.requireNonNull(key, NULL_KEY_MESSAGE); @@ -113,7 +152,7 @@ public final class MetricsUtil { if (!key.supports(node)) { - return Double.NaN; + throw new IllegalArgumentException(key + " cannot be computed on " + node); } ParameterizedMetricKey paramKey = ParameterizedMetricKey.getInstance(key, options); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java index 2f70a75931..800f732a8b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java @@ -42,7 +42,7 @@ public final class JavaMetrics { * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed */ public static double get(MetricKey key, ASTAnyTypeDeclaration node) { - return MetricsUtil.computeMetric(key, node); + return get(key, node, MetricOptions.emptyOptions()); } @@ -57,7 +57,7 @@ public final class JavaMetrics { * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed */ public static double get(MetricKey key, ASTAnyTypeDeclaration node, MetricOptions options) { - return MetricsUtil.computeMetric(key, node, options); + return MetricsUtil.computeMetricOrNaN(key, node, options); } @@ -70,7 +70,7 @@ public final class JavaMetrics { * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed */ public static double get(MetricKey key, MethodLikeNode node) { - return MetricsUtil.computeMetric(key, node); + return get(key, node, MetricOptions.emptyOptions()); } @@ -104,7 +104,7 @@ public final class JavaMetrics { * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed */ public static double get(MetricKey key, MethodLikeNode node, MetricOptions options) { - return MetricsUtil.computeMetric(key, node, options); + return MetricsUtil.computeMetricOrNaN(key, node, options); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java index 4a2c2167c8..60de77b4ac 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java @@ -145,25 +145,26 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { @Override public final Object visit(MethodLikeNode node, Object data) { - int cyclo = (int) MetricsUtil.computeMetric(JavaOperationMetricKey.CYCLO, node, cycloOptions); - if (cyclo >= methodReportLevel) { + if (JavaOperationMetricKey.CYCLO.supports(node)) { + int cyclo = (int) MetricsUtil.computeMetric(JavaOperationMetricKey.CYCLO, node, cycloOptions); + if (cyclo >= methodReportLevel) { - String opname = node instanceof ASTMethodOrConstructorDeclaration - ? PrettyPrintingUtil.displaySignature((ASTMethodOrConstructorDeclaration) node) - : "lambda"; + String opname = node instanceof ASTMethodOrConstructorDeclaration + ? PrettyPrintingUtil.displaySignature((ASTMethodOrConstructorDeclaration) node) + : "lambda"; - String kindname = node instanceof ASTMethodOrConstructorDeclaration - ? node instanceof ASTConstructorDeclaration ? "constructor" : "method" - : "lambda"; + String kindname = node instanceof ASTMethodOrConstructorDeclaration + ? node instanceof ASTConstructorDeclaration ? "constructor" : "method" + : "lambda"; - addViolation(data, node, new String[] {kindname, - opname, - "", - "" + cyclo, }); + addViolation(data, node, new String[] {kindname, + opname, + "", + "" + cyclo, }); + } } - return data; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/DataClassRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/DataClassRule.java index 608fa7f9d6..09072cae8c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/DataClassRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/DataClassRule.java @@ -4,8 +4,12 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey.NOAM; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey.NOPA; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey.WMC; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey.WOC; + import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.util.StringUtil; @@ -27,13 +31,17 @@ public class DataClassRule extends AbstractJavaMetricsRule { @Override public Object visit(ASTAnyTypeDeclaration node, Object data) { + if (!MetricsUtil.supportsAll(node, NOAM, NOPA, WMC, WOC)) { + return super.visit(node, data); + } + boolean isDataClass = interfaceRevealsData(node) && classRevealsDataAndLacksComplexity(node); if (isDataClass) { - double woc = MetricsUtil.computeMetric(JavaClassMetricKey.WOC, node); - int nopa = (int) MetricsUtil.computeMetric(JavaClassMetricKey.NOPA, node); - int noam = (int) MetricsUtil.computeMetric(JavaClassMetricKey.NOAM, node); - int wmc = (int) MetricsUtil.computeMetric(JavaClassMetricKey.WMC, node); + double woc = MetricsUtil.computeMetric(WOC, node); + int nopa = (int) MetricsUtil.computeMetric(NOPA, node); + int noam = (int) MetricsUtil.computeMetric(NOAM, node); + int wmc = (int) MetricsUtil.computeMetric(WMC, node); addViolation(data, node, new Object[] {node.getSimpleName(), StringUtil.percentageString(woc, 3), @@ -45,15 +53,15 @@ public class DataClassRule extends AbstractJavaMetricsRule { private boolean interfaceRevealsData(ASTAnyTypeDeclaration node) { - double woc = MetricsUtil.computeMetric(JavaClassMetricKey.WOC, node); + double woc = MetricsUtil.computeMetric(WOC, node); return woc < WOC_LEVEL; } - private boolean classRevealsDataAndLacksComplexity(ASTAnyTypeDeclaration node) { - int nopa = (int) MetricsUtil.computeMetric(JavaClassMetricKey.NOPA, node); - int noam = (int) MetricsUtil.computeMetric(JavaClassMetricKey.NOAM, node); - int wmc = (int) MetricsUtil.computeMetric(JavaClassMetricKey.WMC, node); + + int nopa = (int) MetricsUtil.computeMetric(NOPA, node); + int noam = (int) MetricsUtil.computeMetric(NOAM, node); + int wmc = (int) MetricsUtil.computeMetric(WMC, node); return nopa + noam > ACCESSOR_OR_FIELD_FEW_LEVEL && wmc < WMC_HIGH_LEVEL || nopa + noam > ACCESSOR_OR_FIELD_MANY_LEVEL && wmc < WMC_VERY_HIGH_LEVEL; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java index 38f309fa74..e019eaa3c9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java @@ -5,8 +5,11 @@ package net.sourceforge.pmd.lang.java.rule.design; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey.ATFD; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey.TCC; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey.WMC; + import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.util.StringUtil; @@ -41,9 +44,13 @@ public class GodClassRule extends AbstractJavaRule { @Override public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { - int wmc = (int) MetricsUtil.computeMetric(JavaClassMetricKey.WMC, node); - double tcc = MetricsUtil.computeMetric(JavaClassMetricKey.TCC, node); - int atfd = (int) MetricsUtil.computeMetric(JavaClassMetricKey.ATFD, node); + if (!MetricsUtil.supportsAll(node, WMC, TCC, ATFD)) { + return super.visit(node, data); + } + + int wmc = (int) MetricsUtil.computeMetric(WMC, node); + double tcc = MetricsUtil.computeMetric(TCC, node); + int atfd = (int) MetricsUtil.computeMetric(ATFD, node); super.visit(node, data); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java index 37c8774949..9260ae6b4f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java @@ -31,8 +31,8 @@ public class NPathComplexityRule extends AbstractJavaMetricsRule { @Deprecated private static final PropertyDescriptor MINIMUM_DESCRIPTOR - = PropertyFactory.doubleProperty("minimum").desc("Deprecated! Minimum reporting threshold") - .require(positive()).defaultValue(200d).build(); + = PropertyFactory.doubleProperty("minimum").desc("Deprecated! Minimum reporting threshold") + .require(positive()).defaultValue(200d).build(); private static final PropertyDescriptor REPORT_LEVEL_DESCRIPTOR @@ -71,10 +71,14 @@ public class NPathComplexityRule extends AbstractJavaMetricsRule { @Override public final Object visit(ASTMethodOrConstructorDeclaration node, Object data) { + if (!JavaOperationMetricKey.NPATH.supports(node)) { + return data; + } + int npath = (int) MetricsUtil.computeMetric(JavaOperationMetricKey.NPATH, node); if (npath >= reportLevel) { - addViolation(data, node, new String[]{node instanceof ASTMethodDeclaration ? "method" : "constructor", - PrettyPrintingUtil.displaySignature(node), "" + npath, }); + addViolation(data, node, new String[] {node instanceof ASTMethodDeclaration ? "method" : "constructor", + PrettyPrintingUtil.displaySignature(node), "" + npath, }); } return data; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java index b2dc4b0642..f457967747 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java @@ -15,6 +15,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; +import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; @@ -37,40 +38,37 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { private static final PropertyDescriptor METHOD_REPORT_LEVEL_DESCRIPTOR = - PropertyFactory.intProperty("methodReportLevel") - .desc("NCSS reporting threshold for methods") - .require(positive()) - .defaultValue(60) - .build(); + PropertyFactory.intProperty("methodReportLevel") + .desc("NCSS reporting threshold for methods") + .require(positive()) + .defaultValue(60) + .build(); private static final PropertyDescriptor CLASS_REPORT_LEVEL_DESCRIPTOR = - PropertyFactory.intProperty("classReportLevel") - .desc("NCSS reporting threshold for classes") - .require(positive()) - .defaultValue(1500) - .build(); - - private static final Map OPTION_MAP; - - - static { - OPTION_MAP = new HashMap<>(); - OPTION_MAP.put(NcssOption.COUNT_IMPORTS.valueName(), NcssOption.COUNT_IMPORTS); - } - - - private static final PropertyDescriptor> NCSS_OPTIONS_DESCRIPTOR = - PropertyFactory.enumListProperty("ncssOptions", OPTION_MAP) - .desc("Choose options for the computation of Ncss") - .emptyDefaultValue() - .build(); - + PropertyFactory.intProperty("classReportLevel") + .desc("NCSS reporting threshold for classes") + .require(positive()) + .defaultValue(1500) + .build(); + private static final PropertyDescriptor> NCSS_OPTIONS_DESCRIPTOR; private int methodReportLevel; private int classReportLevel; private MetricOptions ncssOptions; + static { + Map options = new HashMap<>(); + options.put(NcssOption.COUNT_IMPORTS.valueName(), NcssOption.COUNT_IMPORTS); + + NCSS_OPTIONS_DESCRIPTOR = PropertyFactory.enumListProperty("ncssOptions", options) + .desc("Choose options for the computation of Ncss") + .emptyDefaultValue() + .build(); + + } + + public NcssCountRule() { definePropertyDescriptor(METHOD_REPORT_LEVEL_DESCRIPTOR); definePropertyDescriptor(CLASS_REPORT_LEVEL_DESCRIPTOR); @@ -113,12 +111,14 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { @Override public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - int methodSize = (int) MetricsUtil.computeMetric(JavaOperationMetricKey.NCSS, node, ncssOptions); - if (methodSize >= methodReportLevel) { - addViolation(data, node, new String[] {node instanceof ASTMethodDeclaration ? "method" : "constructor", - PrettyPrintingUtil.displaySignature(node), "" + methodSize, }); + if (JavaOperationMetricKey.NCSS.supports((MethodLikeNode) node)) { + int methodSize = (int) MetricsUtil.computeMetric(JavaOperationMetricKey.NCSS, node, ncssOptions); + if (methodSize >= methodReportLevel) { + addViolation(data, node, new String[] { + node instanceof ASTMethodDeclaration ? "method" : "constructor", + PrettyPrintingUtil.displaySignature(node), "" + methodSize, }); + } } - return data; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/MetricFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/MetricFunction.java index 5969ff7780..03de85754d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/MetricFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/xpath/MetricFunction.java @@ -21,6 +21,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.metrics.MetricKey; import net.sourceforge.pmd.lang.metrics.MetricsUtil; @@ -82,14 +83,18 @@ public class MetricFunction implements Function { public static double getMetric(Node n, String metricKeyName) { if (n instanceof ASTAnyTypeDeclaration) { - return MetricsUtil.computeMetric(getClassMetricKey(metricKeyName), (ASTAnyTypeDeclaration) n); + return computeMetric(getClassMetricKey(metricKeyName), (ASTAnyTypeDeclaration) n); } else if (n instanceof MethodLikeNode) { - return MetricsUtil.computeMetric(getOperationMetricKey(metricKeyName), (MethodLikeNode) n); + return computeMetric(getOperationMetricKey(metricKeyName), (MethodLikeNode) n); } else { throw new IllegalStateException(genericBadNodeMessage()); } } + private static double computeMetric(MetricKey metricKey, T n) { + return metricKey.supports(n) ? MetricsUtil.computeMetric(metricKey, n) : Double.NaN; + } + private static JavaClassMetricKey getClassMetricKey(String s) { String constantName = s.toUpperCase(Locale.ROOT);