From 2123ab3d5d7dcfc867ada3af119c3d3e9cb6183e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 19 Jan 2020 11:41:42 +0100 Subject: [PATCH] Simplify metrics framework --- docs/pages/release_notes.md | 6 + .../pmd/lang/apex/metrics/ApexMetrics.java | 46 ++++-- .../apex/metrics/ApexMetricsComputer.java | 17 +- .../lang/apex/metrics/ApexMetricsFacade.java | 8 +- .../apex/metrics/ApexMetricsProvider.java | 12 +- .../rule/design/CyclomaticComplexityRule.java | 7 +- .../lang/apex/metrics/ApexMetricsHook.java | 25 --- .../apex/metrics/ApexProjectMirrorTest.java | 12 +- .../apex/metrics/impl/AllMetricsTest.java | 10 -- .../rule/design/CyclomaticComplexityTest.java | 7 - .../net/sourceforge/pmd/lang/ast/Node.java | 2 + .../pmd/lang/ast/QualifiableNode.java | 3 + .../pmd/lang/ast/QualifiedName.java | 2 + .../lang/metrics/AbstractMetricsComputer.java | 77 +-------- .../lang/metrics/AbstractMetricsFacade.java | 47 +----- .../pmd/lang/metrics/BasicMetricMemoizer.java | 2 + .../lang/metrics/BasicProjectMemoizer.java | 3 + .../lang/metrics/LanguageMetricsProvider.java | 6 - .../pmd/lang/metrics/MetricKey.java | 3 +- .../pmd/lang/metrics/MetricMemoizer.java | 2 + .../pmd/lang/metrics/MetricsComputer.java | 2 + .../pmd/lang/metrics/MetricsUtil.java | 155 ++++++++++++++++++ .../lang/metrics/ParameterizedMetricKey.java | 8 +- .../pmd/lang/metrics/ProjectMemoizer.java | 2 + .../AbstractLanguageMetricsProvider.java | 18 +- .../metrics/internal/DummyMetricMemoizer.java | 44 ----- .../internal/DummyProjectMemoizer.java | 45 ----- .../pmd/lang/metrics/package-info.java | 16 ++ .../pmd/processor/AbstractPMDProcessor.java | 26 +-- .../net/sourceforge/pmd/util/DataMap.java | 9 +- .../pmd/lang/java/metrics/JavaMetrics.java | 54 +++--- .../java/metrics/JavaMetricsComputer.java | 26 +-- .../lang/java/metrics/JavaMetricsFacade.java | 39 ----- .../java/metrics/JavaMetricsProvider.java | 12 +- .../java/metrics/JavaProjectMemoizer.java | 18 -- .../impl/AbstractJavaOperationMetric.java | 1 + .../rule/design/CyclomaticComplexityRule.java | 5 +- .../lang/java/rule/design/DataClassRule.java | 18 +- .../lang/java/rule/design/GodClassRule.java | 8 +- .../java/rule/design/NPathComplexityRule.java | 5 +- .../lang/java/rule/design/NcssCountRule.java | 5 +- .../pmd/lang/java/xpath/MetricFunction.java | 16 +- .../pmd/lang/java/metrics/MetricsHook.java | 23 --- .../java/metrics/ProjectMemoizerTest.java | 12 +- .../metrics/impl/AbstractMetricTestRule.java | 5 +- .../java/metrics/impl/AllMetricsTest.java | 10 -- .../rule/design/CyclomaticComplexityTest.java | 7 - .../java/rule/design/NPathComplexityTest.java | 7 - .../lang/java/rule/design/NcssCountTest.java | 7 - 49 files changed, 357 insertions(+), 543 deletions(-) delete mode 100644 pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsHook.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsUtil.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/DummyMetricMemoizer.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/DummyProjectMemoizer.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/package-info.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsFacade.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaProjectMemoizer.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/MetricsHook.java diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 69bf8669f2..4849eb3e9a 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -135,6 +135,10 @@ methods on {% jdoc apex::lang.apex.ast.ApexParserVisitor %} and its implementati * Many methods on the {% jdoc core::lang.ast.Node %} interface and {% jdoc core::lang.ast.AbstractNode %} base class. See their javadoc for details. * {% jdoc !!core::lang.ast.Node#isFindBoundary() %} is deprecated for XPath queries. + * Many APIs of {% jdoc_package core::lang.metrics %}, though most of them were internal and + probably not used directly outside of PMD. Use {% jdoc core::lang.metrics.MetricsUtil %} as + a replacement for the language-specific façades too. + * {% jdoc core::lang.ast.QualifiableNode %}, {% jdoc core::lang.ast.QualifiedName %} * pmd-java * {% jdoc java::lang.java.AbstractJavaParser %} * {% jdoc java::lang.java.AbstractJavaHandler %} @@ -162,6 +166,8 @@ methods on {% jdoc apex::lang.apex.ast.ApexParserVisitor %} and its implementati following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression. * {% jdoc java::lang.java.ast.ASTYieldStatement %} will not implement {% jdoc java::lang.java.ast.TypeNode %} anymore come 7.0.0. Test the type of the expression nested within it. + * {% jdoc core::lang.java.metrics.JavaMetrics %}, {% jdoc core::lang.java.metrics.JavaMetricsComputer %}, + {% jdoc core::lang.java.metrics.JavaMetricsProvider %} ### External Contributions 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 30d1fae6a1..3b05c8e8ef 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 @@ -4,11 +4,17 @@ package net.sourceforge.pmd.lang.apex.metrics; +import java.util.ArrayList; +import java.util.List; + +import org.checkerframework.checker.nullness.qual.NonNull; + import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; import net.sourceforge.pmd.lang.metrics.MetricKey; import net.sourceforge.pmd.lang.metrics.MetricOptions; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.lang.metrics.ResultOption; /** @@ -16,7 +22,10 @@ import net.sourceforge.pmd.lang.metrics.ResultOption; * * @author Clément Fournier * @since 6.0.0 + * + * @deprecated Use {@link MetricsUtil} */ +@Deprecated public final class ApexMetrics { private static final ApexMetricsFacade FACADE = new ApexMetricsFacade(); @@ -32,20 +41,12 @@ public final class ApexMetrics { * * @return The facade */ + @Deprecated public static ApexMetricsFacade getFacade() { return FACADE; } - /** - * Resets the entire data structure. - * This needs to be done in case PMD is executed multiple times within one JVM run. - */ - static void reset() { - FACADE.reset(); - } - - /** * Computes the standard value of the metric identified by its code on a class AST node. * @@ -55,7 +56,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 FACADE.computeForType(key, node, MetricOptions.emptyOptions()); + return MetricsUtil.computeMetric(key, node, MetricOptions.emptyOptions()); } @@ -70,7 +71,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 FACADE.computeForType(key, node, options); + return MetricsUtil.computeMetric(key, node, options); } @@ -83,7 +84,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 FACADE.computeForOperation(key, node, MetricOptions.emptyOptions()); + return MetricsUtil.computeMetric(key, node, MetricOptions.emptyOptions()); } @@ -98,7 +99,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 FACADE.computeForOperation(key, node, options); + return MetricsUtil.computeMetric(key, node, options); } @@ -111,10 +112,10 @@ public final class ApexMetrics { * @param resultOption The result option to use * * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed or {@code option} is - * {@code null} + * {@code null} */ public static double get(MetricKey key, ASTUserClassOrInterface node, ResultOption resultOption) { - return FACADE.computeWithResultOption(key, node, MetricOptions.emptyOptions(), resultOption); + return MetricsUtil.computeAggregate(key, findOps(node), resultOption); } @@ -128,12 +129,23 @@ public final class ApexMetrics { * @param resultOption The result option to use * * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed or {@code option} is - * {@code null} + * {@code null} */ public static double get(MetricKey key, ASTUserClassOrInterface node, MetricOptions options, ResultOption resultOption) { - return FACADE.computeWithResultOption(key, node, options, resultOption); + return MetricsUtil.computeAggregate(key, findOps(node), options, resultOption); } + @NonNull + static List findOps(ASTUserClassOrInterface node) { + List candidates = node.findChildrenOfType(ASTMethod.class); + List result = new ArrayList<>(candidates); + for (ASTMethod method : candidates) { + if (method.getImage().matches("(||clone)")) { + result.remove(method); + } + } + return result; + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsComputer.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsComputer.java index 63ccc76f74..0092bc1394 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsComputer.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsComputer.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.metrics; -import java.util.ArrayList; import java.util.List; import net.sourceforge.pmd.annotation.InternalApi; @@ -21,22 +20,14 @@ public class ApexMetricsComputer extends AbstractMetricsComputer findOperations(ASTUserClassOrInterface node) { + return ApexMetrics.findOps(node); + } @InternalApi public static ApexMetricsComputer getInstance() { return INSTANCE; } - - @Override - protected List findOperations(ASTUserClassOrInterface node) { - List candidates = node.findChildrenOfType(ASTMethod.class); - List result = new ArrayList<>(candidates); - for (ASTMethod method : candidates) { - if (method.getImage().matches("(||clone)")) { - result.remove(method); - } - } - return result; - } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsFacade.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsFacade.java index 4ed4fa23d3..ddb45dcaa0 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsFacade.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsFacade.java @@ -13,18 +13,14 @@ import net.sourceforge.pmd.lang.metrics.MetricsComputer; * Backs the static façade. * * @author Clément Fournier + * @deprecated Not useful anymore */ +@Deprecated public class ApexMetricsFacade extends AbstractMetricsFacade, ASTMethod> { private final ApexProjectMemoizer memoizer = new ApexProjectMemoizer(); - /** Resets the entire project mirror. Used for tests. */ - void reset() { - memoizer.reset(); - } - - @Override protected MetricsComputer, ASTMethod> getLanguageSpecificComputer() { return ApexMetricsComputer.getInstance(); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsProvider.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsProvider.java index c3a227b24c..b7b5d852b4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsProvider.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsProvider.java @@ -18,12 +18,7 @@ public class ApexMetricsProvider extends AbstractLanguageMetricsProvider>) (Object) ASTUserClassOrInterface.class, ASTMethod.class, ApexMetricsComputer.getInstance()); - } - - @Override - public void initialize() { - ApexMetrics.reset(); + super((Class>) (Object) ASTUserClassOrInterface.class, ASTMethod.class); } @Override @@ -32,6 +27,11 @@ public class ApexMetricsProvider extends AbstractLanguageMetricsProvider findOps(ASTUserClassOrInterface astUserClassOrInterface) { + return ApexMetrics.findOps(astUserClassOrInterface); + } + @Override public List getAvailableOperationMetrics() { return Arrays.asList(ApexOperationMetricKey.values()); 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 8bb26c4d7b..a10676b530 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 @@ -16,6 +16,7 @@ import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics; import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; +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; @@ -23,7 +24,7 @@ import net.sourceforge.pmd.properties.PropertyFactory; /** * Cyclomatic complexity rule using metrics. Uses Wmc to report classes. - * + * * @author Clément Fournier */ public class CyclomaticComplexityRule extends AbstractApexRule { @@ -69,7 +70,7 @@ public class CyclomaticComplexityRule extends AbstractApexRule { classNames.pop(); if (ApexClassMetricKey.WMC.supports(node)) { - int classWmc = (int) ApexMetrics.get(ApexClassMetricKey.WMC, node); + int classWmc = (int) MetricsUtil.computeMetric(ApexClassMetricKey.WMC, node); if (classWmc >= getProperty(CLASS_LEVEL_DESCRIPTOR)) { int classHighest = (int) ApexMetrics.get(ApexOperationMetricKey.CYCLO, node, ResultOption.HIGHEST); @@ -89,7 +90,7 @@ public class CyclomaticComplexityRule extends AbstractApexRule { @Override public final Object visit(ASTMethod node, Object data) { - int cyclo = (int) ApexMetrics.get(ApexOperationMetricKey.CYCLO, 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" diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsHook.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsHook.java deleted file mode 100644 index c376addaab..0000000000 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetricsHook.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics; - - -/** - * Provides a hook into package-private methods of {@code apex.metrics}. - * - * @author Clément Fournier - */ -public class ApexMetricsHook { - - private ApexMetricsHook() { - - } - - - public static void reset() { - ApexMetrics.reset(); - } - - -} diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/ApexProjectMirrorTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/ApexProjectMirrorTest.java index 97832b1e2c..9fdb994e88 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/ApexProjectMirrorTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/ApexProjectMirrorTest.java @@ -24,8 +24,8 @@ import net.sourceforge.pmd.lang.apex.metrics.impl.AbstractApexClassMetric; import net.sourceforge.pmd.lang.apex.metrics.impl.AbstractApexOperationMetric; import net.sourceforge.pmd.lang.metrics.MetricKey; import net.sourceforge.pmd.lang.metrics.MetricKeyUtil; -import net.sourceforge.pmd.lang.metrics.MetricMemoizer; import net.sourceforge.pmd.lang.metrics.MetricOptions; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; import apex.jorje.semantic.ast.compilation.Compilation; @@ -71,25 +71,19 @@ public class ApexProjectMirrorTest extends ApexParserTestBase { private List visitWith(ApexNode acu, final boolean force) { - final ApexProjectMemoizer toplevel = ApexMetrics.getFacade().getLanguageSpecificProjectMemoizer(); - final List result = new ArrayList<>(); acu.jjtAccept(new ApexParserVisitorAdapter() { @Override public Object visit(ASTMethod node, Object data) { - MetricMemoizer op = toplevel.getOperationMemoizer(node.getQualifiedName()); - result.add((int) ApexMetricsComputer.getInstance().computeForOperation(opMetricKey, node, force, - MetricOptions.emptyOptions(), op)); + result.add((int) MetricsUtil.computeMetric(opMetricKey, node, MetricOptions.emptyOptions(), force)); return super.visit(node, data); } @Override public Object visit(ASTUserClass node, Object data) { - MetricMemoizer> clazz = toplevel.getClassMemoizer(node.getQualifiedName()); - result.add((int) ApexMetricsComputer.getInstance().computeForType(classMetricKey, node, force, - MetricOptions.emptyOptions(), clazz)); + result.add((int) MetricsUtil.computeMetric(classMetricKey, node, MetricOptions.emptyOptions(), force)); return super.visit(node, data); } }, null); diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AllMetricsTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AllMetricsTest.java index b11423671f..4f60d06fa6 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AllMetricsTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AllMetricsTest.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.metrics.impl; -import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.lang.apex.metrics.ApexMetricsHook; import net.sourceforge.pmd.testframework.SimpleAggregatorTst; /** @@ -18,14 +16,6 @@ public class AllMetricsTest extends SimpleAggregatorTst { private static final String RULESET = "rulesets/apex/metrics_test.xml"; - - @Override - protected Rule reinitializeRule(Rule rule) { - ApexMetricsHook.reset(); - return rule; - } - - @Override public void setUp() { addRule(RULESET, "CycloTest"); diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityTest.java index d667350887..50ffb556ea 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityTest.java @@ -4,14 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.design; -import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.lang.apex.metrics.ApexMetricsHook; import net.sourceforge.pmd.testframework.PmdRuleTst; public class CyclomaticComplexityTest extends PmdRuleTst { - @Override - protected Rule reinitializeRule(Rule rule) { - ApexMetricsHook.reset(); - return super.reinitializeRule(rule); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java index 03a7bcbcfc..22eb9b5fe8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java @@ -373,6 +373,7 @@ public interface Node { * unless it has been set via {@link #setUserData(Object)}. * * @return The user data set on this node. + * @deprecated Use {@link #getUserMap()} */ Object getUserData(); @@ -389,6 +390,7 @@ public interface Node { * * @param userData * The data to set on this node. + * @deprecated Use {@link #getUserMap()} */ void setUserData(Object userData); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/QualifiableNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/QualifiableNode.java index 1548cc9cfe..a4b379d084 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/QualifiableNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/QualifiableNode.java @@ -8,7 +8,10 @@ package net.sourceforge.pmd.lang.ast; * Nodes that can be described with a qualified name. * * @author Clément Fournier + * + * @deprecated Not useful anymore */ +@Deprecated public interface QualifiableNode extends Node { /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/QualifiedName.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/QualifiedName.java index 69d5f386ab..670215b544 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/QualifiedName.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/QualifiedName.java @@ -12,7 +12,9 @@ package net.sourceforge.pmd.lang.ast; * from QualifiedName to e.g. JavaQualifiedName. * * @author Clément Fournier + * @deprecated Not useful anymore */ +@Deprecated public interface QualifiedName { @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetricsComputer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetricsComputer.java index d933b4d352..b6cfde2815 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetricsComputer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetricsComputer.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.metrics; -import java.util.ArrayList; import java.util.List; import net.sourceforge.pmd.lang.ast.QualifiableNode; @@ -17,25 +16,16 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode; * * @author Clément Fournier * @since 6.0.0 + * @deprecated See package description */ +@Deprecated public abstract class AbstractMetricsComputer implements MetricsComputer { @Override public double computeForType(MetricKey key, T node, boolean force, MetricOptions options, MetricMemoizer memoizer) { - - ParameterizedMetricKey paramKey = ParameterizedMetricKey.getInstance(key, options); - // if memo.get(key) == null then the metric has never been computed. NaN is a valid value. - Double prev = memoizer.getMemo(paramKey); - if (!force && prev != null) { - return prev; - } - - double val = key.getCalculator().computeFor(node, options); - memoizer.memoize(paramKey, val); - - return val; + return MetricsUtil.computeMetric(key, node, options); } @@ -43,46 +33,14 @@ public abstract class AbstractMetricsComputer key, O node, boolean force, MetricOptions options, MetricMemoizer memoizer) { - ParameterizedMetricKey paramKey = ParameterizedMetricKey.getInstance(key, options); - Double prev = memoizer.getMemo(paramKey); - if (!force && prev != null) { - return prev; - } - - double val = key.getCalculator().computeFor(node, options); - memoizer.memoize(paramKey, val); - return val; + return MetricsUtil.computeMetric(key, node, options); } @Override public double computeWithResultOption(MetricKey key, T node, boolean force, MetricOptions options, ResultOption option, ProjectMemoizer stats) { - - List ops = findOperations(node); - - List values = new ArrayList<>(); - for (O op : ops) { - if (key.supports(op)) { - MetricMemoizer opStats = stats.getOperationMemoizer(op.getQualifiedName()); - double val = this.computeForOperation(key, op, force, options, opStats); - if (val != Double.NaN) { - values.add(val); - } - } - } - - // FUTURE use streams to do that when we upgrade the compiler to 1.8 - switch (option) { - case SUM: - return sum(values); - case HIGHEST: - return highest(values); - case AVERAGE: - return average(values); - default: - return Double.NaN; - } + return MetricsUtil.computeAggregate(key, findOperations(node), options, option); } @@ -97,29 +55,4 @@ public abstract class AbstractMetricsComputer findOperations(T node); // TODO:cf this one is computed every time - private static double sum(List values) { - double sum = 0; - for (double val : values) { - sum += val; - } - return sum; - } - - - private static double highest(List values) { - double highest = Double.NEGATIVE_INFINITY; - for (double val : values) { - if (val > highest) { - highest = val; - } - } - return highest == Double.NEGATIVE_INFINITY ? 0 : highest; - } - - - private static double average(List values) { - return sum(values) / values.size(); - } - - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetricsFacade.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetricsFacade.java index 4b165a51dd..a75a522d32 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetricsFacade.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetricsFacade.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.metrics; -import java.util.Objects; - import net.sourceforge.pmd.lang.ast.QualifiableNode; /** @@ -17,19 +15,18 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode; * * @author Clément Fournier * @since 6.0.0 + * @deprecated See package description */ +@Deprecated public abstract class AbstractMetricsFacade { - private static final String NULL_KEY_MESSAGE = "The metric key must not be null"; - private static final String NULL_OPTIONS_MESSAGE = "The metric options must not be null"; - private static final String NULL_NODE_MESSAGE = "The node must not be null"; - /** * Gets the language specific metrics computer. * * @return The metrics computer */ + @Deprecated protected abstract MetricsComputer getLanguageSpecificComputer(); @@ -38,6 +35,7 @@ public abstract class AbstractMetricsFacade getLanguageSpecificProjectMemoizer(); @@ -52,20 +50,7 @@ public abstract class AbstractMetricsFacade key, T node, MetricOptions options) { - - Objects.requireNonNull(key, NULL_KEY_MESSAGE); - Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE); - Objects.requireNonNull(node, NULL_NODE_MESSAGE); - - if (!key.supports(node)) { - return Double.NaN; - } - - MetricMemoizer memoizer = getLanguageSpecificProjectMemoizer().getClassMemoizer(node.getQualifiedName()); - - return memoizer == null ? Double.NaN - : getLanguageSpecificComputer().computeForType(key, node, false, - options, memoizer); + return MetricsUtil.computeMetric(key, node, options); } @@ -79,22 +64,7 @@ public abstract class AbstractMetricsFacade key, O node, MetricOptions options) { - - Objects.requireNonNull(key, NULL_KEY_MESSAGE); - Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE); - Objects.requireNonNull(node, NULL_NODE_MESSAGE); - - - if (!key.supports(node)) { - return Double.NaN; - } - - MetricMemoizer memoizer = getLanguageSpecificProjectMemoizer().getOperationMemoizer(node.getQualifiedName()); - - return memoizer == null ? Double.NaN - : getLanguageSpecificComputer().computeForOperation(key, node, false, - options, memoizer); - + return MetricsUtil.computeMetric(key, node, options); } @@ -113,11 +83,6 @@ public abstract class AbstractMetricsFacade key, T node, MetricOptions options, ResultOption resultOption) { - Objects.requireNonNull(key, NULL_KEY_MESSAGE); - Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE); - Objects.requireNonNull(node, NULL_NODE_MESSAGE); - Objects.requireNonNull(resultOption, "The result option must not be null"); - return getLanguageSpecificComputer().computeWithResultOption(key, node, false, options, resultOption, getLanguageSpecificProjectMemoizer()); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/BasicMetricMemoizer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/BasicMetricMemoizer.java index 8ae0139593..97ba54f533 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/BasicMetricMemoizer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/BasicMetricMemoizer.java @@ -16,7 +16,9 @@ import net.sourceforge.pmd.lang.ast.Node; * * @author Clément Fournier * @since 6.0.0 + * @deprecated See package description */ +@Deprecated public class BasicMetricMemoizer implements MetricMemoizer { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/BasicProjectMemoizer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/BasicProjectMemoizer.java index e5b6a7463d..c5830b277b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/BasicProjectMemoizer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/BasicProjectMemoizer.java @@ -21,7 +21,10 @@ import net.sourceforge.pmd.lang.ast.QualifiedName; * * @author Clément Fournier * @since 6.0.0 + * + * @deprecated See package description */ +@Deprecated public abstract class BasicProjectMemoizer implements ProjectMemoizer { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/LanguageMetricsProvider.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/LanguageMetricsProvider.java index a1b84240ce..ec57cceff9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/LanguageMetricsProvider.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/LanguageMetricsProvider.java @@ -31,12 +31,6 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode; @Experimental public interface LanguageMetricsProvider { - /** - * Provides a hook to do any initializing before the first file is processed by PMD. - * This can be used by the metrics implementations to reset the cache. - */ - void initialize(); - /** * Returns a list of all supported type metric keys * for the language. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricKey.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricKey.java index 2259ed8956..ead1c63e9e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricKey.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricKey.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.metrics; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.util.DataMap.DataKey; /** * Key identifying a metric. Such keys must implement the hashCode method. Enums are well fitted to serve as @@ -14,7 +15,7 @@ import net.sourceforge.pmd.lang.ast.Node; * @author Clément Fournier * @since 5.8.0 */ -public interface MetricKey { +public interface MetricKey extends DataKey, Double> { /** * Returns the name of the metric. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricMemoizer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricMemoizer.java index a41f8c6a65..bea9041e3d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricMemoizer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricMemoizer.java @@ -14,7 +14,9 @@ import net.sourceforge.pmd.lang.ast.Node; * * @author Clément Fournier * @since 6.0.0 + * @deprecated See package description */ +@Deprecated public interface MetricMemoizer { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsComputer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsComputer.java index 5626539ada..0951822782 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsComputer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsComputer.java @@ -16,7 +16,9 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode; * * @author Clément Fournier * @since 6.0.0 + * @deprecated See package description */ +@Deprecated public interface MetricsComputer { 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 new file mode 100644 index 0000000000..65db7403ab --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricsUtil.java @@ -0,0 +1,155 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.metrics; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import net.sourceforge.pmd.lang.ast.Node; + +/** + * Utilities to use {@link Metric} instances. + */ +public final class MetricsUtil { + + static final String NULL_KEY_MESSAGE = "The metric key must not be null"; + static final String NULL_OPTIONS_MESSAGE = "The metric options must not be null"; + static final String NULL_NODE_MESSAGE = "The node must not be null"; + + private MetricsUtil() { + // util class + } + + public static double computeAggregate(MetricKey key, Iterable ops, ResultOption resultOption) { + return computeAggregate(key, ops, MetricOptions.emptyOptions(), resultOption); + } + + /** + * Computes an aggregate result for a metric, identified with a {@link ResultOption}. + * + * @param key The metric to compute + * @param ops List of nodes for which to aggregate the metric + * @param options The options of the metric + * @param resultOption The type of aggregation to perform + * + * @return The result of the computation, or {@code Double.NaN} if it couldn't be performed + */ + public static double computeAggregate(MetricKey key, Iterable ops, MetricOptions options, ResultOption resultOption) { + + + Objects.requireNonNull(key, NULL_KEY_MESSAGE); + Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE); + Objects.requireNonNull(ops, NULL_NODE_MESSAGE); + Objects.requireNonNull(resultOption, "The result option must not be null"); + + + List values = new ArrayList<>(); + for (O op : ops) { + if (key.supports(op)) { + double val = computeMetric(key, op, options); + if (!Double.isNaN(val)) { + values.add(val); + } + } + } + + // FUTURE use streams to do that when we upgrade the compiler to 1.8 + switch (resultOption) { + case SUM: + return sum(values); + case HIGHEST: + return highest(values); + case AVERAGE: + return average(values); + default: + return Double.NaN; + } + } + + /** + * Computes a metric identified by its code on a node, with the default options. + * + * @param key The key identifying the metric to be computed + * @param node The node on which to compute the metric + * + * @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed + */ + public static double computeMetric(MetricKey key, N node) { + return computeMetric(key, node, MetricOptions.emptyOptions()); + } + + /** + * Computes a metric identified by its code on a node, possibly + * selecting a variant with the {@code options} parameter. + * + * @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, or {@code Double.NaN} if the value couldn't be computed + */ + public static double computeMetric(MetricKey key, N node, MetricOptions options) { + 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. + * + * @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 + */ + public static double computeMetric(MetricKey key, N node, MetricOptions options, boolean forceRecompute) { + Objects.requireNonNull(key, NULL_KEY_MESSAGE); + Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE); + Objects.requireNonNull(node, NULL_NODE_MESSAGE); + + + if (!key.supports(node)) { + return Double.NaN; + } + + ParameterizedMetricKey paramKey = ParameterizedMetricKey.getInstance(key, options); + Double prev = node.getUserMap().get(paramKey); + if (!forceRecompute && prev != null) { + return prev; + } + + double val = key.getCalculator().computeFor(node, options); + node.getUserMap().set(paramKey, val); + return val; + } + + private static double sum(List values) { + double sum = 0; + for (double val : values) { + sum += val; + } + return sum; + } + + + private static double highest(List values) { + double highest = Double.NEGATIVE_INFINITY; + for (double val : values) { + if (val > highest) { + highest = val; + } + } + return highest == Double.NEGATIVE_INFINITY ? 0 : highest; + } + + + private static double average(List values) { + return sum(values) / values.size(); + } + + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKey.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKey.java index e0a8dbb799..474852c8ec 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKey.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKey.java @@ -7,7 +7,9 @@ package net.sourceforge.pmd.lang.metrics; import java.util.HashMap; import java.util.Map; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.util.DataMap.DataKey; /** * Represents a key parameterized with its options. Used to index memoization maps. @@ -16,8 +18,11 @@ import net.sourceforge.pmd.lang.ast.Node; * * @author Clément Fournier * @since 5.8.0 + * @deprecated Is internal API */ -public final class ParameterizedMetricKey { +@InternalApi +@Deprecated +public final class ParameterizedMetricKey implements DataKey, Double> { private static final Map, ParameterizedMetricKey> POOL = new HashMap<>(); @@ -65,6 +70,7 @@ public final class ParameterizedMetricKey { */ @SuppressWarnings("PMD.SingletonClassReturningNewInstance") public static ParameterizedMetricKey getInstance(MetricKey key, MetricOptions options) { + // sharing instances allows using DataMap, which uses reference identity ParameterizedMetricKey tmp = new ParameterizedMetricKey<>(key, options); if (!POOL.containsKey(tmp)) { POOL.put(tmp, tmp); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/ProjectMemoizer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/ProjectMemoizer.java index 04651b2a32..d4e889ed2d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/ProjectMemoizer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/ProjectMemoizer.java @@ -19,7 +19,9 @@ import net.sourceforge.pmd.lang.ast.QualifiedName; * * @author Clément Fournier * @since 6.0.0 + * @deprecated See package description */ +@Deprecated public interface ProjectMemoizer { /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/AbstractLanguageMetricsProvider.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/AbstractLanguageMetricsProvider.java index d6f46e0d7a..05a4ce33dc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/AbstractLanguageMetricsProvider.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/AbstractLanguageMetricsProvider.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.metrics.internal; import java.util.HashMap; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.lang.ast.Node; @@ -12,7 +13,7 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode; import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; import net.sourceforge.pmd.lang.metrics.MetricKey; import net.sourceforge.pmd.lang.metrics.MetricOptions; -import net.sourceforge.pmd.lang.metrics.MetricsComputer; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.lang.metrics.ResultOption; @@ -26,15 +27,12 @@ public abstract class AbstractLanguageMetricsProvider tClass; private final Class oClass; - private final MetricsComputer myComputer; protected AbstractLanguageMetricsProvider(Class tClass, - Class oClass, - MetricsComputer computer) { + Class oClass) { this.tClass = tClass; this.oClass = oClass; - this.myComputer = computer; } @@ -52,21 +50,23 @@ public abstract class AbstractLanguageMetricsProvider key, T node, MetricOptions options) { - return myComputer.computeForType(key, node, true, options, DummyMetricMemoizer.getInstance()); + return MetricsUtil.computeMetric(key, node, options, true); } @Override public double computeForOperation(MetricKey key, O node, MetricOptions options) { - return myComputer.computeForOperation(key, node, true, options, DummyMetricMemoizer.getInstance()); + return MetricsUtil.computeMetric(key, node, options, true); } @Override - public double computeWithResultOption(MetricKey key, T node, MetricOptions options, ResultOption option) { - return myComputer.computeWithResultOption(key, node, true, options, option, DummyProjectMemoizer.getInstance()); + public double computeWithResultOption(MetricKey key, T node, MetricOptions options, ResultOption resultOption) { + return MetricsUtil.computeAggregate(key, findOps(node), options, resultOption); } + protected abstract List findOps(T t); + @Override public Map, Double> computeAllMetricsFor(Node node) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/DummyMetricMemoizer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/DummyMetricMemoizer.java deleted file mode 100644 index 1d6cae45a1..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/DummyMetricMemoizer.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.metrics.internal; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.metrics.MetricMemoizer; -import net.sourceforge.pmd.lang.metrics.ParameterizedMetricKey; - - -/** - * Memoizes nothing. - * - * @author Clément Fournier - * @since 6.11.0 - */ -public final class DummyMetricMemoizer implements MetricMemoizer { - - private static final DummyMetricMemoizer INSTANCE = new DummyMetricMemoizer<>(); - - - private DummyMetricMemoizer() { - - } - - - @Override - public Double getMemo(ParameterizedMetricKey key) { - return null; - } - - - @Override - public void memoize(ParameterizedMetricKey key, double value) { - // do nothing - } - - - @SuppressWarnings("unchecked") - public static DummyMetricMemoizer getInstance() { - return (DummyMetricMemoizer) INSTANCE; - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/DummyProjectMemoizer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/DummyProjectMemoizer.java deleted file mode 100644 index 10abe75a9e..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/DummyProjectMemoizer.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.metrics.internal; - -import net.sourceforge.pmd.lang.ast.QualifiableNode; -import net.sourceforge.pmd.lang.ast.QualifiedName; -import net.sourceforge.pmd.lang.metrics.MetricMemoizer; -import net.sourceforge.pmd.lang.metrics.ProjectMemoizer; - - -/** - * Memoizes nothing. - * - * @author Clément Fournier - * @since 6.11.0 - */ -public final class DummyProjectMemoizer implements ProjectMemoizer { - - private static final DummyProjectMemoizer INSTANCE = new DummyProjectMemoizer<>(); - - - private DummyProjectMemoizer() { - - } - - - @Override - public MetricMemoizer getOperationMemoizer(QualifiedName qname) { - return DummyMetricMemoizer.getInstance(); - } - - - @Override - public MetricMemoizer getClassMemoizer(QualifiedName qname) { - return DummyMetricMemoizer.getInstance(); - } - - - @SuppressWarnings("unchecked") - public static DummyProjectMemoizer getInstance() { - return (DummyProjectMemoizer) INSTANCE; - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/package-info.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/package-info.java new file mode 100644 index 0000000000..e42b2b08fc --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/package-info.java @@ -0,0 +1,16 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * Language-independent framework to represent code metrics. If you want + * to compute code metrics in your rules, then you should find the language-specific + * enums containing {@link net.sourceforge.pmd.lang.metrics.MetricKey}s + * in the relevant language modules. + * + *

Metrics are cached by default on the nodes they're computed on. + * Many APIs here are deprecated, this is because metrics were previously + * cached in big static maps, which is replaced by caching on nodes. + * + */ +package net.sourceforge.pmd.lang.metrics; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java index ee0bb7f382..f6518a2d2a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java @@ -24,9 +24,6 @@ import net.sourceforge.pmd.SourceCodeProcessor; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; import net.sourceforge.pmd.benchmark.TimedOperationCategory; -import net.sourceforge.pmd.lang.Language; -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.util.datasource.DataSource; @@ -37,7 +34,7 @@ import net.sourceforge.pmd.util.datasource.DataSource; public abstract class AbstractPMDProcessor { private static final Logger LOG = Logger.getLogger(AbstractPMDProcessor.class.getName()); - + protected final PMDConfiguration configuration; public AbstractPMDProcessor(PMDConfiguration configuration) { @@ -56,7 +53,7 @@ public abstract class AbstractPMDProcessor { } /** - * + * * @deprecated this method will be removed. It was once used to determine a short filename * for the file being analyzed, so that shortnames can be reported. But the logic has * been moved to the renderers. @@ -78,15 +75,15 @@ public abstract class AbstractPMDProcessor { */ protected RuleSets createRuleSets(RuleSetFactory factory, Report report) { final RuleSets rs = RulesetsFactoryUtils.getRuleSets(configuration.getRuleSets(), factory); - + final Set brokenRules = removeBrokenRules(rs); for (final Rule rule : brokenRules) { report.addConfigError(new Report.ConfigurationError(rule, rule.dysfunctionReason())); } - + return rs; } - + /** * Remove and return the misconfigured rules from the rulesets and log them * for good measure. @@ -117,8 +114,6 @@ public abstract class AbstractPMDProcessor { configuration.getAnalysisCache().checkValidity(rs, configuration.getClassLoader()); final SourceCodeProcessor processor = new SourceCodeProcessor(configuration); - resetMetrics(); - for (final DataSource dataSource : files) { // this is the real, canonical and absolute filename (not shortened) String realFileName = dataSource.getNiceFileName(false, null); @@ -128,7 +123,7 @@ public abstract class AbstractPMDProcessor { // render base report first - general errors renderReports(renderers, ctx.getReport()); - + // then add analysis results per file collectReports(renderers); @@ -139,15 +134,6 @@ public abstract class AbstractPMDProcessor { } } - private void resetMetrics() { - for (Language language : LanguageRegistry.getLanguages()) { - LanguageMetricsProvider languageMetricsProvider = language.getDefaultVersion().getLanguageVersionHandler().getLanguageMetricsProvider(); - if (languageMetricsProvider != null) { - languageMetricsProvider.initialize(); - } - } - } - protected abstract void runAnalysis(PmdRunnable runnable); protected abstract void collectReports(List renderers); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java index 7a38e975bc..05d4bcd2c5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java @@ -8,11 +8,14 @@ import java.util.IdentityHashMap; import java.util.Map; /** - * An opaque, strongly typed heterogeneous data container. + * An opaque, strongly typed heterogeneous data container. Data maps can + * be set to accept only a certain type of key, with the type parameter. + * The key can itself constrain the type of values, using its own type + * parameter {@code T}. * - * @param Type of keys in this map + * @param Type of keys in this map. */ -public class DataMap { +public final class DataMap { private final Map, Object> map = new IdentityHashMap<>(); 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 de4282675d..8d2247fdc0 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 @@ -5,11 +5,16 @@ package net.sourceforge.pmd.lang.java.metrics; +import java.util.ArrayList; +import java.util.List; + +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; import net.sourceforge.pmd.lang.metrics.MetricKey; import net.sourceforge.pmd.lang.metrics.MetricOptions; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.lang.metrics.ResultOption; @@ -17,36 +22,17 @@ import net.sourceforge.pmd.lang.metrics.ResultOption; * User bound façade of the Metrics Framework. Provides a uniform interface for the calculation of metrics. * * @author Clément Fournier + * @deprecated Use {@link MetricsUtil} */ +@Deprecated public final class JavaMetrics { - private static final JavaMetricsFacade FACADE = new JavaMetricsFacade(); - private JavaMetrics() { // Cannot be instantiated } - /** - * Returns the underlying façade. - * - * @return The underlying façade instance - */ - static JavaMetricsFacade getFacade() { - return FACADE; - } - - - /** - * Resets the entire data structure. - * This needs to be done in case PMD is executed multiple times within one JVM run. - */ - static void reset() { - FACADE.reset(); - } - - /** * Computes the standard value of the metric identified by its code on a class AST node. * @@ -56,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 FACADE.computeForType(key, node, MetricOptions.emptyOptions()); + return MetricsUtil.computeMetric(key, node); } @@ -71,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 FACADE.computeForType(key, node, options); + return MetricsUtil.computeMetric(key, node, options); } @@ -84,14 +70,14 @@ 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 FACADE.computeForOperation(key, node, MetricOptions.emptyOptions()); + return MetricsUtil.computeMetric(key, node); } /** * @see #get(MetricKey, MethodLikeNode) * @deprecated Provided here for backwards binary compatibility with {@link #get(MetricKey, MethodLikeNode)}. - * Please explicitly link your code to that method and recompile your code. Will be remove with 7.0.0 + * Please explicitly link your code to that method and recompile your code. Will be remove with 7.0.0 */ public static double get(MetricKey key, ASTMethodOrConstructorDeclaration node) { return get(key, (MethodLikeNode) node); @@ -101,7 +87,7 @@ public final class JavaMetrics { /** * @see #get(MetricKey, MethodLikeNode, MetricOptions) * @deprecated Provided here for backwards binary compatibility with {@link #get(MetricKey, MethodLikeNode, MetricOptions)}. - * Please explicitly link your code to that method and recompile your code. Will be remove with 7.0.0 + * Please explicitly link your code to that method and recompile your code. Will be remove with 7.0.0 */ @Deprecated public static double get(MetricKey key, ASTMethodOrConstructorDeclaration node, MetricOptions options) { @@ -118,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 FACADE.computeForOperation(key, node, options); + return MetricsUtil.computeMetric(key, node, options); } @@ -133,7 +119,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, ResultOption resultOption) { - return FACADE.computeWithResultOption(key, node, MetricOptions.emptyOptions(), resultOption); + return MetricsUtil.computeAggregate(key, findOps(node), resultOption); } @@ -150,7 +136,17 @@ public final class JavaMetrics { */ public static double get(MetricKey key, ASTAnyTypeDeclaration node, MetricOptions options, ResultOption resultOption) { - return FACADE.computeWithResultOption(key, node, options, resultOption); + return MetricsUtil.computeAggregate(key, findOps(node), options, resultOption); } + static List findOps(ASTAnyTypeDeclaration node) { + List operations = new ArrayList<>(); + + for (ASTAnyTypeBodyDeclaration decl : node.getDeclarations()) { + if (decl.getNumChildren() > 0 && decl.getDeclarationNode() instanceof ASTMethodOrConstructorDeclaration) { + operations.add((MethodLikeNode) decl.getChild(0)); + } + } + return operations; + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsComputer.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsComputer.java index 8c6934f352..65b4ddeaeb 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsComputer.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsComputer.java @@ -4,21 +4,21 @@ package net.sourceforge.pmd.lang.java.metrics; -import java.util.ArrayList; import java.util.List; import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; import net.sourceforge.pmd.lang.metrics.AbstractMetricsComputer; +import net.sourceforge.pmd.lang.metrics.MetricsComputer; /** * Computes a metric. * * @author Clément Fournier + * @deprecated See {@link MetricsComputer} */ +@Deprecated public final class JavaMetricsComputer extends AbstractMetricsComputer { private static final JavaMetricsComputer INSTANCE = new JavaMetricsComputer(); @@ -27,25 +27,15 @@ public final class JavaMetricsComputer extends AbstractMetricsComputer findOperations(ASTAnyTypeDeclaration node) { + return JavaMetrics.findOps(node); + } @InternalApi public static JavaMetricsComputer getInstance() { return INSTANCE; } - - // TODO: doesn't consider lambdas - @Override - protected List findOperations(ASTAnyTypeDeclaration node) { - - List operations = new ArrayList<>(); - - for (ASTAnyTypeBodyDeclaration decl : node.getDeclarations()) { - if (decl.getNumChildren() > 0 && decl.getChild(0) instanceof ASTMethodOrConstructorDeclaration) { - operations.add((MethodLikeNode) decl.getChild(0)); - } - } - return operations; - } - } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsFacade.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsFacade.java deleted file mode 100644 index f239407db7..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsFacade.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.metrics.AbstractMetricsFacade; -import net.sourceforge.pmd.lang.metrics.MetricsComputer; - -/** - * Inner façade of the Java metrics framework. The static façade delegates to an instance of this class. - * - * @author Clément Fournier - */ -class JavaMetricsFacade extends AbstractMetricsFacade { - - private final JavaProjectMemoizer memoizer = new JavaProjectMemoizer(); - - - /** Resets the entire data structure. Used for tests. */ - void reset() { - memoizer.reset(); - } - - - @Override - public JavaProjectMemoizer getLanguageSpecificProjectMemoizer() { - return memoizer; - } - - - @Override - protected MetricsComputer getLanguageSpecificComputer() { - return JavaMetricsComputer.getInstance(); - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProvider.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProvider.java index 8070454c64..8f73f937d8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProvider.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProvider.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.metrics; import java.util.Arrays; import java.util.List; +import net.sourceforge.pmd.annotation.InternalApi; 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; @@ -14,15 +15,20 @@ import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; import net.sourceforge.pmd.lang.metrics.MetricKey; import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider; +/** + * @deprecated This is internal API + */ +@Deprecated +@InternalApi public class JavaMetricsProvider extends AbstractLanguageMetricsProvider { public JavaMetricsProvider() { - super(ASTAnyTypeDeclaration.class, MethodLikeNode.class, JavaMetricsComputer.getInstance()); + super(ASTAnyTypeDeclaration.class, MethodLikeNode.class); } @Override - public void initialize() { - JavaMetrics.reset(); + protected List findOps(ASTAnyTypeDeclaration astAnyTypeDeclaration) { + return JavaMetrics.findOps(astAnyTypeDeclaration); } @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaProjectMemoizer.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaProjectMemoizer.java deleted file mode 100644 index 0d30549a51..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaProjectMemoizer.java +++ /dev/null @@ -1,18 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.metrics.BasicProjectMemoizer; - -/** - * Shorthand for a project memoizer parameterized with Java-specific node types. - * - * @author Clément Fournier - */ -class JavaProjectMemoizer extends BasicProjectMemoizer { - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractJavaOperationMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractJavaOperationMetric.java index f9eed4f242..264d9e3c1e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractJavaOperationMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractJavaOperationMetric.java @@ -26,6 +26,7 @@ public abstract class AbstractJavaOperationMetric extends AbstractJavaMetric= classReportLevel) { int classHighest = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, node, cycloOptions, ResultOption.HIGHEST); @@ -144,7 +145,7 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { @Override public final Object visit(MethodLikeNode node, Object data) { - int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, node, cycloOptions); + int cyclo = (int) MetricsUtil.computeMetric(JavaOperationMetricKey.CYCLO, node, cycloOptions); if (cyclo >= methodReportLevel) { 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 780831ac46..608fa7f9d6 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 @@ -5,9 +5,9 @@ package net.sourceforge.pmd.lang.java.rule.design; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; 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; /** @@ -30,10 +30,10 @@ public class DataClassRule extends AbstractJavaMetricsRule { boolean isDataClass = interfaceRevealsData(node) && classRevealsDataAndLacksComplexity(node); if (isDataClass) { - double woc = JavaMetrics.get(JavaClassMetricKey.WOC, node); - int nopa = (int) JavaMetrics.get(JavaClassMetricKey.NOPA, node); - int noam = (int) JavaMetrics.get(JavaClassMetricKey.NOAM, node); - int wmc = (int) JavaMetrics.get(JavaClassMetricKey.WMC, node); + 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); addViolation(data, node, new Object[] {node.getSimpleName(), StringUtil.percentageString(woc, 3), @@ -45,15 +45,15 @@ public class DataClassRule extends AbstractJavaMetricsRule { private boolean interfaceRevealsData(ASTAnyTypeDeclaration node) { - double woc = JavaMetrics.get(JavaClassMetricKey.WOC, node); + double woc = MetricsUtil.computeMetric(JavaClassMetricKey.WOC, node); return woc < WOC_LEVEL; } private boolean classRevealsDataAndLacksComplexity(ASTAnyTypeDeclaration node) { - int nopa = (int) JavaMetrics.get(JavaClassMetricKey.NOPA, node); - int noam = (int) JavaMetrics.get(JavaClassMetricKey.NOAM, node); - int wmc = (int) JavaMetrics.get(JavaClassMetricKey.WMC, 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); 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 8e610ee758..38f309fa74 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 @@ -6,9 +6,9 @@ package net.sourceforge.pmd.lang.java.rule.design; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; 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 +41,9 @@ public class GodClassRule extends AbstractJavaRule { @Override public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { - int wmc = (int) JavaMetrics.get(JavaClassMetricKey.WMC, node); - double tcc = JavaMetrics.get(JavaClassMetricKey.TCC, node); - int atfd = (int) JavaMetrics.get(JavaClassMetricKey.ATFD, node); + int wmc = (int) MetricsUtil.computeMetric(JavaClassMetricKey.WMC, node); + double tcc = MetricsUtil.computeMetric(JavaClassMetricKey.TCC, node); + int atfd = (int) MetricsUtil.computeMetric(JavaClassMetricKey.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 895f5f0609..37c8774949 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 @@ -11,11 +11,10 @@ import java.util.logging.Logger; 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.JavaOperationMetricKey; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -72,7 +71,7 @@ public class NPathComplexityRule extends AbstractJavaMetricsRule { @Override public final Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - int npath = (int) JavaMetrics.get(JavaOperationMetricKey.NPATH, (MethodLikeNode) node); + 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, }); 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 a90e4ddd59..b2dc4b0642 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 @@ -22,6 +22,7 @@ import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; import net.sourceforge.pmd.lang.java.metrics.impl.NcssMetric.NcssOption; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; 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; @@ -94,7 +95,7 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { super.visit(node, data); if (JavaClassMetricKey.NCSS.supports(node)) { - int classSize = (int) JavaMetrics.get(JavaClassMetricKey.NCSS, node, ncssOptions); + int classSize = (int) MetricsUtil.computeMetric(JavaClassMetricKey.NCSS, node, ncssOptions); int classHighest = (int) JavaMetrics.get(JavaOperationMetricKey.NCSS, node, ncssOptions, ResultOption.HIGHEST); if (classSize >= classReportLevel) { @@ -112,7 +113,7 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { @Override public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - int methodSize = (int) JavaMetrics.get(JavaOperationMetricKey.NCSS, node, ncssOptions); + 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, }); 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 29e9c2bb69..5969ff7780 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 @@ -19,9 +19,9 @@ import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** @@ -82,9 +82,9 @@ public class MetricFunction implements Function { public static double getMetric(Node n, String metricKeyName) { if (n instanceof ASTAnyTypeDeclaration) { - return getClassMetric((ASTAnyTypeDeclaration) n, getClassMetricKey(metricKeyName)); + return MetricsUtil.computeMetric(getClassMetricKey(metricKeyName), (ASTAnyTypeDeclaration) n); } else if (n instanceof MethodLikeNode) { - return getOpMetric((MethodLikeNode) n, getOperationMetricKey(metricKeyName)); + return MetricsUtil.computeMetric(getOperationMetricKey(metricKeyName), (MethodLikeNode) n); } else { throw new IllegalStateException(genericBadNodeMessage()); } @@ -109,16 +109,6 @@ public class MetricFunction implements Function { } - private static double getOpMetric(MethodLikeNode node, JavaOperationMetricKey key) { - return JavaMetrics.get(key, node); - } - - - private static double getClassMetric(ASTAnyTypeDeclaration node, JavaClassMetricKey key) { - return JavaMetrics.get(key, node); - } - - public static void registerSelfInSimpleContext() { ((SimpleFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "metric", diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/MetricsHook.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/MetricsHook.java deleted file mode 100644 index b24e0b81f1..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/MetricsHook.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics; - -/** - * Provides a hook into package-private methods of {@code java.metrics}. - * - * @author Clément Fournier - */ -public class MetricsHook { - - private MetricsHook() { - - } - - - public static void reset() { - JavaMetrics.reset(); - } - -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/ProjectMemoizerTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/ProjectMemoizerTest.java index 62418ba82b..e77ab3fc4b 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/ProjectMemoizerTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/ProjectMemoizerTest.java @@ -25,8 +25,8 @@ import net.sourceforge.pmd.lang.java.metrics.testdata.MetricsVisitorTestData; import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; import net.sourceforge.pmd.lang.metrics.MetricKey; import net.sourceforge.pmd.lang.metrics.MetricKeyUtil; -import net.sourceforge.pmd.lang.metrics.MetricMemoizer; import net.sourceforge.pmd.lang.metrics.MetricOptions; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** * @author Clément Fournier @@ -66,25 +66,19 @@ public class ProjectMemoizerTest extends BaseNonParserTest { private List visitWith(ASTCompilationUnit acu, final boolean force) { - final JavaProjectMemoizer toplevel = JavaMetrics.getFacade().getLanguageSpecificProjectMemoizer(); - final List result = new ArrayList<>(); acu.jjtAccept(new JavaParserVisitorReducedAdapter() { @Override public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - MetricMemoizer op = toplevel.getOperationMemoizer(node.getQualifiedName()); - result.add((int) JavaMetricsComputer.getInstance().computeForOperation(opMetricKey, node, force, - MetricOptions.emptyOptions(), op)); + result.add((int) MetricsUtil.computeMetric(opMetricKey, node, MetricOptions.emptyOptions(), force)); return super.visit(node, data); } @Override public Object visit(ASTAnyTypeDeclaration node, Object data) { - MetricMemoizer clazz = toplevel.getClassMemoizer(node.getQualifiedName()); - result.add((int) JavaMetricsComputer.getInstance().computeForType(classMetricKey, node, force, - MetricOptions.emptyOptions(), clazz)); + result.add((int) MetricsUtil.computeMetric(classMetricKey, node, MetricOptions.emptyOptions(), force)); return super.visit(node, data); } }, null); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java index afd8f068fa..7c1c6aaab6 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java @@ -18,6 +18,7 @@ import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; 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; @@ -151,7 +152,7 @@ public abstract class AbstractMetricTestRule extends AbstractJavaMetricsRule { @Override public Object visit(ASTAnyTypeDeclaration node, Object data) { if (classKey != null && reportClasses && classKey.supports(node)) { - double classValue = JavaMetrics.get(classKey, node, metricOptions); + double classValue = MetricsUtil.computeMetric(classKey, node, metricOptions); String valueReport = niceDoubleString(classValue); @@ -170,7 +171,7 @@ public abstract class AbstractMetricTestRule extends AbstractJavaMetricsRule { @Override public Object visit(MethodLikeNode node, Object data) { if (opKey != null && reportMethods && opKey.supports(node)) { - double methodValue = JavaMetrics.get(opKey, node, metricOptions); + double methodValue = MetricsUtil.computeMetric(opKey, node, metricOptions); if (methodValue >= reportLevel) { addViolation(data, node, new String[] {node.getQualifiedName().toString(), "" + niceDoubleString(methodValue), }); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AllMetricsTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AllMetricsTest.java index 2614a4a6e4..f9e96dff5b 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AllMetricsTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AllMetricsTest.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.lang.java.metrics.MetricsHook; import net.sourceforge.pmd.testframework.SimpleAggregatorTst; /** @@ -18,14 +16,6 @@ public class AllMetricsTest extends SimpleAggregatorTst { private static final String RULESET = "rulesets/java/metrics_test.xml"; - - @Override - protected Rule reinitializeRule(Rule rule) { - MetricsHook.reset(); - return rule; - } - - @Override public void setUp() { addRule(RULESET, "CycloTest"); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityTest.java index 2a922b0d8f..0555622065 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityTest.java @@ -4,14 +4,7 @@ package net.sourceforge.pmd.lang.java.rule.design; -import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.lang.java.metrics.MetricsHook; import net.sourceforge.pmd.testframework.PmdRuleTst; public class CyclomaticComplexityTest extends PmdRuleTst { - @Override - protected Rule reinitializeRule(Rule rule) { - MetricsHook.reset(); - return rule; - } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityTest.java index 7cfb3bc81d..085c1be123 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityTest.java @@ -4,14 +4,7 @@ package net.sourceforge.pmd.lang.java.rule.design; -import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.lang.java.metrics.MetricsHook; import net.sourceforge.pmd.testframework.PmdRuleTst; public class NPathComplexityTest extends PmdRuleTst { - @Override - protected Rule reinitializeRule(Rule rule) { - MetricsHook.reset(); - return rule; - } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountTest.java index 7a70967a7d..a9d4359f97 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountTest.java @@ -4,14 +4,7 @@ package net.sourceforge.pmd.lang.java.rule.design; -import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.lang.java.metrics.MetricsHook; import net.sourceforge.pmd.testframework.PmdRuleTst; public class NcssCountTest extends PmdRuleTst { - @Override - protected Rule reinitializeRule(Rule rule) { - MetricsHook.reset(); - return rule; - } }