From 050938f1bce3c560078ce53474715e7425f2556d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 11 Dec 2020 07:47:16 +0100 Subject: [PATCH 001/101] Remove some dead code --- .../pmd/lang/java/types/MapFunction.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/MapFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/MapFunction.java index 79b78eb95f..cd85884be7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/MapFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/MapFunction.java @@ -9,14 +9,11 @@ import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - /** - * A partial function built on a map + * A partial function built on a map. */ -class MapFunction implements Function { +abstract class MapFunction implements Function { private final Map map; @@ -24,7 +21,7 @@ class MapFunction implements Function { this.map = map; } - public Map getMap() { + protected Map getMap() { return map; } @@ -32,11 +29,6 @@ class MapFunction implements Function { return map.isEmpty(); } - @Override - public @Nullable R apply(@NonNull T var) { - return map.get(var); - } - @Override public String toString() { return map.entrySet().stream() From 5a13a9425d951810ac9ca24e763e579564b01159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 28 Aug 2020 19:36:08 +0200 Subject: [PATCH 002/101] Refactor metrics --- .../pmd/lang/apex/ApexHandler.java | 35 +- .../pmd/lang/apex/metrics/ApexMetrics.java | 77 +++++ .../metrics/impl/AbstractApexClassMetric.java | 24 -- .../impl/AbstractApexOperationMetric.java | 32 -- .../impl/ClassCognitiveComplexityMetric.java | 22 -- .../impl/CognitiveComplexityMetric.java | 26 -- .../pmd/lang/apex/metrics/impl/WmcMetric.java | 23 -- .../ApexMetricsHelper.java} | 24 +- .../CognitiveComplexityVisitor.java | 8 +- .../StandardCycloVisitor.java | 15 +- .../rule/design/CognitiveComplexityRule.java | 13 +- .../rule/design/CyclomaticComplexityRule.java | 13 +- .../impl/AbstractApexMetricTestRule.java | 2 +- .../pmd/lang/LanguageVersionHandler.java | 2 +- .../pmd/lang/metrics/AbstractMetric.java | 2 +- .../lang/metrics/LanguageMetricsProvider.java | 46 +-- .../sourceforge/pmd/lang/metrics/Metric.java | 80 ++++- .../pmd/lang/metrics/MetricKey.java | 15 +- .../pmd/lang/metrics/MetricsUtil.java | 44 +-- .../lang/metrics/ParameterizedMetricKey.java | 18 +- .../AbstractLanguageMetricsProvider.java | 66 ---- .../java/internal/JavaLanguageHandler.java | 45 ++- .../java/metrics/AbstractJavaClassMetric.java | 18 +- .../lang/java/metrics/AbstractJavaMetric.java | 20 -- .../metrics/AbstractJavaOperationMetric.java | 4 +- .../lang/java/metrics/api/JavaMetrics.java | 316 ++++++++++++++++++ .../java/metrics/internal/AtfdMetric.java | 55 --- .../metrics/internal/ClassFanOutMetric.java | 4 +- .../java/metrics/internal/CycloMetric.java | 96 ------ .../lang/java/metrics/internal/LocMetric.java | 53 --- .../java/metrics/internal/NcssMetric.java | 78 ----- .../java/metrics/internal/NoamMetric.java | 31 -- .../java/metrics/internal/NopaMetric.java | 30 -- .../java/metrics/internal/NpathMetric.java | 26 -- .../lang/java/metrics/internal/TccMetric.java | 78 ----- .../lang/java/metrics/internal/WmcMetric.java | 27 -- .../lang/java/metrics/internal/WocMetric.java | 37 -- .../internal/visitors/CycloVisitor.java | 16 +- .../internal/visitors/NpathBaseVisitor.java | 16 +- .../multifile/signature/JavaAstUtils.java | 90 +++++ .../rule/design/CyclomaticComplexityRule.java | 58 ++-- .../lang/java/rule/design/DataClassRule.java | 26 +- .../lang/java/rule/design/GodClassRule.java | 14 +- .../lang/java/rule/design/NcssCountRule.java | 20 +- .../rule/xpath/internal/MetricFunction.java | 57 +--- 45 files changed, 776 insertions(+), 1026 deletions(-) create mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexClassMetric.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexOperationMetric.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/ClassCognitiveComplexityMetric.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/CognitiveComplexityMetric.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/WmcMetric.java rename pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/{impl/CycloMetric.java => internal/ApexMetricsHelper.java} (57%) rename pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/{impl/visitors => internal}/CognitiveComplexityVisitor.java (96%) rename pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/{impl/visitors => internal}/StandardCycloVisitor.java (75%) delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/AbstractLanguageMetricsProvider.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaMetric.java create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/LocMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NcssMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NoamMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NopaMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/TccMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/WmcMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/WocMetric.java create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaAstUtils.java diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java index b2d57eb9c9..7774182693 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java @@ -4,21 +4,19 @@ package net.sourceforge.pmd.lang.apex; -import java.util.Arrays; -import java.util.List; +import static net.sourceforge.pmd.util.CollectionUtil.setOf; + +import java.util.Set; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler; import net.sourceforge.pmd.lang.Parser; import net.sourceforge.pmd.lang.ParserOptions; -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; import net.sourceforge.pmd.lang.apex.ast.ApexParser; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; +import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics; import net.sourceforge.pmd.lang.apex.rule.internal.ApexRuleViolationFactory; import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; -import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider; +import net.sourceforge.pmd.lang.metrics.Metric; import net.sourceforge.pmd.lang.rule.RuleViolationFactory; @InternalApi @@ -44,27 +42,20 @@ public class ApexHandler extends AbstractPmdLanguageVersionHandler { @Override - public LanguageMetricsProvider, ASTMethod> getLanguageMetricsProvider() { + public LanguageMetricsProvider getLanguageMetricsProvider() { return myMetricsProvider; } - private static class ApexMetricsProvider extends AbstractLanguageMetricsProvider, ASTMethod> { - - @SuppressWarnings("unchecked") - ApexMetricsProvider() { - // a wild double cast - super((Class>) (Object) ASTUserClassOrInterface.class, ASTMethod.class); - } - - @Override - public List getAvailableTypeMetrics() { - return Arrays.asList(ApexClassMetricKey.values()); - } + private static class ApexMetricsProvider implements LanguageMetricsProvider { @Override - public List getAvailableOperationMetrics() { - return Arrays.asList(ApexOperationMetricKey.values()); + public Set> getMetrics() { + return setOf( + ApexMetrics.COGNITIVE_COMPLEXITY, + ApexMetrics.CYCLO, + ApexMetrics.WEIGHED_METHOD_COUNT + ); } } } 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 new file mode 100644 index 0000000000..e97bc7953d --- /dev/null +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java @@ -0,0 +1,77 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.metrics; + +import static net.sourceforge.pmd.internal.util.PredicateUtil.always; + +import java.util.function.Function; +import java.util.function.Predicate; + +import org.apache.commons.lang3.mutable.MutableInt; + +import net.sourceforge.pmd.internal.util.PredicateUtil; +import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; +import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; +import net.sourceforge.pmd.lang.apex.ast.ApexNode; +import net.sourceforge.pmd.lang.apex.metrics.internal.CognitiveComplexityVisitor; +import net.sourceforge.pmd.lang.apex.metrics.internal.CognitiveComplexityVisitor.State; +import net.sourceforge.pmd.lang.apex.metrics.internal.StandardCycloVisitor; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.metrics.Metric; +import net.sourceforge.pmd.lang.metrics.MetricOptions; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; + +/** + * + */ +public final class ApexMetrics { + + public static final Metric, Integer> CYCLO = + Metric.of(ApexMetrics::computeCyclo, isApexNode(), + "Cyclomatic Complexity", "Cyclo"); + + public static final Metric, Integer> COGNITIVE_COMPLEXITY = + Metric.of(ApexMetrics::computeCognitiveComp, isApexNode(), + "Cognitive Complexity"); + + + public static final Metric, Integer> WEIGHED_METHOD_COUNT = + Metric.of(ApexMetrics::computeWmc, filterMapNode(ASTUserClass.class, PredicateUtil.always()), + "Weighed Method Count", "WMC"); + + private ApexMetrics() { + // utility class + } + + + + private static Function> isApexNode() { + return filterMapNode(ApexNode.class, always()); + } + + private static Function filterMapNode(Class klass, Predicate pred) { + return n -> n.asStream().filterIs(klass).filter(pred).first(); + } + + private static int computeCyclo(ApexNode node, MetricOptions ignored) { + MutableInt result = new MutableInt(1); + node.acceptVisitor(new StandardCycloVisitor(), result); + return result.getValue(); + } + + private static int computeCognitiveComp(ApexNode node, MetricOptions ignored) { + State state = new State(); + node.acceptVisitor(CognitiveComplexityVisitor.INSTANCE, state); + return state.getComplexity(); + } + + + + private static int computeWmc(ASTUserClassOrInterface node, MetricOptions options) { + return (int) MetricsUtil.computeStatistics(CYCLO, node.getMethods(), options).getSum(); + } + + +} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexClassMetric.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexClassMetric.java deleted file mode 100644 index ca0dbc5980..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexClassMetric.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.impl; - -import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; -import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface.TypeKind; -import net.sourceforge.pmd.lang.apex.metrics.AbstractApexMetric; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetric; - -/** - * Base class for Apex metrics. - * - * @author Clément Fournier - */ -public abstract class AbstractApexClassMetric extends AbstractApexMetric> - implements ApexClassMetric { - - @Override - public boolean supports(ASTUserClassOrInterface node) { - return node.getTypeKind() == TypeKind.CLASS; - } -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexOperationMetric.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexOperationMetric.java deleted file mode 100644 index 54a7ad66a1..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexOperationMetric.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.impl; - -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; -import net.sourceforge.pmd.lang.apex.metrics.AbstractApexMetric; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetric; - -/** - * Base class for Apex operation metrics. - * - * @author Clément Fournier - */ -public abstract class AbstractApexOperationMetric extends AbstractApexMetric implements ApexOperationMetric { - - /** - * Checks if the metric can be computed on the node. For now, we filter out {@literal , and clone}, - * which are present in all apex class nodes even if they're not implemented, which may yield unexpected results. - * - * @param node The node to check - * - * @return True if the metric can be computed - */ - @Override - public boolean supports(ASTMethod node) { - return !node.isSynthetic() - && !node.getFirstChildOfType(ASTModifierNode.class).isAbstract(); - } -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/ClassCognitiveComplexityMetric.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/ClassCognitiveComplexityMetric.java deleted file mode 100644 index 3193727c30..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/ClassCognitiveComplexityMetric.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.impl; - -import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; -import net.sourceforge.pmd.lang.metrics.MetricOptions; -import net.sourceforge.pmd.lang.metrics.MetricsUtil; - -/** - * The sum of the cognitive complexities of all the methods within a class. - * - * @author Gwilym Kuiper - */ -public class ClassCognitiveComplexityMetric extends AbstractApexClassMetric { - @Override - public double computeFor(ASTUserClassOrInterface node, MetricOptions options) { - return MetricsUtil.computeStatistics(ApexOperationMetricKey.COGNITIVE, node.getMethods()).getSum(); - } -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/CognitiveComplexityMetric.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/CognitiveComplexityMetric.java deleted file mode 100644 index ce508231a5..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/CognitiveComplexityMetric.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.impl; - -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.metrics.impl.visitors.CognitiveComplexityVisitor; -import net.sourceforge.pmd.lang.apex.metrics.impl.visitors.CognitiveComplexityVisitor.State; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - -/** - * Measures the cognitive complexity of a Class / Method in Apex. - * - * See https://www.sonarsource.com/docs/CognitiveComplexity.pdf for information about the metric - * - * @author Gwilym Kuiper - */ -public class CognitiveComplexityMetric extends AbstractApexOperationMetric { - @Override - public double computeFor(ASTMethod node, MetricOptions options) { - State state = new State(); - node.acceptVisitor(CognitiveComplexityVisitor.INSTANCE, state); - return state.getComplexity(); - } -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/WmcMetric.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/WmcMetric.java deleted file mode 100644 index dc13dc9d23..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/WmcMetric.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.apex.metrics.impl; - -import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; -import net.sourceforge.pmd.lang.metrics.MetricOptions; -import net.sourceforge.pmd.lang.metrics.MetricsUtil; - -/** - * See the doc for the Java metric. - * - * @author Clément Fournier - */ -public class WmcMetric extends AbstractApexClassMetric { - - @Override - public double computeFor(ASTUserClassOrInterface node, MetricOptions options) { - return MetricsUtil.computeStatistics(ApexOperationMetricKey.CYCLO, node.getMethods()).getSum(); - } -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/CycloMetric.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/internal/ApexMetricsHelper.java similarity index 57% rename from pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/CycloMetric.java rename to pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/internal/ApexMetricsHelper.java index da9d0483e9..5a93ea7260 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/CycloMetric.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/internal/ApexMetricsHelper.java @@ -1,38 +1,26 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.apex.metrics.impl; +package net.sourceforge.pmd.lang.apex.metrics.internal; import java.util.HashSet; import java.util.Set; -import org.apache.commons.lang3.mutable.MutableInt; - import net.sourceforge.pmd.lang.apex.ast.ASTBooleanExpression; -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTStandardCondition; -import net.sourceforge.pmd.lang.apex.metrics.impl.visitors.StandardCycloVisitor; -import net.sourceforge.pmd.lang.metrics.MetricOptions; import apex.jorje.data.ast.BooleanOp; /** - * See the doc for the Java metric. * - * @author Clément Fournier */ -public class CycloMetric extends AbstractApexOperationMetric { +public final class ApexMetricsHelper { - - @Override - public double computeFor(ASTMethod node, MetricOptions options) { - MutableInt result = new MutableInt(1); - node.acceptVisitor(new StandardCycloVisitor(), result); - return result.doubleValue(); + private ApexMetricsHelper() { + // utility class } - /** * Computes the number of control flow paths through that expression, which is the number of {@code ||} and {@code * &&} operators. Used both by Npath and Cyclo. @@ -41,7 +29,7 @@ public class CycloMetric extends AbstractApexOperationMetric { * * @return The complexity of the expression */ - public static int booleanExpressionComplexity(ASTStandardCondition expression) { + static int booleanExpressionComplexity(ASTStandardCondition expression) { Set subs = new HashSet<>(expression.findDescendantsOfType(ASTBooleanExpression.class)); int complexity = 0; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/CognitiveComplexityVisitor.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/internal/CognitiveComplexityVisitor.java similarity index 96% rename from pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/CognitiveComplexityVisitor.java rename to pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/internal/CognitiveComplexityVisitor.java index 3653ce4517..f6953c0660 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/CognitiveComplexityVisitor.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/internal/CognitiveComplexityVisitor.java @@ -1,8 +1,8 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.apex.metrics.impl.visitors; +package net.sourceforge.pmd.lang.apex.metrics.internal; import net.sourceforge.pmd.lang.apex.ast.ASTBlockStatement; import net.sourceforge.pmd.lang.apex.ast.ASTBooleanExpression; @@ -21,7 +21,7 @@ import net.sourceforge.pmd.lang.apex.ast.ASTTernaryExpression; import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.ast.ApexVisitorBase; -import net.sourceforge.pmd.lang.apex.metrics.impl.visitors.CognitiveComplexityVisitor.State; +import net.sourceforge.pmd.lang.apex.metrics.internal.CognitiveComplexityVisitor.State; import apex.jorje.data.ast.BooleanOp; import apex.jorje.data.ast.PrefixOp; @@ -41,7 +41,7 @@ public class CognitiveComplexityVisitor extends ApexVisitorBase { private BooleanOp currentBooleanOperation = null; private String methodName = null; - public double getComplexity() { + public int getComplexity() { return complexity; } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/StandardCycloVisitor.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/internal/StandardCycloVisitor.java similarity index 75% rename from pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/StandardCycloVisitor.java rename to pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/internal/StandardCycloVisitor.java index 462aa48107..8cfdc83f68 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/StandardCycloVisitor.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/internal/StandardCycloVisitor.java @@ -1,8 +1,8 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.apex.metrics.impl.visitors; +package net.sourceforge.pmd.lang.apex.metrics.internal; import org.apache.commons.lang3.mutable.MutableInt; @@ -17,7 +17,6 @@ import net.sourceforge.pmd.lang.apex.ast.ASTTernaryExpression; import net.sourceforge.pmd.lang.apex.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement; import net.sourceforge.pmd.lang.apex.ast.ApexVisitorBase; -import net.sourceforge.pmd.lang.apex.metrics.impl.CycloMetric; /** * @author Clément Fournier @@ -32,7 +31,7 @@ public class StandardCycloVisitor extends ApexVisitorBase { @Override public Void visit(ASTIfBlockStatement node, MutableInt data) { - data.add(1 + CycloMetric.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); + data.add(1 + ApexMetricsHelper.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); return super.visit(node, data); } @@ -47,7 +46,7 @@ public class StandardCycloVisitor extends ApexVisitorBase { @Override public Void visit(ASTForLoopStatement node, MutableInt data) { data.add( - 1 + CycloMetric.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); + 1 + ApexMetricsHelper.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); return super.visit(node, data); } @@ -68,7 +67,7 @@ public class StandardCycloVisitor extends ApexVisitorBase { @Override public Void visit(ASTWhileLoopStatement node, MutableInt data) { data.add( - 1 + CycloMetric.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); + 1 + ApexMetricsHelper.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); return super.visit(node, data); } @@ -76,7 +75,7 @@ public class StandardCycloVisitor extends ApexVisitorBase { @Override public Void visit(ASTDoLoopStatement node, MutableInt data) { data.add( - 1 + CycloMetric.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); + 1 + ApexMetricsHelper.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); return super.visit(node, data); } @@ -84,7 +83,7 @@ public class StandardCycloVisitor extends ApexVisitorBase { @Override public Void visit(ASTTernaryExpression node, MutableInt data) { data.add( - 1 + CycloMetric.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); + 1 + ApexMetricsHelper.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTStandardCondition.class))); return super.visit(node, data); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CognitiveComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CognitiveComplexityRule.java index 5c4018404c..0be66af8ad 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CognitiveComplexityRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CognitiveComplexityRule.java @@ -11,8 +11,7 @@ import java.util.Stack; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserTrigger; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; +import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -60,11 +59,11 @@ public class CognitiveComplexityRule extends AbstractApexRule { super.visit(node, data); classNames.pop(); - if (ApexClassMetricKey.COGNITIVE.supports(node)) { - int classCognitive = (int) MetricsUtil.computeMetric(ApexClassMetricKey.COGNITIVE, node); + if (ApexMetrics.COGNITIVE_COMPLEXITY.supports(node)) { + int classCognitive = MetricsUtil.computeMetric(ApexMetrics.COGNITIVE_COMPLEXITY, node); if (classCognitive >= getProperty(CLASS_LEVEL_DESCRIPTOR)) { - int classHighest = (int) MetricsUtil.computeStatistics(ApexOperationMetricKey.COGNITIVE, node.getMethods()).getMax(); + int classHighest = (int) MetricsUtil.computeStatistics(ApexMetrics.COGNITIVE_COMPLEXITY, node.getMethods()).getMax(); String[] messageParams = { "class", @@ -83,8 +82,8 @@ public class CognitiveComplexityRule extends AbstractApexRule { @Override public final Object visit(ASTMethod node, Object data) { - if (ApexOperationMetricKey.COGNITIVE.supports(node)) { - int cognitive = (int) MetricsUtil.computeMetric(ApexOperationMetricKey.COGNITIVE, node); + if (ApexMetrics.COGNITIVE_COMPLEXITY.supports(node)) { + int cognitive = MetricsUtil.computeMetric(ApexMetrics.COGNITIVE_COMPLEXITY, node); if (cognitive >= getProperty(METHOD_LEVEL_DESCRIPTOR)) { String opType = inTrigger ? "trigger" : node.getImage().equals(classNames.peek()) ? "constructor" 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 a6170dec30..52eda89bb7 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 @@ -12,8 +12,7 @@ import java.util.Stack; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserTrigger; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; +import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -67,11 +66,11 @@ public class CyclomaticComplexityRule extends AbstractApexRule { super.visit(node, data); classNames.pop(); - if (ApexClassMetricKey.WMC.supports(node)) { - int classWmc = (int) MetricsUtil.computeMetric(ApexClassMetricKey.WMC, node); + if (ApexMetrics.WEIGHED_METHOD_COUNT.supports(node)) { + int classWmc = MetricsUtil.computeMetric(ApexMetrics.WEIGHED_METHOD_COUNT, node); if (classWmc >= getProperty(CLASS_LEVEL_DESCRIPTOR)) { - int classHighest = (int) MetricsUtil.computeStatistics(ApexOperationMetricKey.CYCLO, node.getMethods()).getMax(); + int classHighest = (int) MetricsUtil.computeStatistics(ApexMetrics.CYCLO, node.getMethods()).getMax(); String[] messageParams = {"class", node.getImage(), @@ -88,8 +87,8 @@ public class CyclomaticComplexityRule extends AbstractApexRule { @Override public final Object visit(ASTMethod node, Object data) { - if (ApexOperationMetricKey.CYCLO.supports(node)) { - int cyclo = (int) MetricsUtil.computeMetric(ApexOperationMetricKey.CYCLO, node); + if (ApexMetrics.CYCLO.supports(node)) { + int cyclo = MetricsUtil.computeMetric(ApexMetrics.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/impl/AbstractApexMetricTestRule.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java index 1621829bd1..40e7433683 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 @@ -124,7 +124,7 @@ public abstract class AbstractApexMetricTestRule extends AbstractApexRule { @Override - public Object visit(ASTUserClass node, Object data) { + public Object visit(ApN node, Object data) { reportClasses = getProperty(reportClassesDescriptor); reportMethods = getProperty(reportMethodsDescriptor); reportLevel = getProperty(reportLevelDescriptor); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionHandler.java index 16b0e724ae..2be3f7f109 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionHandler.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/LanguageVersionHandler.java @@ -80,7 +80,7 @@ public interface LanguageVersionHandler { * instance the return type will probably be changed to an Optional. */ @Experimental - default LanguageMetricsProvider getLanguageMetricsProvider() { + default LanguageMetricsProvider getLanguageMetricsProvider() { return null; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetric.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetric.java index 68cc055f09..b8d436ca22 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetric.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetric.java @@ -14,7 +14,7 @@ import net.sourceforge.pmd.lang.ast.Node; * @author Clément Fournier * @since 6.0.0 */ -public abstract class AbstractMetric implements Metric { +public abstract class AbstractMetric implements Metric { /** * Metrics should be stateless, thus any instance of the same metric class should be equal. 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 5f67aa1238..66ef23689c 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 @@ -4,8 +4,11 @@ package net.sourceforge.pmd.lang.metrics; -import java.util.List; +import java.util.HashMap; import java.util.Map; +import java.util.Set; + +import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.annotation.Experimental; import net.sourceforge.pmd.lang.LanguageVersionHandler; @@ -28,35 +31,9 @@ import net.sourceforge.pmd.lang.ast.Node; * @since 6.11.0 */ @Experimental -public interface LanguageMetricsProvider { - - /** - * Returns a list of all supported type metric keys - * for the language. - */ - List> getAvailableTypeMetrics(); - - - /** - * Returns a list of all supported operation metric keys - * for the language. - */ - List> getAvailableOperationMetrics(); - - - /** - * Returns the given node casted to {@link T} if it's of the correct - * type, otherwise returns null. - */ - T asTypeNode(Node anyNode); - - - /** - * Returns the given node casted to {@link O} if it's of the correct - * type, otherwise returns null. - */ - O asOperationNode(Node anyNode); +public interface LanguageMetricsProvider { + Set> getMetrics(); /** * Computes all metrics available on the given node. @@ -66,5 +43,14 @@ public interface LanguageMetricsProvider { * * @return A map of metric key to their result, possibly empty, but with no null value */ - Map, Double> computeAllMetricsFor(Node node); + default Map, Number> computeAllMetricsFor(Node node) { + Map, Number> results = new HashMap<>(); + for (Metric metric : getMetrics()) { + @Nullable Number result = Metric.compute(metric, MetricOptions.emptyOptions(), node); + if (result != null) { + results.put(metric, result); + } + } + return results; + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java index 36fad4e812..8e000d4456 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java @@ -4,7 +4,15 @@ package net.sourceforge.pmd.lang.metrics; +import java.util.function.BiFunction; +import java.util.function.Function; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import net.sourceforge.pmd.internal.util.AssertionUtil; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.util.DataMap.DataKey; /** * Object computing a metric on a node. Metric objects are stateless, which means that instances of the same @@ -15,7 +23,9 @@ import net.sourceforge.pmd.lang.ast.Node; * @author Clément Fournier * @since 6.0.0 */ -public interface Metric { +public interface Metric extends DataKey, R> { + + String name(); /** @@ -26,7 +36,15 @@ public interface Metric { * * @return True if the metric can be computed */ - boolean supports(N node); + default boolean supports(Node node) { + return asN(node) != null; + } + + default boolean maySupport(Node node) { + return true; + } + + @Nullable N asN(Node node); /** @@ -37,6 +55,62 @@ public interface Metric { * * @return The value of the metric, or {@code Double.NaN} if it could not be computed. */ - double computeFor(N node, MetricOptions options); + R computeFor(N node, MetricOptions options); + + + interface MetricTargetSelector { + + N filterCast(Node node); + + boolean maySupport(Node node); + } + + /** + * Creates a new metric key from its metric and name. + * + * @param name The name of the metric + * @param compute Implementation for {@link #computeFor(Node, MetricOptions)} + * @param supports Implementation for {@link #supports(Node)} + * @param Type of node the metric can be computed on + * + * @return The metric key + * + * @throws NullPointerException If either parameter is null + */ + static Metric of(BiFunction compute, + Function supports, + @NonNull String name, + String... aliases) { + AssertionUtil.requireParamNotNull("name", name); + AssertionUtil.requireParamNotNull("compute", compute); + AssertionUtil.requireParamNotNull("supports", supports); + + return new Metric() { + @Override + public String name() { + return name; + } + + @Override + public @Nullable T asN(Node node) { + return supports.apply(node); + } + + @Override + public R computeFor(T node, MetricOptions options) { + return compute.apply(node, options); + } + + }; + } + + + static @Nullable R compute(Metric metric, MetricOptions options, Node node) { + N n = metric.asN(node); + if (n != null) { + return metric.computeFor(n, options); + } + return null; + } } 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 6f4833e8d8..4fe1af401d 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 @@ -21,7 +21,7 @@ import net.sourceforge.pmd.util.DataMap.DataKey; * @author Clément Fournier * @since 5.8.0 */ -public interface MetricKey extends DataKey, Double> { +public interface MetricKey extends DataKey, R> { /** * Returns the name of the metric. @@ -36,18 +36,17 @@ public interface MetricKey extends DataKey, Double> * * @return The calculator */ - Metric getCalculator(); + Metric getCalculator(); /** * Returns true if the metric held by this key can be computed on this node. - * TODO this should be turned into supports(Node) * * @param node The node to test * * @return Whether or not the metric can be computed on this node */ - boolean supports(N node); + boolean supports(Node node); // TODO the metric key should know about supported options @@ -63,11 +62,11 @@ public interface MetricKey extends DataKey, Double> * * @throws NullPointerException If either parameter is null */ - static MetricKey of(@NonNull String name, @NonNull Metric metric) { + static MetricKey of(@NonNull Metric metric, @NonNull String name, String... aliases) { AssertionUtil.requireParamNotNull("name", name); AssertionUtil.requireParamNotNull("metric", metric); - return new MetricKey() { + return new MetricKey() { @Override public String name() { return name; @@ -75,13 +74,13 @@ public interface MetricKey extends DataKey, Double> @Override - public Metric getCalculator() { + public Metric getCalculator() { return metric; } @Override - public boolean supports(T node) { + public boolean supports(Node node) { return metric.supports(node); } 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 1c01933988..ec0516cab8 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 @@ -24,8 +24,8 @@ public final class MetricsUtil { // util class } - public static boolean supportsAll(N node, MetricKey... metrics) { - for (MetricKey metric : metrics) { + public static boolean supportsAll(Node node, Metric... metrics) { + for (Metric metric : metrics) { if (!metric.supports(node)) { return false; } @@ -42,7 +42,7 @@ public final class MetricsUtil { * * @return Statistics for the value of the metric over all the nodes */ - public static DoubleSummaryStatistics computeStatistics(MetricKey key, Iterable ops) { + public static DoubleSummaryStatistics computeStatistics(Metric key, Iterable ops) { return computeStatistics(key, ops, MetricOptions.emptyOptions()); } @@ -55,7 +55,7 @@ public final class MetricsUtil { * * @return Statistics for the value of the metric over all the nodes */ - public static DoubleSummaryStatistics computeStatistics(MetricKey key, + public static DoubleSummaryStatistics computeStatistics(Metric key, Iterable ops, MetricOptions options) { @@ -66,7 +66,7 @@ public final class MetricsUtil { return StreamSupport.stream(ops.spliterator(), false) .filter(key::supports) - .collect(Collectors.summarizingDouble(op -> computeMetric(key, op, options))); + .collect(Collectors.summarizingDouble(op -> computeMetric(key, op, options).doubleValue())); } /** @@ -77,32 +77,10 @@ public final class MetricsUtil { * * @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) { + public static R computeMetric(Metric 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 - * - * @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. @@ -118,7 +96,7 @@ public final class MetricsUtil { * * @throws IllegalArgumentException If the metric does not support the given node */ - public static double computeMetric(MetricKey key, N node, MetricOptions options) { + public static R computeMetric(Metric key, N node, MetricOptions options) { return computeMetric(key, node, options, false); } @@ -138,7 +116,7 @@ public final class MetricsUtil { * * @throws IllegalArgumentException If the metric does not support the given node */ - public static double computeMetric(MetricKey key, N node, MetricOptions options, boolean forceRecompute) { + public static R computeMetric(Metric 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); @@ -148,13 +126,13 @@ public final class MetricsUtil { throw new IllegalArgumentException(key + " cannot be computed on " + node); } - ParameterizedMetricKey paramKey = ParameterizedMetricKey.getInstance(key, options); - Double prev = node.getUserMap().get(paramKey); + ParameterizedMetricKey paramKey = ParameterizedMetricKey.getInstance(key, options); + R prev = node.getUserMap().get(paramKey); if (!forceRecompute && prev != null) { return prev; } - double val = key.getCalculator().computeFor(node, options); + R val = key.computeFor(node, options); node.getUserMap().set(paramKey, val); return val; } 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 4a88780b20..c693211f5b 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 @@ -18,18 +18,18 @@ import net.sourceforge.pmd.util.DataMap.DataKey; * @author Clément Fournier * @since 5.8.0 */ -final class ParameterizedMetricKey implements DataKey, Double> { +final class ParameterizedMetricKey implements DataKey, R> { - private static final ConcurrentMap, ParameterizedMetricKey> POOL = new ConcurrentHashMap<>(); + private static final ConcurrentMap, ParameterizedMetricKey> POOL = new ConcurrentHashMap<>(); /** The metric key. */ - public final MetricKey key; + public final Metric key; /** The options of the metric. */ public final MetricOptions options; /** Used internally by the pooler. */ - private ParameterizedMetricKey(MetricKey key, MetricOptions options) { + private ParameterizedMetricKey(Metric key, MetricOptions options) { this.key = key; this.options = options; } @@ -44,8 +44,8 @@ final class ParameterizedMetricKey implements DataKey) o).key.equals(key) + && ((ParameterizedMetricKey) o).options.equals(options); } @@ -65,13 +65,13 @@ final class ParameterizedMetricKey implements DataKey ParameterizedMetricKey getInstance(MetricKey key, MetricOptions options) { + public static ParameterizedMetricKey getInstance(Metric key, MetricOptions options) { // sharing instances allows using DataMap, which uses reference identity - ParameterizedMetricKey tmp = new ParameterizedMetricKey<>(key, options); + ParameterizedMetricKey tmp = new ParameterizedMetricKey<>(key, options); POOL.putIfAbsent(tmp, tmp); @SuppressWarnings("unchecked") - ParameterizedMetricKey result = (ParameterizedMetricKey) POOL.get(tmp); + ParameterizedMetricKey result = (ParameterizedMetricKey) POOL.get(tmp); return result; } } 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 deleted file mode 100644 index 0f03e64415..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/internal/AbstractLanguageMetricsProvider.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.metrics.internal; - -import java.util.HashMap; -import java.util.Map; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; -import net.sourceforge.pmd.lang.metrics.MetricKey; -import net.sourceforge.pmd.lang.metrics.MetricsUtil; - - -/** - * Base implementation for {@link LanguageMetricsProvider}. - * - * @author Clément Fournier - * @since 6.11.0 - */ -public abstract class AbstractLanguageMetricsProvider implements LanguageMetricsProvider { - - private final Class tClass; - private final Class oClass; - - - protected AbstractLanguageMetricsProvider(Class tClass, - Class oClass) { - this.tClass = tClass; - this.oClass = oClass; - } - - - @Override - public T asTypeNode(Node anyNode) { - return tClass.isInstance(anyNode) ? tClass.cast(anyNode) : null; - } - - - @Override - public O asOperationNode(Node anyNode) { - return oClass.isInstance(anyNode) ? oClass.cast(anyNode) : null; - } - - - @Override - public Map, Double> computeAllMetricsFor(Node node) { - Map, Double> results = new HashMap<>(); - T t = asTypeNode(node); - if (t != null) { - for (MetricKey tkey : getAvailableTypeMetrics()) { - results.put(tkey, MetricsUtil.computeMetric(tkey, t)); - } - } - O o = asOperationNode(node); - if (o != null) { - for (MetricKey okey : getAvailableOperationMetrics()) { - results.put(okey, MetricsUtil.computeMetric(okey, o)); - } - } - - return results; - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java index c3a41d8329..5fe0ecbe30 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java @@ -4,19 +4,17 @@ package net.sourceforge.pmd.lang.java.internal; -import java.util.Arrays; -import java.util.List; +import static net.sourceforge.pmd.util.CollectionUtil.setOf; + +import java.util.Set; import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler; import net.sourceforge.pmd.lang.Parser; import net.sourceforge.pmd.lang.ParserOptions; -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.JavaParser; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; import net.sourceforge.pmd.lang.java.ast.internal.LanguageLevelChecker; import net.sourceforge.pmd.lang.java.ast.internal.ReportingStrategy; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleViolationFactory; import net.sourceforge.pmd.lang.java.rule.xpath.internal.BaseContextNodeTestFun; import net.sourceforge.pmd.lang.java.rule.xpath.internal.GetCommentOnFunction; @@ -25,8 +23,7 @@ import net.sourceforge.pmd.lang.java.rule.xpath.internal.MatchesSignatureFunctio import net.sourceforge.pmd.lang.java.rule.xpath.internal.MetricFunction; import net.sourceforge.pmd.lang.java.rule.xpath.internal.NodeIsFunction; import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; -import net.sourceforge.pmd.lang.metrics.MetricKey; -import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider; +import net.sourceforge.pmd.lang.metrics.Metric; import net.sourceforge.pmd.lang.rule.RuleViolationFactory; import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler; import net.sourceforge.pmd.util.designerbindings.DesignerBindings; @@ -47,7 +44,7 @@ public class JavaLanguageHandler extends AbstractPmdLanguageVersionHandler { ); private final LanguageLevelChecker levelChecker; - private final LanguageMetricsProvider myMetricsProvider = new JavaMetricsProvider(); + private final LanguageMetricsProvider myMetricsProvider = new JavaMetricsProvider(); public JavaLanguageHandler(int jdkVersion) { this(jdkVersion, false); @@ -84,26 +81,28 @@ public class JavaLanguageHandler extends AbstractPmdLanguageVersionHandler { @Override - public LanguageMetricsProvider getLanguageMetricsProvider() { + public LanguageMetricsProvider getLanguageMetricsProvider() { return myMetricsProvider; } - private static class JavaMetricsProvider extends AbstractLanguageMetricsProvider { - - JavaMetricsProvider() { - super(ASTAnyTypeDeclaration.class, MethodLikeNode.class); - } + public static class JavaMetricsProvider implements LanguageMetricsProvider { @Override - public List> getAvailableTypeMetrics() { - return Arrays.asList(JavaClassMetricKey.values()); - } - - - @Override - public List> getAvailableOperationMetrics() { - return Arrays.asList(JavaOperationMetricKey.values()); + public Set> getMetrics() { + return setOf( + JavaMetrics.ACCESS_TO_FOREIGN_DATA, + JavaMetrics.CYCLO, + JavaMetrics.NPATH, + JavaMetrics.NCSS, + JavaMetrics.LINES_OF_CODE, + JavaMetrics.FAN_OUT, + JavaMetrics.WEIGHED_METHOD_COUNT, + JavaMetrics.WEIGHT_OF_CLASS, + JavaMetrics.NUMBER_OF_ACCESSORS, + JavaMetrics.NUMBER_OF_PUBLIC_FIELDS, + JavaMetrics.TIGHT_CLASS_COHESION + ); } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java index 9573b9d363..5192be7789 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java @@ -10,9 +10,9 @@ import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetric; import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSigMask; import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSigMask; +import net.sourceforge.pmd.lang.metrics.AbstractMetric; /** @@ -20,7 +20,7 @@ import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSigMask; * * @author Clément Fournier */ -public abstract class AbstractJavaClassMetric extends AbstractJavaMetric implements JavaClassMetric { +public abstract class AbstractJavaClassMetric extends AbstractMetric { /** @@ -32,8 +32,8 @@ public abstract class AbstractJavaClassMetric extends AbstractJavaMetric decls = getMethodsAndConstructors(classNode); @@ -67,7 +67,7 @@ public abstract class AbstractJavaClassMetric extends AbstractJavaMetric decls = getFields(classNode); @@ -88,7 +88,7 @@ public abstract class AbstractJavaClassMetric extends AbstractJavaMetric getMethodsAndConstructors(ASTAnyTypeDeclaration node) { + protected static List getMethodsAndConstructors(ASTAnyTypeDeclaration node) { return getDeclarationsOfType(node, ASTMethodOrConstructorDeclaration.class); } @@ -100,12 +100,12 @@ public abstract class AbstractJavaClassMetric extends AbstractJavaMetric getFields(ASTAnyTypeDeclaration node) { + protected static List getFields(ASTAnyTypeDeclaration node) { return getDeclarationsOfType(node, ASTFieldDeclaration.class); } - private List getDeclarationsOfType(ASTAnyTypeDeclaration node, Class tClass) { + private static List getDeclarationsOfType(ASTAnyTypeDeclaration node, Class tClass) { return node.getDeclarations().filterIs(tClass).toList(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaMetric.java deleted file mode 100644 index b287e0400e..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaMetric.java +++ /dev/null @@ -1,20 +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.ast.Node; -import net.sourceforge.pmd.lang.metrics.AbstractMetric; - - -/** - * Base class for metrics. Metric objects encapsulate the computational logic required to compute a metric from a node. - * - * @param Type of node the metric can be computed on - * - * @author Clément Fournier - */ -public abstract class AbstractJavaMetric extends AbstractMetric { - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaOperationMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaOperationMetric.java index c6ecc5b9c5..7a4721a71c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaOperationMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaOperationMetric.java @@ -16,8 +16,8 @@ import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetric; * * @author Clément Fournier */ -public abstract class AbstractJavaOperationMetric extends AbstractJavaMetric - implements JavaOperationMetric { +public abstract class AbstractJavaOperationMetric extends net.sourceforge.pmd.lang.metrics.AbstractMetric + implements JavaOperationMetric { /** * Returns true if the metric can be computed on this operation. By default, abstract operations are filtered out. diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java new file mode 100644 index 0000000000..43cbe0c211 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -0,0 +1,316 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.metrics.api; + +import static net.sourceforge.pmd.internal.util.PredicateUtil.always; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; + +import org.apache.commons.lang3.mutable.MutableInt; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression; +import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression; +import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.AccessNode; +import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.metrics.internal.visitors.AtfdBaseVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.visitors.ClassFanOutVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.visitors.CycloVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NcssVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NpathBaseVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.visitors.TccAttributeAccessCollector; +import net.sourceforge.pmd.lang.java.multifile.signature.JavaAstUtils; +import net.sourceforge.pmd.lang.metrics.Metric; +import net.sourceforge.pmd.lang.metrics.MetricOption; +import net.sourceforge.pmd.lang.metrics.MetricOptions; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; + +/** + * + */ +public final class JavaMetrics { + + + public static final Metric LINES_OF_CODE = + Metric.of(JavaMetrics::computeLoc, isJavaNode(), + "Lines of code", "LOC"); + + public static final Metric NCSS = + Metric.of(JavaMetrics::computeNcss, isJavaNode(), + "Non-commenting source statements", "NCSS"); + + public static final Metric NUMBER_OF_ACCESSORS = + Metric.of(JavaMetrics::computeNoam, asClass(always()), + "Number of accessor methods", "NOAM"); + + public static final Metric NUMBER_OF_PUBLIC_FIELDS = + Metric.of(JavaMetrics::computeNopa, asClass(always()), + "Number of public attributes", "NOPA"); + + public static final Metric TIGHT_CLASS_COHESION = + Metric.of(JavaMetrics::computeTcc, asClass(it -> !it.isInterface()), + "Tight Class Cohesion", "TCC"); + + public static final Metric CYCLO = + Metric.of(JavaMetrics::computeCyclo, isJavaNode(), + "Cyclomatic Complexity", "Cyclo"); + + public static final Metric NPATH = + Metric.of(JavaMetrics::computeNpath, isJavaNode(), + "NPath Complexity", "NPath"); + + public static final Metric WEIGHED_METHOD_COUNT = + Metric.of(JavaMetrics::computeWmc, asClass(it -> !it.isInterface()), + "Weighed Method Count", "WMC"); + + public static final Metric ACCESS_TO_FOREIGN_DATA = + Metric.of(JavaMetrics::computeAtfd, isJavaNode(), + "Access To Foreign Data", "ATFD"); + + + public static final Metric WEIGHT_OF_CLASS = + Metric.of(JavaMetrics::computeWoc, asClass(it -> !it.isInterface()), + "Weight Of Class", "WOC"); + + + public static final Metric FAN_OUT = + Metric.of(JavaMetrics::computeFanOut, isJavaNode(), + "Fan-Out", "CFO"); + + + private JavaMetrics() { + // utility class + } + + + private static Function isJavaNode() { + return filterMapNode(JavaNode.class, always()); + } + + private static Function filterMapNode(Class klass, Predicate pred) { + return n -> n.asStream().filterIs(klass).filter(pred).first(); + } + + + private static Function asClass(Predicate pred) { + return filterMapNode(ASTAnyTypeDeclaration.class, pred); + } + + + private static int computeNoam(ASTAnyTypeDeclaration node, MetricOptions ignored) { + return node.getDeclarations() + .filterIs(ASTMethodDeclaration.class) + .filter(JavaAstUtils::isGetterOrSetter) + .count(); + } + + private static int computeNopa(ASTAnyTypeDeclaration node, MetricOptions ignored) { + return node.getDeclarations() + .filterIs(ASTFieldDeclaration.class) + .filter(AccessNode::isPublic) + .flatMap(ASTFieldDeclaration::getVarIds) + .count(); + } + + private static int computeNcss(JavaNode node, MetricOptions options) { + MutableInt ncss = (MutableInt) node.acceptVisitor(new NcssVisitor(options, node), new MutableInt(0)); + return ncss.getValue(); + } + + private static int computeLoc(JavaNode node, MetricOptions ignored) { + return 1 + node.getEndLine() - node.getBeginLine(); + } + + + private static int computeCyclo(JavaNode node, MetricOptions options) { + MutableInt counter = new MutableInt(1); + node.acceptVisitor(new CycloVisitor(options, node), counter); + return counter.getValue(); + } + + private static int computeNpath(JavaNode node, MetricOptions ignored) { + return (Integer) node.acceptVisitor(NpathBaseVisitor.INSTANCE, null); + } + + private static int computeWmc(ASTAnyTypeDeclaration node, MetricOptions options) { + return (int) MetricsUtil.computeStatistics(CYCLO, node.getOperations(), options).getSum(); + } + + + private static double computeTcc(ASTAnyTypeDeclaration node, MetricOptions ignored) { + Map> usagesByMethod = new TccAttributeAccessCollector(node).start(); + + int numPairs = numMethodsRelatedByAttributeAccess(usagesByMethod); + int maxPairs = maxMethodPairs(usagesByMethod.size()); + + return numPairs / (double) maxPairs; + } + + + /** + * Gets the number of pairs of methods that use at least one attribute in common. + * + * @param usagesByMethod Map of method name to names of local attributes accessed + * + * @return The number of pairs + */ + private static int numMethodsRelatedByAttributeAccess(Map> usagesByMethod) { + List methods = new ArrayList<>(usagesByMethod.keySet()); + int methodCount = methods.size(); + int pairs = 0; + + if (methodCount > 1) { + for (int i = 0; i < methodCount - 1; i++) { + for (int j = i + 1; j < methodCount; j++) { + String firstMethodName = methods.get(i); + String secondMethodName = methods.get(j); + + if (!Collections.disjoint(usagesByMethod.get(firstMethodName), + usagesByMethod.get(secondMethodName))) { + pairs++; + } + } + } + } + return pairs; + } + + + /** + * Calculates the number of possible method pairs of two methods. + * + * @param methods Number of methods in the class + * + * @return Number of possible method pairs + */ + private static int maxMethodPairs(int methods) { + return methods * (methods - 1) / 2; + } + + + /** Variants of NCSS. */ + public enum NcssOption implements MetricOption { + /** Counts import and package statement. This makes the metric JavaNCSS compliant. */ + COUNT_IMPORTS("countImports"); + + private final String vName; + + + NcssOption(String valueName) { + this.vName = valueName; + } + + + @Override + public String valueName() { + return vName; + } + } + + /** + * Evaluates the number of paths through a boolean expression. This is the total number of {@code &&} and {@code ||} + * operators appearing in the expression. This is used in the calculation of cyclomatic and n-path complexity. + * + * @param expr Expression to analyse + * + * @return The number of paths through the expression + */ + public static int booleanExpressionComplexity(Node expr) { + if (expr == null) { + return 0; + } + + List andNodes = expr.findDescendantsOfType(ASTConditionalAndExpression.class); + List orNodes = expr.findDescendantsOfType(ASTConditionalOrExpression.class); + + int complexity = 0; + + if (expr instanceof ASTConditionalOrExpression || expr instanceof ASTConditionalAndExpression) { + complexity++; + } + + for (ASTConditionalOrExpression element : orNodes) { + complexity += element.getNumChildren() - 1; + } + + for (ASTConditionalAndExpression element : andNodes) { + complexity += element.getNumChildren() - 1; + } + + return complexity; + } + + + /** Options for CYCLO. */ + public enum CycloOption implements MetricOption { + /** Do not count the paths in boolean expressions as decision points. */ + IGNORE_BOOLEAN_PATHS("ignoreBooleanPaths"), + /** Consider assert statements. */ + CONSIDER_ASSERT("considerAssert"); + + private final String vName; + + + CycloOption(String valueName) { + this.vName = valueName; + } + + + @Override + public String valueName() { + return vName; + } + } + + private static int computeAtfd(JavaNode node, MetricOptions options) { + return ((MutableInt) node.acceptVisitor(new AtfdBaseVisitor(), new MutableInt(0))).getValue(); + } + + + private static double computeWoc(ASTAnyTypeDeclaration node, MetricOptions ignored) { + NodeStream methods = + node.getDeclarations() + .filterIs(ASTMethodDeclaration.class) + .filter(it -> !it.isPrivate()); + + int notSetter = methods.filter(it -> !JavaAstUtils.isGetterOrSetter(it)).count(); + int total = methods.count(); + + return notSetter / (double) total; + } + + + private static int computeFanOut(JavaNode node, MetricOptions options) { + MutableInt cfo = (MutableInt) node.acceptVisitor(new ClassFanOutVisitor(options, node), new MutableInt(0)); + return cfo.getValue(); + } + + + public enum ClassFanOutOption implements MetricOption { + /** Whether to include Classes in the java.lang package. */ + INCLUDE_JAVA_LANG("includeJavaLang"); + + private final String vName; + + ClassFanOutOption(String valueName) { + this.vName = valueName; + } + + @Override + public String valueName() { + return vName; + } + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdMetric.java deleted file mode 100644 index 5eca7948dd..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdMetric.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import org.apache.commons.lang3.mutable.MutableInt; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaClassMetric; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.AtfdBaseVisitor; -import net.sourceforge.pmd.lang.metrics.MetricOptions; -import net.sourceforge.pmd.lang.metrics.MetricsUtil; - -/** - * Access to Foreign Data. Quantifies the number of foreign fields accessed directly or via accessors. - * - * @author Clément Fournier - * @since 6.0.0 - */ -public final class AtfdMetric { - - - public static final class AtfdOperationMetric extends AbstractJavaOperationMetric { - - @Override - public boolean supports(MethodLikeNode node) { - return node instanceof ASTMethodDeclaration && super.supports(node); - } - - - @Override - public double computeFor(MethodLikeNode node, MetricOptions options) { - return ((MutableInt) node.acceptVisitor(new AtfdBaseVisitor(), new MutableInt(0))).getValue(); - } - - } - - public static final class AtfdClassMetric extends AbstractJavaClassMetric { - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - // TODO maybe consider code outside methods - return MetricsUtil.computeStatistics(JavaOperationMetricKey.ATFD, node.getOperations(), options).getSum(); - } - - - } - - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutMetric.java index a3047a64bc..927e786e9d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutMetric.java @@ -43,9 +43,9 @@ public final class ClassFanOutMetric { @Override public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - MutableInt cfo = (MutableInt) node.acceptVisitor(new ClassFanOutVisitor(options, node), new MutableInt(0)); - return (double) cfo.getValue(); + return computeFanOut(node, options); } + } public static final class ClassFanOutOperationMetric extends AbstractJavaOperationMetric { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloMetric.java deleted file mode 100644 index 0875c445b6..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloMetric.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import java.util.List; - -import org.apache.commons.lang3.mutable.MutableInt; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression; -import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.CycloVisitor; -import net.sourceforge.pmd.lang.metrics.MetricOption; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - - -/** - * Cyclomatic Complexity. See the documentation site. - * - * @author Clément Fournier - * @since June 2017 - */ -public final class CycloMetric extends AbstractJavaOperationMetric { - - - // TODO:cf Cyclo should develop factorized boolean operators to count them - - - @Override - public double computeFor(MethodLikeNode node, MetricOptions options) { - MutableInt counter = new MutableInt(1); - node.acceptVisitor(new CycloVisitor(options, node), counter); - return (double) counter.getValue(); - } - - - /** - * Evaluates the number of paths through a boolean expression. This is the total number of {@code &&} and {@code ||} - * operators appearing in the expression. This is used in the calculation of cyclomatic and n-path complexity. - * - * @param expr Expression to analyse - * - * @return The number of paths through the expression - */ - public static int booleanExpressionComplexity(Node expr) { - if (expr == null) { - return 0; - } - - List andNodes = expr.findDescendantsOfType(ASTConditionalAndExpression.class); - List orNodes = expr.findDescendantsOfType(ASTConditionalOrExpression.class); - - int complexity = 0; - - if (expr instanceof ASTConditionalOrExpression || expr instanceof ASTConditionalAndExpression) { - complexity++; - } - - for (ASTConditionalOrExpression element : orNodes) { - complexity += element.getNumChildren() - 1; - } - - for (ASTConditionalAndExpression element : andNodes) { - complexity += element.getNumChildren() - 1; - } - - return complexity; - } - - - /** Options for CYCLO. */ - public enum CycloOption implements MetricOption { - /** Do not count the paths in boolean expressions as decision points. */ - IGNORE_BOOLEAN_PATHS("ignoreBooleanPaths"), - /** Consider assert statements. */ - CONSIDER_ASSERT("considerAssert"); - - private final String vName; - - - CycloOption(String valueName) { - this.vName = valueName; - } - - - @Override - public String valueName() { - return vName; - } - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/LocMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/LocMetric.java deleted file mode 100644 index e50c227bb6..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/LocMetric.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaClassMetric; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaOperationMetric; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - -/** - * Lines of Code. See the documentation site. - * - * @author Clément Fournier - * @see NcssMetric - * @since June 2017 - */ -public final class LocMetric { - - - public static final class LocOperationMetric extends AbstractJavaOperationMetric { - - @Override - public boolean supports(MethodLikeNode node) { - return true; - } - - - @Override - public double computeFor(MethodLikeNode node, MetricOptions options) { - return 1 + node.getEndLine() - node.getBeginLine(); - } - } - - public static final class LocClassMetric extends AbstractJavaClassMetric { - - @Override - public boolean supports(ASTAnyTypeDeclaration node) { - return true; - } - - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - return 1 + node.getEndLine() - node.getBeginLine(); - } - - - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NcssMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NcssMetric.java deleted file mode 100644 index 7149c6202e..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NcssMetric.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import org.apache.commons.lang3.mutable.MutableInt; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaClassMetric; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NcssVisitor; -import net.sourceforge.pmd.lang.metrics.MetricOption; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - -/** - * Non-commenting source statements. See the documentation site. - * - * @author Clément Fournier - * @see LocMetric - * @since June 2017 - */ -public final class NcssMetric { - - - /** Variants of NCSS. */ - public enum NcssOption implements MetricOption { - /** Counts import and package statement. This makes the metric JavaNCSS compliant. */ - COUNT_IMPORTS("countImports"); - - private final String vName; - - - NcssOption(String valueName) { - this.vName = valueName; - } - - - @Override - public String valueName() { - return vName; - } - } - - public static final class NcssClassMetric extends AbstractJavaClassMetric { - - @Override - public boolean supports(ASTAnyTypeDeclaration node) { - return true; - } - - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - MutableInt ncss = (MutableInt) node.acceptVisitor(new NcssVisitor(options, node), new MutableInt(0)); - return (double) ncss.getValue(); - } - - } - - public static final class NcssOperationMetric extends AbstractJavaOperationMetric { - - @Override - public boolean supports(MethodLikeNode node) { - return true; - } - - - @Override - public double computeFor(MethodLikeNode node, MetricOptions options) { - MutableInt ncss = (MutableInt) node.acceptVisitor(new NcssVisitor(options, node), new MutableInt(0)); - return (double) ncss.getValue(); - } - - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NoamMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NoamMetric.java deleted file mode 100644 index 0355976f5f..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NoamMetric.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaClassMetric; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSigMask; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature.Role; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaSignature.Visibility; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - -/** - * Number of accessor methods. - * - * @author Clément Fournier - * @since 6.0.0 - */ -public class NoamMetric extends AbstractJavaClassMetric { - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - JavaOperationSigMask mask = new JavaOperationSigMask(); - mask.restrictRolesTo(Role.GETTER_OR_SETTER); - mask.restrictVisibilitiesTo(Visibility.PUBLIC); - - - return countMatchingOpSigs(node, mask); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NopaMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NopaMetric.java deleted file mode 100644 index e788664cb4..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NopaMetric.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaClassMetric; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSigMask; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaSignature.Visibility; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - -/** - * Number of public attributes. - * - * @author Clément Fournier - * @since 6.0.0 - */ -public class NopaMetric extends AbstractJavaClassMetric { - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - - JavaFieldSigMask mask = new JavaFieldSigMask(); - mask.restrictVisibilitiesTo(Visibility.PUBLIC); - - return countMatchingFieldSigs(node, mask); - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathMetric.java deleted file mode 100644 index dab3227750..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathMetric.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - - -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NpathBaseVisitor; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - -/** - * NPath complexity. See the documentation site. - * - * @author Clément Fournier - * @since 6.0.0 - */ -public class NpathMetric extends AbstractJavaOperationMetric { - - @Override - public double computeFor(MethodLikeNode node, MetricOptions options) { - return (Integer) node.acceptVisitor(NpathBaseVisitor.INSTANCE, null); - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/TccMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/TccMetric.java deleted file mode 100644 index 8518d8e878..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/TccMetric.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaClassMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.TccAttributeAccessCollector; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - -/** - * Tight class cohesion. - * - * @author Clément Fournier - * @since 6.0.0 - */ -public class TccMetric extends AbstractJavaClassMetric { - - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - Map> usagesByMethod = new TccAttributeAccessCollector(node).start(); - - int numPairs = numMethodsRelatedByAttributeAccess(usagesByMethod); - int maxPairs = maxMethodPairs(usagesByMethod.size()); - - return numPairs / (double) maxPairs; - } - - - /** - * Gets the number of pairs of methods that use at least one attribute in common. - * - * @param usagesByMethod Map of method name to names of local attributes accessed - * - * @return The number of pairs - */ - private int numMethodsRelatedByAttributeAccess(Map> usagesByMethod) { - List methods = new ArrayList<>(usagesByMethod.keySet()); - int methodCount = methods.size(); - int pairs = 0; - - if (methodCount > 1) { - for (int i = 0; i < methodCount - 1; i++) { - for (int j = i + 1; j < methodCount; j++) { - String firstMethodName = methods.get(i); - String secondMethodName = methods.get(j); - - if (!Collections.disjoint(usagesByMethod.get(firstMethodName), - usagesByMethod.get(secondMethodName))) { - pairs++; - } - } - } - } - return pairs; - } - - - /** - * Calculates the number of possible method pairs of two methods. - * - * @param methods Number of methods in the class - * - * @return Number of possible method pairs - */ - private int maxMethodPairs(int methods) { - return methods * (methods - 1) / 2; - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/WmcMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/WmcMetric.java deleted file mode 100644 index 2ce51b8dc7..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/WmcMetric.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaClassMetric; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; -import net.sourceforge.pmd.lang.metrics.MetricOptions; -import net.sourceforge.pmd.lang.metrics.MetricsUtil; - -/** - * Weighed Method count. See the documentation - * site. - * - * @author Clément Fournier - * @since June 2017 - */ -public final class WmcMetric extends AbstractJavaClassMetric { - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - return MetricsUtil.computeStatistics(JavaOperationMetricKey.CYCLO, node.getOperations(), options).getSum(); - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/WocMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/WocMetric.java deleted file mode 100644 index 830ff0de17..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/WocMetric.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaClassMetric; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSigMask; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature.Role; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaSignature.Visibility; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - -/** - * Weight of class. - * - * @author Clément Fournier - * @since 6.0.0 - */ -public class WocMetric extends AbstractJavaClassMetric { - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - - JavaOperationSigMask mask = new JavaOperationSigMask(); - mask.forbid(Role.CONSTRUCTOR, Role.GETTER_OR_SETTER); - mask.restrictVisibilitiesTo(Visibility.PUBLIC); - - int functionalMethods = countMatchingOpSigs(node, mask); - - mask.coverAllRoles(); - - int totalPublicMethods = countMatchingOpSigs(node, mask); - - return functionalMethods / (double) totalPublicMethods; - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java index 01be0d4b10..6dfd14bf6c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java @@ -23,7 +23,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; -import net.sourceforge.pmd.lang.java.metrics.internal.CycloMetric; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.internal.CycloMetric.CycloOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; @@ -66,7 +66,7 @@ public class CycloVisitor extends JavaVisitorBase { private Void handleSwitch(ASTSwitchLike node, MutableInt data) { if (considerBooleanPaths) { - data.add(CycloMetric.booleanExpressionComplexity(node.getChild(0))); + data.add(JavaMetrics.booleanExpressionComplexity(node.getChild(0))); } for (ASTSwitchBranch branch : node) { @@ -92,7 +92,7 @@ public class CycloVisitor extends JavaVisitorBase { public Void visit(ASTConditionalExpression node, MutableInt data) { data.increment(); if (considerBooleanPaths) { - data.add(CycloMetric.booleanExpressionComplexity(node.getCondition())); + data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); } @@ -102,7 +102,7 @@ public class CycloVisitor extends JavaVisitorBase { public Void visit(ASTWhileStatement node, MutableInt data) { data.increment(); if (considerBooleanPaths) { - data.add(CycloMetric.booleanExpressionComplexity(node.getCondition())); + data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); } @@ -112,7 +112,7 @@ public class CycloVisitor extends JavaVisitorBase { public Void visit(ASTIfStatement node, MutableInt data) { data.increment(); if (considerBooleanPaths) { - data.add(CycloMetric.booleanExpressionComplexity(node.getCondition())); + data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); @@ -124,7 +124,7 @@ public class CycloVisitor extends JavaVisitorBase { data.increment(); if (considerBooleanPaths) { - data.add(CycloMetric.booleanExpressionComplexity(node.getCondition())); + data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); @@ -140,7 +140,7 @@ public class CycloVisitor extends JavaVisitorBase { public Void visit(ASTDoStatement node, MutableInt data) { data.increment(); if (considerBooleanPaths) { - data.add(CycloMetric.booleanExpressionComplexity(node.getCondition())); + data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); @@ -167,7 +167,7 @@ public class CycloVisitor extends JavaVisitorBase { data.add(2); // equivalent to if (condition) { throw .. } if (considerBooleanPaths) { - data.add(CycloMetric.booleanExpressionComplexity(node.getCondition())); + data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java index 54778ba4fc..08ee0647dc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java @@ -25,7 +25,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; -import net.sourceforge.pmd.lang.java.metrics.internal.CycloMetric; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; /** @@ -109,7 +109,7 @@ public class NpathBaseVisitor extends JavaParserVisitorAdapter { complexity += (int) element.jjtAccept(this, data); } - int boolCompIf = CycloMetric.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); + int boolCompIf = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); return boolCompIf + complexity; } @@ -118,7 +118,7 @@ public class NpathBaseVisitor extends JavaParserVisitorAdapter { public Object visit(ASTWhileStatement node, Object data) { // (npath of while + bool_comp of while + 1) * npath of next - int boolCompWhile = CycloMetric.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); + int boolCompWhile = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); int nPathWhile = (int) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data); @@ -130,7 +130,7 @@ public class NpathBaseVisitor extends JavaParserVisitorAdapter { public Object visit(ASTDoStatement node, Object data) { // (npath of do + bool_comp of do + 1) * npath of next - int boolCompDo = CycloMetric.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); + int boolCompDo = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); int nPathDo = (int) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data); @@ -142,7 +142,7 @@ public class NpathBaseVisitor extends JavaParserVisitorAdapter { public Object visit(ASTForStatement node, Object data) { // (npath of for + bool_comp of for + 1) * npath of next - int boolCompFor = CycloMetric.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class)); + int boolCompFor = JavaMetrics.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class)); int nPathFor = (int) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data); @@ -160,7 +160,7 @@ public class NpathBaseVisitor extends JavaParserVisitorAdapter { return 1; } - int boolCompReturn = CycloMetric.booleanExpressionComplexity(expr); + int boolCompReturn = JavaMetrics.booleanExpressionComplexity(expr); int conditionalExpressionComplexity = multiplyChildrenComplexities(expr, data); if (conditionalExpressionComplexity > 1) { @@ -184,7 +184,7 @@ public class NpathBaseVisitor extends JavaParserVisitorAdapter { public int handleSwitch(ASTSwitchLike node, Object data) { // bool_comp of switch + sum(npath(case_range)) - int boolCompSwitch = CycloMetric.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); + int boolCompSwitch = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); int npath = 0; int caseRange = 0; @@ -221,7 +221,7 @@ public class NpathBaseVisitor extends JavaParserVisitorAdapter { public Object visit(ASTConditionalExpression node, Object data) { // bool comp of guard clause + complexity of last two children (= total - 1) - int boolCompTernary = CycloMetric.booleanExpressionComplexity(node.getCondition()); + int boolCompTernary = JavaMetrics.booleanExpressionComplexity(node.getCondition()); return boolCompTernary + sumChildrenComplexities(node, data) - 1; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaAstUtils.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaAstUtils.java new file mode 100644 index 0000000000..598185cdbb --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaAstUtils.java @@ -0,0 +1,90 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.multifile.signature; + +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; + +/** + * + */ +public final class JavaAstUtils { + private static final Pattern FIELD_NAME_PATTERN = Pattern.compile("(?:m_|_)?(\\w+)"); + + private JavaAstUtils() { + // utility class + } + + + public static boolean isGetterOrSetter(ASTMethodDeclaration node) { + + // fields names mapped to their types + Map fieldNames = + node.getEnclosingType() + .getDeclarations() + .filterIs(ASTFieldDeclaration.class) + .flatMap(ASTFieldDeclaration::getVarIds) + .collect(Collectors.toMap( + f -> { + Matcher matcher = FIELD_NAME_PATTERN.matcher(f.getVariableName()); + return matcher.find() ? matcher.group(1) : f.getVariableName(); + }, + f -> f.getTypeNode().getTypeImage() + )); + + return isGetter(node, fieldNames) || isSetter(node, fieldNames); + } + + + /** Attempts to determine if the method is a getter. */ + private static boolean isGetter(ASTMethodDeclaration node, Map fieldNames) { + + if (node.getArity() != 0 || node.isVoid()) { + return false; + } + + if (node.getName().startsWith("get")) { + return containsIgnoreCase(fieldNames.keySet(), node.getName().substring(3)); + } else if (node.getName().startsWith("is")) { + return containsIgnoreCase(fieldNames.keySet(), node.getName().substring(2)); + } + + + return fieldNames.containsKey(node.getName()); + } + + + /** Attempts to determine if the method is a setter. */ + private static boolean isSetter(ASTMethodDeclaration node, Map fieldNames) { + + if (node.getArity() != 1 || !node.isVoid()) { + return false; + } + + if (node.getName().startsWith("set")) { + return containsIgnoreCase(fieldNames.keySet(), node.getName().substring(3)); + } + + return fieldNames.containsKey(node.getName()); + } + + + private static boolean containsIgnoreCase(Set set, String str) { + for (String s : set) { + if (str.equalsIgnoreCase(s)) { + return true; + } + } + return false; + } + + +} 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 19174e38ae..6d02451617 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 @@ -14,14 +14,13 @@ import java.util.logging.Logger; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; +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.JavaNode; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; -import net.sourceforge.pmd.lang.java.metrics.internal.CycloMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.CycloMetric.CycloOption; -import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.CycloOption; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -32,10 +31,9 @@ import net.sourceforge.pmd.properties.PropertyFactory; * Cyclomatic complexity rule using metrics. * * @author Clément Fournier, based on work by Alan Hohn and Donald A. Leckie - * @see CycloMetric * @version 6.0.0 */ -public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { +public class CyclomaticComplexityRule extends AbstractJavaRule { private static final Logger LOG = Logger.getLogger(CyclomaticComplexityRule.class.getName()); @@ -118,15 +116,22 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { @Override - public Object visit(ASTAnyTypeDeclaration node, Object data) { + public Object visitJavaNode(JavaNode node, Object param) { + if (node instanceof ASTAnyTypeDeclaration) { + visitTypeDecl((ASTAnyTypeDeclaration) node, param); + } + return null; + } - super.visit(node, data); + public Object visitTypeDecl(ASTAnyTypeDeclaration node, Object data) { - if (JavaClassMetricKey.WMC.supports(node)) { - int classWmc = (int) MetricsUtil.computeMetric(JavaClassMetricKey.WMC, node, cycloOptions); + super.visitJavaNode(node, data); + + if (JavaMetrics.WEIGHED_METHOD_COUNT.supports(node)) { + int classWmc = MetricsUtil.computeMetric(JavaMetrics.WEIGHED_METHOD_COUNT, node, cycloOptions); if (classWmc >= classReportLevel) { - int classHighest = (int) MetricsUtil.computeStatistics(JavaOperationMetricKey.CYCLO, node.getOperations(), cycloOptions).getMax(); + int classHighest = (int) MetricsUtil.computeStatistics(JavaMetrics.CYCLO, node.getOperations(), cycloOptions).getMax(); String[] messageParams = {PrettyPrintingUtil.kindName(node), node.getSimpleName(), @@ -141,29 +146,34 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { @Override - public final Object visit(MethodLikeNode node, Object data) { + public final Object visit(ASTMethodDeclaration node, Object data) { + visitMethodLike(node, data); + return super.visit(node, data); + } - if (JavaOperationMetricKey.CYCLO.supports(node)) { - int cyclo = (int) MetricsUtil.computeMetric(JavaOperationMetricKey.CYCLO, node, cycloOptions); + @Override + public final Object visit(ASTConstructorDeclaration node, Object data) { + visitMethodLike(node, data); + return super.visit(node, data); + } + + private void visitMethodLike(ASTMethodOrConstructorDeclaration node, Object data) { + if (JavaMetrics.CYCLO.supports(node)) { + int cyclo = MetricsUtil.computeMetric(JavaMetrics.CYCLO, node, cycloOptions); if (cyclo >= methodReportLevel) { - String opname = node instanceof ASTMethodOrConstructorDeclaration - ? PrettyPrintingUtil.displaySignature((ASTMethodOrConstructorDeclaration) node) - : "lambda"; + String opname = PrettyPrintingUtil.displaySignature(node); - String kindname = node instanceof ASTMethodOrConstructorDeclaration - ? node instanceof ASTConstructorDeclaration ? "constructor" : "method" - : "lambda"; + String kindname = node instanceof ASTConstructorDeclaration ? "constructor" : "method"; addViolation(data, node, new String[] {kindname, opname, "", - "" + cyclo, }); + "" + 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 09072cae8c..27a4e1a656 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,10 +4,10 @@ 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 static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NUMBER_OF_ACCESSORS; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NUMBER_OF_PUBLIC_FIELDS; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.WEIGHED_METHOD_COUNT; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.WEIGHT_OF_CLASS; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; @@ -31,17 +31,17 @@ public class DataClassRule extends AbstractJavaMetricsRule { @Override public Object visit(ASTAnyTypeDeclaration node, Object data) { - if (!MetricsUtil.supportsAll(node, NOAM, NOPA, WMC, WOC)) { + if (!MetricsUtil.supportsAll(node, NUMBER_OF_ACCESSORS, NUMBER_OF_PUBLIC_FIELDS, WEIGHED_METHOD_COUNT, WEIGHT_OF_CLASS)) { return super.visit(node, data); } boolean isDataClass = interfaceRevealsData(node) && classRevealsDataAndLacksComplexity(node); if (isDataClass) { - 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); + double woc = MetricsUtil.computeMetric(WEIGHT_OF_CLASS, node); + int nopa = MetricsUtil.computeMetric(NUMBER_OF_PUBLIC_FIELDS, node); + int noam = MetricsUtil.computeMetric(NUMBER_OF_ACCESSORS, node); + int wmc = MetricsUtil.computeMetric(WEIGHED_METHOD_COUNT, node); addViolation(data, node, new Object[] {node.getSimpleName(), StringUtil.percentageString(woc, 3), @@ -53,15 +53,15 @@ public class DataClassRule extends AbstractJavaMetricsRule { private boolean interfaceRevealsData(ASTAnyTypeDeclaration node) { - double woc = MetricsUtil.computeMetric(WOC, node); + double woc = MetricsUtil.computeMetric(WEIGHT_OF_CLASS, node); return woc < WOC_LEVEL; } private boolean classRevealsDataAndLacksComplexity(ASTAnyTypeDeclaration node) { - int nopa = (int) MetricsUtil.computeMetric(NOPA, node); - int noam = (int) MetricsUtil.computeMetric(NOAM, node); - int wmc = (int) MetricsUtil.computeMetric(WMC, node); + int nopa = MetricsUtil.computeMetric(NUMBER_OF_PUBLIC_FIELDS, node); + int noam = MetricsUtil.computeMetric(NUMBER_OF_ACCESSORS, node); + int wmc = MetricsUtil.computeMetric(WEIGHED_METHOD_COUNT, 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 e019eaa3c9..d8e8096c66 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,9 +5,9 @@ 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 static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.ACCESS_TO_FOREIGN_DATA; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.TIGHT_CLASS_COHESION; +import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.WEIGHED_METHOD_COUNT; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; @@ -44,13 +44,13 @@ public class GodClassRule extends AbstractJavaRule { @Override public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { - if (!MetricsUtil.supportsAll(node, WMC, TCC, ATFD)) { + if (!MetricsUtil.supportsAll(node, WEIGHED_METHOD_COUNT, TIGHT_CLASS_COHESION, ACCESS_TO_FOREIGN_DATA)) { 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); + int wmc = MetricsUtil.computeMetric(WEIGHED_METHOD_COUNT, node); + double tcc = MetricsUtil.computeMetric(TIGHT_CLASS_COHESION, node); + int atfd = MetricsUtil.computeMetric(ACCESS_TO_FOREIGN_DATA, node); super.visit(node, 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 a11696b81c..2e583f1442 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 @@ -14,11 +14,9 @@ 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.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; -import net.sourceforge.pmd.lang.java.metrics.internal.NcssMetric.NcssOption; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NcssOption; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; @@ -89,14 +87,14 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { super.visit(node, data); - if (JavaClassMetricKey.NCSS.supports(node)) { - int classSize = (int) MetricsUtil.computeMetric(JavaClassMetricKey.NCSS, node, ncssOptions); - int classHighest = (int) MetricsUtil.computeStatistics(JavaOperationMetricKey.NCSS, node.getOperations(), ncssOptions).getMax(); + if (JavaMetrics.NCSS.supports(node)) { + int classSize = MetricsUtil.computeMetric(JavaMetrics.NCSS, node, ncssOptions); + int classHighest = (int) MetricsUtil.computeStatistics(JavaMetrics.NCSS, node.getOperations(), ncssOptions).getMax(); if (classSize >= classReportLevel) { String[] messageParams = {PrettyPrintingUtil.kindName(node), node.getSimpleName(), - classSize + " (Highest = " + classHighest + ")", }; + classSize + " (Highest = " + classHighest + ")",}; addViolation(data, node, messageParams); } @@ -108,12 +106,12 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { @Override public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - if (JavaOperationMetricKey.NCSS.supports((MethodLikeNode) node)) { - int methodSize = (int) MetricsUtil.computeMetric(JavaOperationMetricKey.NCSS, node, ncssOptions); + if (JavaMetrics.NCSS.supports(node)) { + int methodSize = MetricsUtil.computeMetric(JavaMetrics.NCSS, node, ncssOptions); if (methodSize >= methodReportLevel) { addViolation(data, node, new String[] { node instanceof ASTMethodDeclaration ? "method" : "constructor", - PrettyPrintingUtil.displaySignature(node), "" + methodSize, }); + PrettyPrintingUtil.displaySignature(node), "" + methodSize,}); } } return data; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java index 9e2a1c9260..9bfb8b0744 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java @@ -4,18 +4,10 @@ package net.sourceforge.pmd.lang.java.rule.xpath.internal; -import java.util.Locale; -import java.util.Map; - -import org.apache.commons.lang3.EnumUtils; - import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -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; +import net.sourceforge.pmd.lang.java.internal.JavaLanguageHandler.JavaMetricsProvider; +import net.sourceforge.pmd.lang.metrics.Metric; +import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.rule.xpath.internal.AstElementNode; import net.sf.saxon.expr.XPathContext; @@ -39,8 +31,7 @@ public final class MetricFunction extends BaseJavaXPathFunction { public static final MetricFunction INSTANCE = new MetricFunction(); - private static final Map CLASS_METRIC_KEY_MAP = EnumUtils.getEnumMap(JavaClassMetricKey.class); - private static final Map OPERATION_METRIC_KEY_MAP = EnumUtils.getEnumMap(JavaOperationMetricKey.class); + private static final JavaMetricsProvider METRICS = new JavaMetricsProvider(); private MetricFunction() { super("metric"); @@ -48,7 +39,7 @@ public final class MetricFunction extends BaseJavaXPathFunction { @Override public SequenceType[] getArgumentTypes() { - return new SequenceType[]{SequenceType.SINGLE_STRING}; + return new SequenceType[] {SequenceType.SINGLE_STRING}; } @@ -85,7 +76,7 @@ public final class MetricFunction extends BaseJavaXPathFunction { static String badClassMetricKeyMessage(String constantName) { - return String.format("'%s' is not the name of a class metric", constantName); + return String.format("'%s' is not the name of a metric", constantName); } @@ -93,36 +84,16 @@ public final class MetricFunction extends BaseJavaXPathFunction { return "Incorrect node type: the 'metric' function cannot be applied"; } - private static double getMetric(Node n, String metricKeyName) throws XPathException { - if (n instanceof ASTAnyTypeDeclaration) { - return computeMetric(getClassMetricKey(metricKeyName), (ASTAnyTypeDeclaration) n); - } else if (n instanceof ASTMethodOrConstructorDeclaration) { - return computeMetric(getOperationMetricKey(metricKeyName), (ASTMethodOrConstructorDeclaration) n); - } else { - throw new XPathException(genericBadNodeMessage()); + private static double getMetric(Node n, String metricKeyName) { + for (Metric metric : METRICS.getMetrics()) { + if (metric.name().equalsIgnoreCase(metricKeyName)) { + // todo aliases + Number computed = Metric.compute(metric, MetricOptions.emptyOptions(), n); + return computed == null ? Double.NaN : computed.doubleValue(); + } } - } - private static double computeMetric(MetricKey metricKey, T n) { - return metricKey.supports(n) ? MetricsUtil.computeMetric(metricKey, n) : Double.NaN; - } - - - private static JavaClassMetricKey getClassMetricKey(String s) throws XPathException { - String constantName = s.toUpperCase(Locale.ROOT); - if (!CLASS_METRIC_KEY_MAP.containsKey(constantName)) { - throw new XPathException(badClassMetricKeyMessage(constantName)); - } - return CLASS_METRIC_KEY_MAP.get(constantName); - } - - - private static JavaOperationMetricKey getOperationMetricKey(String s) throws XPathException { - String constantName = s.toUpperCase(Locale.ROOT); - if (!OPERATION_METRIC_KEY_MAP.containsKey(constantName)) { - throw new XPathException(badOperationMetricKeyMessage(constantName)); - } - return OPERATION_METRIC_KEY_MAP.get(constantName); + throw new IllegalArgumentException(badClassMetricKeyMessage()); } } From 83389f7d473c7b17725c281d3126eea6a636dedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 29 Aug 2020 15:17:05 +0200 Subject: [PATCH 003/101] Update tests --- .../lang/apex/metrics/AbstractApexMetric.java | 18 -- .../pmd/lang/apex/metrics/ApexMetrics.java | 16 +- .../apex/metrics/api/ApexClassMetric.java | 14 -- .../apex/metrics/api/ApexClassMetricKey.java | 39 ----- .../apex/metrics/api/ApexOperationMetric.java | 14 -- .../metrics/api/ApexOperationMetricKey.java | 38 ---- .../impl/AbstractApexMetricTestRule.java | 165 ------------------ .../apex/metrics/impl/AllMetricsTest.java | 8 + .../impl/CognitiveComplexityTestRule.java | 24 ++- .../lang/apex/metrics/impl/CycloTestRule.java | 25 ++- .../lang/apex/metrics/impl/WmcTestRule.java | 21 +-- .../lang/apex/metrics/impl/xml/CycloTest.xml | 18 +- .../lang/metrics/ParameterizedMetricKey.java | 12 +- .../metrics/ParameterizedMetricKeyTest.java | 41 ++--- .../pmd/test/AbstractMetricTestRule.java | 131 ++++++++++++++ 15 files changed, 217 insertions(+), 367 deletions(-) delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/AbstractApexMetric.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexClassMetric.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexClassMetricKey.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexOperationMetric.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexOperationMetricKey.java delete mode 100644 pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java create mode 100644 pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/AbstractApexMetric.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/AbstractApexMetric.java deleted file mode 100644 index 0b8c5c9594..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/AbstractApexMetric.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.apex.metrics; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.metrics.AbstractMetric; - -/** - * Base class for all Apex metrics. - * - * @author Clément Fournier - */ -public abstract class AbstractApexMetric extends AbstractMetric { - - -} 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 e97bc7953d..c66cd02e05 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,14 +4,13 @@ package net.sourceforge.pmd.lang.apex.metrics; -import static net.sourceforge.pmd.internal.util.PredicateUtil.always; - import java.util.function.Function; import java.util.function.Predicate; import org.apache.commons.lang3.mutable.MutableInt; import net.sourceforge.pmd.internal.util.PredicateUtil; +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.apex.ast.ApexNode; @@ -27,13 +26,17 @@ import net.sourceforge.pmd.lang.metrics.MetricsUtil; * */ public final class ApexMetrics { + @SuppressWarnings({"unchecked", "rawtypes"}) + private static final Class> GENERIC_APEX_NODE_CLASS = + (Class) ApexNode.class; // this is a Class, the raw type + public static final Metric, Integer> CYCLO = - Metric.of(ApexMetrics::computeCyclo, isApexNode(), + Metric.of(ApexMetrics::computeCyclo, isRegularApexNode(), "Cyclomatic Complexity", "Cyclo"); public static final Metric, Integer> COGNITIVE_COMPLEXITY = - Metric.of(ApexMetrics::computeCognitiveComp, isApexNode(), + Metric.of(ApexMetrics::computeCognitiveComp, isRegularApexNode(), "Cognitive Complexity"); @@ -47,10 +50,11 @@ public final class ApexMetrics { - private static Function> isApexNode() { - return filterMapNode(ApexNode.class, always()); + private static Function> isRegularApexNode() { + return filterMapNode(GENERIC_APEX_NODE_CLASS, n -> !(n instanceof ASTMethod && ((ASTMethod) n).isSynthetic())); } + private static Function filterMapNode(Class klass, Predicate pred) { return n -> n.asStream().filterIs(klass).filter(pred).first(); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexClassMetric.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexClassMetric.java deleted file mode 100644 index 83bb142865..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexClassMetric.java +++ /dev/null @@ -1,14 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.api; - -import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; -import net.sourceforge.pmd.lang.metrics.Metric; - -/** - * @author Clément Fournier - */ -public interface ApexClassMetric extends Metric> { -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexClassMetricKey.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexClassMetricKey.java deleted file mode 100644 index 73a08d5f2c..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexClassMetricKey.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.apex.metrics.api; - -import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; -import net.sourceforge.pmd.lang.apex.metrics.impl.ClassCognitiveComplexityMetric; -import net.sourceforge.pmd.lang.apex.metrics.impl.WmcMetric; -import net.sourceforge.pmd.lang.metrics.MetricKey; - -/** - * @author Clément Fournier - */ -public enum ApexClassMetricKey implements MetricKey> { - COGNITIVE(new ClassCognitiveComplexityMetric()), - WMC(new WmcMetric()); - - - private final ApexClassMetric calculator; - - - ApexClassMetricKey(ApexClassMetric m) { - calculator = m; - } - - - @Override - public ApexClassMetric getCalculator() { - return calculator; - } - - - @Override - public boolean supports(ASTUserClassOrInterface node) { - return calculator.supports(node); - } - -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexOperationMetric.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexOperationMetric.java deleted file mode 100644 index 79ed8323c4..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexOperationMetric.java +++ /dev/null @@ -1,14 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.api; - -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.metrics.Metric; - -/** - * @author Clément Fournier - */ -public interface ApexOperationMetric extends Metric { -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexOperationMetricKey.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexOperationMetricKey.java deleted file mode 100644 index e5816c5e6c..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/api/ApexOperationMetricKey.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.api; - -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.metrics.impl.CognitiveComplexityMetric; -import net.sourceforge.pmd.lang.apex.metrics.impl.CycloMetric; -import net.sourceforge.pmd.lang.metrics.MetricKey; - -/** - * @author Clément Fournier - */ -public enum ApexOperationMetricKey implements MetricKey { - CYCLO(new CycloMetric()), - COGNITIVE(new CognitiveComplexityMetric()); - - - private final ApexOperationMetric calculator; - - - ApexOperationMetricKey(ApexOperationMetric m) { - calculator = m; - } - - - @Override - public ApexOperationMetric getCalculator() { - return calculator; - } - - - @Override - public boolean supports(ASTMethod node) { - return calculator.supports(node); - } -} 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 deleted file mode 100644 index 40e7433683..0000000000 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java +++ /dev/null @@ -1,165 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.impl; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; -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.MetricOption; -import net.sourceforge.pmd.lang.metrics.MetricOptions; -import net.sourceforge.pmd.lang.metrics.MetricsUtil; -import net.sourceforge.pmd.properties.PropertyDescriptor; -import net.sourceforge.pmd.properties.PropertyFactory; - - -/** - * Abstract test rule for a metric. Tests of metrics use the standard framework for rule testing, using one dummy rule - * per metric. Default parameters can be overridden by overriding the protected methods of this class. - * - * @author Clément Fournier - */ -public abstract class AbstractApexMetricTestRule extends AbstractApexRule { - - private final PropertyDescriptor> optionsDescriptor = - PropertyFactory.enumListProperty("metricOptions", optionMappings()) - .desc("Choose a variant of the metric or the standard") - .emptyDefaultValue().build(); - - private final PropertyDescriptor reportClassesDescriptor = - PropertyFactory.booleanProperty("reportClasses") - .desc("Add class violations to the report") - .defaultValue(isReportClasses()).build(); - - private final PropertyDescriptor reportMethodsDescriptor = - PropertyFactory.booleanProperty("reportMethods") - .desc("Add method violations to the report") - .defaultValue(isReportMethods()).build(); - - private final PropertyDescriptor reportLevelDescriptor = - PropertyFactory.doubleProperty("reportLevel") - .desc("Minimum value required to report") - .defaultValue(defaultReportLevel()).build(); - - private MetricOptions metricOptions; - private boolean reportClasses; - private boolean reportMethods; - private double reportLevel; - private ApexClassMetricKey classKey; - private ApexOperationMetricKey opKey; - - - public AbstractApexMetricTestRule() { - classKey = getClassKey(); - opKey = getOpKey(); - - definePropertyDescriptor(reportClassesDescriptor); - definePropertyDescriptor(reportMethodsDescriptor); - definePropertyDescriptor(reportLevelDescriptor); - definePropertyDescriptor(optionsDescriptor); - } - - - /** - * Returns the class metric key to test, or null if we shouldn't test classes. - * - * @return The class metric key to test. - */ - protected abstract ApexClassMetricKey getClassKey(); - - - /** - * Returns the class metric key to test, or null if we shouldn't test classes. - * - * @return The class metric key to test. - */ - protected abstract ApexOperationMetricKey getOpKey(); - - - /** - * Sets the default for reportClasses descriptor. - * - * @return The default for reportClasses descriptor - */ - protected boolean isReportClasses() { - return true; - } - - - /** - * Sets the default for reportMethods descriptor. - * - * @return The default for reportMethods descriptor - */ - protected boolean isReportMethods() { - return true; - } - - - /** - * Mappings of labels to options for use in the options property. - * - * @return A map of labels to options - */ - protected Map optionMappings() { - return new HashMap<>(); - } - - - /** - * Default report level, which is 0. - * - * @return The default report level. - */ - protected double defaultReportLevel() { - return 0.; - } - - - @Override - public Object visit(ApN node, Object data) { - reportClasses = getProperty(reportClassesDescriptor); - reportMethods = getProperty(reportMethodsDescriptor); - reportLevel = getProperty(reportLevelDescriptor); - if (metricOptions == null) { - metricOptions = MetricOptions.ofOptions(getProperty(optionsDescriptor)); - } - - if (classKey != null && reportClasses && classKey.supports(node)) { - int classValue = (int) MetricsUtil.computeMetric(classKey, node, metricOptions); - - String valueReport = String.valueOf(classValue); - - if (opKey != null) { - int highest = (int) MetricsUtil.computeStatistics(opKey, node.getMethods(), metricOptions).getMax(); - if (highest == Double.NEGATIVE_INFINITY) { - highest = 0; - } - valueReport += " highest " + highest; - } - if (classValue >= reportLevel) { - addViolation(data, node, new String[] {node.getQualifiedName().toString(), valueReport}); - } - } - return super.visit(node, data); - } - - - @Override - public Object visit(ASTMethod node, Object data) { - if (opKey != null && reportMethods && opKey.supports(node)) { - int methodValue = (int) MetricsUtil.computeMetric(opKey, node, metricOptions); - if (methodValue >= reportLevel) { - addViolation(data, node, new String[] {node.getQualifiedName().toString(), "" + methodValue}); - } - } - return data; - } -} 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 f829c0ee65..f0b8d664cc 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,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.metrics.impl; +import net.sourceforge.pmd.lang.apex.ast.ApexQualifiableNode; +import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.testframework.SimpleAggregatorTst; /** @@ -23,4 +25,10 @@ public class AllMetricsTest extends SimpleAggregatorTst { addRule(RULESET, "CognitiveComplexityTest"); } + static String formatApexMessage(Node node, Integer result, String defaultMessage) { + if (node instanceof ApexQualifiableNode) { + return "''" + ((ApexQualifiableNode) node).getQualifiedName() + "'' has value " + result + "."; + } + return defaultMessage; + } } diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/CognitiveComplexityTestRule.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/CognitiveComplexityTestRule.java index 5bb127e5e7..569f16e6f8 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/CognitiveComplexityTestRule.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/CognitiveComplexityTestRule.java @@ -4,20 +4,28 @@ package net.sourceforge.pmd.lang.apex.metrics.impl; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; +import net.sourceforge.pmd.lang.apex.ast.ASTMethod; +import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Gwilym Kuiper */ -public class CognitiveComplexityTestRule extends AbstractApexMetricTestRule { - @Override - protected ApexClassMetricKey getClassKey() { - return null; +public class CognitiveComplexityTestRule extends AbstractMetricTestRule.OfInt { + + public CognitiveComplexityTestRule() { + super(ApexMetrics.COGNITIVE_COMPLEXITY); } @Override - protected ApexOperationMetricKey getOpKey() { - return ApexOperationMetricKey.COGNITIVE; + protected boolean reportOn(Node node) { + return node instanceof ASTMethod; } + + @Override + protected String violationMessage(Node node, Integer result) { + return AllMetricsTest.formatApexMessage(node, result, super.violationMessage(node, result)); + } + } diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/CycloTestRule.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/CycloTestRule.java index dc2f1d128d..195d6f3192 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/CycloTestRule.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/CycloTestRule.java @@ -4,25 +4,34 @@ package net.sourceforge.pmd.lang.apex.metrics.impl; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; +import net.sourceforge.pmd.lang.apex.ast.ASTMethod; +import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; +import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * Tests standard cyclo. * * @author Clément Fournier */ -public class CycloTestRule extends AbstractApexMetricTestRule { +public class CycloTestRule extends AbstractMetricTestRule.OfInt { - @Override - protected ApexClassMetricKey getClassKey() { - return null; + public CycloTestRule() { + super(ApexMetrics.CYCLO); } @Override - protected ApexOperationMetricKey getOpKey() { - return ApexOperationMetricKey.CYCLO; + protected boolean reportOn(Node node) { + return node instanceof ASTUserClassOrInterface || node instanceof ASTMethod; + } + + + + @Override + protected String violationMessage(Node node, Integer result) { + return AllMetricsTest.formatApexMessage(node, result, super.violationMessage(node, result)); } } diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/WmcTestRule.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/WmcTestRule.java index a5d71e5be8..12063ede03 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/WmcTestRule.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/WmcTestRule.java @@ -4,28 +4,23 @@ package net.sourceforge.pmd.lang.apex.metrics.impl; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; -import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; +import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier */ -public class WmcTestRule extends AbstractApexMetricTestRule { +public class WmcTestRule extends AbstractMetricTestRule.OfInt { - @Override - protected boolean isReportMethods() { - return false; + public WmcTestRule() { + super(ApexMetrics.WEIGHED_METHOD_COUNT); } @Override - protected ApexClassMetricKey getClassKey() { - return ApexClassMetricKey.WMC; + protected String violationMessage(Node node, Integer result) { + return AllMetricsTest.formatApexMessage(node, result, super.violationMessage(node, result)); } - - @Override - protected ApexOperationMetricKey getOpKey() { - return null; - } } diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/metrics/impl/xml/CycloTest.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/metrics/impl/xml/CycloTest.xml index ca8ccfdca1..52397c2809 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/metrics/impl/xml/CycloTest.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/metrics/impl/xml/CycloTest.xml @@ -55,8 +55,9 @@ Complicated method - Standard - 2 + 3 + 'c__Complicated' has value 21. 'c__Complicated#exception()' has value 4. 'c__Complicated#example()' has value 18. @@ -66,9 +67,9 @@ Empty methods should count 1 - false - 1 + 2 + 'c__Foo' has value 1. 'c__Foo#foo()' has value 1. @@ -98,9 +99,9 @@ #984 Cyclomatic complexity should treat constructors like methods - false - 1 + 2 + 'c__Test' has value 4. 'c__Test#Test()' has value 4. @@ -124,9 +125,9 @@ Standard Cyclo should count boolean paths - false - 1 + 2 + 'c__Foo' has value 8. 'c__Foo#foo()' has value 8. @@ -134,8 +135,9 @@ Ternary expression counts 1 + boolean complexity - 1 + 2 + 'c__Foo' has value 3. 'c__Foo#bar()' has value 3. 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 c693211f5b..e904609fbe 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 @@ -23,35 +23,35 @@ final class ParameterizedMetricKey implements private static final ConcurrentMap, ParameterizedMetricKey> POOL = new ConcurrentHashMap<>(); /** The metric key. */ - public final Metric key; + public final Metric metric; /** The options of the metric. */ public final MetricOptions options; /** Used internally by the pooler. */ - private ParameterizedMetricKey(Metric key, MetricOptions options) { - this.key = key; + private ParameterizedMetricKey(Metric metric, MetricOptions options) { + this.metric = metric; this.options = options; } @Override public String toString() { - return "ParameterizedMetricKey{key=" + key.name() + ", options=" + options + '}'; + return "ParameterizedMetricKey{key=" + metric.name() + ", options=" + options + '}'; } @Override public boolean equals(Object o) { return o instanceof ParameterizedMetricKey - && ((ParameterizedMetricKey) o).key.equals(key) + && ((ParameterizedMetricKey) o).metric.equals(metric) && ((ParameterizedMetricKey) o).options.equals(options); } @Override public int hashCode() { - return 31 * key.hashCode() + options.hashCode(); + return 31 * metric.hashCode() + options.hashCode(); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKeyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKeyTest.java index 3514a32442..2c49c53781 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKeyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKeyTest.java @@ -13,19 +13,19 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; -import net.sourceforge.pmd.lang.ast.DummyNode; +import net.sourceforge.pmd.lang.ast.Node; public class ParameterizedMetricKeyTest { private static final MetricOptions DUMMY_VERSION_1 = MetricOptions.ofOptions(Options.DUMMY1, Options.DUMMY2); private static final MetricOptions DUMMY_VERSION_2 = MetricOptions.ofOptions(Options.DUMMY2); + private static final Metric DUMMY_METRIC = Metric.of((n, opts) -> 0., t -> t, "dummy"); @Test public void testIdentity() { - MetricKey key = MetricKey.of("metric", new DummyMetric()); - ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(key, DUMMY_VERSION_1); - ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(key, DUMMY_VERSION_1); + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(DUMMY_METRIC, DUMMY_VERSION_1); + ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(DUMMY_METRIC, DUMMY_VERSION_1); assertEquals(key1, key2); assertSame(key1, key2); } @@ -33,10 +33,9 @@ public class ParameterizedMetricKeyTest { @Test public void testVersioning() { - MetricKey key = MetricKey.of("metric", new DummyMetric()); - ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(key, DUMMY_VERSION_1); - ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(key, DUMMY_VERSION_2); + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(DUMMY_METRIC, DUMMY_VERSION_1); + ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(DUMMY_METRIC, DUMMY_VERSION_2); assertNotEquals(key1, key2); assertNotSame(key1, key2); } @@ -45,10 +44,8 @@ public class ParameterizedMetricKeyTest { @Test public void testToString() { - MetricKey adHocKey = MetricKey.of("metric", new DummyMetric()); - - ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(adHocKey, DUMMY_VERSION_1); - assertTrue(key1.toString().contains(key1.key.name())); + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(DUMMY_METRIC, DUMMY_VERSION_1); + assertTrue(key1.toString().contains(key1.metric.name())); assertTrue(key1.toString().contains(key1.options.toString())); } @@ -56,17 +53,14 @@ public class ParameterizedMetricKeyTest { @Test public void testAdHocMetricKey() { - MetricKey adHocKey = MetricKey.of("metric", new DummyMetric()); - - - ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(adHocKey, DUMMY_VERSION_1); - ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(adHocKey, DUMMY_VERSION_1); + ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(DUMMY_METRIC, DUMMY_VERSION_1); + ParameterizedMetricKey key2 = ParameterizedMetricKey.getInstance(DUMMY_METRIC, DUMMY_VERSION_1); assertNotNull(key1); assertNotNull(key2); assertSame(key1, key2); assertEquals(key1, key2); - assertTrue(key1.toString().contains(key1.key.name())); + assertTrue(key1.toString().contains(key1.metric.name())); assertTrue(key1.toString().contains(key1.options.toString())); } @@ -82,18 +76,5 @@ public class ParameterizedMetricKeyTest { } } - class DummyMetric extends AbstractMetric { - - @Override - public boolean supports(DummyNode node) { - return true; - } - - @Override - public double computeFor(DummyNode node, MetricOptions options) { - return 0; - } - } - } diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java new file mode 100644 index 0000000000..fa9a7a4bfa --- /dev/null +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java @@ -0,0 +1,131 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.test; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.metrics.Metric; +import net.sourceforge.pmd.lang.metrics.MetricOption; +import net.sourceforge.pmd.lang.metrics.MetricOptions; +import net.sourceforge.pmd.lang.rule.AbstractRule; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + + +/** + * Abstract test rule for a metric. Tests of metrics use the standard framework for rule testing, using one dummy rule + * per metric. Default parameters can be overridden by overriding the protected methods of this class. + * + * @author Clément Fournier + */ +public abstract class AbstractMetricTestRule> extends AbstractRule { + + private final PropertyDescriptor> optionsDescriptor = + PropertyFactory.enumListProperty("metricOptions", optionMappings()) + .desc("Choose a variant of the metric or the standard") + .emptyDefaultValue() + .build(); + + private final PropertyDescriptor reportLevelDescriptor = + PropertyFactory.stringProperty("reportLevel") + .desc("Minimum value required to report") + .defaultValue("" + defaultReportLevel()) + .build(); + + private final Metric metric; + + public AbstractMetricTestRule(Metric metric) { + this.metric = metric; + + definePropertyDescriptor(reportLevelDescriptor); + definePropertyDescriptor(optionsDescriptor); + } + + protected abstract N parseReportLevel(String value); + + protected boolean reportOn(Node node) { + return metric.supports(node); + } + + /** + * Mappings of labels to options for use in the options property. + * + * @return A map of labels to options + */ + protected Map optionMappings() { + return new HashMap<>(); + } + + + /** + * Default report level, which is 0. + * + * @return The default report level. + */ + protected abstract N defaultReportLevel(); + + protected String violationMessage(Node node, N result) { + return MessageFormat.format("At line {0} level {1}", node.getBeginLine(), result); + } + + @Override + public void apply(Node target, RuleContext ctx) { + if (reportOn(target)) { + MetricOptions options = MetricOptions.ofOptions(getProperty(optionsDescriptor)); + N reportLevel = parseReportLevel(getProperty(reportLevelDescriptor)); + N result = Metric.compute(metric, options, target); + + if (result != null && reportLevel.compareTo(result) <= 0) { + addViolationWithMessage(ctx, target, violationMessage(target, result)); + } + } + + // visit the whole tree + for (Node child : target.children()) { + apply(child, ctx); + } + } + + + public abstract static class OfInt extends AbstractMetricTestRule { + + protected OfInt(Metric metric) { + super(metric); + } + + @Override + protected Integer parseReportLevel(String value) { + return Integer.parseInt(value); + } + + @Override + protected Integer defaultReportLevel() { + return 0; + } + } + + public abstract static class OfDouble extends AbstractMetricTestRule { + + protected OfDouble(Metric metric) { + super(metric); + } + + @Override + protected Double parseReportLevel(String value) { + return Double.parseDouble(value); + } + + @Override + protected Double defaultReportLevel() { + return 0.; + } + } + +} From 2f2153bba57d2d43b9002a81d48b135c993a24a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 29 Aug 2020 15:52:19 +0200 Subject: [PATCH 004/101] Update java tests WIP This needs to wait for java-grammar to be finished + metrics to be ported. --- .../java/metrics/AbstractJavaClassMetric.java | 113 ----------- .../metrics/AbstractJavaOperationMetric.java | 45 ----- .../java/metrics/api/JavaClassMetric.java | 18 -- .../java/metrics/api/JavaClassMetricKey.java | 110 ----------- .../lang/java/metrics/api/JavaMetrics.java | 5 +- .../java/metrics/api/JavaOperationMetric.java | 18 -- .../metrics/api/JavaOperationMetricKey.java | 99 ---------- .../metrics/internal/ClassFanOutMetric.java | 64 ------ .../internal/visitors/ClassFanOutVisitor.java | 2 +- .../internal/visitors/CycloVisitor.java | 2 +- .../internal/visitors/NcssVisitor.java | 2 +- .../java/rule/design/NPathComplexityRule.java | 6 +- .../java/metrics/JavaMetricsProviderTest.java | 31 ++- .../java/metrics/ProjectMemoizerTest.java | 43 ++-- .../metrics/impl/AbstractMetricTestRule.java | 184 ------------------ .../java/metrics/impl/AllMetricsTest.java | 23 ++- .../lang/java/metrics/impl/AtfdTestRule.java | 16 +- .../lang/java/metrics/impl/CfoTestRule.java | 18 +- .../lang/java/metrics/impl/CycloTestRule.java | 20 +- .../metrics/impl/JavaIntMetricTestRule.java | 31 +++ .../lang/java/metrics/impl/LocTestRule.java | 16 +- .../lang/java/metrics/impl/NPathTestRule.java | 17 +- .../lang/java/metrics/impl/NcssTestRule.java | 27 +-- .../lang/java/metrics/impl/NoamTestRule.java | 17 +- .../lang/java/metrics/impl/NopaTestRule.java | 17 +- .../lang/java/metrics/impl/TccTestRule.java | 17 +- .../lang/java/metrics/impl/WmcTestRule.java | 21 +- .../lang/java/metrics/impl/WocTestRule.java | 17 +- .../missingoverride/EnumWithInterfaces.java | 18 +- .../missingoverride/InterfaceWithBound.java | 15 ++ .../bestpractices/xml/MissingOverride.xml | 54 +++-- 31 files changed, 191 insertions(+), 895 deletions(-) delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaOperationMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetricKey.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetric.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetricKey.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutMetric.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/InterfaceWithBound.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java deleted file mode 100644 index 5192be7789..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java +++ /dev/null @@ -1,113 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics; - -import java.util.List; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSigMask; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSigMask; -import net.sourceforge.pmd.lang.metrics.AbstractMetric; - - -/** - * Base class for class metrics. - * - * @author Clément Fournier - */ -public abstract class AbstractJavaClassMetric extends AbstractMetric { - - - /** - * Returns true if the metric can be computed on this type declaration. By default, annotation and interface - * declarations are filtered out. - * - * @param node The type declaration - * - * @return True if the metric can be computed on this type declaration - */ - @Override - public boolean supports(Node node) { - return node instanceof ASTAnyTypeDeclaration && !((ASTAnyTypeDeclaration) node).isInterface(); - } - - - /** - * Counts the operations matching the signature mask in this class. - * - * @param classNode The class on which to count - * @param mask The mask - * - * @return The number of operations matching the signature mask - */ - protected static int countMatchingOpSigs(ASTAnyTypeDeclaration classNode, JavaOperationSigMask mask) { - int count = 0; - List decls = getMethodsAndConstructors(classNode); - - for (ASTMethodOrConstructorDeclaration decl : decls) { - if (mask.covers(decl.getSignature())) { - count++; - } - } - - return count; - } - - - /** - * Counts the fields matching the signature mask in this class. - * - * @param classNode The class on which to count - * @param mask The mask - * - * @return The number of fields matching the signature mask - */ - protected static int countMatchingFieldSigs(ASTAnyTypeDeclaration classNode, JavaFieldSigMask mask) { - int count = 0; - List decls = getFields(classNode); - - for (ASTFieldDeclaration decl : decls) { - if (mask.covers(decl.getSignature())) { - count++; - } - } - - return count; - } - - - /** - * Gets a list of all methods and constructors declared in the class. - * - * @param node The class - * - * @return The list of all methods and constructors - */ - protected static List getMethodsAndConstructors(ASTAnyTypeDeclaration node) { - return getDeclarationsOfType(node, ASTMethodOrConstructorDeclaration.class); - } - - - /** - * Gets a list of all fields declared in the class. - * - * @param node The class - * - * @return The list of all fields - */ - protected static List getFields(ASTAnyTypeDeclaration node) { - return getDeclarationsOfType(node, ASTFieldDeclaration.class); - } - - - private static List getDeclarationsOfType(ASTAnyTypeDeclaration node, Class tClass) { - return node.getDeclarations().filterIs(tClass).toList(); - } - - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaOperationMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaOperationMetric.java deleted file mode 100644 index 7a4721a71c..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaOperationMetric.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.java.metrics; - -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.metrics.api.JavaOperationMetric; - - -/** - * Base class for operation metrics. Can be applied on method and constructor declarations, and - * lambda expressions. - * - * @author Clément Fournier - */ -public abstract class AbstractJavaOperationMetric extends net.sourceforge.pmd.lang.metrics.AbstractMetric - implements JavaOperationMetric { - - /** - * Returns true if the metric can be computed on this operation. By default, abstract operations are filtered out. - * - * @param node The operation - * - * @return True if the metric can be computed on this operation - */ - @Override - public boolean supports(MethodLikeNode node) { - return !(node instanceof ASTMethodDeclaration && ((ASTMethodDeclaration) node).isAbstract()); - } - - - /** - * @see #supports(MethodLikeNode) - * @deprecated Provided here for backwards binary compatibility with {@link #supports(MethodLikeNode)}. - * Please explicitly link your code to that method and recompile your code. Will be remove with 7.0.0 - */ - public boolean supports(ASTMethodOrConstructorDeclaration node) { - return supports((MethodLikeNode) node); - } - - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetric.java deleted file mode 100644 index 51c7159e1d..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetric.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.api; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.metrics.Metric; - -/** - * Metric that can be computed on a class node. - * - * @author Clément Fournier - */ -public interface JavaClassMetric extends Metric { - - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetricKey.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetricKey.java deleted file mode 100644 index e436238167..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaClassMetricKey.java +++ /dev/null @@ -1,110 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.api; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.metrics.internal.AtfdMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.AtfdMetric.AtfdClassMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.ClassFanOutMetric.ClassFanOutClassMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.LocMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.LocMetric.LocClassMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.NcssMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.NcssMetric.NcssClassMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.NoamMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.NopaMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.TccMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.WmcMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.WocMetric; -import net.sourceforge.pmd.lang.metrics.MetricKey; - -/** - * Keys identifying standard class metrics. - */ -public enum JavaClassMetricKey implements MetricKey { - - /** - * Access to Foreign Data. - * - * @see AtfdMetric - */ - ATFD(new AtfdClassMetric()), - - /** - * Weighed Method Count. - * - * @see WmcMetric - */ - WMC(new WmcMetric()), - - /** - * Non Commenting Source Statements. - * - * @see NcssMetric - */ - NCSS(new NcssClassMetric()), - - /** - * Lines of Code. - * - * @see LocMetric - */ - LOC(new LocClassMetric()), - - /** - * Number of Public Attributes. - * - * @see NopaMetric - */ - NOPA(new NopaMetric()), - - /** - * Number of Accessor Methods. - * - * @see NopaMetric - */ - NOAM(new NoamMetric()), - - /** - * Weight of class. - * - * @see WocMetric - */ - WOC(new WocMetric()), - - /** - * Tight Class Cohesion. - * - * @see TccMetric - */ - TCC(new TccMetric()), - - /** - * ClassFanOut Complexity - * - * @see ClassFanOutClassMetric - */ - CLASS_FAN_OUT(new ClassFanOutClassMetric()); - - - private final JavaClassMetric calculator; - - - JavaClassMetricKey(JavaClassMetric m) { - calculator = m; - } - - - @Override - public JavaClassMetric getCalculator() { - return calculator; - } - - - @Override - public boolean supports(ASTAnyTypeDeclaration node) { - return calculator.supports(node); - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index 43cbe0c211..09b522ade4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -23,6 +23,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression; import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.AtfdBaseVisitor; @@ -67,8 +68,8 @@ public final class JavaMetrics { Metric.of(JavaMetrics::computeCyclo, isJavaNode(), "Cyclomatic Complexity", "Cyclo"); - public static final Metric NPATH = - Metric.of(JavaMetrics::computeNpath, isJavaNode(), + public static final Metric NPATH = + Metric.of(JavaMetrics::computeNpath, n -> n.asStream().filterIs(ASTMethodOrConstructorDeclaration.class).first(), "NPath Complexity", "NPath"); public static final Metric WEIGHED_METHOD_COUNT = diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetric.java deleted file mode 100644 index 656cb658e8..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetric.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.api; - -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.metrics.Metric; - -/** - * Metric that can be computed on an operation. - * - * @author Clément Fournier - */ -public interface JavaOperationMetric extends Metric { - - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetricKey.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetricKey.java deleted file mode 100644 index 163e873a06..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaOperationMetricKey.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.api; - -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.internal.AtfdMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.AtfdMetric.AtfdOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.ClassFanOutMetric.ClassFanOutOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.CycloMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.LocMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.LocMetric.LocOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.NcssMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.NcssMetric.NcssOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.NpathMetric; -import net.sourceforge.pmd.lang.metrics.MetricKey; - - -/** - * Keys identifying standard operation metrics. - */ -public enum JavaOperationMetricKey implements MetricKey { - - /** - * Access to Foreign Data. - * - * @see AtfdMetric - */ - ATFD(new AtfdOperationMetric()), - - /** - * Cyclomatic complexity. - * - * @see CycloMetric - */ - CYCLO(new CycloMetric()), - - /** - * Non Commenting Source Statements. - * - * @see NcssMetric - */ - NCSS(new NcssOperationMetric()), - - /** - * Lines of Code. - * - * @see LocMetric - */ - LOC(new LocOperationMetric()), - - - /** - * N-path complexity. - * - * @see NpathMetric - */ - NPATH(new NpathMetric()), - - /** - * ClassFanOut Complexity - * - * @see ClassFanOutOperationMetric - */ - CLASS_FAN_OUT(new ClassFanOutOperationMetric()); - - - private final JavaOperationMetric calculator; - - - JavaOperationMetricKey(JavaOperationMetric m) { - calculator = m; - } - - - @Override - public JavaOperationMetric getCalculator() { - return calculator; - } - - - @Override - public boolean supports(MethodLikeNode node) { - return calculator.supports(node); - } - - - /** - * @see #supports(MethodLikeNode) - * @deprecated Provided here for backwards binary compatibility with {@link #supports(MethodLikeNode)}. - * Please explicitly link your code to that method and recompile your code. Will be remove with 7.0.0 - */ - @Deprecated - public boolean supports(ASTMethodOrConstructorDeclaration node) { - return this.supports((MethodLikeNode) node); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutMetric.java deleted file mode 100644 index 927e786e9d..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutMetric.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal; - -import org.apache.commons.lang3.mutable.MutableInt; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaClassMetric; -import net.sourceforge.pmd.lang.java.metrics.AbstractJavaOperationMetric; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.ClassFanOutVisitor; -import net.sourceforge.pmd.lang.metrics.MetricOption; -import net.sourceforge.pmd.lang.metrics.MetricOptions; - - -/** - * The ClassFanOutComplexity counts the usage of other classes within this class. - * - * @author Andreas Pabst - * @since October 2019 - */ -public final class ClassFanOutMetric { - - public enum ClassFanOutOption implements MetricOption { - /** Whether to include Classes in the java.lang package. */ - INCLUDE_JAVA_LANG("includeJavaLang"); - - private final String vName; - - ClassFanOutOption(String valueName) { - this.vName = valueName; - } - - @Override - public String valueName() { - return vName; - } - } - - public static final class ClassFanOutClassMetric extends AbstractJavaClassMetric { - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - return computeFanOut(node, options); - } - - } - - public static final class ClassFanOutOperationMetric extends AbstractJavaOperationMetric { - - @Override - public boolean supports(MethodLikeNode node) { - return true; - } - - @Override - public double computeFor(MethodLikeNode node, MetricOptions options) { - MutableInt cfo = (MutableInt) node.acceptVisitor(new ClassFanOutVisitor(options, node), new MutableInt(0)); - return (double) cfo.getValue(); - } - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java index 3d66a00ca8..d1eb078942 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java @@ -14,7 +14,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; import net.sourceforge.pmd.lang.java.ast.TypeNode; -import net.sourceforge.pmd.lang.java.metrics.internal.ClassFanOutMetric.ClassFanOutOption; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.ClassFanOutOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java index 6dfd14bf6c..7072925e65 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java @@ -24,7 +24,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.lang.java.metrics.internal.CycloMetric.CycloOption; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.CycloOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java index 8ed41865fc..8b797602bd 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java @@ -40,7 +40,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; -import net.sourceforge.pmd.lang.java.metrics.internal.NcssMetric.NcssOption; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NcssOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; 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 656cce0fee..0228525f33 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 @@ -12,7 +12,7 @@ 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.internal.PrettyPrintingUtil; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -71,11 +71,11 @@ public class NPathComplexityRule extends AbstractJavaMetricsRule { @Override public final Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - if (!JavaOperationMetricKey.NPATH.supports(node)) { + if (!JavaMetrics.NPATH.supports(node)) { return data; } - int npath = (int) MetricsUtil.computeMetric(JavaOperationMetricKey.NPATH, node); + int npath = MetricsUtil.computeMetric(JavaMetrics.NPATH, node); if (npath >= reportLevel) { addViolation(data, node, new String[] {node instanceof ASTMethodDeclaration ? "method" : "constructor", PrettyPrintingUtil.displaySignature(node), diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java index f33e3fd3b9..2bb8ca23e4 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java @@ -5,8 +5,8 @@ package net.sourceforge.pmd.lang.java.metrics; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; import java.util.Map; @@ -16,11 +16,9 @@ import org.junit.Test; import net.sourceforge.pmd.lang.java.JavaParsingHelper; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -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.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; -import net.sourceforge.pmd.lang.metrics.MetricKey; +import net.sourceforge.pmd.lang.metrics.Metric; /** @@ -34,43 +32,40 @@ public class JavaMetricsProviderTest { @Test public void testComputeAllMetrics() { - LanguageMetricsProvider provider = java8.getHandler("1.8").getLanguageMetricsProvider(); + LanguageMetricsProvider provider = java8.getHandler("1.8").getLanguageMetricsProvider(); ASTCompilationUnit acu = java8.parse("class Foo { void bar() { System.out.println(1); } }"); ASTAnyTypeDeclaration type = acu.getFirstDescendantOfType(ASTAnyTypeDeclaration.class); - Map, Double> results = provider.computeAllMetricsFor(type); + Map, Number> results = provider.computeAllMetricsFor(type); - for (JavaClassMetricKey key : JavaClassMetricKey.values()) { - assertTrue(results.containsKey(key)); - } + assertEquals(10, results.size()); - MethodLikeNode op = acu.getFirstDescendantOfType(MethodLikeNode.class); - Map, Double> opResults = provider.computeAllMetricsFor(op); + ASTMethodDeclaration op = acu.getFirstDescendantOfType(ASTMethodDeclaration.class); - for (JavaOperationMetricKey key : JavaOperationMetricKey.values()) { - assertTrue(opResults.containsKey(key)); - } + Map, Number> opResults = provider.computeAllMetricsFor(op); + + assertEquals(10, results.size()); } @Test public void testThereIsNoMemoisation() { - LanguageMetricsProvider provider = java8.getHandler("1.8").getLanguageMetricsProvider(); + LanguageMetricsProvider provider = java8.getHandler("1.8").getLanguageMetricsProvider(); ASTAnyTypeDeclaration tdecl1 = java8.parse("class Foo { void bar() { System.out.println(1); } }") .getFirstDescendantOfType(ASTAnyTypeDeclaration.class); - Map, Double> reference = provider.computeAllMetricsFor(tdecl1); + Map, Number> reference = provider.computeAllMetricsFor(tdecl1); // same name, different characteristics ASTAnyTypeDeclaration tdecl2 = java8.parse("class Foo { void bar(){} \npublic void hey() { System.out.println(1); } }") .getFirstDescendantOfType(ASTAnyTypeDeclaration.class); - Map, Double> secondTest = provider.computeAllMetricsFor(tdecl2); + Map, Number> secondTest = provider.computeAllMetricsFor(tdecl2); assertNotEquals(reference, secondTest); 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 9d9512ba37..e1f8fd7d49 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 @@ -14,25 +14,27 @@ import java.util.Random; import org.junit.Test; +import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; 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.Metric; import net.sourceforge.pmd.lang.metrics.MetricOptions; -import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** * @author Clément Fournier */ public class ProjectMemoizerTest extends BaseNonParserTest { - private MetricKey classMetricKey = MetricKey.of("null", new RandomClassMetric()); - private MetricKey opMetricKey = MetricKey.of("null", new RandomOperationMetric()); + private final Metric randomMetric = randomMetric(); + private static Metric randomMetric() { + Random capturedRandom = new Random(); + return Metric.of((t, opts)-> capturedRandom.nextInt(), t -> t, "randomMetric"); + } @Test public void memoizationTest() { @@ -68,8 +70,9 @@ public class ProjectMemoizerTest extends BaseNonParserTest { acu.jjtAccept(new JavaParserVisitorAdapter() { @Override public Object visitMethodOrCtor(ASTMethodOrConstructorDeclaration node, Object data) { - if (opMetricKey.supports(node)) { - result.add((int) MetricsUtil.computeMetric(opMetricKey, node, MetricOptions.emptyOptions(), force)); + Integer value = Metric.compute(randomMetric, MetricOptions.emptyOptions(), node); + if (value != null) { + result.add(value); } return super.visitMethodOrCtor(node, data); } @@ -77,8 +80,9 @@ public class ProjectMemoizerTest extends BaseNonParserTest { @Override public Object visitTypeDecl(ASTAnyTypeDeclaration node, Object data) { - if (classMetricKey.supports(node)) { - result.add((int) MetricsUtil.computeMetric(classMetricKey, node, MetricOptions.emptyOptions(), force)); + Integer value = Metric.compute(randomMetric, MetricOptions.emptyOptions(), node); + if (value != null) { + result.add(value); } return super.visitTypeDecl(node, data); } @@ -88,26 +92,5 @@ public class ProjectMemoizerTest extends BaseNonParserTest { } - private class RandomOperationMetric extends AbstractJavaOperationMetric { - - private Random random = new Random(); - - - @Override - public double computeFor(MethodLikeNode node, MetricOptions options) { - return random.nextInt(); - } - } - - private class RandomClassMetric extends AbstractJavaClassMetric { - - private Random random = new Random(); - - - @Override - public double computeFor(ASTAnyTypeDeclaration node, MetricOptions options) { - return random.nextInt(); - } - } } 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 deleted file mode 100644 index dc31c9199a..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AbstractMetricTestRule.java +++ /dev/null @@ -1,184 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.impl; - -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -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.properties.PropertyDescriptor; -import net.sourceforge.pmd.properties.PropertyFactory; - - -/** - * Abstract test rule for a metric. Tests of metrics use the standard framework for rule testing, using one dummy rule - * per metric. Default parameters can be overridden by overriding the protected methods of this class. - * - * @author Clément Fournier - */ -public abstract class AbstractMetricTestRule extends AbstractJavaMetricsRule { - - - private final PropertyDescriptor> optionsDescriptor = - PropertyFactory.enumListProperty("metricOptions", optionMappings()) - .desc("Choose a variant of the metric or the standard") - .emptyDefaultValue().build(); - - private final PropertyDescriptor reportClassesDescriptor = - PropertyFactory.booleanProperty("reportClasses") - .desc("Add class violations to the report") - .defaultValue(isReportClasses()).build(); - - private final PropertyDescriptor reportMethodsDescriptor = - PropertyFactory.booleanProperty("reportMethods") - .desc("Add method violations to the report") - .defaultValue(isReportMethods()).build(); - - private final PropertyDescriptor reportLevelDescriptor = - PropertyFactory.doubleProperty("reportLevel") - .desc("Minimum value required to report") - .defaultValue(defaultReportLevel()).build(); - - private MetricOptions metricOptions; - private boolean reportClasses; - private boolean reportMethods; - private double reportLevel; - private JavaClassMetricKey classKey; - private JavaOperationMetricKey opKey; - - - public AbstractMetricTestRule() { - classKey = getClassKey(); - opKey = getOpKey(); - - definePropertyDescriptor(reportClassesDescriptor); - definePropertyDescriptor(reportMethodsDescriptor); - definePropertyDescriptor(reportLevelDescriptor); - definePropertyDescriptor(optionsDescriptor); - } - - - /** - * Returns the class metric key to test, or null if we shouldn't test classes. - * - * @return The class metric key to test. - */ - protected abstract JavaClassMetricKey getClassKey(); - - - /** - * Returns the class metric key to test, or null if we shouldn't test classes. - * - * @return The class metric key to test. - */ - protected abstract JavaOperationMetricKey getOpKey(); - - - @Override - public Object visit(ASTCompilationUnit node, Object data) { - reportClasses = getProperty(reportClassesDescriptor); - reportMethods = getProperty(reportMethodsDescriptor); - reportLevel = getProperty(reportLevelDescriptor); - metricOptions = MetricOptions.ofOptions(getProperty(optionsDescriptor)); - - return super.visit(node, data); - } - - - /** - * Sets the default for reportClasses descriptor. - * - * @return The default for reportClasses descriptor - */ - protected boolean isReportClasses() { - return true; - } - - - /** - * Sets the default for reportMethods descriptor. - * - * @return The default for reportMethods descriptor - */ - protected boolean isReportMethods() { - return true; - } - - - /** - * Mappings of labels to versions for use in the options property. - * - * @return A map of labels to versions - */ - protected Map optionMappings() { - return new HashMap<>(); - } - - - /** - * Default report level, which is 0. - * - * @return The default report level. - */ - protected double defaultReportLevel() { - return 0.; - } - - - /** Gets a nice string representation of a double. */ - private String niceDoubleString(double val) { - if (val == (int) val) { - return String.valueOf((int) val); - } else { - return String.format(Locale.ROOT, "%.4f", val); - } - } - - - @Override - public Object visit(ASTAnyTypeDeclaration node, Object data) { - if (classKey != null && reportClasses && classKey.supports(node)) { - double classValue = MetricsUtil.computeMetric(classKey, node, metricOptions); - - String valueReport = niceDoubleString(classValue); - - if (opKey != null) { - double highest = MetricsUtil.computeStatistics(opKey, node.getOperations(), metricOptions).getMax(); - if (highest == Double.NEGATIVE_INFINITY) { - highest = 0; - } - valueReport += " highest " + niceDoubleString(highest); - } - if (classValue >= reportLevel) { - addViolation(data, node, new String[] {node.getBinaryName(), valueReport, }); - } - } - return super.visit(node, data); - } - - - @Override - public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - if (opKey != null && reportMethods && opKey.supports(node)) { - double methodValue = MetricsUtil.computeMetric(opKey, node, metricOptions); - if (methodValue >= reportLevel) { - addViolation(data, node, new String[] {node.getEnclosingType().getBinaryName() + "#" + PrettyPrintingUtil.displaySignature(node), - "" + niceDoubleString(methodValue), }); - } - } - return super.visit(node, data); - } -} 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 8c4e092d9f..fad0e180bf 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,10 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import org.junit.Ignore; - +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; +import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.testframework.SimpleAggregatorTst; /** @@ -13,7 +15,7 @@ import net.sourceforge.pmd.testframework.SimpleAggregatorTst; * * @author Clément Fournier */ -@Ignore("Metrics tests are ignored until we stabilise the AST, like rules") +//@Ignore("Metrics tests are ignored until we stabilise the AST, like rules") public class AllMetricsTest extends SimpleAggregatorTst { @@ -34,4 +36,19 @@ public class AllMetricsTest extends SimpleAggregatorTst { addRule(RULESET, "CfoTest"); } + + static String formatJavaMessage(Node node, Object result, String defaultMessage) { + String qname = null; + if (node instanceof ASTAnyTypeDeclaration) { + qname = ((ASTAnyTypeDeclaration) node).getBinaryName(); + } else if (node instanceof ASTMethodOrConstructorDeclaration) { + qname = PrettyPrintingUtil.displaySignature((ASTMethodOrConstructorDeclaration) node); + } + + if (qname != null) { + return "''" + qname + "'' has value " + result + "."; + } + return defaultMessage; + } + } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java index 11a17bb4a4..f5966f6b9f 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java @@ -4,23 +4,23 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier * @since 6.0.0 */ -public class AtfdTestRule extends AbstractMetricTestRule { +public class AtfdTestRule extends JavaIntMetricTestRule { - @Override - protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.ATFD; + public AtfdTestRule() { + super(JavaMetrics.ACCESS_TO_FOREIGN_DATA); } @Override - protected JavaOperationMetricKey getOpKey() { - return JavaOperationMetricKey.ATFD; + protected String violationMessage(Node node, Integer result) { + return super.violationMessage(node, result); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CfoTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CfoTestRule.java index e480e37673..fffd368485 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CfoTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CfoTestRule.java @@ -6,25 +6,17 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import java.util.Map; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; -import net.sourceforge.pmd.lang.java.metrics.internal.ClassFanOutMetric.ClassFanOutOption; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.ClassFanOutOption; import net.sourceforge.pmd.lang.metrics.MetricOption; /** * @author Andreas Pabst */ -public class CfoTestRule extends AbstractMetricTestRule { +public class CfoTestRule extends JavaIntMetricTestRule { - @Override - protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.CLASS_FAN_OUT; - } - - - @Override - protected JavaOperationMetricKey getOpKey() { - return JavaOperationMetricKey.CLASS_FAN_OUT; + public CfoTestRule() { + super(JavaMetrics.FAN_OUT); } @Override diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java index 643829e3fe..ab0d783f61 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java @@ -6,30 +6,22 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import java.util.Map; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; -import net.sourceforge.pmd.lang.java.metrics.internal.CycloMetric.CycloOption; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.CycloOption; import net.sourceforge.pmd.lang.metrics.MetricOption; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * Tests cyclo. * * @author Clément Fournier */ -public class CycloTestRule extends AbstractMetricTestRule { +public class CycloTestRule extends JavaIntMetricTestRule { - @Override - protected JavaClassMetricKey getClassKey() { - return null; + public CycloTestRule() { + super(JavaMetrics.CYCLO); } - - @Override - protected JavaOperationMetricKey getOpKey() { - return JavaOperationMetricKey.CYCLO; - } - - @Override protected Map optionMappings() { Map mappings = super.optionMappings(); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java new file mode 100644 index 0000000000..f26cdad1ae --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java @@ -0,0 +1,31 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.metrics.impl; + +import net.sourceforge.pmd.lang.ast.AstProcessingStage; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.metrics.Metric; +import net.sourceforge.pmd.test.AbstractMetricTestRule; + +/** + * + */ +public abstract class JavaIntMetricTestRule extends AbstractMetricTestRule.OfInt { + + protected JavaIntMetricTestRule(Metric metric) { + super(metric); + } + + + @Override + public boolean dependsOn(AstProcessingStage stage) { + return true; + } + + @Override + protected String violationMessage(Node node, Integer result) { + return AllMetricsTest.formatJavaMessage(node, result, super.violationMessage(node, result)); + } +} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java index b110bba11b..d455ed3854 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java @@ -4,21 +4,15 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier */ -public class LocTestRule extends AbstractMetricTestRule { +public class LocTestRule extends JavaIntMetricTestRule { - @Override - protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.LOC; - } - - @Override - protected JavaOperationMetricKey getOpKey() { - return JavaOperationMetricKey.LOC; + public LocTestRule() { + super(JavaMetrics.LINES_OF_CODE); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java index f41e222558..2c0c61ba47 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java @@ -4,22 +4,15 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier */ -public class NPathTestRule extends AbstractMetricTestRule { +public class NPathTestRule extends JavaIntMetricTestRule { - @Override - protected JavaClassMetricKey getClassKey() { - return null; - } - - - @Override - protected JavaOperationMetricKey getOpKey() { - return JavaOperationMetricKey.NPATH; + public NPathTestRule() { + super(JavaMetrics.NPATH); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java index 26ee70a32b..24ec89aa51 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java @@ -6,34 +6,27 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import java.util.Map; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; -import net.sourceforge.pmd.lang.java.metrics.internal.NcssMetric.NcssOption; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTBodyDeclaration; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NcssOption; import net.sourceforge.pmd.lang.metrics.MetricOption; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier */ -public class NcssTestRule extends AbstractMetricTestRule { +public class NcssTestRule extends JavaIntMetricTestRule { - @Override - protected boolean isReportClasses() { - return false; + public NcssTestRule() { + super(JavaMetrics.NCSS); } - @Override - protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.NCSS; + protected boolean reportOn(Node node) { + return node instanceof ASTBodyDeclaration; } - - @Override - protected JavaOperationMetricKey getOpKey() { - return JavaOperationMetricKey.NCSS; - } - - @Override protected Map optionMappings() { Map mappings = super.optionMappings(); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java index eeec1f4851..562a41920e 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java @@ -4,23 +4,16 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier * @since 6.0.0 */ -public class NoamTestRule extends AbstractMetricTestRule { +public class NoamTestRule extends JavaIntMetricTestRule { - @Override - protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.NOAM; - } - - - @Override - protected JavaOperationMetricKey getOpKey() { - return null; + public NoamTestRule() { + super(JavaMetrics.NUMBER_OF_ACCESSORS); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java index 444f69de00..eacf4a8a83 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java @@ -4,23 +4,16 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier * @since 6.0.0 */ -public class NopaTestRule extends AbstractMetricTestRule { +public class NopaTestRule extends JavaIntMetricTestRule { - @Override - protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.NOPA; - } - - - @Override - protected JavaOperationMetricKey getOpKey() { - return null; + public NopaTestRule() { + super(JavaMetrics.NUMBER_OF_PUBLIC_FIELDS); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java index 2b478a1a44..4868a1f922 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java @@ -4,23 +4,16 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier * @since 6.0.0 */ -public class TccTestRule extends AbstractMetricTestRule { +public class TccTestRule extends AbstractMetricTestRule.OfDouble { - @Override - protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.TCC; - } - - - @Override - protected JavaOperationMetricKey getOpKey() { - return null; + public TccTestRule() { + super(JavaMetrics.TIGHT_CLASS_COHESION); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java index dabfb75532..156637761c 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java @@ -4,26 +4,15 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier */ -public class WmcTestRule extends AbstractMetricTestRule { +public class WmcTestRule extends JavaIntMetricTestRule { - @Override - protected boolean isReportMethods() { - return false; - } - - @Override - protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.WMC; - } - - @Override - protected JavaOperationMetricKey getOpKey() { - return null; + public WmcTestRule() { + super(JavaMetrics.WEIGHED_METHOD_COUNT); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java index 123f81bf45..57fd9769f4 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java @@ -4,23 +4,16 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey; -import net.sourceforge.pmd.lang.java.metrics.api.JavaOperationMetricKey; +import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier * @since 6.0.0 */ -public class WocTestRule extends AbstractMetricTestRule { +public class WocTestRule extends AbstractMetricTestRule.OfDouble { - @Override - protected JavaClassMetricKey getClassKey() { - return JavaClassMetricKey.WOC; - } - - - @Override - protected JavaOperationMetricKey getOpKey() { - return null; + public WocTestRule() { + super(JavaMetrics.WEIGHT_OF_CLASS); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumWithInterfaces.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumWithInterfaces.java index f493b8c097..e03ecaa15d 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumWithInterfaces.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/EnumWithInterfaces.java @@ -4,31 +4,21 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices.missingoverride; -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.metrics.Metric; -import net.sourceforge.pmd.lang.metrics.MetricKey; - /** * @author Clément Fournier * @since 6.2.0 */ -public enum EnumWithInterfaces implements MetricKey { +public enum EnumWithInterfaces implements InterfaceWithBound { Foo { @Override - public Metric getCalculator() { - return null; + public void handle(int[] ints) { + super.handle(ints); } }; @Override - public Metric getCalculator() { - return null; - } + public void handle(int[] ints) { - - @Override - public boolean supports(ASTAnyTypeDeclaration node) { - return false; } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/InterfaceWithBound.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/InterfaceWithBound.java new file mode 100644 index 0000000000..9673b0d7da --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/missingoverride/InterfaceWithBound.java @@ -0,0 +1,15 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.bestpractices.missingoverride; + +/** + * + */ +public interface InterfaceWithBound { + + + void handle(K k); + +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml index 70b797df76..53c7c419d2 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml @@ -129,29 +129,20 @@ public class AnonClassExample { { +public enum EnumWithInterfaces implements InterfaceWithBound { Foo { @Override - public Metric getCalculator() { - return null; + public void handle(int[] ints) { + super.handle(ints); } }; @Override - public Metric getCalculator() { - return null; - } + public void handle(int[] ints) { - - @Override - public boolean supports(ASTAnyTypeDeclaration node) { - return false; } } + ]]> @@ -162,22 +153,20 @@ public enum EnumWithInterfaces implements MetricKey { { +public enum EnumWithInterfaces implements InterfaceWithBound { Foo { - public Metric getCalculator() { - return null; + @Override + public void handle(int[] ints) { + super.handle(ints); } }; + @Override + public void handle(int[] ints) { - public Metric getCalculator() { - return null; } } + ]]> @@ -244,19 +233,20 @@ public enum EnumWithAnonClass { { + Foo { + @Override + public void handle(int[] ints) { + super.handle(ints); + } + }; -public enum EnumWithInterfaces implements MetricKey { - Foo; + @Override + public void handle(int[] ints) { - // missing - // this is determined from the bridge method, but only works if there are no overloads - public boolean supports(ASTAnyTypeDeclaration node) { - return false; } } + ]]> From d9347d61786ebc7b080e0e86b3a374fdce2f0575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 29 Aug 2020 19:03:26 +0200 Subject: [PATCH 005/101] Doc --- .../pmd/lang/metrics/AbstractMetric.java | 35 ------ .../sourceforge/pmd/lang/metrics/Metric.java | 102 ++++++++++++------ .../pmd/lang/metrics/MetricKey.java | 102 ------------------ .../pmd/lang/metrics/package-info.java | 4 +- .../bestpractices/xml/MissingOverride.xml | 4 - 5 files changed, 74 insertions(+), 173 deletions(-) delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetric.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricKey.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetric.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetric.java deleted file mode 100644 index b8d436ca22..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/AbstractMetric.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.metrics; - -import net.sourceforge.pmd.lang.ast.Node; - -/** - * Abstract class for all metrics. - * - * @param Type of nodes the metric can be computed on - * - * @author Clément Fournier - * @since 6.0.0 - */ -public abstract class AbstractMetric implements Metric { - - /** - * Metrics should be stateless, thus any instance of the same metric class should be equal. - * - * {@inheritDoc} - */ - @Override - public final boolean equals(Object o) { - return o != null && o.getClass() == this.getClass(); - } - - - @Override - public final int hashCode() { - return getClass().hashCode(); - } - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java index 8e000d4456..f664c067ab 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java @@ -4,6 +4,9 @@ package net.sourceforge.pmd.lang.metrics; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + +import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; @@ -15,62 +18,80 @@ import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.util.DataMap.DataKey; /** - * Object computing a metric on a node. Metric objects are stateless, which means that instances of the same - * metric are all equal. + * Object computing a metric on a node. Metric objects are stateless, + * which means that instances of the same metric are all equal. * * @param Type of nodes the metric can be computed on + * @param Result type of the metric * * @author Clément Fournier * @since 6.0.0 */ public interface Metric extends DataKey, R> { + /** + * The full name of the metric. This is the preferred name for displaying. + * Avoid using abbreviations. + */ String name(); + /** + * List of name aliases by which the metric is recognisable. This + * list includes the {@link #name()} of the metric. + */ + List nameAliases(); + /** * Checks if the metric can be computed on the node. - * TODO this should be turned into supports(Node) * * @param node The node to check * * @return True if the metric can be computed + * + * @throws NullPointerException If the parameter is null */ default boolean supports(Node node) { - return asN(node) != null; + return castIfSupported(node) != null; } - default boolean maySupport(Node node) { - return true; - } - - @Nullable N asN(Node node); + /** + * Casts the node to the more specific type {@code } if this metric + * can be computed on it. Returns null if the node is node supported. + * + * @param node An arbitrary node + * + * @return The same node, if it is supported + * + * @throws NullPointerException If the parameter is null + */ + @Nullable N castIfSupported(@NonNull Node node); /** - * Actually computes the value of a metric for an AST node. + * Computes the value of the metric for the given node. Behavior if + * the node is unsupported ({@link #castIfSupported(Node)}) is undefined: + * the method may throw, return null, or return a garbage value. For that + * reason the node should be tested beforehand. * * @param node The node * @param options The options of the metric * - * @return The value of the metric, or {@code Double.NaN} if it could not be computed. + * @return The value of the metric, or null if it could not be computed. + * + * @throws NullPointerException if either parameter is null */ R computeFor(N node, MetricOptions options); - interface MetricTargetSelector { - - N filterCast(Node node); - - boolean maySupport(Node node); - } - /** - * Creates a new metric key from its metric and name. + * Factory method for a metric. * - * @param name The name of the metric * @param compute Implementation for {@link #computeFor(Node, MetricOptions)} - * @param supports Implementation for {@link #supports(Node)} + * @param cast Implementation for {@link #castIfSupported(Node)} + * @param fullName The full name of the metric + * @param aliases Aliases for the name + * @param Return type of the metric * @param Type of node the metric can be computed on * * @return The metric key @@ -78,22 +99,30 @@ public interface Metric extends DataKey Metric of(BiFunction compute, - Function supports, - @NonNull String name, + Function cast, + @NonNull String fullName, String... aliases) { - AssertionUtil.requireParamNotNull("name", name); AssertionUtil.requireParamNotNull("compute", compute); - AssertionUtil.requireParamNotNull("supports", supports); + AssertionUtil.requireParamNotNull("cast", cast); + AssertionUtil.requireParamNotNull("fullName", fullName); + AssertionUtil.requireParamNotNull("aliases", aliases); + + List allNames = listOf(fullName, aliases); return new Metric() { @Override public String name() { - return name; + return fullName; } @Override - public @Nullable T asN(Node node) { - return supports.apply(node); + public List nameAliases() { + return allNames; + } + + @Override + public @Nullable T castIfSupported(@NonNull Node node) { + return cast.apply(node); } @Override @@ -104,9 +133,22 @@ public interface Metric extends DataKey Type of nodes the metric supports + * @param Return type + * + * @return Null if the node is unsupported, otherwise the result of the metric. + * + * @throws NullPointerException if any of the parameters is null + */ static @Nullable R compute(Metric metric, MetricOptions options, Node node) { - N n = metric.asN(node); + N n = metric.castIfSupported(node); if (n != null) { return metric.computeFor(n, options); } 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 deleted file mode 100644 index 4fe1af401d..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricKey.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.metrics; - -import java.util.Objects; - -import org.checkerframework.checker.nullness.qual.NonNull; - -import net.sourceforge.pmd.internal.util.AssertionUtil; -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 - * metric keys. - * - * @param Type of nodes the metric can be computed on - * - * @author Clément Fournier - * @since 5.8.0 - */ -public interface MetricKey extends DataKey, R> { - - /** - * Returns the name of the metric. - * - * @return The name of the metric - */ - String name(); - - - /** - * Returns the object used to calculate the metric. - * - * @return The calculator - */ - Metric getCalculator(); - - - /** - * Returns true if the metric held by this key can be computed on this node. - * - * @param node The node to test - * - * @return Whether or not the metric can be computed on this node - */ - boolean supports(Node node); - - // TODO the metric key should know about supported options - - - /** - * Creates a new metric key from its metric and name. - * - * @param name The name of the metric - * @param metric The metric to use - * @param Type of node the metric can be computed on - * - * @return The metric key - * - * @throws NullPointerException If either parameter is null - */ - static MetricKey of(@NonNull Metric metric, @NonNull String name, String... aliases) { - AssertionUtil.requireParamNotNull("name", name); - AssertionUtil.requireParamNotNull("metric", metric); - - return new MetricKey() { - @Override - public String name() { - return name; - } - - - @Override - public Metric getCalculator() { - return metric; - } - - - @Override - public boolean supports(Node node) { - return metric.supports(node); - } - - - @Override - public boolean equals(Object obj) { - return obj != null && getClass() == obj.getClass() - && Objects.equals(name(), ((MetricKey) obj).name()) - && Objects.equals(getCalculator(), ((MetricKey) obj).getCalculator()); - } - - - @Override - public int hashCode() { - return metric.hashCode() * 31 + name.hashCode(); - } - }; - } -} 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 index e42b2b08fc..8f20baa9f4 100644 --- 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 @@ -5,8 +5,8 @@ /** * 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. + * utility class containing {@link net.sourceforge.pmd.lang.metrics.Metric} + * constants, eg in java, {@code JavaMetrics}. * *

Metrics are cached by default on the nodes they're computed on. * Many APIs here are deprecated, this is because metrics were previously diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml index 53c7c419d2..bcd80bfac9 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml @@ -198,10 +198,6 @@ public class ConcreteClassArrayParams extends AbstractClass { Date: Sat, 29 Aug 2020 19:06:12 +0200 Subject: [PATCH 006/101] Deprecate signatures --- .../lang/apex/metrics/signature/ApexOperationSigMask.java | 3 +++ .../lang/apex/metrics/signature/ApexOperationSignature.java | 3 +++ .../pmd/lang/apex/metrics/signature/ApexSignature.java | 3 +++ .../main/java/net/sourceforge/pmd/lang/ast/SignedNode.java | 5 +++++ .../main/java/net/sourceforge/pmd/lang/metrics/SigMask.java | 4 ++++ .../java/net/sourceforge/pmd/lang/metrics/Signature.java | 3 +++ .../pmd/lang/java/multifile/signature/JavaFieldSigMask.java | 4 ++++ .../lang/java/multifile/signature/JavaFieldSignature.java | 3 +++ .../lang/java/multifile/signature/JavaOperationSigMask.java | 3 +++ .../java/multifile/signature/JavaOperationSignature.java | 3 +++ .../pmd/lang/java/multifile/signature/JavaSigMask.java | 3 +++ .../pmd/lang/java/multifile/signature/JavaSignature.java | 3 +++ 12 files changed, 40 insertions(+) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSigMask.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSigMask.java index feb8e6f5bc..be7326494d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSigMask.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSigMask.java @@ -8,11 +8,14 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.Set; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.apex.metrics.signature.ApexSignature.Visibility; /** * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public class ApexOperationSigMask { private Set visMask = EnumSet.allOf(Visibility.class); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSignature.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSignature.java index 3d2206f8ae..ed599719c6 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSignature.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSignature.java @@ -7,12 +7,15 @@ package net.sourceforge.pmd.lang.apex.metrics.signature; import java.util.HashMap; import java.util.Map; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.metrics.Signature; /** * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public final class ApexOperationSignature extends ApexSignature implements Signature { private static final Map POOL = new HashMap<>(); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexSignature.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexSignature.java index d780e5d75a..18b7a75a4d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexSignature.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexSignature.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.metrics.signature; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; @@ -12,6 +13,8 @@ import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; * * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public abstract class ApexSignature { /** Visibility of the field or method. */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SignedNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SignedNode.java index 6d29939d1a..b92723ae80 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SignedNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SignedNode.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.ast; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.metrics.Signature; /** @@ -14,6 +15,8 @@ import net.sourceforge.pmd.lang.metrics.Signature; * * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public interface SignedNode extends Node { /** @@ -21,6 +24,8 @@ public interface SignedNode extends Node { * * @return The signature */ + @Deprecated + @DeprecatedUntil700 Signature getSignature(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/SigMask.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/SigMask.java index 887cd419be..c17dd6aadf 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/SigMask.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/SigMask.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.metrics; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; + /** * Generic signature mask. * @@ -12,6 +14,8 @@ package net.sourceforge.pmd.lang.metrics; * @author Clément Fournier * @since 6.0.0 */ +@Deprecated +@DeprecatedUntil700 public interface SigMask> { /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Signature.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Signature.java index d13fb8e64d..547a14a277 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Signature.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Signature.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.metrics; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.ast.SignedNode; /** @@ -14,5 +15,7 @@ import net.sourceforge.pmd.lang.ast.SignedNode; * @author Clément Fournier * @since 6.0.0 */ +@Deprecated +@DeprecatedUntil700 public interface Signature> { } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSigMask.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSigMask.java index f6649490d1..587911cb10 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSigMask.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSigMask.java @@ -4,11 +4,15 @@ package net.sourceforge.pmd.lang.java.multifile.signature; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; + /** * Signature mask for a field. Newly created masks cover any field. * * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public final class JavaFieldSigMask extends JavaSigMask { private boolean coverFinal = true; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSignature.java index 83b8f1bd2f..aacee3dcc0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSignature.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSignature.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.multifile.signature; import java.util.HashMap; import java.util.Map; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; /** @@ -14,6 +15,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; * * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public final class JavaFieldSignature extends JavaSignature { private static final Map POOL = new HashMap<>(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSigMask.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSigMask.java index ecd9bb79ae..0ddda40809 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSigMask.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSigMask.java @@ -8,6 +8,7 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.Set; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature.Role; /** @@ -15,6 +16,8 @@ import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature. * * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public final class JavaOperationSigMask extends JavaSigMask { private Set roleMask = EnumSet.allOf(Role.class); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java index d0f7856266..296af1805b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java @@ -8,6 +8,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; @@ -18,6 +19,8 @@ import net.sourceforge.pmd.lang.java.symbols.JElementSymbol; * * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public final class JavaOperationSignature extends JavaSignature { private static final Map POOL = new ConcurrentHashMap<>(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSigMask.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSigMask.java index 54e51c4069..0b1ae93a66 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSigMask.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSigMask.java @@ -8,6 +8,7 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.Set; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.java.multifile.signature.JavaSignature.Visibility; import net.sourceforge.pmd.lang.metrics.SigMask; @@ -18,6 +19,8 @@ import net.sourceforge.pmd.lang.metrics.SigMask; * * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public abstract class JavaSigMask> implements SigMask { /** Visibility mask. */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSignature.java index 36a32ab828..95f77d093c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSignature.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSignature.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.java.multifile.signature; +import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.ast.SignedNode; import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.lang.metrics.Signature; @@ -13,6 +14,8 @@ import net.sourceforge.pmd.lang.metrics.Signature; * * @author Clément Fournier */ +@Deprecated +@DeprecatedUntil700 public abstract class JavaSignature> implements Signature { /** Visibility. */ From 148d3d5397267b4b3a119fe4aec6475142aa3c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 29 Aug 2020 19:26:04 +0200 Subject: [PATCH 007/101] Update release notes --- docs/pages/7_0_0_release_notes.md | 19 +++++++++++++++++-- .../lang/metrics/LanguageMetricsProvider.java | 7 ------- .../sourceforge/pmd/lang/metrics/Metric.java | 4 ++-- .../pmd/lang/metrics/MetricOption.java | 11 ++++------- .../pmd/lang/metrics/MetricOptions.java | 2 +- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 03c8619c6a..16a4a99181 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -168,8 +168,23 @@ The following previously deprecated rules have been finally removed: #### Metrics framework -* {% jdoc_old !!core::lang.metrics.MetricKeyUtil#of(java.lang.String, core::lang.metrics.Metric) %} is replaced with {% jdoc_old !!core::lang.metrics.MetricKey#of(java.lang.String, core::lang.metrics.Metric) %} -* {% jdoc_old !!core::lang.metrics.MetricsUtil#computeAggregate(core::lang.metrics.MetricKey, java.lang.Iterable, core::lang.metrics.ResultOption) %} and its overload are replaced with {% jdoc_old !!core::lang.metrics.MetricsUtil#computeStatistics(core::lang.metrics.MetricKey, java.lang.Iterable) %}, {% jdoc_old core::lang.metrics.ResultOption %} is removed +The metrics framework has been made simpler and more general. + +* The metric interface takes an additional type parameter, representing the result type of the metric. This is usually `Integer` or `Double`. It avoids widening the result to a `double` just to narrow it down. + + This makes it so, that `Double.NaN` is not an appropriate sentinel value to represent "not supported" anymore. Instead, `computeFor` may return `null` in that case (or a garbage value). The value `null` may have caused problems with the narrowing casts, which through unboxing, might have thrown an NPE. But when we deprecated the language-specific metrics façades to replace them with the generic `MetricsUtil`, we took care of making the new methods throw an exception if the metric cannot be computed on the parameter. This forces you to guard calls to `MetricsUtil::computeMetric` with something like `if (metric.supports(node))`. If you're following this pattern, then you won't observe the undefined behavior. + +* The `MetricKey` interface is not so useful and has been merged into the `Metric` interface and removed. So the `Metric` interface has the new method `String name()`. + +* The framework is not tied to at most 2 node types per language anymore. Previously those were nodes for classes and for methods/constructors. Instead, many metrics support more node types. For example, NCSS can be computed on any code block. + + For that reason, keeping around a hard distinction between "class metrics" and "operation metrics" is not useful. So in the Java framework for example, we removed the interfaces `JavaClassMetric`, `JavaOperationMetric`, abstract classes for those, `JavaClassMetricKey`, and `JavaOperationMetricKey`. Metric constants are now all inside the `JavaMetrics` utility class. The same was done in the Apex framework. + + We don't really need abstract classes for metrics now. So `AbstractMetric` is also removed from core. There is a factory method on the `Metric` interface to create a metric easily. + +* This makes it so, that `LanguageMetricsProvider` does not need type parameters. It can just return a `Set>` to list available metrics. + +* `Signature`s, their implementations, and the interface `SignedNode` have been deprecated until PMD 7. They don't carry their weight, and node streams allow replacing their usages very easily. ### External Contributions 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 66ef23689c..052f0820a6 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 @@ -10,7 +10,6 @@ import java.util.Set; import org.checkerframework.checker.nullness.qual.Nullable; -import net.sourceforge.pmd.annotation.Experimental; import net.sourceforge.pmd.lang.LanguageVersionHandler; import net.sourceforge.pmd.lang.ast.Node; @@ -21,16 +20,10 @@ import net.sourceforge.pmd.lang.ast.Node; * like the designer, in a language independent way. Accessible through * {@link LanguageVersionHandler#getLanguageMetricsProvider()}. * - * Note: this is experimental, ie unstable until 7.0.0, after which it will probably - * be promoted to a real API. - * - * @param Type of type declaration nodes of the language - * @param Type of operation declaration nodes of the language * * @author Clément Fournier * @since 6.11.0 */ -@Experimental public interface LanguageMetricsProvider { Set> getMetrics(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java index f664c067ab..994e607b1b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java @@ -18,8 +18,8 @@ import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.util.DataMap.DataKey; /** - * Object computing a metric on a node. Metric objects are stateless, - * which means that instances of the same metric are all equal. + * A named computation that can be carried out on some nodes. Example + * include complexity metrics. * * @param Type of nodes the metric can be computed on * @param Result type of the metric diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOption.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOption.java index de9e017e3d..79226400ba 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOption.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOption.java @@ -5,14 +5,11 @@ package net.sourceforge.pmd.lang.metrics; /** - * Option to pass to a metric. Options modify the behaviour of a metric. You must bundle them into a - * {@link MetricOptions} to pass them all to a metric. + * Option to pass to a metric. Options modify the behaviour of a metric. + * You must bundle them into a {@link MetricOptions} to pass them all to a metric. * - *

Options must implement hashCode and equals. - * - *

Combining options together may be done with a decorator pattern. If you use an AST visitor to compute your - * metric, look at the Cyclo metric in the Java framework for an example (the decorator pattern is not applicable as - * is on a visitor, a modified version of it has been implemented for the Java framework). + *

Options must be suitable for use in sets (implement equals/hashcode, + * or be singletons). * * @author Clément Fournier * @since 6.0.0 diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java index 7a0562839e..17c3aa43e8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java @@ -21,7 +21,7 @@ public class MetricOptions { private static final Map POOL = new HashMap<>(); private static final MetricOptions EMPTY_OPTIONS; - private Set options; + private final Set options; static { From 06f2c96e3c935b887df6d67fa9a14da4455c702f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 16:14:18 +0100 Subject: [PATCH 008/101] Fix tests --- .../lang/metrics/LanguageMetricsProvider.java | 12 +++++++++++ .../rule/xpath/internal/MetricFunction.java | 21 +++++++------------ .../internal/XPathMetricFunctionTest.java | 6 +++--- 3 files changed, 22 insertions(+), 17 deletions(-) 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 052f0820a6..0f2215e429 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 @@ -28,6 +28,18 @@ public interface LanguageMetricsProvider { Set> getMetrics(); + + default @Nullable Metric getMetricWithName(String nameIgnoringCase) { + for (Metric metric : getMetrics()) { + for (String nameAlias : metric.nameAliases()) { + if (nameAlias.equalsIgnoreCase(nameIgnoringCase)) { + return metric; + } + } + } + return null; + } + /** * Computes all metrics available on the given node. * The returned results may contain Double.NaN as a value. diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java index 9bfb8b0744..76ff57a242 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java @@ -70,12 +70,7 @@ public final class MetricFunction extends BaseJavaXPathFunction { } - static String badOperationMetricKeyMessage(String constantName) { - return String.format("'%s' is not the name of an operation metric", constantName); - } - - - static String badClassMetricKeyMessage(String constantName) { + static String badMetricKeyMessage(String constantName) { return String.format("'%s' is not the name of a metric", constantName); } @@ -84,16 +79,14 @@ public final class MetricFunction extends BaseJavaXPathFunction { return "Incorrect node type: the 'metric' function cannot be applied"; } - private static double getMetric(Node n, String metricKeyName) { - for (Metric metric : METRICS.getMetrics()) { - if (metric.name().equalsIgnoreCase(metricKeyName)) { - // todo aliases - Number computed = Metric.compute(metric, MetricOptions.emptyOptions(), n); - return computed == null ? Double.NaN : computed.doubleValue(); - } + private static double getMetric(Node n, String metricKeyName) throws XPathException { + Metric metric = METRICS.getMetricWithName(metricKeyName); + if (metric == null) { + throw new XPathException(badMetricKeyMessage(metricKeyName)); } - throw new IllegalArgumentException(badClassMetricKeyMessage()); + Number computed = Metric.compute(metric, MetricOptions.emptyOptions(), n); + return computed == null ? Double.NaN : computed.doubleValue(); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/XPathMetricFunctionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/XPathMetricFunctionTest.java index 1bc8b347f5..cfeb68c6f9 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/XPathMetricFunctionTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/XPathMetricFunctionTest.java @@ -49,7 +49,7 @@ public class XPathMetricFunctionTest extends BaseXPathFunctionTest { testWithExpectedException( "//ConstructorDeclaration[pmd-java:metric('FOOBAR') > 1]", "class Joo { Joo() {if(true){}} }", - e -> assertThat(e.getMessage(), containsString(MetricFunction.badOperationMetricKeyMessage("FOOBAR")))); + e -> assertThat(e.getMessage(), containsString(MetricFunction.badMetricKeyMessage("FOOBAR")))); } @@ -67,7 +67,7 @@ public class XPathMetricFunctionTest extends BaseXPathFunctionTest { testWithExpectedException( "//EnumDeclaration[pmd-java:metric('CYCLO') > 1]", "enum Loo { FOO; }", - e -> assertThat(e.getMessage(), containsString(MetricFunction.badClassMetricKeyMessage("CYCLO")))); + e -> assertThat(e.getMessage(), containsString(MetricFunction.badMetricKeyMessage("CYCLO")))); } @@ -76,7 +76,7 @@ public class XPathMetricFunctionTest extends BaseXPathFunctionTest { testWithExpectedException( "//MethodDeclaration[pmd-java:metric('WMC') > 1]", "class Moo { void foo() {if(true){}} }", - e -> assertThat(e.getMessage(), containsString(MetricFunction.badOperationMetricKeyMessage("WMC")))); + e -> assertThat(e.getMessage(), containsString(MetricFunction.badMetricKeyMessage("WMC")))); } From 90c123621a03a8d017845ca94319969618c53c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 16:38:31 +0100 Subject: [PATCH 009/101] Make NPath return BigInteger --- .../sourceforge/pmd/lang/metrics/Metric.java | 2 +- .../lang/java/metrics/api/JavaMetrics.java | 11 +- .../internal/visitors/CycloVisitor.java | 2 +- .../internal/visitors/NpathBaseVisitor.java | 140 +++++++----------- .../java/rule/design/NPathComplexityRule.java | 5 +- .../rule/xpath/internal/MetricFunction.java | 8 +- .../lang/java/metrics/impl/NPathTestRule.java | 14 +- .../xpath/internal/BaseXPathFunctionTest.java | 1 - .../internal/XPathMetricFunctionTest.java | 31 ++-- .../pmd/test/AbstractMetricTestRule.java | 9 +- 10 files changed, 103 insertions(+), 120 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java index 994e607b1b..e219aa8c63 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java @@ -57,7 +57,7 @@ public interface Metric extends DataKey} if this metric - * can be computed on it. Returns null if the node is node supported. + * can be computed on it. Returns null if the node is not supported. * * @param node An arbitrary node * diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index 09b522ade4..fedb85ddc0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.metrics.api; import static net.sourceforge.pmd.internal.util.PredicateUtil.always; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -15,12 +16,14 @@ import java.util.function.Function; import java.util.function.Predicate; import org.apache.commons.lang3.mutable.MutableInt; +import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression; import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; @@ -68,7 +71,7 @@ public final class JavaMetrics { Metric.of(JavaMetrics::computeCyclo, isJavaNode(), "Cyclomatic Complexity", "Cyclo"); - public static final Metric NPATH = + public static final Metric NPATH = Metric.of(JavaMetrics::computeNpath, n -> n.asStream().filterIs(ASTMethodOrConstructorDeclaration.class).first(), "NPath Complexity", "NPath"); @@ -141,8 +144,8 @@ public final class JavaMetrics { return counter.getValue(); } - private static int computeNpath(JavaNode node, MetricOptions ignored) { - return (Integer) node.acceptVisitor(NpathBaseVisitor.INSTANCE, null); + private static BigInteger computeNpath(JavaNode node, MetricOptions ignored) { + return (BigInteger) node.acceptVisitor(NpathBaseVisitor.INSTANCE, null); } private static int computeWmc(ASTAnyTypeDeclaration node, MetricOptions options) { @@ -228,7 +231,7 @@ public final class JavaMetrics { * * @return The number of paths through the expression */ - public static int booleanExpressionComplexity(Node expr) { + public static int booleanExpressionComplexity(@Nullable ASTExpression expr) { if (expr == null) { return 0; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java index 7072925e65..411912429d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java @@ -66,7 +66,7 @@ public class CycloVisitor extends JavaVisitorBase { private Void handleSwitch(ASTSwitchLike node, MutableInt data) { if (considerBooleanPaths) { - data.add(JavaMetrics.booleanExpressionComplexity(node.getChild(0))); + data.add(JavaMetrics.booleanExpressionComplexity(node.getTestedExpression())); } for (ASTSwitchBranch branch : node) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java index 08ee0647dc..084cb8541a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java @@ -4,8 +4,9 @@ package net.sourceforge.pmd.lang.java.metrics.internal.visitors; -import java.util.List; +import java.math.BigInteger; +import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; import net.sourceforge.pmd.lang.java.ast.ASTExpression; @@ -24,7 +25,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; +import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; @@ -34,28 +35,19 @@ import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; * @author Clément Fournier * @author Jason Bennett */ -public class NpathBaseVisitor extends JavaParserVisitorAdapter { +public class NpathBaseVisitor extends JavaVisitorBase { /** Instance. */ public static final NpathBaseVisitor INSTANCE = new NpathBaseVisitor(); /* Multiplies the complexity of the children of this node. */ - private int multiplyChildrenComplexities(JavaNode node, Object data) { - int product = 1; + private BigInteger multiplyChildrenComplexities(JavaNode node, Void data) { + BigInteger product = BigInteger.ONE; - for (int i = 0; i < node.getNumChildren(); i++) { - JavaNode n = node.getChild(i); - int childComplexity = (int) n.jjtAccept(this, data); - - int newProduct = product * childComplexity; - if (newProduct >= product) { - product = newProduct; - } else { - // Overflow happened - product = Integer.MAX_VALUE; - break; - } + for (JavaNode child : node.children()) { + BigInteger childComplexity = child.acceptVisitor(this, data); + product = product.multiply(childComplexity); } return product; @@ -63,21 +55,12 @@ public class NpathBaseVisitor extends JavaParserVisitorAdapter { /* Sums the complexity of the children of the node. */ - private int sumChildrenComplexities(JavaNode node, Object data) { - int sum = 0; + private BigInteger sumChildrenComplexities(JavaNode node, Void data) { + BigInteger sum = BigInteger.ZERO; - for (int i = 0; i < node.getNumChildren(); i++) { - JavaNode n = node.getChild(i); - int childComplexity = (int) n.jjtAccept(this, data); - - int newSum = sum + childComplexity; - if (newSum >= sum) { - sum = newSum; - } else { - // Overflow happened - sum = Integer.MAX_VALUE; - break; - } + for (JavaNode child : node.children()) { + BigInteger childComplexity = child.acceptVisitor(this, data); + sum = sum.add(childComplexity); } return sum; @@ -85,150 +68,137 @@ public class NpathBaseVisitor extends JavaParserVisitorAdapter { @Override - public Object visitMethodOrCtor(ASTMethodOrConstructorDeclaration node, Object data) { + public BigInteger visitMethodOrCtor(ASTMethodOrConstructorDeclaration node, Void data) { return multiplyChildrenComplexities(node, data); } @Override - public Object visitJavaNode(JavaNode node, Object data) { + public BigInteger visitJavaNode(JavaNode node, Void data) { return multiplyChildrenComplexities(node, data); } @Override - public Object visit(ASTIfStatement node, Object data) { + public BigInteger visit(ASTIfStatement node, Void data) { // (npath of if + npath of else (or 1) + bool_comp of if) * npath of next - List statementChildren = node.findChildrenOfType(ASTStatement.class); + NodeStream statementChildren = node.children(ASTStatement.class); // add path for not taking if - int complexity = node.hasElse() ? 0 : 1; + BigInteger complexity = node.hasElse() ? BigInteger.ZERO : BigInteger.ONE; for (ASTStatement element : statementChildren) { - complexity += (int) element.jjtAccept(this, data); + complexity = complexity.add(element.acceptVisitor(this, data)); } int boolCompIf = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); - return boolCompIf + complexity; + return complexity.add(BigInteger.valueOf(boolCompIf)); } @Override - public Object visit(ASTWhileStatement node, Object data) { + public BigInteger visit(ASTWhileStatement node, Void data) { // (npath of while + bool_comp of while + 1) * npath of next - int boolCompWhile = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); - - int nPathWhile = (int) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data); - - return boolCompWhile + nPathWhile + 1; + int boolComp = JavaMetrics.booleanExpressionComplexity(node.getCondition()); + BigInteger nPathBody = node.getBody().acceptVisitor(this, data); + return nPathBody.add(BigInteger.valueOf(boolComp + 1)); } @Override - public Object visit(ASTDoStatement node, Object data) { + public BigInteger visit(ASTDoStatement node, Void data) { // (npath of do + bool_comp of do + 1) * npath of next - int boolCompDo = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); - - int nPathDo = (int) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data); - - return boolCompDo + nPathDo + 1; + int boolComp = JavaMetrics.booleanExpressionComplexity(node.getCondition()); + BigInteger nPathBody = node.getBody().acceptVisitor(this, data); + return nPathBody.add(BigInteger.valueOf(boolComp + 1)); } @Override - public Object visit(ASTForStatement node, Object data) { + public BigInteger visit(ASTForStatement node, Void data) { // (npath of for + bool_comp of for + 1) * npath of next - int boolCompFor = JavaMetrics.booleanExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class)); - - int nPathFor = (int) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data); - - return boolCompFor + nPathFor + 1; + int boolComp = JavaMetrics.booleanExpressionComplexity(node.getCondition()); + BigInteger nPathBody = node.getBody().acceptVisitor(this, data); + return nPathBody.add(BigInteger.valueOf(boolComp + 1)); } @Override - public Object visit(ASTReturnStatement node, Object data) { + public BigInteger visit(ASTReturnStatement node, Void data) { // return statements are valued at 1, or the value of the boolean expression - ASTExpression expr = node.getFirstChildOfType(ASTExpression.class); + ASTExpression expr = node.getExpr(); if (expr == null) { - return 1; + return BigInteger.ONE; } int boolCompReturn = JavaMetrics.booleanExpressionComplexity(expr); - int conditionalExpressionComplexity = multiplyChildrenComplexities(expr, data); + BigInteger conditionalExpressionComplexity = multiplyChildrenComplexities(expr, data); - if (conditionalExpressionComplexity > 1) { - boolCompReturn += conditionalExpressionComplexity; - } - - return boolCompReturn > 0 ? boolCompReturn : 1; + return conditionalExpressionComplexity.add(BigInteger.valueOf(boolCompReturn)); } @Override - public Object visit(ASTSwitchExpression node, Object data) { + public BigInteger visit(ASTSwitchExpression node, Void data) { return handleSwitch(node, data); } @Override - public Object visit(ASTSwitchStatement node, Object data) { + public BigInteger visit(ASTSwitchStatement node, Void data) { return handleSwitch(node, data); } - public int handleSwitch(ASTSwitchLike node, Object data) { + public BigInteger handleSwitch(ASTSwitchLike node, Void data) { // bool_comp of switch + sum(npath(case_range)) int boolCompSwitch = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); - int npath = 0; - int caseRange = 0; + BigInteger npath = BigInteger.ZERO; + BigInteger caseRange = BigInteger.ZERO; for (ASTSwitchBranch n : node) { // Fall-through labels count as 1 for complexity if (n instanceof ASTSwitchFallthroughBranch) { - npath += caseRange; - caseRange = 1; + npath = npath.add(caseRange); + caseRange = BigInteger.ONE; } else if (n instanceof ASTSwitchArrowBranch) { - npath += caseRange; - int complexity = (int) n.jjtAccept(this, data); - caseRange = complexity; + npath = npath.add(caseRange); + caseRange = n.acceptVisitor(this, data); } else { - int complexity = (int) n.jjtAccept(this, data); - caseRange *= complexity; + caseRange = caseRange.multiply(n.acceptVisitor(this, data)); } } // add in npath of last label - npath += caseRange; - return boolCompSwitch + npath; + return npath.add(caseRange).add(BigInteger.valueOf(boolCompSwitch)); } @Override - public Object visit(ASTSwitchLabel node, Object data) { + public BigInteger visit(ASTSwitchLabel node, Void data) { if (node.isDefault()) { - return 1; + return BigInteger.ONE; } - return node.findChildrenOfType(ASTExpression.class).size(); + return BigInteger.valueOf(node.children(ASTExpression.class).count()); } @Override - public Object visit(ASTConditionalExpression node, Object data) { + public BigInteger visit(ASTConditionalExpression node, Void data) { // bool comp of guard clause + complexity of last two children (= total - 1) int boolCompTernary = JavaMetrics.booleanExpressionComplexity(node.getCondition()); - return boolCompTernary + sumChildrenComplexities(node, data) - 1; + return sumChildrenComplexities(node, data).add(BigInteger.valueOf(boolCompTernary - 1)); } @Override - public Object visit(ASTTryStatement node, Object data) { + public BigInteger visit(ASTTryStatement node, Void data) { /* * This scenario was not addressed by the original paper. Based on the * principles outlined in the paper, as well as the Checkstyle NPath 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 0228525f33..08040b2d2c 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 @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.rule.design; import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; +import java.math.BigInteger; import java.util.logging.Logger; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; @@ -75,8 +76,8 @@ public class NPathComplexityRule extends AbstractJavaMetricsRule { return data; } - int npath = MetricsUtil.computeMetric(JavaMetrics.NPATH, node); - if (npath >= reportLevel) { + BigInteger npath = MetricsUtil.computeMetric(JavaMetrics.NPATH, node); + if (npath.compareTo(BigInteger.valueOf(reportLevel)) >= 0) { addViolation(data, node, new String[] {node instanceof ASTMethodDeclaration ? "method" : "constructor", PrettyPrintingUtil.displaySignature(node), String.valueOf(npath), diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java index 76ff57a242..adb6de5293 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java @@ -15,6 +15,7 @@ import net.sf.saxon.lib.ExtensionFunctionCall; import net.sf.saxon.om.Sequence; import net.sf.saxon.trans.XPathException; import net.sf.saxon.value.BigDecimalValue; +import net.sf.saxon.value.EmptySequence; import net.sf.saxon.value.SequenceType; @@ -45,7 +46,7 @@ public final class MetricFunction extends BaseJavaXPathFunction { @Override public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { - return SequenceType.SINGLE_DECIMAL; + return SequenceType.OPTIONAL_DECIMAL; } @@ -64,7 +65,10 @@ public final class MetricFunction extends BaseJavaXPathFunction { Node contextNode = ((AstElementNode) context.getContextItem()).getUnderlyingNode(); String metricKey = arguments[0].head().getStringValue(); - return new BigDecimalValue(getMetric(contextNode, metricKey)); + double metric = getMetric(contextNode, metricKey); + return Double.isFinite(metric) + ? new BigDecimalValue(metric) + : EmptySequence.getInstance(); } }; } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java index 2c0c61ba47..096a699a09 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java @@ -4,15 +4,27 @@ package net.sourceforge.pmd.lang.java.metrics.impl; +import java.math.BigInteger; + import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier */ -public class NPathTestRule extends JavaIntMetricTestRule { +public class NPathTestRule extends AbstractMetricTestRule { public NPathTestRule() { super(JavaMetrics.NPATH); } + + @Override + protected BigInteger parseReportLevel(String value) { + return new BigInteger(value); + } + + @Override + protected BigInteger defaultReportLevel() { + return BigInteger.ZERO; + } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseXPathFunctionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseXPathFunctionTest.java index 86ae4e3389..0100fac002 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseXPathFunctionTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/BaseXPathFunctionTest.java @@ -56,7 +56,6 @@ public class BaseXPathFunctionTest extends BaseNonParserTest { Consumer exceptionSpec) { Rule rule = makeXpathRuleFromXPath(xpath); - PmdXPathException thrown = Assert.assertThrows(PmdXPathException.class, () -> executeRule(rule, code)); exceptionSpec.accept(thrown); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/XPathMetricFunctionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/XPathMetricFunctionTest.java index cfeb68c6f9..be0beb8b79 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/XPathMetricFunctionTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/XPathMetricFunctionTest.java @@ -54,31 +54,20 @@ public class XPathMetricFunctionTest extends BaseXPathFunctionTest { @Test - public void testWrongNodeTypeGeneric() { - testWithExpectedException( - "//IfStatement[pmd-java:metric('NCSS') > 1]", - "class Koo { Koo() {if(true){}} }", - e -> assertThat(e.getMessage(), containsString(MetricFunction.genericBadNodeMessage()))); + public void testIfStmt() { + Rule rule = makeXpathRuleFromXPath("//IfStatement[pmd-java:metric('NCSS') = 1]"); + String code = "class Hoo { Hoo() {if(true){}} }"; + + assertFinds(rule, 1, code); } @Test - public void testWrongMetricKeyForTypeDeclaration() { - testWithExpectedException( - "//EnumDeclaration[pmd-java:metric('CYCLO') > 1]", - "enum Loo { FOO; }", - e -> assertThat(e.getMessage(), containsString(MetricFunction.badMetricKeyMessage("CYCLO")))); + public void testWrongNodeTypeMeansEmptySequence() { + Rule rule = makeXpathRuleFromXPath("//EnumDeclaration[not(pmd-java:metric('NPATH'))]"); + String code = "enum Loo { FOO; }"; + + assertFinds(rule, 1, code); } - - @Test - public void testWrongMetricKeyForOperationDeclaration() { - testWithExpectedException( - "//MethodDeclaration[pmd-java:metric('WMC') > 1]", - "class Moo { void foo() {if(true){}} }", - e -> assertThat(e.getMessage(), containsString(MetricFunction.badMetricKeyMessage("WMC")))); - - } - - } diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java index fa9a7a4bfa..580db93bf0 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java @@ -20,8 +20,13 @@ import net.sourceforge.pmd.properties.PropertyFactory; /** - * Abstract test rule for a metric. Tests of metrics use the standard framework for rule testing, using one dummy rule - * per metric. Default parameters can be overridden by overriding the protected methods of this class. + * Abstract test rule for a metric. Tests of metrics use the standard + * framework for rule testing, using one dummy rule per metric. Default + * parameters can be overridden by overriding the protected methods of + * this class. + * + * @param Result type of the metric. The nested subclasses provide + * defaults for common result types * * @author Clément Fournier */ From b7b8199ce926e6bece8b96cadaa20dac6b1bbc36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 16:47:14 +0100 Subject: [PATCH 010/101] Remove duplicate --- .../signature => internal}/JavaAstUtils.java | 2 +- .../lang/java/metrics/api/JavaMetrics.java | 2 +- .../signature/JavaOperationSignature.java | 53 +------------------ 3 files changed, 4 insertions(+), 53 deletions(-) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/{multifile/signature => internal}/JavaAstUtils.java (97%) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaAstUtils.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java similarity index 97% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaAstUtils.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java index 598185cdbb..11076da856 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaAstUtils.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.java.multifile.signature; +package net.sourceforge.pmd.lang.java.internal; import java.util.Map; import java.util.Set; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index fedb85ddc0..44dea411f3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -35,7 +35,7 @@ import net.sourceforge.pmd.lang.java.metrics.internal.visitors.CycloVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NcssVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NpathBaseVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.TccAttributeAccessCollector; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaAstUtils; +import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; import net.sourceforge.pmd.lang.metrics.Metric; import net.sourceforge.pmd.lang.metrics.MetricOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java index 296af1805b..578b4d2ea1 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java @@ -6,12 +6,12 @@ package net.sourceforge.pmd.lang.java.multifile.signature; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Pattern; import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; +import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.symbols.JElementSymbol; /** @@ -85,8 +85,6 @@ public final class JavaOperationSignature extends JavaSignature Date: Tue, 1 Dec 2020 16:53:41 +0100 Subject: [PATCH 011/101] Rename metric name method --- .../pmd/lang/metrics/LanguageMetricsProvider.java | 2 ++ .../main/java/net/sourceforge/pmd/lang/metrics/Metric.java | 7 ++++--- .../pmd/lang/metrics/ParameterizedMetricKey.java | 2 +- .../pmd/lang/metrics/ParameterizedMetricKeyTest.java | 4 ++-- .../pmd/lang/java/metrics/ProjectMemoizerTest.java | 3 +-- 5 files changed, 10 insertions(+), 8 deletions(-) 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 0f2215e429..def0787615 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 @@ -26,9 +26,11 @@ import net.sourceforge.pmd.lang.ast.Node; */ public interface LanguageMetricsProvider { + /** Returns the set of all metrics supported by the language. */ Set> getMetrics(); + /** Fetch a metric using its name. */ default @Nullable Metric getMetricWithName(String nameIgnoringCase) { for (Metric metric : getMetrics()) { for (String nameAlias : metric.nameAliases()) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java index e219aa8c63..3f9888b38e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java @@ -33,11 +33,12 @@ public interface Metric extends DataKey nameAliases(); @@ -111,7 +112,7 @@ public interface Metric extends DataKey() { @Override - public String name() { + public String displayName() { return fullName; } 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 e904609fbe..230c8a033b 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 @@ -37,7 +37,7 @@ final class ParameterizedMetricKey implements @Override public String toString() { - return "ParameterizedMetricKey{key=" + metric.name() + ", options=" + options + '}'; + return "ParameterizedMetricKey{key=" + metric.displayName() + ", options=" + options + '}'; } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKeyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKeyTest.java index 2c49c53781..97dfc80ea6 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKeyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/metrics/ParameterizedMetricKeyTest.java @@ -45,7 +45,7 @@ public class ParameterizedMetricKeyTest { public void testToString() { ParameterizedMetricKey key1 = ParameterizedMetricKey.getInstance(DUMMY_METRIC, DUMMY_VERSION_1); - assertTrue(key1.toString().contains(key1.metric.name())); + assertTrue(key1.toString().contains(key1.metric.displayName())); assertTrue(key1.toString().contains(key1.options.toString())); } @@ -60,7 +60,7 @@ public class ParameterizedMetricKeyTest { assertNotNull(key2); assertSame(key1, key2); assertEquals(key1, key2); - assertTrue(key1.toString().contains(key1.metric.name())); + assertTrue(key1.toString().contains(key1.metric.displayName())); assertTrue(key1.toString().contains(key1.options.toString())); } 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 e1f8fd7d49..a0c662ff2a 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 @@ -33,7 +33,7 @@ public class ProjectMemoizerTest extends BaseNonParserTest { private static Metric randomMetric() { Random capturedRandom = new Random(); - return Metric.of((t, opts)-> capturedRandom.nextInt(), t -> t, "randomMetric"); + return Metric.of((t, opts) -> capturedRandom.nextInt(), t -> t, "randomMetric"); } @Test @@ -92,5 +92,4 @@ public class ProjectMemoizerTest extends BaseNonParserTest { } - } From bb2c27bd6f393aa4a32bd823a8c0b37bc965cbda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 16:58:16 +0100 Subject: [PATCH 012/101] Checkstyle --- .../net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java | 2 ++ .../sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java | 2 +- .../pmd/lang/java/rule/design/CyclomaticComplexityRule.java | 2 +- .../pmd/lang/java/rule/design/NcssCountRule.java | 4 ++-- .../pmd/lang/java/metrics/JavaMetricsProviderTest.java | 6 +++--- .../pmd/lang/java/metrics/impl/AtfdTestRule.java | 1 - .../pmd/lang/java/metrics/impl/CycloTestRule.java | 1 - .../sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java | 1 - .../pmd/lang/java/metrics/impl/NcssTestRule.java | 1 - .../pmd/lang/java/metrics/impl/NoamTestRule.java | 1 - .../pmd/lang/java/metrics/impl/NopaTestRule.java | 1 - .../sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java | 1 - 12 files changed, 9 insertions(+), 14 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 c66cd02e05..1faaa15e88 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 @@ -59,12 +59,14 @@ public final class ApexMetrics { return n -> n.asStream().filterIs(klass).filter(pred).first(); } + @SuppressWarnings("PMD.UnusedFormalParameter") private static int computeCyclo(ApexNode node, MetricOptions ignored) { MutableInt result = new MutableInt(1); node.acceptVisitor(new StandardCycloVisitor(), result); return result.getValue(); } + @SuppressWarnings("PMD.UnusedFormalParameter") private static int computeCognitiveComp(ApexNode node, MetricOptions ignored) { State state = new State(); node.acceptVisitor(CognitiveComplexityVisitor.INSTANCE, state); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index 44dea411f3..32f0734549 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -29,13 +29,13 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.AtfdBaseVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.ClassFanOutVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.CycloVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NcssVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NpathBaseVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.TccAttributeAccessCollector; -import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; import net.sourceforge.pmd.lang.metrics.Metric; import net.sourceforge.pmd.lang.metrics.MetricOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; 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 6d02451617..8706e59332 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 @@ -171,7 +171,7 @@ public class CyclomaticComplexityRule extends AbstractJavaRule { addViolation(data, node, new String[] {kindname, opname, "", - "" + cyclo,}); + "" + cyclo, }); } } } 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 2e583f1442..62656b49ff 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 @@ -94,7 +94,7 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { if (classSize >= classReportLevel) { String[] messageParams = {PrettyPrintingUtil.kindName(node), node.getSimpleName(), - classSize + " (Highest = " + classHighest + ")",}; + classSize + " (Highest = " + classHighest + ")", }; addViolation(data, node, messageParams); } @@ -111,7 +111,7 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { if (methodSize >= methodReportLevel) { addViolation(data, node, new String[] { node instanceof ASTMethodDeclaration ? "method" : "constructor", - PrettyPrintingUtil.displaySignature(node), "" + methodSize,}); + PrettyPrintingUtil.displaySignature(node), "" + methodSize, }); } } return data; diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java index 2bb8ca23e4..a316cd9205 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java @@ -45,7 +45,7 @@ public class JavaMetricsProviderTest { ASTMethodDeclaration op = acu.getFirstDescendantOfType(ASTMethodDeclaration.class); - Map, Number> opResults = provider.computeAllMetricsFor(op); + results = provider.computeAllMetricsFor(op); assertEquals(10, results.size()); } @@ -59,13 +59,13 @@ public class JavaMetricsProviderTest { ASTAnyTypeDeclaration tdecl1 = java8.parse("class Foo { void bar() { System.out.println(1); } }") .getFirstDescendantOfType(ASTAnyTypeDeclaration.class); - Map, Number> reference = provider.computeAllMetricsFor(tdecl1); + Map, Number> reference = provider.computeAllMetricsFor(tdecl1); // same name, different characteristics ASTAnyTypeDeclaration tdecl2 = java8.parse("class Foo { void bar(){} \npublic void hey() { System.out.println(1); } }") .getFirstDescendantOfType(ASTAnyTypeDeclaration.class); - Map, Number> secondTest = provider.computeAllMetricsFor(tdecl2); + Map, Number> secondTest = provider.computeAllMetricsFor(tdecl2); assertNotEquals(reference, secondTest); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java index f5966f6b9f..edbfc7e3bb 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java index ab0d783f61..0b6a95aa3d 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java @@ -9,7 +9,6 @@ import java.util.Map; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.CycloOption; import net.sourceforge.pmd.lang.metrics.MetricOption; -import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * Tests cyclo. diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java index d455ed3854..c65ff28869 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java index 24ec89aa51..46a9dbcdb0 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java @@ -11,7 +11,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTBodyDeclaration; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NcssOption; import net.sourceforge.pmd.lang.metrics.MetricOption; -import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java index 562a41920e..d7335c6313 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java index eacf4a8a83..5f8dfbf414 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java index 156637761c..c6c70a9148 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier From e4cb5f74d809ffd8db4868bca42b2cd3616c8e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 17:05:14 +0100 Subject: [PATCH 013/101] Fix metrics tests --- .../java/metrics/JavaMetricsProviderTest.java | 16 +++------------- .../lang/java/metrics/ProjectMemoizerTest.java | 9 +++++---- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java index a316cd9205..c9ac6cfe59 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java @@ -10,13 +10,11 @@ import static org.junit.Assert.assertNotEquals; import java.util.Map; -import org.junit.Ignore; import org.junit.Test; import net.sourceforge.pmd.lang.java.JavaParsingHelper; 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.metrics.LanguageMetricsProvider; import net.sourceforge.pmd.lang.metrics.Metric; @@ -24,7 +22,6 @@ import net.sourceforge.pmd.lang.metrics.Metric; /** * @author Clément Fournier */ -@Ignore("metrics are like rules, they've not been ported to the new grammar yet") public class JavaMetricsProviderTest { private final JavaParsingHelper java8 = JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("1.8"); @@ -36,18 +33,11 @@ public class JavaMetricsProviderTest { ASTCompilationUnit acu = java8.parse("class Foo { void bar() { System.out.println(1); } }"); - ASTAnyTypeDeclaration type = acu.getFirstDescendantOfType(ASTAnyTypeDeclaration.class); + ASTAnyTypeDeclaration type = acu.getTypeDeclarations().firstOrThrow(); Map, Number> results = provider.computeAllMetricsFor(type); assertEquals(10, results.size()); - - - ASTMethodDeclaration op = acu.getFirstDescendantOfType(ASTMethodDeclaration.class); - - results = provider.computeAllMetricsFor(op); - - assertEquals(10, results.size()); } @@ -57,13 +47,13 @@ public class JavaMetricsProviderTest { LanguageMetricsProvider provider = java8.getHandler("1.8").getLanguageMetricsProvider(); ASTAnyTypeDeclaration tdecl1 = java8.parse("class Foo { void bar() { System.out.println(1); } }") - .getFirstDescendantOfType(ASTAnyTypeDeclaration.class); + .getTypeDeclarations().firstOrThrow(); Map, Number> reference = provider.computeAllMetricsFor(tdecl1); // same name, different characteristics ASTAnyTypeDeclaration tdecl2 = java8.parse("class Foo { void bar(){} \npublic void hey() { System.out.println(1); } }") - .getFirstDescendantOfType(ASTAnyTypeDeclaration.class); + .getTypeDeclarations().firstOrThrow(); Map, Number> secondTest = provider.computeAllMetricsFor(tdecl2); 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 a0c662ff2a..2e8a976930 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 @@ -18,11 +18,12 @@ import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; +import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.metrics.testdata.MetricsVisitorTestData; import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; import net.sourceforge.pmd.lang.metrics.Metric; import net.sourceforge.pmd.lang.metrics.MetricOptions; +import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** * @author Clément Fournier @@ -67,10 +68,10 @@ public class ProjectMemoizerTest extends BaseNonParserTest { private List visitWith(ASTCompilationUnit acu, final boolean force) { final List result = new ArrayList<>(); - acu.jjtAccept(new JavaParserVisitorAdapter() { + acu.acceptVisitor(new JavaVisitorBase() { @Override public Object visitMethodOrCtor(ASTMethodOrConstructorDeclaration node, Object data) { - Integer value = Metric.compute(randomMetric, MetricOptions.emptyOptions(), node); + Integer value = MetricsUtil.computeMetric(randomMetric, node, MetricOptions.emptyOptions(), force); if (value != null) { result.add(value); } @@ -80,7 +81,7 @@ public class ProjectMemoizerTest extends BaseNonParserTest { @Override public Object visitTypeDecl(ASTAnyTypeDeclaration node, Object data) { - Integer value = Metric.compute(randomMetric, MetricOptions.emptyOptions(), node); + Integer value = MetricsUtil.computeMetric(randomMetric, node, MetricOptions.emptyOptions(), force); if (value != null) { result.add(value); } From 4863ebda965c0d42d7d8c8066eb60256a179cf96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 17:18:40 +0100 Subject: [PATCH 014/101] Fix ATFD --- .../lang/java/metrics/api/JavaMetrics.java | 4 +- .../internal/visitors/AtfdBaseVisitor.java | 124 +++--------------- .../java/metrics/impl/AllMetricsTest.java | 4 +- .../lang/java/metrics/impl/AtfdTestRule.java | 7 + .../lang/java/metrics/impl/xml/AtfdTest.xml | 31 +++-- 5 files changed, 48 insertions(+), 122 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index 32f0734549..2b947544aa 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -279,7 +279,9 @@ public final class JavaMetrics { } private static int computeAtfd(JavaNode node, MetricOptions options) { - return ((MutableInt) node.acceptVisitor(new AtfdBaseVisitor(), new MutableInt(0))).getValue(); + MutableInt result = new MutableInt(0); + node.acceptVisitor(new AtfdBaseVisitor(), result); + return result.getValue(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/AtfdBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/AtfdBaseVisitor.java index 46b4dc9118..e5db32304d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/AtfdBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/AtfdBaseVisitor.java @@ -4,20 +4,12 @@ package net.sourceforge.pmd.lang.java.metrics.internal.visitors; -import static net.sourceforge.pmd.lang.ast.NodeStream.asInstanceOf; - -import java.util.List; - -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.mutable.MutableInt; -import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression; -import net.sourceforge.pmd.lang.java.ast.ASTLiteral; -import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; -import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; +import net.sourceforge.pmd.lang.java.ast.ASTFieldAccess; +import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; +import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; +import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; /** @@ -26,108 +18,28 @@ import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; * @author Clément Fournier * @since 6.0.0 */ -public class AtfdBaseVisitor extends JavaParserVisitorAdapter { - +public class AtfdBaseVisitor extends JavaVisitorBase { @Override - public Object visit(ASTPrimaryExpression node, Object data) { - if (isForeignAttributeOrMethod(node)) { - if (isAttributeAccess(node)) { - ((MutableInt) data).increment(); - } else { - ((MutableInt) data).add(countForeignGetterSetterCalls(node)); - } + public Void visit(ASTMethodCall node, MutableInt data) { + if (isForeignMethod(node)) { + data.increment(); } - return super.visit(node, data); + return visitChildren(node, data); } - - private boolean isForeignGetterSetterCall(ASTPrimaryExpression node) { - String methodOrAttributeName = getMethodOrAttributeName(node); - return isForeignGetterSetterCall(methodOrAttributeName); - } - - - private boolean isForeignGetterSetterCall(String methodOrAttributeName) { - return methodOrAttributeName != null && StringUtils.startsWithAny(methodOrAttributeName, "get", "is", "set"); - } - - - private int countForeignGetterSetterCalls(ASTPrimaryExpression node) { - if (!isForeignGetterSetterCall(node) || !isForeignAttributeOrMethod(node)) { - return 0; + @Override + public Void visit(ASTFieldAccess node, MutableInt data) { + JFieldSymbol sym = node.getReferencedSym(); + if (sym != null && !sym.getEnclosingClass().equals(node.getEnclosingType().getSymbol())) { + data.increment(); } - - List suffixes = node.findDescendantsOfType(ASTPrimarySuffix.class); - int result = 0; - for (ASTPrimarySuffix suffix : suffixes) { - if (suffix.isArguments()) { - result++; - } else { - String methodOrAttributeName = getMethodOrAttributeName(suffix); - if (!isForeignGetterSetterCall(methodOrAttributeName)) { - break; - } - } - } - return result; + return visitChildren(node, data); } - - private boolean isForeignAttributeOrMethod(ASTPrimaryExpression node) { - boolean result; - String nameImage = getNameImage(node); - - if (nameImage != null && (!nameImage.contains(".") || nameImage.startsWith("this."))) { - result = false; - } else if (nameImage == null && node.getFirstDescendantOfType(ASTPrimaryPrefix.class).usesThisModifier()) { - result = false; - } else if (nameImage == null && node.descendants().map(asInstanceOf(ASTLiteral.class, ASTAllocationExpression.class)).nonEmpty()) { - result = false; - } else { - result = true; - } - - return result; - } - - - private String getNameImage(ASTPrimaryExpression node) { - ASTPrimaryPrefix prefix = node.getFirstDescendantOfType(ASTPrimaryPrefix.class); - ASTName name = prefix.getFirstDescendantOfType(ASTName.class); - - String image = null; - if (name != null) { - image = name.getImage(); - } - return image; - } - - - private String getMethodOrAttributeName(ASTPrimaryExpression node) { - ASTPrimaryPrefix prefix = node.getFirstDescendantOfType(ASTPrimaryPrefix.class); - ASTName name = prefix.getFirstDescendantOfType(ASTName.class); - - String methodOrAttributeName = null; - - if (name != null) { - int dotIndex = name.getImage().indexOf("."); - if (dotIndex > -1) { - methodOrAttributeName = name.getImage().substring(dotIndex + 1); - } - } - - return methodOrAttributeName; - } - - - private String getMethodOrAttributeName(ASTPrimarySuffix node) { - return node.getImage(); - } - - - private boolean isAttributeAccess(ASTPrimaryExpression node) { - return !node.hasDescendantOfType(ASTPrimarySuffix.class); + private boolean isForeignMethod(ASTMethodCall node) { + return node.getMethodName().startsWith("set") + || node.getMethodName().startsWith("get"); } } 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 fad0e180bf..d289df2bf1 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 @@ -15,7 +15,6 @@ import net.sourceforge.pmd.testframework.SimpleAggregatorTst; * * @author Clément Fournier */ -//@Ignore("Metrics tests are ignored until we stabilise the AST, like rules") public class AllMetricsTest extends SimpleAggregatorTst { @@ -42,7 +41,8 @@ public class AllMetricsTest extends SimpleAggregatorTst { if (node instanceof ASTAnyTypeDeclaration) { qname = ((ASTAnyTypeDeclaration) node).getBinaryName(); } else if (node instanceof ASTMethodOrConstructorDeclaration) { - qname = PrettyPrintingUtil.displaySignature((ASTMethodOrConstructorDeclaration) node); + String enclosing = ((ASTMethodOrConstructorDeclaration) node).getEnclosingType().getBinaryName(); + qname = enclosing + "#" + PrettyPrintingUtil.displaySignature((ASTMethodOrConstructorDeclaration) node); } if (qname != null) { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java index edbfc7e3bb..74712215e9 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java @@ -5,6 +5,8 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; /** @@ -17,6 +19,11 @@ public class AtfdTestRule extends JavaIntMetricTestRule { super(JavaMetrics.ACCESS_TO_FOREIGN_DATA); } + @Override + protected boolean reportOn(Node node) { + return node instanceof ASTMethodOrConstructorDeclaration + || node instanceof ASTAnyTypeDeclaration; + } @Override protected String violationMessage(Node node, Integer result) { diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/AtfdTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/AtfdTest.xml index 3e01c584b2..a895ce8a7d 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/AtfdTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/AtfdTest.xml @@ -125,16 +125,17 @@ public class StatementAndBraceFinder extends JavaParserVisitorAdapter { - Full example - 7 + Full example + 8 - 'StatementAndBraceFinder' has value 36 highest 18. - 'StatementAndBraceFinder#buildDataFlowFor(JavaNode)' has value 6. - 'StatementAndBraceFinder#tryToLog(String, NodeType, Node)' has value 4. + 'StatementAndBraceFinder' has value 18. + 'StatementAndBraceFinder#StatementAndBraceFinder(DataFlowHandler)' has value 0. + 'StatementAndBraceFinder#buildDataFlowFor(JavaNode)' has value 4. + 'StatementAndBraceFinder#tryToLog(String, NodeType, Node)' has value 2. 'StatementAndBraceFinder#tryToLog(NodeType, Node)' has value 0. - 'StatementAndBraceFinder#visit(ASTStatementExpression, Object)' has value 4. - 'StatementAndBraceFinder#visit(ASTVariableDeclarator, Object)' has value 4. - 'StatementAndBraceFinder#visit(ASTExpression, Object)' has value 18. + 'StatementAndBraceFinder#visit(ASTStatementExpression, Object)' has value 2. + 'StatementAndBraceFinder#visit(ASTVariableDeclarator, Object)' has value 2. + 'StatementAndBraceFinder#visit(ASTExpression, Object)' has value 6. @@ -160,7 +161,7 @@ public class Foo { Test empty class 1 - 'Foo' has value 0 highest 0. + 'Foo' has value 0. - ATFD doesn't support interfaces or annotations - 0 + ATFD with interfaces or annotations + 2 + + 'Foo' has value 0. + 'Foo$Tag' has value 0. + ATFD without method call chains 2 - 'Foo' has value 2 highest 2. + 'Foo' has value 2. 'Foo#bar()' has value 2. ATFD with method call chains 2 - 'Foo' has value 2 highest 2. + 'Foo' has value 2. 'Foo#bar()' has value 2. Date: Tue, 1 Dec 2020 17:53:16 +0100 Subject: [PATCH 015/101] Fix cyclo --- .../pmd/lang/java/ast/ASTSwitchLabel.java | 7 +-- .../pmd/lang/java/internal/JavaAstUtils.java | 11 +++++ .../lang/java/metrics/api/JavaMetrics.java | 44 ++++++++----------- .../internal/visitors/CycloVisitor.java | 20 ++++++--- .../lang/java/metrics/impl/AtfdTestRule.java | 6 --- .../metrics/impl/JavaIntMetricTestRule.java | 8 ++++ .../lang/java/metrics/impl/xml/CycloTest.xml | 8 +--- 7 files changed, 55 insertions(+), 49 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabel.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabel.java index 41bbcfa803..847f5f4725 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabel.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabel.java @@ -5,7 +5,8 @@ package net.sourceforge.pmd.lang.java.ast; import java.util.Iterator; -import java.util.List; + +import net.sourceforge.pmd.lang.ast.NodeStream; /** @@ -43,8 +44,8 @@ public final class ASTSwitchLabel extends AbstractJavaNode implements Iterable getExprList() { - return findChildrenOfType(ASTExpression.class); + public NodeStream getExprList() { + return children(ASTExpression.class); } @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java index 11076da856..d5d378aa91 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java @@ -11,7 +11,10 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.BinaryOp; +import net.sourceforge.pmd.lang.java.ast.JavaNode; /** * @@ -87,4 +90,12 @@ public final class JavaAstUtils { } + public static boolean isConditional(JavaNode ifx) { + if (ifx instanceof ASTInfixExpression) { + BinaryOp op = ((ASTInfixExpression) ifx).getOperator(); + return op == BinaryOp.CONDITIONAL_AND + || op == BinaryOp.CONDITIONAL_OR; + } + return false; + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index 2b947544aa..3e650a5725 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -21,8 +21,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression; -import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; @@ -67,12 +65,12 @@ public final class JavaMetrics { Metric.of(JavaMetrics::computeTcc, asClass(it -> !it.isInterface()), "Tight Class Cohesion", "TCC"); - public static final Metric CYCLO = - Metric.of(JavaMetrics::computeCyclo, isJavaNode(), + public static final Metric CYCLO = + Metric.of(JavaMetrics::computeCyclo, asMethodOrCtor(), "Cyclomatic Complexity", "Cyclo"); public static final Metric NPATH = - Metric.of(JavaMetrics::computeNpath, n -> n.asStream().filterIs(ASTMethodOrConstructorDeclaration.class).first(), + Metric.of(JavaMetrics::computeNpath, asMethodOrCtor(), "NPath Complexity", "NPath"); public static final Metric WEIGHED_METHOD_COUNT = @@ -100,9 +98,14 @@ public final class JavaMetrics { private static Function isJavaNode() { - return filterMapNode(JavaNode.class, always()); + return n -> n instanceof JavaNode ? (JavaNode) n : null; } + private static Function asMethodOrCtor() { + return n -> n instanceof ASTMethodOrConstructorDeclaration ? (ASTMethodOrConstructorDeclaration) n : null; + } + + private static Function filterMapNode(Class klass, Predicate pred) { return n -> n.asStream().filterIs(klass).filter(pred).first(); } @@ -139,13 +142,13 @@ public final class JavaMetrics { private static int computeCyclo(JavaNode node, MetricOptions options) { - MutableInt counter = new MutableInt(1); + MutableInt counter = new MutableInt(0); node.acceptVisitor(new CycloVisitor(options, node), counter); return counter.getValue(); } private static BigInteger computeNpath(JavaNode node, MetricOptions ignored) { - return (BigInteger) node.acceptVisitor(NpathBaseVisitor.INSTANCE, null); + return node.acceptVisitor(NpathBaseVisitor.INSTANCE, null); } private static int computeWmc(ASTAnyTypeDeclaration node, MetricOptions options) { @@ -236,24 +239,13 @@ public final class JavaMetrics { return 0; } - List andNodes = expr.findDescendantsOfType(ASTConditionalAndExpression.class); - List orNodes = expr.findDescendantsOfType(ASTConditionalOrExpression.class); - - int complexity = 0; - - if (expr instanceof ASTConditionalOrExpression || expr instanceof ASTConditionalAndExpression) { - complexity++; - } - - for (ASTConditionalOrExpression element : orNodes) { - complexity += element.getNumChildren() - 1; - } - - for (ASTConditionalAndExpression element : andNodes) { - complexity += element.getNumChildren() - 1; - } - - return complexity; + return expr.descendantsOrSelf() + .reduce(0, (acc, ifx) -> { + if (JavaAstUtils.isConditional(ifx)) { + return acc + 1; + } + return acc; + }); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java index 411912429d..d791b4573c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java @@ -7,14 +7,13 @@ package net.sourceforge.pmd.lang.java.metrics.internal.visitors; import org.apache.commons.lang3.mutable.MutableInt; import net.sourceforge.pmd.lang.java.ast.ASTAssertStatement; -import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement; import net.sourceforge.pmd.lang.java.ast.ASTCatchClause; import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; -import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTForStatement; import net.sourceforge.pmd.lang.java.ast.ASTForeachStatement; import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; +import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTSwitchBranch; import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression; import net.sourceforge.pmd.lang.java.ast.ASTSwitchLike; @@ -76,12 +75,13 @@ public class CycloVisitor extends JavaVisitorBase { } if (considerBooleanPaths) { - data.add(branch.findChildrenOfType(ASTExpression.class).size()); - } else if (node.getNumChildren() > 1 + branch.getIndexInParent() - && node.getChild(branch.getIndexInParent() + 1) instanceof ASTBlockStatement) { - // an empty label is only counted if we count boolean paths - data.increment(); + data.add(branch.getLabel().getExprList().count()); } +// else if (branch instanceof ASTSwitchFallthroughBranch) { +// if (considerBooleanPaths && ((ASTSwitchFallthroughBranch) branch).getStatements().isEmpty()) + // an empty label is only counted if we count boolean paths +// data.increment(); +// } } return visitJavaNode(node, data); @@ -136,6 +136,12 @@ public class CycloVisitor extends JavaVisitorBase { return super.visit(node, data); } + @Override + public Void visitMethodOrCtor(ASTMethodOrConstructorDeclaration node, MutableInt data) { + data.increment(); + return super.visitMethodOrCtor(node, data); + } + @Override public Void visit(ASTDoStatement node, MutableInt data) { data.increment(); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java index 74712215e9..9bb1863364 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java @@ -19,12 +19,6 @@ public class AtfdTestRule extends JavaIntMetricTestRule { super(JavaMetrics.ACCESS_TO_FOREIGN_DATA); } - @Override - protected boolean reportOn(Node node) { - return node instanceof ASTMethodOrConstructorDeclaration - || node instanceof ASTAnyTypeDeclaration; - } - @Override protected String violationMessage(Node node, Integer result) { return super.violationMessage(node, result); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java index f26cdad1ae..01a0bbb28b 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java @@ -6,6 +6,8 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.ast.AstProcessingStage; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.metrics.Metric; import net.sourceforge.pmd.test.AbstractMetricTestRule; @@ -18,6 +20,12 @@ public abstract class JavaIntMetricTestRule extends AbstractMetricTestRule.OfInt super(metric); } + @Override + protected boolean reportOn(Node node) { + return super.reportOn(node) + && (node instanceof ASTMethodOrConstructorDeclaration + || node instanceof ASTAnyTypeDeclaration); + } @Override public boolean dependsOn(AstProcessingStage stage) { diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml index 621adf49de..bae077b3eb 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml @@ -152,7 +152,6 @@ public class Complicated { Empty methods should count 1 - false 1 'Foo#foo()' has value 1. @@ -180,7 +179,6 @@ public class Test { #984 Cyclomatic complexity should treat constructors like methods - false 1 'Test#Test()' has value 4. @@ -204,7 +202,6 @@ class Foo { Standard Cyclo should count empty switch labels too - false 2 1 @@ -230,7 +227,6 @@ class Foo { Standard Cyclo should count boolean paths - false 1 'Foo#foo()' has value 8. @@ -344,11 +340,9 @@ public class LambdaTest { Complexity of lambdas doesn't affect the complexity of the method, refs #837 - 3 + 4 'LambdaTest#notSoComplex(int)' has value 4. - 'LambdaTest#lambda$notSoComplex$0' has value 2. - 'LambdaTest#lambda$notSoComplex$1' has value 8. From 31a623d9cb46e1cd31c34fed7176659472d0bb39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 18:05:01 +0100 Subject: [PATCH 016/101] Fix ncss --- .../lang/java/metrics/api/JavaMetrics.java | 5 +- .../internal/visitors/NcssVisitor.java | 120 +++++++++--------- .../lang/java/metrics/impl/NcssTestRule.java | 15 ++- .../lang/java/metrics/impl/xml/NcssTest.xml | 56 ++------ 4 files changed, 89 insertions(+), 107 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index 3e650a5725..c5458f9449 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -132,8 +132,9 @@ public final class JavaMetrics { } private static int computeNcss(JavaNode node, MetricOptions options) { - MutableInt ncss = (MutableInt) node.acceptVisitor(new NcssVisitor(options, node), new MutableInt(0)); - return ncss.getValue(); + MutableInt result = new MutableInt(0); + node.acceptVisitor(new NcssVisitor(options, node), result); + return result.getValue(); } private static int computeLoc(JavaNode node, MetricOptions ignored) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java index 8b797602bd..7f7f0c9fbc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java @@ -39,7 +39,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTSynchronizedStatement; import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; +import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NcssOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; @@ -50,7 +50,7 @@ import net.sourceforge.pmd.lang.metrics.MetricOptions; * @author Clément Fournier * @since 6.7.0 */ -public class NcssVisitor extends JavaParserVisitorAdapter { +public class NcssVisitor extends JavaVisitorBase { protected final boolean countImports; @@ -64,14 +64,14 @@ public class NcssVisitor extends JavaParserVisitorAdapter { @Override - public final Object visitJavaNode(JavaNode node, Object data) { + public final Void visitJavaNode(JavaNode node, MutableInt data) { // same here return super.visitJavaNode(node, data); } @Override - public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { + public Void visit(ASTClassOrInterfaceDeclaration node, MutableInt data) { if (countImports) { ASTCompilationUnit acu = node.getFirstParentOfType(ASTCompilationUnit.class); List imports = acu.findChildrenOfType(ASTImportDeclaration.class); @@ -80,56 +80,56 @@ public class NcssVisitor extends JavaParserVisitorAdapter { if (!acu.findChildrenOfType(ASTPackageDeclaration.class).isEmpty()) { increment++; } - ((MutableInt) data).add(increment); + data.add(increment); } - ((MutableInt) data).increment(); + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTEnumDeclaration node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTEnumDeclaration node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTAnnotationTypeDeclaration node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTAnnotationTypeDeclaration node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTFieldDeclaration node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTFieldDeclaration node, MutableInt data) { + data.increment(); // May use a lambda return super.visit(node, data); } @Override - public Object visit(ASTMethodDeclaration node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTMethodDeclaration node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTConstructorDeclaration node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTConstructorDeclaration node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTLocalVariableDeclaration node, Object data) { + public Void visit(ASTLocalVariableDeclaration node, MutableInt data) { // doesn't count variable declared inside a for initializer if (!(node.getParent() instanceof ASTForInit)) { - ((MutableInt) data).increment(); + data.increment(); } // May declare a lambda return super.visit(node, data); @@ -137,10 +137,10 @@ public class NcssVisitor extends JavaParserVisitorAdapter { @Override - public Object visit(ASTIfStatement node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTIfStatement node, MutableInt data) { + data.increment(); if (node.hasElse()) { - ((MutableInt) data).increment(); + data.increment(); } return super.visit(node, data); @@ -148,122 +148,122 @@ public class NcssVisitor extends JavaParserVisitorAdapter { @Override - public Object visit(ASTWhileStatement node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTWhileStatement node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTSwitchStatement node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTSwitchStatement node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTExpressionStatement node, Object data) { + public Void visit(ASTExpressionStatement node, MutableInt data) { if (!(node.getParent().getParent() instanceof ASTForUpdate)) { - ((MutableInt) data).increment(); + data.increment(); } - return data; + return null; } @Override - public Object visit(ASTExplicitConstructorInvocation node, Object data) { - ((MutableInt) data).increment(); - return data; + public Void visit(ASTExplicitConstructorInvocation node, MutableInt data) { + data.increment(); + return null; } @Override - public Object visit(ASTContinueStatement node, Object data) { - ((MutableInt) data).increment(); - return data; + public Void visit(ASTContinueStatement node, MutableInt data) { + data.increment(); + return null; } @Override - public Object visit(ASTBreakStatement node, Object data) { - ((MutableInt) data).increment(); - return data; + public Void visit(ASTBreakStatement node, MutableInt data) { + data.increment(); + return null; } @Override - public Object visit(ASTReturnStatement node, Object data) { - ((MutableInt) data).increment(); - return data; + public Void visit(ASTReturnStatement node, MutableInt data) { + data.increment(); + return null; } @Override - public Object visit(ASTDoStatement node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTDoStatement node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTForStatement node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTForStatement node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTSynchronizedStatement node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTSynchronizedStatement node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTCatchClause node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTCatchClause node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTThrowStatement node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTThrowStatement node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTFinallyClause node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTFinallyClause node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTLabeledStatement node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTLabeledStatement node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTSwitchLabel node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTSwitchLabel node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTInitializer node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTInitializer node, MutableInt data) { + data.increment(); return super.visit(node, data); } @Override - public Object visit(ASTAssertStatement node, Object data) { - ((MutableInt) data).increment(); + public Void visit(ASTAssertStatement node, MutableInt data) { + data.increment(); return super.visit(node, data); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java index 46a9dbcdb0..ca9c69d68f 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java @@ -7,23 +7,34 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import java.util.Map; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTBodyDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NcssOption; import net.sourceforge.pmd.lang.metrics.MetricOption; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; /** * @author Clément Fournier */ public class NcssTestRule extends JavaIntMetricTestRule { + static final PropertyDescriptor reportClasses = + PropertyFactory.booleanProperty("reportClasses") + .desc("...") + .defaultValue(false).build(); + public NcssTestRule() { super(JavaMetrics.NCSS); + definePropertyDescriptor(reportClasses); } @Override protected boolean reportOn(Node node) { - return node instanceof ASTBodyDeclaration; + return super.reportOn(node) + && (node instanceof ASTMethodOrConstructorDeclaration + || getProperty(reportClasses) && node instanceof ASTAnyTypeDeclaration); } @Override diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml index cea437ff07..265b73d68f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml @@ -52,7 +52,7 @@ public class Foo extends Bar { } } - super(z); + supexx(z); } public void foo() { @@ -126,7 +126,7 @@ public class Foo extends Bar { true 5 - 'com.company.money.Foo' has value 66 highest 21. + 'com.company.money.Foo' has value 66. 'com.company.money.Foo#Foo()' has value 2. 'com.company.money.Foo#Foo(int)' has value 13. 'com.company.money.Foo#foo()' has value 14. @@ -141,7 +141,7 @@ public class Foo extends Bar { countImports 5 - 'com.company.money.Foo' has value 69 highest 21. + 'com.company.money.Foo' has value 69. 'com.company.money.Foo#Foo()' has value 2. 'com.company.money.Foo#Foo(int)' has value 13. 'com.company.money.Foo#foo()' has value 14. @@ -170,7 +170,7 @@ public class Foo { true 1 - 'Foo' has value 1 highest 0. + 'Foo' has value 1. Nested classes are counted true - false - 2 + 4 - 'Boo' has value 8 highest 2. - 'Boo$Barnabee' has value 5 highest 2. - - - - - - Nested classes are counted - true - false - 2 - - 'Boo' has value 8 highest 2. - 'Boo$Barnabee' has value 5 highest 2. + 'Boo' has value 8. + 'Boo#foo()' has value 2. + 'Boo$Barnabee' has value 5. + 'Boo$Barnabee#getX()' has value 2. Enum constants are not counted true - false 1 - 'Shoo' has value 1 highest 0. + 'Shoo' has value 1. Annotation declarations are counted true - false 1 - 'Moo' has value 1 highest 0. + 'Moo' has value 1. Lambdas themselves don't count, only the code within - 2 + 1 'Koo#bar()' has value 2. - 'Koo#lambda$bar$0' has value 0. Code inside lambdas is counted by default - 2 + 1 'Koo#bar()' has value 4. - 'Koo#lambda$bar$0' has value 2. Date: Tue, 1 Dec 2020 18:39:38 +0100 Subject: [PATCH 017/101] Fix npath --- .../main/java/net/sourceforge/pmd/Rule.java | 2 +- .../internal/visitors/NpathBaseVisitor.java | 45 ++++++++++--------- .../java/metrics/impl/AllMetricsTest.java | 18 ++++---- .../metrics/impl/JavaIntMetricTestRule.java | 6 --- .../lang/java/metrics/impl/NPathTestRule.java | 6 +++ .../lang/java/metrics/impl/xml/NPathTest.xml | 26 +++++++++-- 6 files changed, 64 insertions(+), 39 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/Rule.java b/pmd-core/src/main/java/net/sourceforge/pmd/Rule.java index 92b1fea733..f298b6018d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/Rule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/Rule.java @@ -288,7 +288,7 @@ public interface Rule extends PropertySource { */ @Experimental default boolean dependsOn(AstProcessingStage stage) { - return false; + return true; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java index 084cb8541a..62b4122be0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java @@ -42,15 +42,12 @@ public class NpathBaseVisitor extends JavaVisitorBase { /* Multiplies the complexity of the children of this node. */ - private BigInteger multiplyChildrenComplexities(JavaNode node, Void data) { - BigInteger product = BigInteger.ONE; + private BigInteger multiplyChildrenComplexities(JavaNode node) { + return multiplyComplexities(node.children()); + } - for (JavaNode child : node.children()) { - BigInteger childComplexity = child.acceptVisitor(this, data); - product = product.multiply(childComplexity); - } - - return product; + private BigInteger multiplyComplexities(NodeStream nodes) { + return nodes.reduce(BigInteger.ONE, (acc, n) -> acc.multiply(n.acceptVisitor(this, null))); } @@ -69,13 +66,13 @@ public class NpathBaseVisitor extends JavaVisitorBase { @Override public BigInteger visitMethodOrCtor(ASTMethodOrConstructorDeclaration node, Void data) { - return multiplyChildrenComplexities(node, data); + return multiplyChildrenComplexities(node); } @Override public BigInteger visitJavaNode(JavaNode node, Void data) { - return multiplyChildrenComplexities(node, data); + return multiplyChildrenComplexities(node); } @@ -138,7 +135,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { } int boolCompReturn = JavaMetrics.booleanExpressionComplexity(expr); - BigInteger conditionalExpressionComplexity = multiplyChildrenComplexities(expr, data); + BigInteger conditionalExpressionComplexity = multiplyChildrenComplexities(expr); return conditionalExpressionComplexity.add(BigInteger.valueOf(boolCompReturn)); } @@ -157,26 +154,34 @@ public class NpathBaseVisitor extends JavaVisitorBase { public BigInteger handleSwitch(ASTSwitchLike node, Void data) { // bool_comp of switch + sum(npath(case_range)) - int boolCompSwitch = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); + int boolCompSwitch = JavaMetrics.booleanExpressionComplexity(node.getTestedExpression()); BigInteger npath = BigInteger.ZERO; - BigInteger caseRange = BigInteger.ZERO; + int caseRange = 0; for (ASTSwitchBranch n : node) { // Fall-through labels count as 1 for complexity if (n instanceof ASTSwitchFallthroughBranch) { - npath = npath.add(caseRange); - caseRange = BigInteger.ONE; + caseRange += numAlternatives(n); + NodeStream statements = ((ASTSwitchFallthroughBranch) n).getStatements(); + if (statements.nonEmpty()) { + BigInteger branchNpath = multiplyComplexities(statements); + npath = npath.add(branchNpath.multiply(BigInteger.valueOf(caseRange))); + caseRange = 0; + } } else if (n instanceof ASTSwitchArrowBranch) { - npath = npath.add(caseRange); - caseRange = n.acceptVisitor(this, data); - } else { - caseRange = caseRange.multiply(n.acceptVisitor(this, data)); + int numAlts = numAlternatives(n); + BigInteger branchNpath = ((ASTSwitchArrowBranch) n).getRightHandSide().acceptVisitor(this, data); + npath = npath.add(branchNpath.multiply(BigInteger.valueOf(numAlts))); } } // add in npath of last label - return npath.add(caseRange).add(BigInteger.valueOf(boolCompSwitch)); + return npath.add(BigInteger.valueOf(boolCompSwitch)); + } + + private int numAlternatives(ASTSwitchBranch n) { + return n.isDefault() ? 1 : n.getLabel().getExprList().count(); } @Override 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 d289df2bf1..241015eb4f 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 @@ -22,17 +22,17 @@ public class AllMetricsTest extends SimpleAggregatorTst { @Override public void setUp() { - addRule(RULESET, "CycloTest"); +// addRule(RULESET, "CycloTest"); addRule(RULESET, "NcssTest"); - addRule(RULESET, "WmcTest"); - addRule(RULESET, "LocTest"); +// addRule(RULESET, "WmcTest"); +// addRule(RULESET, "LocTest"); addRule(RULESET, "NPathTest"); - addRule(RULESET, "NopaTest"); - addRule(RULESET, "NoamTest"); - addRule(RULESET, "WocTest"); - addRule(RULESET, "TccTest"); - addRule(RULESET, "AtfdTest"); - addRule(RULESET, "CfoTest"); +// addRule(RULESET, "NopaTest"); +// addRule(RULESET, "NoamTest"); +// addRule(RULESET, "WocTest"); +// addRule(RULESET, "TccTest"); +// addRule(RULESET, "AtfdTest"); +// addRule(RULESET, "CfoTest"); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java index 01a0bbb28b..ede81d82cf 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaIntMetricTestRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.ast.AstProcessingStage; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; @@ -27,11 +26,6 @@ public abstract class JavaIntMetricTestRule extends AbstractMetricTestRule.OfInt || node instanceof ASTAnyTypeDeclaration); } - @Override - public boolean dependsOn(AstProcessingStage stage) { - return true; - } - @Override protected String violationMessage(Node node, Integer result) { return AllMetricsTest.formatJavaMessage(node, result, super.violationMessage(node, result)); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java index 096a699a09..d9b6cd04f4 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import java.math.BigInteger; +import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; import net.sourceforge.pmd.test.AbstractMetricTestRule; @@ -18,6 +19,11 @@ public class NPathTestRule extends AbstractMetricTestRule { super(JavaMetrics.NPATH); } + @Override + protected String violationMessage(Node node, BigInteger result) { + return AllMetricsTest.formatJavaMessage(node, result, super.violationMessage(node, result)); + } + @Override protected BigInteger parseReportLevel(String value) { return new BigInteger(value); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml index 4a0857d5df..4483047805 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml @@ -423,7 +423,7 @@ public class Test { 6 1 - 'SOFExample#usefulMethod(List)' has value 272. + 'SOFExample#usefulMethod(List)' has value 256. 6 1 - 'SOFExample#usefulMethod(List)' has value 272. + 'SOFExample#usefulMethod(List)' has value 256. 0 1 - 'NPathComplexityOverflow#complexMethod()' has value 2147483647. + 'NPathComplexityOverflow#complexMethod()' has value 2147483648. + + Switch expressions (simpler) + 1 + + 'NPathTest#buildProduct(String, Language)' has value 2. + + fr(title); + default -> de(title); + }; + return product; + } + } + ]]> + From adb4030ab16f5845f628c5f9d0dc444080582cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 18:40:18 +0100 Subject: [PATCH 018/101] Fix loc --- .../pmd/lang/java/metrics/impl/AllMetricsTest.java | 2 +- .../pmd/lang/java/metrics/impl/xml/LocTest.xml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) 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 241015eb4f..6857d89163 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 @@ -25,7 +25,7 @@ public class AllMetricsTest extends SimpleAggregatorTst { // addRule(RULESET, "CycloTest"); addRule(RULESET, "NcssTest"); // addRule(RULESET, "WmcTest"); -// addRule(RULESET, "LocTest"); + addRule(RULESET, "LocTest"); addRule(RULESET, "NPathTest"); // addRule(RULESET, "NopaTest"); // addRule(RULESET, "NoamTest"); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/LocTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/LocTest.xml index 7f5d9f2bb8..5365271dcd 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/LocTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/LocTest.xml @@ -69,7 +69,7 @@ public class Foo { Full example 3 - 'Foo' has value 58 highest 40. + 'Foo' has value 58. 'Foo#foo()' has value 1. 'Foo#main(String)' has value 40. @@ -80,7 +80,7 @@ public class Foo { Empty method 2 - 'Foo' has value 5 highest 3. + 'Foo' has value 5. 'Foo#foo()' has value 3. Empty class 1 - 'Foo' has value 2 highest 0. + 'Foo' has value 2. Switch 2 - 'Foo' has value 12 highest 10. + 'Foo' has value 12. 'Foo#foo()' has value 10. Date: Tue, 1 Dec 2020 18:40:40 +0100 Subject: [PATCH 019/101] Fix wmc --- .../pmd/lang/java/metrics/impl/AllMetricsTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 6857d89163..4235d0e0e7 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 @@ -24,14 +24,14 @@ public class AllMetricsTest extends SimpleAggregatorTst { public void setUp() { // addRule(RULESET, "CycloTest"); addRule(RULESET, "NcssTest"); -// addRule(RULESET, "WmcTest"); + addRule(RULESET, "WmcTest"); addRule(RULESET, "LocTest"); addRule(RULESET, "NPathTest"); // addRule(RULESET, "NopaTest"); // addRule(RULESET, "NoamTest"); // addRule(RULESET, "WocTest"); // addRule(RULESET, "TccTest"); -// addRule(RULESET, "AtfdTest"); + addRule(RULESET, "AtfdTest"); // addRule(RULESET, "CfoTest"); } From 22d28ec1a43c15d54351bfcfe73a35563b8eb0d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 18:49:40 +0100 Subject: [PATCH 020/101] Fix WOC --- .../lang/java/metrics/api/JavaMetrics.java | 4 ++- .../java/metrics/impl/AllMetricsTest.java | 2 +- .../impl/JavaDoubleMetricTestRule.java | 36 +++++++++++++++++++ .../lang/java/metrics/impl/WocTestRule.java | 3 +- .../lang/java/metrics/impl/xml/WocTest.xml | 26 +++----------- 5 files changed, 46 insertions(+), 25 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaDoubleMetricTestRule.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index c5458f9449..1941f319a1 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -286,7 +286,9 @@ public final class JavaMetrics { int notSetter = methods.filter(it -> !JavaAstUtils.isGetterOrSetter(it)).count(); int total = methods.count(); - + if (total == 0) { + return 0; + } return notSetter / (double) total; } 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 4235d0e0e7..4f4f3e778e 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 @@ -29,7 +29,7 @@ public class AllMetricsTest extends SimpleAggregatorTst { addRule(RULESET, "NPathTest"); // addRule(RULESET, "NopaTest"); // addRule(RULESET, "NoamTest"); -// addRule(RULESET, "WocTest"); + addRule(RULESET, "WocTest"); // addRule(RULESET, "TccTest"); addRule(RULESET, "AtfdTest"); // addRule(RULESET, "CfoTest"); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaDoubleMetricTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaDoubleMetricTestRule.java new file mode 100644 index 0000000000..45f6957828 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/JavaDoubleMetricTestRule.java @@ -0,0 +1,36 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.metrics.impl; + +import java.util.Locale; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; +import net.sourceforge.pmd.lang.metrics.Metric; +import net.sourceforge.pmd.test.AbstractMetricTestRule; + +/** + * + */ +public abstract class JavaDoubleMetricTestRule extends AbstractMetricTestRule.OfDouble { + + protected JavaDoubleMetricTestRule(Metric metric) { + super(metric); + } + + @Override + protected boolean reportOn(Node node) { + return super.reportOn(node) + && (node instanceof ASTMethodOrConstructorDeclaration + || node instanceof ASTAnyTypeDeclaration); + } + + @Override + protected String violationMessage(Node node, Double result) { + String fmt = String.format(Locale.ROOT, "%.4f", result); + return AllMetricsTest.formatJavaMessage(node, fmt, super.violationMessage(node, result)); + } +} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java index 57fd9769f4..ffc3683726 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java @@ -5,13 +5,12 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier * @since 6.0.0 */ -public class WocTestRule extends AbstractMetricTestRule.OfDouble { +public class WocTestRule extends JavaDoubleMetricTestRule { public WocTestRule() { super(JavaMetrics.WEIGHT_OF_CLASS); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/WocTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/WocTest.xml index be803947e5..c1d0cbd608 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/WocTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/WocTest.xml @@ -66,37 +66,21 @@ public class Property implements Comparable { Full example 1 - 'Property' has value 0.1111. + 'Property' has value 0.1429. Test empty class - 0 + 1 + + 'Foo' has value 0.0000. + - - NOPA doesn't support enums, interfaces or annotations - 0 - - From 736086a45ffc914f27aeff0c6ab793ea298adbbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 18:50:39 +0100 Subject: [PATCH 021/101] Fix nopa --- .../pmd/lang/java/metrics/impl/AllMetricsTest.java | 2 +- .../sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 4f4f3e778e..668105674f 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 @@ -27,7 +27,7 @@ public class AllMetricsTest extends SimpleAggregatorTst { addRule(RULESET, "WmcTest"); addRule(RULESET, "LocTest"); addRule(RULESET, "NPathTest"); -// addRule(RULESET, "NopaTest"); + addRule(RULESET, "NopaTest"); // addRule(RULESET, "NoamTest"); addRule(RULESET, "WocTest"); // addRule(RULESET, "TccTest"); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml index 052b1ab97b..9456375fe1 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml @@ -47,8 +47,8 @@ public class Foo { - NOPA doesn't support enums, interfaces or annotations - 0 + NOPA supports enums, interfaces or annotations + 3 Date: Tue, 1 Dec 2020 19:03:15 +0100 Subject: [PATCH 022/101] Try fixing noam --- .../pmd/lang/java/internal/JavaAstUtils.java | 55 +++++++------------ .../java/metrics/impl/AllMetricsTest.java | 2 +- .../lang/java/metrics/impl/xml/NoamTest.xml | 6 +- 3 files changed, 24 insertions(+), 39 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java index d5d378aa91..4d863d7d30 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java @@ -4,23 +4,17 @@ package net.sourceforge.pmd.lang.java.internal; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; /** * */ public final class JavaAstUtils { - private static final Pattern FIELD_NAME_PATTERN = Pattern.compile("(?:m_|_)?(\\w+)"); private JavaAstUtils() { // utility class @@ -28,61 +22,52 @@ public final class JavaAstUtils { public static boolean isGetterOrSetter(ASTMethodDeclaration node) { - - // fields names mapped to their types - Map fieldNames = - node.getEnclosingType() - .getDeclarations() - .filterIs(ASTFieldDeclaration.class) - .flatMap(ASTFieldDeclaration::getVarIds) - .collect(Collectors.toMap( - f -> { - Matcher matcher = FIELD_NAME_PATTERN.matcher(f.getVariableName()); - return matcher.find() ? matcher.group(1) : f.getVariableName(); - }, - f -> f.getTypeNode().getTypeImage() - )); - - return isGetter(node, fieldNames) || isSetter(node, fieldNames); + return isGetter(node) || isSetter(node); } /** Attempts to determine if the method is a getter. */ - private static boolean isGetter(ASTMethodDeclaration node, Map fieldNames) { + private static boolean isGetter(ASTMethodDeclaration node) { if (node.getArity() != 0 || node.isVoid()) { return false; } + ASTAnyTypeDeclaration enclosing = node.getEnclosingType(); if (node.getName().startsWith("get")) { - return containsIgnoreCase(fieldNames.keySet(), node.getName().substring(3)); + return hasField(enclosing, node.getName().substring(3)); } else if (node.getName().startsWith("is")) { - return containsIgnoreCase(fieldNames.keySet(), node.getName().substring(2)); + return hasField(enclosing, node.getName().substring(2)); } - - return fieldNames.containsKey(node.getName()); + return hasField(enclosing, node.getName()); } /** Attempts to determine if the method is a setter. */ - private static boolean isSetter(ASTMethodDeclaration node, Map fieldNames) { + private static boolean isSetter(ASTMethodDeclaration node) { if (node.getArity() != 1 || !node.isVoid()) { return false; } + ASTAnyTypeDeclaration enclosing = node.getEnclosingType(); + if (node.getName().startsWith("set")) { - return containsIgnoreCase(fieldNames.keySet(), node.getName().substring(3)); + return hasField(enclosing, node.getName().substring(3)); } - return fieldNames.containsKey(node.getName()); + return hasField(enclosing, node.getName()); } - private static boolean containsIgnoreCase(Set set, String str) { - for (String s : set) { - if (str.equalsIgnoreCase(s)) { + private static boolean hasField(ASTAnyTypeDeclaration node, String name) { + for (JFieldSymbol f : node.getSymbol().getDeclaredFields()) { + String fname = f.getSimpleName(); + if (fname.startsWith("m_") || fname.startsWith("_")) { + fname = fname.substring(fname.indexOf('_') + 1); + } + if (fname.equalsIgnoreCase(name)) { return true; } } 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 668105674f..302f50e870 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 @@ -28,7 +28,7 @@ public class AllMetricsTest extends SimpleAggregatorTst { addRule(RULESET, "LocTest"); addRule(RULESET, "NPathTest"); addRule(RULESET, "NopaTest"); -// addRule(RULESET, "NoamTest"); + addRule(RULESET, "NoamTest"); addRule(RULESET, "WocTest"); // addRule(RULESET, "TccTest"); addRule(RULESET, "AtfdTest"); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NoamTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NoamTest.xml index 63691782ac..fea62ba5c0 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NoamTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NoamTest.xml @@ -48,7 +48,7 @@ public class Foo { Full example 1 - 'Foo' has value 4. + 'Foo' has value 7. @@ -66,8 +66,8 @@ public class Foo { - NOPA doesn't support enums, interfaces or annotations - 0 + NOAM supports enums, interfaces or annotations + 3 Date: Tue, 1 Dec 2020 19:55:57 +0100 Subject: [PATCH 023/101] Fix tcc --- .../lang/java/metrics/api/JavaMetrics.java | 49 ++++-- .../visitors/TccAttributeAccessCollector.java | 163 ------------------ .../java/metrics/impl/AllMetricsTest.java | 2 +- .../lang/java/metrics/impl/TccTestRule.java | 3 +- .../lang/java/metrics/impl/xml/TccTest.xml | 26 ++- 5 files changed, 52 insertions(+), 191 deletions(-) delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/TccAttributeAccessCollector.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index 1941f319a1..8fe894c0b2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -9,8 +9,8 @@ import static net.sourceforge.pmd.internal.util.PredicateUtil.always; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; @@ -21,6 +21,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; @@ -33,7 +34,9 @@ import net.sourceforge.pmd.lang.java.metrics.internal.visitors.ClassFanOutVisito import net.sourceforge.pmd.lang.java.metrics.internal.visitors.CycloVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NcssVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NpathBaseVisitor; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.TccAttributeAccessCollector; +import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; +import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; +import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; import net.sourceforge.pmd.lang.metrics.Metric; import net.sourceforge.pmd.lang.metrics.MetricOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; @@ -158,15 +161,43 @@ public final class JavaMetrics { private static double computeTcc(ASTAnyTypeDeclaration node, MetricOptions ignored) { - Map> usagesByMethod = new TccAttributeAccessCollector(node).start(); + List> usagesByMethod = attributeAccessesByMethod(node); int numPairs = numMethodsRelatedByAttributeAccess(usagesByMethod); int maxPairs = maxMethodPairs(usagesByMethod.size()); + if (maxPairs == 0) { + return 0; + } + return numPairs / (double) maxPairs; } + /** + * Collects the attribute accesses by method into a map, for TCC. + */ + private static List> attributeAccessesByMethod(ASTAnyTypeDeclaration type) { + final List> map = new ArrayList<>(); + final JClassSymbol typeSym = type.getSymbol(); + for (ASTMethodDeclaration decl : type.getDeclarations(ASTMethodDeclaration.class)) { + Set attrs = new HashSet<>(); + decl.descendants().crossFindBoundaries() + .filterIs(ASTNamedReferenceExpr.class) + .forEach(it -> { + JVariableSymbol sym = it.getReferencedSym(); + if (sym instanceof JFieldSymbol && typeSym.equals(((JFieldSymbol) sym).getEnclosingClass())) { + attrs.add(sym.getSimpleName()); + } + }); + + map.add(attrs); + + } + return map; + } + + /** * Gets the number of pairs of methods that use at least one attribute in common. * @@ -174,19 +205,15 @@ public final class JavaMetrics { * * @return The number of pairs */ - private static int numMethodsRelatedByAttributeAccess(Map> usagesByMethod) { - List methods = new ArrayList<>(usagesByMethod.keySet()); - int methodCount = methods.size(); + private static int numMethodsRelatedByAttributeAccess(List> usagesByMethod) { + int methodCount = usagesByMethod.size(); int pairs = 0; if (methodCount > 1) { for (int i = 0; i < methodCount - 1; i++) { for (int j = i + 1; j < methodCount; j++) { - String firstMethodName = methods.get(i); - String secondMethodName = methods.get(j); - - if (!Collections.disjoint(usagesByMethod.get(firstMethodName), - usagesByMethod.get(secondMethodName))) { + if (!Collections.disjoint(usagesByMethod.get(i), + usagesByMethod.get(j))) { pairs++; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/TccAttributeAccessCollector.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/TccAttributeAccessCollector.java deleted file mode 100644 index 11dac75119..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/TccAttributeAccessCollector.java +++ /dev/null @@ -1,163 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics.internal.visitors; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; -import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; -import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; -import net.sourceforge.pmd.lang.java.symboltable.ClassScope; -import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; -import net.sourceforge.pmd.lang.symboltable.Scope; - - -/** - * Returns the map of method names to the set of local attributes accessed when visiting a class. - * - * @author Clément Fournier - * @since 6.0.0 - */ -public class TccAttributeAccessCollector extends JavaParserVisitorAdapter { - - private final ASTAnyTypeDeclaration exploredClass; - - - /** The name of the current method. */ - private String currentMethodName; - - private Map> methodAttributeAccess; - - - public TccAttributeAccessCollector(ASTAnyTypeDeclaration exploredClass) { - this.exploredClass = exploredClass; - } - - - /** - * Collects the attribute accesses by method into a map. - */ - @SuppressWarnings("unchecked") - public Map> start() { - return (Map>) this.visitTypeDecl(exploredClass, new HashMap>()); - } - - - @Override - public Object visitTypeDecl(ASTAnyTypeDeclaration node, Object data) { - if (Objects.equals(node, exploredClass)) { - methodAttributeAccess = new HashMap<>(); - super.visitTypeDecl(node, data); - } else if (node.isLocal()) { - super.visitTypeDecl(node, data); - } - return methodAttributeAccess; - } - - - @Override - public Object visit(ASTMethodDeclaration node, Object data) { - - if (!node.isAbstract()) { - if (node.getFirstParentOfType(ASTAnyTypeDeclaration.class) == exploredClass) { - currentMethodName = PrettyPrintingUtil.displaySignature(node); - methodAttributeAccess.put(currentMethodName, new HashSet<>()); - - super.visit(node, data); - currentMethodName = null; - } else { - super.visit(node, data); - } - } - - return null; - } - - - @Override - public Object visit(ASTConstructorDeclaration node, Object data) { - return data; // we're only looking for method pairs - } - - - /** - * The primary expression node is used to detect access - * to attributes and method calls. If the access is not for a - * foreign class, then the {@link #methodAttributeAccess} - * map is updated for the current method. - */ - @Override - public Object visit(ASTPrimaryExpression node, Object data) { - if (currentMethodName != null) { - Set methodAccess = methodAttributeAccess.get(currentMethodName); - String variableName = getVariableName(node); - if (isLocalAttributeAccess(variableName, node.getScope())) { - methodAccess.add(variableName); - } - } - - return super.visit(node, data); - } - - - private String getVariableName(ASTPrimaryExpression node) { - ASTPrimaryPrefix prefix = node.getFirstDescendantOfType(ASTPrimaryPrefix.class); - - if (prefix.usesThisModifier()) { - List suffixes = node.findChildrenOfType(ASTPrimarySuffix.class); - if (suffixes.size() > 1) { - if (!suffixes.get(1).isArguments()) { // not a method call - return suffixes.get(0).getImage(); - } - } - } - - ASTName name = prefix.getFirstDescendantOfType(ASTName.class); - - String variableName = null; - - if (name != null) { - int dotIndex = name.getImage().indexOf("."); - if (dotIndex == -1) { - variableName = name.getImage(); - } else { - variableName = name.getImage().substring(0, dotIndex); - } - } - - return variableName; - } - - - private boolean isLocalAttributeAccess(String varName, Scope scope) { - Scope currentScope = scope; - - while (currentScope != null) { - for (VariableNameDeclaration decl : currentScope.getDeclarations(VariableNameDeclaration.class).keySet()) { - if (decl.getImage().equals(varName)) { - if (currentScope instanceof ClassScope - && ((ClassScope) currentScope).getClassDeclaration().getNode() == exploredClass) { - return true; - } - } - } - currentScope = currentScope.getParent(); // WARNING doesn't consider inherited fields or static imports - } - - return false; - } - -} 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 302f50e870..b711e0b7ab 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 @@ -30,7 +30,7 @@ public class AllMetricsTest extends SimpleAggregatorTst { addRule(RULESET, "NopaTest"); addRule(RULESET, "NoamTest"); addRule(RULESET, "WocTest"); -// addRule(RULESET, "TccTest"); + addRule(RULESET, "TccTest"); addRule(RULESET, "AtfdTest"); // addRule(RULESET, "CfoTest"); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java index 4868a1f922..0e97bf5258 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java @@ -5,13 +5,12 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.test.AbstractMetricTestRule; /** * @author Clément Fournier * @since 6.0.0 */ -public class TccTestRule extends AbstractMetricTestRule.OfDouble { +public class TccTestRule extends JavaDoubleMetricTestRule { public TccTestRule() { super(JavaMetrics.TIGHT_CLASS_COHESION); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/TccTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/TccTest.xml index ac63297d82..04c49e4967 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/TccTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/TccTest.xml @@ -73,7 +73,10 @@ public class Property implements Comparable { Test empty class - 0 + 1 + + 'Foo' has value 0.0000. + Do not crash on local class, refs #827 - 1 + 2 - 'com.pack.Pack$1Inner' has value 0. + 'com.pack.Pack' has value 0.0000. + 'com.pack.Pack$1Inner' has value 1.0000. Attribute accesses in local class count as accesses of the method 2 - 'com.pack.Pack' has value 1. - 'com.pack.Pack$1Inner' has value 0. + 'com.pack.Pack' has value 1.0000. + 'com.pack.Pack$1Inner' has value 0.0000. get() { - - class Inner implements IInner { - - - public Inner(Map results) { - this.results = results; - } + class Inner { public void method() { - this.results = new HashMap(); + results = new HashMap(); } private void otherMethod() { - this.results.clear(); + results.clear(); } } return null; From e46ed39b067183997e8b09901f7945be802c4478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 20:01:06 +0100 Subject: [PATCH 024/101] Finish cyclo --- .../pmd/lang/java/internal/JavaAstUtils.java | 5 +++++ .../java/metrics/internal/visitors/CycloVisitor.java | 12 ++++++------ .../metrics/internal/visitors/NpathBaseVisitor.java | 9 +++------ .../pmd/lang/java/metrics/impl/AllMetricsTest.java | 2 +- .../pmd/lang/java/metrics/impl/xml/CycloTest.xml | 2 +- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java index 4d863d7d30..a8e11be6dc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.internal; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchBranch; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; @@ -83,4 +84,8 @@ public final class JavaAstUtils { } return false; } + + public static int numAlternatives(ASTSwitchBranch n) { + return n.isDefault() ? 1 : n.getLabel().getExprList().count(); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java index d791b4573c..041b612801 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java @@ -16,12 +16,14 @@ import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTSwitchBranch; import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchFallthroughBranch; import net.sourceforge.pmd.lang.java.ast.ASTSwitchLike; import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; +import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.CycloOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; @@ -75,13 +77,11 @@ public class CycloVisitor extends JavaVisitorBase { } if (considerBooleanPaths) { - data.add(branch.getLabel().getExprList().count()); + data.add(JavaAstUtils.numAlternatives(branch)); + } else if (branch instanceof ASTSwitchFallthroughBranch + && ((ASTSwitchFallthroughBranch) branch).getStatements().nonEmpty()) { + data.increment(); } -// else if (branch instanceof ASTSwitchFallthroughBranch) { -// if (considerBooleanPaths && ((ASTSwitchFallthroughBranch) branch).getStatements().isEmpty()) - // an empty label is only counted if we count boolean paths -// data.increment(); -// } } return visitJavaNode(node, data); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java index 62b4122be0..77fa27cf5b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java @@ -26,6 +26,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; +import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; @@ -163,7 +164,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { // Fall-through labels count as 1 for complexity if (n instanceof ASTSwitchFallthroughBranch) { - caseRange += numAlternatives(n); + caseRange += JavaAstUtils.numAlternatives(n); NodeStream statements = ((ASTSwitchFallthroughBranch) n).getStatements(); if (statements.nonEmpty()) { BigInteger branchNpath = multiplyComplexities(statements); @@ -171,7 +172,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { caseRange = 0; } } else if (n instanceof ASTSwitchArrowBranch) { - int numAlts = numAlternatives(n); + int numAlts = JavaAstUtils.numAlternatives(n); BigInteger branchNpath = ((ASTSwitchArrowBranch) n).getRightHandSide().acceptVisitor(this, data); npath = npath.add(branchNpath.multiply(BigInteger.valueOf(numAlts))); } @@ -180,10 +181,6 @@ public class NpathBaseVisitor extends JavaVisitorBase { return npath.add(BigInteger.valueOf(boolCompSwitch)); } - private int numAlternatives(ASTSwitchBranch n) { - return n.isDefault() ? 1 : n.getLabel().getExprList().count(); - } - @Override public BigInteger visit(ASTSwitchLabel node, Void data) { if (node.isDefault()) { 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 b711e0b7ab..f19fae0ff4 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 @@ -22,7 +22,7 @@ public class AllMetricsTest extends SimpleAggregatorTst { @Override public void setUp() { -// addRule(RULESET, "CycloTest"); + addRule(RULESET, "CycloTest"); addRule(RULESET, "NcssTest"); addRule(RULESET, "WmcTest"); addRule(RULESET, "LocTest"); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml index bae077b3eb..5f3bc645bc 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CycloTest.xml @@ -340,7 +340,7 @@ public class LambdaTest { Complexity of lambdas doesn't affect the complexity of the method, refs #837 - 4 + 1 'LambdaTest#notSoComplex(int)' has value 4. From c423266ba088b395fb9ca3b0340cf83cc7b00cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 20:12:59 +0100 Subject: [PATCH 025/101] Fix fan out --- .../lang/java/metrics/api/JavaMetrics.java | 5 +- .../internal/visitors/ClassFanOutVisitor.java | 86 +++++++++---------- .../java/metrics/impl/AllMetricsTest.java | 2 +- .../lang/java/metrics/impl/xml/CfoTest.xml | 12 +-- 4 files changed, 52 insertions(+), 53 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index 8fe894c0b2..31c781cab5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -321,8 +321,9 @@ public final class JavaMetrics { private static int computeFanOut(JavaNode node, MetricOptions options) { - MutableInt cfo = (MutableInt) node.acceptVisitor(new ClassFanOutVisitor(options, node), new MutableInt(0)); - return cfo.getValue(); + Set cfo = new HashSet<>(); + node.acceptVisitor(ClassFanOutVisitor.getInstance(options), cfo); + return cfo.size(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java index d1eb078942..0cbe320d12 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java @@ -4,17 +4,15 @@ package net.sourceforge.pmd.lang.java.metrics.internal.visitors; -import java.util.HashSet; import java.util.Set; -import org.apache.commons.lang3.mutable.MutableInt; - import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; -import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; +import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.ClassFanOutOption; +import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; +import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol; import net.sourceforge.pmd.lang.metrics.MetricOptions; @@ -23,50 +21,50 @@ import net.sourceforge.pmd.lang.metrics.MetricOptions; * * @author Andreas Pabst */ -public class ClassFanOutVisitor extends JavaParserVisitorAdapter { +public class ClassFanOutVisitor extends JavaVisitorBase, Void> { + + private static final ClassFanOutVisitor INCLUDE_JLANG = new ClassFanOutVisitor(true); + private static final ClassFanOutVisitor EXCLUDE_JLANG = new ClassFanOutVisitor(false); - private static final String JAVA_LANG_PACKAGE_NAME = "java.lang"; - protected Set> classes = new HashSet<>(); private final boolean includeJavaLang; - @SuppressWarnings("PMD.UnusedFormalParameter") - public ClassFanOutVisitor(MetricOptions options, JavaNode topNode) { - includeJavaLang = options.getOptions().contains(ClassFanOutOption.INCLUDE_JAVA_LANG); - // topNode is unused, but we'll need it if we want to discount lambdas - // if we add it later, we break binary compatibility + private ClassFanOutVisitor(boolean includeJavaLang) { + this.includeJavaLang = includeJavaLang; } - @Override - public Object visit(ASTClassOrInterfaceType node, Object data) { - check(node, (MutableInt) data); - return super.visit(node, data); - } - - @Override - public Object visit(ASTName node, Object data) { - check(node, (MutableInt) data); - return super.visit(node, data); - } - - private void check(TypeNode node, MutableInt counter) { - if (!classes.contains(node.getType()) && shouldBeIncluded(node.getType())) { - classes.add(node.getType()); - counter.increment(); - } - } - - private boolean shouldBeIncluded(Class classToCheck) { - if (includeJavaLang || classToCheck == null) { - // include all packages - return true; + public static ClassFanOutVisitor getInstance(MetricOptions options) { + if (options.getOptions().contains(ClassFanOutOption.INCLUDE_JAVA_LANG)) { + return INCLUDE_JLANG; } else { - // exclude the java.lang package - Package packageToCheck = classToCheck.getPackage(); - if (packageToCheck == null) { - return true; - } - - return !JAVA_LANG_PACKAGE_NAME.equals(packageToCheck.getName()); + return EXCLUDE_JLANG; } } + + @Override + public Void visitExpression(ASTExpression node, Set data) { + check(node, data); + return visitChildren(node, data); + } + + @Override + public Void visit(ASTClassOrInterfaceType node, Set data) { + check(node, data); + return visitChildren(node, data); + } + + private void check(TypeNode node, Set classes) { + JTypeDeclSymbol symbol = node.getTypeMirror().getSymbol(); + if (!(symbol instanceof JClassSymbol) + || ((JClassSymbol) symbol).isPrimitive() + || ((JClassSymbol) symbol).isArray()) { + return; + } + if (shouldBeIncluded((JClassSymbol) symbol)) { + classes.add((JClassSymbol) symbol); + } + } + + private boolean shouldBeIncluded(JClassSymbol classToCheck) { + return includeJavaLang || !JClassSymbol.PRIMITIVE_PACKAGE.equals(classToCheck.getPackageName()); + } } 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 f19fae0ff4..d289df2bf1 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 @@ -32,7 +32,7 @@ public class AllMetricsTest extends SimpleAggregatorTst { addRule(RULESET, "WocTest"); addRule(RULESET, "TccTest"); addRule(RULESET, "AtfdTest"); -// addRule(RULESET, "CfoTest"); + addRule(RULESET, "CfoTest"); } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CfoTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CfoTest.xml index c486a3b57e..d32e1fc516 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CfoTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/CfoTest.xml @@ -42,11 +42,11 @@ public class Foo { Full example with default options 6 - 'Foo' has value 7 highest 2. + 'Foo' has value 7. 'Foo#Foo(Data)' has value 1. 'Foo#foo(List)' has value 2. 'Foo#getMapSize()' has value 1. - 'Foo$Data' has value 0 highest 0. + 'Foo$Data' has value 0. 'Foo$Data#getAmountFormatted()' has value 0. @@ -57,11 +57,11 @@ public class Foo { includeJavaLang 6 - 'Foo' has value 12 highest 5. + 'Foo' has value 12. 'Foo#Foo(Data)' has value 1. 'Foo#foo(List)' has value 5. 'Foo#getMapSize()' has value 1. - 'Foo$Data' has value 2 highest 2. + 'Foo$Data' has value 2. 'Foo$Data#getAmountFormatted()' has value 2. @@ -71,7 +71,7 @@ public class Foo { Test empty class 1 - 'Foo' has value 0 highest 0. + 'Foo' has value 0. Test class with single other class 1 - 'Foo' has value 1 highest 0. + 'Foo' has value 1. Date: Tue, 1 Dec 2020 20:17:32 +0100 Subject: [PATCH 026/101] Checkstyle --- .../pmd/lang/java/metrics/impl/AtfdTestRule.java | 2 -- .../pmd/lang/java/metrics/impl/NcssTestRule.java | 6 +++--- .../pmd/test/AbstractMetricTestRule.java | 14 +++++++------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java index 9bb1863364..78f6fd0e4e 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java @@ -5,8 +5,6 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; /** diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java index ca9c69d68f..33d124bced 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java @@ -20,21 +20,21 @@ import net.sourceforge.pmd.properties.PropertyFactory; */ public class NcssTestRule extends JavaIntMetricTestRule { - static final PropertyDescriptor reportClasses = + static final PropertyDescriptor REPORT_CLASSES = PropertyFactory.booleanProperty("reportClasses") .desc("...") .defaultValue(false).build(); public NcssTestRule() { super(JavaMetrics.NCSS); - definePropertyDescriptor(reportClasses); + definePropertyDescriptor(REPORT_CLASSES); } @Override protected boolean reportOn(Node node) { return super.reportOn(node) && (node instanceof ASTMethodOrConstructorDeclaration - || getProperty(reportClasses) && node instanceof ASTAnyTypeDeclaration); + || getProperty(REPORT_CLASSES) && node instanceof ASTAnyTypeDeclaration); } @Override diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java index 580db93bf0..9aa2c782f5 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java @@ -116,9 +116,9 @@ public abstract class AbstractMetricTestRule> e } } - public abstract static class OfDouble extends AbstractMetricTestRule { + public abstract static class OfDouble extends AbstractMetricTestRule { - protected OfDouble(Metric metric) { + protected OfDouble(Metric metric) { super(metric); } @@ -127,10 +127,10 @@ public abstract class AbstractMetricTestRule> e return Double.parseDouble(value); } - @Override - protected Double defaultReportLevel() { - return 0.; - } - } + @Override + protected Double defaultReportLevel() { + return 0.; + } + } } From 0307300891c7127a2a17ecd83d25bd338bfbe0a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 20:37:34 +0100 Subject: [PATCH 027/101] Fix tests --- .../java/ast/internal/PrettyPrintingUtil.java | 25 +++++++++++++++---- .../lang/java/metrics/api/JavaMetrics.java | 3 ++- .../internal/visitors/ClassFanOutVisitor.java | 2 +- .../java/metrics/JavaMetricsProviderTest.java | 2 +- .../pmd/lang/java/ast/TestExtensions.kt | 2 +- .../bestpractices/xml/MissingOverride.xml | 18 ++++--------- 6 files changed, 30 insertions(+), 22 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java index 0e36fbf788..def163cf40 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java @@ -6,13 +6,17 @@ package net.sourceforge.pmd.lang.java.ast.internal; import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTArrayType; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType; import net.sourceforge.pmd.lang.java.ast.ASTRecordDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTType; /** * @author Clément Fournier @@ -39,10 +43,7 @@ public final class PrettyPrintingUtil { } first = false; - sb.append(param.getTypeNode().getTypeImage()); - if (param.isVarargs()) { - sb.append("..."); - } + prettyPrintTypeNode(param.getTypeNode(), sb); } sb.append(')'); @@ -50,11 +51,25 @@ public final class PrettyPrintingUtil { return sb.toString(); } + private static void prettyPrintTypeNode(ASTType t, StringBuilder sb) { + if (t instanceof ASTPrimitiveType) { + sb.append(((ASTPrimitiveType) t).getKind().getSimpleName()); + } else if (t instanceof ASTClassOrInterfaceType) { + sb.append(((ASTClassOrInterfaceType) t).getSimpleName()); + } else if (t instanceof ASTArrayType) { + prettyPrintTypeNode(((ASTArrayType) t).getElementType(), sb); + int depth = ((ASTArrayType) t).getArrayDepth(); + for (int i = 0; i < depth; i++) { + sb.append("[]"); + } + } + } + /** * Returns a normalized method name. This just looks at the image of the types of the parameters. */ public static String displaySignature(ASTMethodOrConstructorDeclaration node) { - ASTFormalParameters params = node.getFirstDescendantOfType(ASTFormalParameters.class); + ASTFormalParameters params = node.getFormalParameters(); String name = node instanceof ASTMethodDeclaration ? node.getName() : node.getImage(); return displaySignature(name, params); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java index 31c781cab5..5cf298c996 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java @@ -45,6 +45,7 @@ import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** * */ +@SuppressWarnings("PMD.UnusedFormalParameter") // #2838 public final class JavaMetrics { @@ -298,7 +299,7 @@ public final class JavaMetrics { } } - private static int computeAtfd(JavaNode node, MetricOptions options) { + private static int computeAtfd(JavaNode node, MetricOptions ignored) { MutableInt result = new MutableInt(0); node.acceptVisitor(new AtfdBaseVisitor(), result); return result.getValue(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java index 0cbe320d12..d305acee7e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java @@ -21,7 +21,7 @@ import net.sourceforge.pmd.lang.metrics.MetricOptions; * * @author Andreas Pabst */ -public class ClassFanOutVisitor extends JavaVisitorBase, Void> { +public final class ClassFanOutVisitor extends JavaVisitorBase, Void> { private static final ClassFanOutVisitor INCLUDE_JLANG = new ClassFanOutVisitor(true); private static final ClassFanOutVisitor EXCLUDE_JLANG = new ClassFanOutVisitor(false); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java index c9ac6cfe59..42e4b873b5 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/JavaMetricsProviderTest.java @@ -37,7 +37,7 @@ public class JavaMetricsProviderTest { Map, Number> results = provider.computeAllMetricsFor(type); - assertEquals(10, results.size()); + assertEquals(9, results.size()); } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TestExtensions.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TestExtensions.kt index 8232dff3b3..b13a0cc27b 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TestExtensions.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TestExtensions.kt @@ -587,7 +587,7 @@ fun TreeNodeWrapper.switchLabel(assertions: NodeSpec = fun TreeNodeWrapper.switchDefaultLabel(assertions: NodeSpec = EmptyAssertions) = child(ignoreChildren = assertions == EmptyAssertions) { it::isDefault shouldBe true - it::getExprList shouldBe emptyList() + it.exprList.toList() shouldBe emptyList() assertions() } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml index bcd80bfac9..42e494cc10 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml @@ -149,19 +149,17 @@ public enum EnumWithInterfaces implements InterfaceWithBound { Consider enum methods 2 2 - 9,15 + 5,10 { Foo { - @Override public void handle(int[] ints) { super.handle(ints); } }; - @Override public void handle(int[] ints) { } @@ -173,8 +171,8 @@ public enum EnumWithInterfaces implements InterfaceWithBound { Consider methods with array parameters 1 - - The method 'arrayParams(String, int, StringBuilder)' is missing an @Override annotation. + + The method 'arrayParams(String, int[], StringBuilder[])' is missing an @Override annotation. Consider method inherited from generic supertype 1 - The method 'supports(ASTAnyTypeDeclaration)' is missing an @Override annotation. + The method 'handle(int[])' is missing an @Override annotation. { Foo { - @Override public void handle(int[] ints) { super.handle(ints); } - }; - - @Override - public void handle(int[] ints) { - } } @@ -304,7 +296,7 @@ public class SubclassWithGenericMethod extends AbstractClass { Consider varargs parameter 1 - The method 'setProperty(MultiValuePropertyDescriptor, V...)' is missing an @Override annotation. + The method 'setProperty(MultiValuePropertyDescriptor, V[])' is missing an @Override annotation. Date: Tue, 1 Dec 2020 20:55:33 +0100 Subject: [PATCH 028/101] Move files around --- .../java/internal/JavaLanguageHandler.java | 2 +- .../java/metrics/{api => }/JavaMetrics.java | 36 +++------------ .../{visitors => }/AtfdBaseVisitor.java | 4 +- .../{visitors => }/ClassFanOutVisitor.java | 6 +-- .../internal/{visitors => }/CycloVisitor.java | 44 ++++++++++++++----- .../internal/{visitors => }/NcssVisitor.java | 6 +-- .../{visitors => }/NpathBaseVisitor.java | 19 ++++---- .../rule/design/CyclomaticComplexityRule.java | 4 +- .../lang/java/rule/design/DataClassRule.java | 8 ++-- .../lang/java/rule/design/GodClassRule.java | 6 +-- .../java/rule/design/NPathComplexityRule.java | 2 +- .../lang/java/rule/design/NcssCountRule.java | 4 +- .../lang/java/metrics/impl/AtfdTestRule.java | 2 +- .../lang/java/metrics/impl/CfoTestRule.java | 4 +- .../lang/java/metrics/impl/CycloTestRule.java | 4 +- .../lang/java/metrics/impl/LocTestRule.java | 2 +- .../lang/java/metrics/impl/NPathTestRule.java | 2 +- .../lang/java/metrics/impl/NcssTestRule.java | 4 +- .../lang/java/metrics/impl/NoamTestRule.java | 2 +- .../lang/java/metrics/impl/NopaTestRule.java | 2 +- .../lang/java/metrics/impl/TccTestRule.java | 2 +- .../lang/java/metrics/impl/WmcTestRule.java | 2 +- .../lang/java/metrics/impl/WocTestRule.java | 2 +- 23 files changed, 84 insertions(+), 85 deletions(-) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/{api => }/JavaMetrics.java (89%) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/{visitors => }/AtfdBaseVisitor.java (94%) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/{visitors => }/ClassFanOutVisitor.java (93%) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/{visitors => }/CycloVisitor.java (76%) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/{visitors => }/NcssVisitor.java (98%) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/{visitors => }/NpathBaseVisitor.java (90%) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java index 5fe0ecbe30..fac2623998 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java @@ -14,7 +14,7 @@ import net.sourceforge.pmd.lang.ParserOptions; import net.sourceforge.pmd.lang.java.ast.JavaParser; import net.sourceforge.pmd.lang.java.ast.internal.LanguageLevelChecker; import net.sourceforge.pmd.lang.java.ast.internal.ReportingStrategy; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleViolationFactory; import net.sourceforge.pmd.lang.java.rule.xpath.internal.BaseContextNodeTestFun; import net.sourceforge.pmd.lang.java.rule.xpath.internal.GetCommentOnFunction; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java similarity index 89% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java index 5cf298c996..69085e104b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/api/JavaMetrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.java.metrics.api; +package net.sourceforge.pmd.lang.java.metrics; import static net.sourceforge.pmd.internal.util.PredicateUtil.always; @@ -29,11 +29,11 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.AtfdBaseVisitor; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.ClassFanOutVisitor; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.CycloVisitor; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NcssVisitor; -import net.sourceforge.pmd.lang.java.metrics.internal.visitors.NpathBaseVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.AtfdBaseVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.ClassFanOutVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.CycloVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.NcssVisitor; +import net.sourceforge.pmd.lang.java.metrics.internal.NpathBaseVisitor; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; @@ -43,7 +43,7 @@ import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** - * + * A collection of java metrics. */ @SuppressWarnings("PMD.UnusedFormalParameter") // #2838 public final class JavaMetrics { @@ -255,28 +255,6 @@ public final class JavaMetrics { } } - /** - * Evaluates the number of paths through a boolean expression. This is the total number of {@code &&} and {@code ||} - * operators appearing in the expression. This is used in the calculation of cyclomatic and n-path complexity. - * - * @param expr Expression to analyse - * - * @return The number of paths through the expression - */ - public static int booleanExpressionComplexity(@Nullable ASTExpression expr) { - if (expr == null) { - return 0; - } - - return expr.descendantsOrSelf() - .reduce(0, (acc, ifx) -> { - if (JavaAstUtils.isConditional(ifx)) { - return acc + 1; - } - return acc; - }); - } - /** Options for CYCLO. */ public enum CycloOption implements MetricOption { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/AtfdBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java similarity index 94% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/AtfdBaseVisitor.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java index e5db32304d..085e04cb43 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/AtfdBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java @@ -1,8 +1,8 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.java.metrics.internal.visitors; +package net.sourceforge.pmd.lang.java.metrics.internal; import org.apache.commons.lang3.mutable.MutableInt; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutVisitor.java similarity index 93% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutVisitor.java index d305acee7e..25aad2f2bb 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/ClassFanOutVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutVisitor.java @@ -1,8 +1,8 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.java.metrics.internal.visitors; +package net.sourceforge.pmd.lang.java.metrics.internal; import java.util.Set; @@ -10,7 +10,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.ast.TypeNode; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.ClassFanOutOption; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.ClassFanOutOption; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol; import net.sourceforge.pmd.lang.metrics.MetricOptions; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloVisitor.java similarity index 76% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloVisitor.java index 041b612801..a5bec1a34e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/CycloVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloVisitor.java @@ -1,15 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.java.metrics.internal.visitors; +package net.sourceforge.pmd.lang.java.metrics.internal; import org.apache.commons.lang3.mutable.MutableInt; +import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.java.ast.ASTAssertStatement; import net.sourceforge.pmd.lang.java.ast.ASTCatchClause; import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTForStatement; import net.sourceforge.pmd.lang.java.ast.ASTForeachStatement; import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; @@ -24,8 +26,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.CycloOption; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.CycloOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; @@ -67,7 +68,7 @@ public class CycloVisitor extends JavaVisitorBase { private Void handleSwitch(ASTSwitchLike node, MutableInt data) { if (considerBooleanPaths) { - data.add(JavaMetrics.booleanExpressionComplexity(node.getTestedExpression())); + data.add(booleanExpressionComplexity(node.getTestedExpression())); } for (ASTSwitchBranch branch : node) { @@ -92,7 +93,7 @@ public class CycloVisitor extends JavaVisitorBase { public Void visit(ASTConditionalExpression node, MutableInt data) { data.increment(); if (considerBooleanPaths) { - data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); + data.add(booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); } @@ -102,7 +103,7 @@ public class CycloVisitor extends JavaVisitorBase { public Void visit(ASTWhileStatement node, MutableInt data) { data.increment(); if (considerBooleanPaths) { - data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); + data.add(booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); } @@ -112,7 +113,7 @@ public class CycloVisitor extends JavaVisitorBase { public Void visit(ASTIfStatement node, MutableInt data) { data.increment(); if (considerBooleanPaths) { - data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); + data.add(booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); @@ -124,7 +125,7 @@ public class CycloVisitor extends JavaVisitorBase { data.increment(); if (considerBooleanPaths) { - data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); + data.add(booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); @@ -146,7 +147,7 @@ public class CycloVisitor extends JavaVisitorBase { public Void visit(ASTDoStatement node, MutableInt data) { data.increment(); if (considerBooleanPaths) { - data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); + data.add(booleanExpressionComplexity(node.getCondition())); } return super.visit(node, data); @@ -173,11 +174,32 @@ public class CycloVisitor extends JavaVisitorBase { data.add(2); // equivalent to if (condition) { throw .. } if (considerBooleanPaths) { - data.add(JavaMetrics.booleanExpressionComplexity(node.getCondition())); + data.add(booleanExpressionComplexity(node.getCondition())); } } return super.visit(node, data); } + /** + * Evaluates the number of paths through a boolean expression. This is the total number of {@code &&} and {@code ||} + * operators appearing in the expression. This is used in the calculation of cyclomatic and n-path complexity. + * + * @param expr Expression to analyse + * + * @return The number of paths through the expression + */ + public static int booleanExpressionComplexity(@Nullable ASTExpression expr) { + if (expr == null) { + return 0; + } + + return expr.descendantsOrSelf() + .reduce(0, (acc, ifx) -> { + if (JavaAstUtils.isConditional(ifx)) { + return acc + 1; + } + return acc; + }); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NcssVisitor.java similarity index 98% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NcssVisitor.java index 7f7f0c9fbc..8d9b7a97e3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NcssVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NcssVisitor.java @@ -1,8 +1,8 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.java.metrics.internal.visitors; +package net.sourceforge.pmd.lang.java.metrics.internal; import java.util.List; @@ -40,7 +40,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NcssOption; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.NcssOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java similarity index 90% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java index 77fa27cf5b..2bc55dd851 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/visitors/NpathBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java @@ -1,8 +1,8 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.java.metrics.internal.visitors; +package net.sourceforge.pmd.lang.java.metrics.internal; import java.math.BigInteger; @@ -27,7 +27,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; /** @@ -90,7 +89,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { complexity = complexity.add(element.acceptVisitor(this, data)); } - int boolCompIf = JavaMetrics.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); + int boolCompIf = CycloVisitor.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); return complexity.add(BigInteger.valueOf(boolCompIf)); } @@ -99,7 +98,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { public BigInteger visit(ASTWhileStatement node, Void data) { // (npath of while + bool_comp of while + 1) * npath of next - int boolComp = JavaMetrics.booleanExpressionComplexity(node.getCondition()); + int boolComp = CycloVisitor.booleanExpressionComplexity(node.getCondition()); BigInteger nPathBody = node.getBody().acceptVisitor(this, data); return nPathBody.add(BigInteger.valueOf(boolComp + 1)); } @@ -109,7 +108,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { public BigInteger visit(ASTDoStatement node, Void data) { // (npath of do + bool_comp of do + 1) * npath of next - int boolComp = JavaMetrics.booleanExpressionComplexity(node.getCondition()); + int boolComp = CycloVisitor.booleanExpressionComplexity(node.getCondition()); BigInteger nPathBody = node.getBody().acceptVisitor(this, data); return nPathBody.add(BigInteger.valueOf(boolComp + 1)); } @@ -119,7 +118,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { public BigInteger visit(ASTForStatement node, Void data) { // (npath of for + bool_comp of for + 1) * npath of next - int boolComp = JavaMetrics.booleanExpressionComplexity(node.getCondition()); + int boolComp = CycloVisitor.booleanExpressionComplexity(node.getCondition()); BigInteger nPathBody = node.getBody().acceptVisitor(this, data); return nPathBody.add(BigInteger.valueOf(boolComp + 1)); } @@ -135,7 +134,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { return BigInteger.ONE; } - int boolCompReturn = JavaMetrics.booleanExpressionComplexity(expr); + int boolCompReturn = CycloVisitor.booleanExpressionComplexity(expr); BigInteger conditionalExpressionComplexity = multiplyChildrenComplexities(expr); return conditionalExpressionComplexity.add(BigInteger.valueOf(boolCompReturn)); @@ -155,7 +154,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { public BigInteger handleSwitch(ASTSwitchLike node, Void data) { // bool_comp of switch + sum(npath(case_range)) - int boolCompSwitch = JavaMetrics.booleanExpressionComplexity(node.getTestedExpression()); + int boolCompSwitch = CycloVisitor.booleanExpressionComplexity(node.getTestedExpression()); BigInteger npath = BigInteger.ZERO; int caseRange = 0; @@ -193,7 +192,7 @@ public class NpathBaseVisitor extends JavaVisitorBase { public BigInteger visit(ASTConditionalExpression node, Void data) { // bool comp of guard clause + complexity of last two children (= total - 1) - int boolCompTernary = JavaMetrics.booleanExpressionComplexity(node.getCondition()); + int boolCompTernary = CycloVisitor.booleanExpressionComplexity(node.getCondition()); return sumChildrenComplexities(node, data).add(BigInteger.valueOf(boolCompTernary - 1)); } 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 8706e59332..4b7a826eb1 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 @@ -18,8 +18,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.CycloOption; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.CycloOption; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; 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 27a4e1a656..32fc96cc8f 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,10 +4,10 @@ package net.sourceforge.pmd.lang.java.rule.design; -import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NUMBER_OF_ACCESSORS; -import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NUMBER_OF_PUBLIC_FIELDS; -import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.WEIGHED_METHOD_COUNT; -import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.WEIGHT_OF_CLASS; +import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.NUMBER_OF_ACCESSORS; +import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.NUMBER_OF_PUBLIC_FIELDS; +import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.WEIGHED_METHOD_COUNT; +import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.WEIGHT_OF_CLASS; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; 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 d8e8096c66..bb2bf7f3fd 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,9 +5,9 @@ package net.sourceforge.pmd.lang.java.rule.design; -import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.ACCESS_TO_FOREIGN_DATA; -import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.TIGHT_CLASS_COHESION; -import static net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.WEIGHED_METHOD_COUNT; +import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.ACCESS_TO_FOREIGN_DATA; +import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.TIGHT_CLASS_COHESION; +import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.WEIGHED_METHOD_COUNT; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; 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 08040b2d2c..b1da86eaad 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 @@ -13,7 +13,7 @@ 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.internal.PrettyPrintingUtil; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; 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 62656b49ff..b0e57b01d3 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,8 +15,8 @@ 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.internal.PrettyPrintingUtil; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NcssOption; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.NcssOption; import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java index 78f6fd0e4e..1839a8afad 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/AtfdTestRule.java @@ -5,7 +5,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CfoTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CfoTestRule.java index fffd368485..ec1300277d 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CfoTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CfoTestRule.java @@ -6,8 +6,8 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import java.util.Map; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.ClassFanOutOption; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.ClassFanOutOption; import net.sourceforge.pmd.lang.metrics.MetricOption; /** diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java index 0b6a95aa3d..29a27de2ef 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/CycloTestRule.java @@ -6,8 +6,8 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import java.util.Map; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.CycloOption; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.CycloOption; import net.sourceforge.pmd.lang.metrics.MetricOption; /** diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java index c65ff28869..d7caaa24b7 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/LocTestRule.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java index d9b6cd04f4..80850a2795 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NPathTestRule.java @@ -7,7 +7,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl; import java.math.BigInteger; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; import net.sourceforge.pmd.test.AbstractMetricTestRule; /** diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java index 33d124bced..4bcd8e665b 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NcssTestRule.java @@ -9,8 +9,8 @@ import java.util.Map; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics.NcssOption; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.NcssOption; import net.sourceforge.pmd.lang.metrics.MetricOption; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java index d7335c6313..1277803630 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NoamTestRule.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java index 5f8dfbf414..bffb6b6231 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/NopaTestRule.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java index 0e97bf5258..081740505b 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/TccTestRule.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java index c6c70a9148..980adce044 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WmcTestRule.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; /** * @author Clément Fournier diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java index ffc3683726..93d5a291f7 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/impl/WocTestRule.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl; -import net.sourceforge.pmd.lang.java.metrics.api.JavaMetrics; +import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; /** * @author Clément Fournier From de37639d1d26076e1639100dbbf801046cdbba81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 1 Dec 2020 21:03:49 +0100 Subject: [PATCH 029/101] Merge both ast util classes --- .../pmd/lang/java/internal/JavaAstUtils.java | 57 ------------------- .../pmd/lang/java/metrics/JavaMetrics.java | 7 +-- .../signature/JavaOperationSignature.java | 5 +- .../lang/java/rule/internal/JavaRuleUtil.java | 51 +++++++++++++++++ 4 files changed, 56 insertions(+), 64 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java index a8e11be6dc..14b49e36b5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java @@ -4,13 +4,10 @@ package net.sourceforge.pmd.lang.java.internal; -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTSwitchBranch; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; /** * @@ -22,60 +19,6 @@ public final class JavaAstUtils { } - public static boolean isGetterOrSetter(ASTMethodDeclaration node) { - return isGetter(node) || isSetter(node); - } - - - /** Attempts to determine if the method is a getter. */ - private static boolean isGetter(ASTMethodDeclaration node) { - - if (node.getArity() != 0 || node.isVoid()) { - return false; - } - - ASTAnyTypeDeclaration enclosing = node.getEnclosingType(); - if (node.getName().startsWith("get")) { - return hasField(enclosing, node.getName().substring(3)); - } else if (node.getName().startsWith("is")) { - return hasField(enclosing, node.getName().substring(2)); - } - - return hasField(enclosing, node.getName()); - } - - - /** Attempts to determine if the method is a setter. */ - private static boolean isSetter(ASTMethodDeclaration node) { - - if (node.getArity() != 1 || !node.isVoid()) { - return false; - } - - ASTAnyTypeDeclaration enclosing = node.getEnclosingType(); - - if (node.getName().startsWith("set")) { - return hasField(enclosing, node.getName().substring(3)); - } - - return hasField(enclosing, node.getName()); - } - - - private static boolean hasField(ASTAnyTypeDeclaration node, String name) { - for (JFieldSymbol f : node.getSymbol().getDeclaredFields()) { - String fname = f.getSimpleName(); - if (fname.startsWith("m_") || fname.startsWith("_")) { - fname = fname.substring(fname.indexOf('_') + 1); - } - if (fname.equalsIgnoreCase(name)) { - return true; - } - } - return false; - } - - public static boolean isConditional(JavaNode ifx) { if (ifx instanceof ASTInfixExpression) { BinaryOp op = ((ASTInfixExpression) ifx).getOperator(); 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 69085e104b..1f81d293a1 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 @@ -22,18 +22,17 @@ import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; -import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.metrics.internal.AtfdBaseVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.ClassFanOutVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.CycloVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.NcssVisitor; import net.sourceforge.pmd.lang.java.metrics.internal.NpathBaseVisitor; +import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; @@ -123,7 +122,7 @@ public final class JavaMetrics { private static int computeNoam(ASTAnyTypeDeclaration node, MetricOptions ignored) { return node.getDeclarations() .filterIs(ASTMethodDeclaration.class) - .filter(JavaAstUtils::isGetterOrSetter) + .filter(JavaRuleUtil::isGetterOrSetter) .count(); } @@ -290,7 +289,7 @@ public final class JavaMetrics { .filterIs(ASTMethodDeclaration.class) .filter(it -> !it.isPrivate()); - int notSetter = methods.filter(it -> !JavaAstUtils.isGetterOrSetter(it)).count(); + int notSetter = methods.filter(it -> !JavaRuleUtil.isGetterOrSetter(it)).count(); int total = methods.count(); if (total == 0) { return 0; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java index 578b4d2ea1..94328c4d39 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java @@ -11,8 +11,7 @@ import net.sourceforge.pmd.annotation.DeprecatedUntil700; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.internal.JavaAstUtils; -import net.sourceforge.pmd.lang.java.symbols.JElementSymbol; +import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; /** * Signature for an operation. @@ -94,7 +93,7 @@ public final class JavaOperationSignature extends JavaSignature Date: Thu, 3 Dec 2020 11:32:03 +0100 Subject: [PATCH 030/101] Update some of the old metrics rules --- .../pmd/lang/java/metrics/JavaMetrics.java | 4 +- .../lang/java/rule/design/DataClassRule.java | 20 +++++--- .../lang/java/rule/design/NcssCountRule.java | 49 +++++++++++-------- .../lang/java/rule/design/DataClassTest.java | 1 - .../lang/java/rule/design/NcssCountTest.java | 1 - .../lang/java/rule/design/xml/DataClass.xml | 4 +- .../lang/java/rule/design/xml/NcssCount.xml | 2 +- 7 files changed, 49 insertions(+), 32 deletions(-) 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 1f81d293a1..84cbce72fb 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,9 @@ import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** - * A collection of java metrics. + * A collection of Java metrics. + * + * @see Online documentation */ @SuppressWarnings("PMD.UnusedFormalParameter") // #2838 public final class JavaMetrics { 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 32fc96cc8f..dfbe31b126 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 @@ -9,8 +9,10 @@ import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.NUMBER_OF_PUBLIC import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.WEIGHED_METHOD_COUNT; import static net.sourceforge.pmd.lang.java.metrics.JavaMetrics.WEIGHT_OF_CLASS; +import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; +import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.util.StringUtil; @@ -18,7 +20,7 @@ import net.sourceforge.pmd.util.StringUtil; * @author Clément Fournier * @since 6.0.0 */ -public class DataClassRule extends AbstractJavaMetricsRule { +public class DataClassRule extends AbstractJavaRulechainRule { // probably not worth using properties private static final int ACCESSOR_OR_FIELD_FEW_LEVEL = 3; @@ -27,12 +29,20 @@ public class DataClassRule extends AbstractJavaMetricsRule { private static final int WMC_HIGH_LEVEL = 31; private static final int WMC_VERY_HIGH_LEVEL = 47; + public DataClassRule() { + super(ASTAnyTypeDeclaration.class); + } @Override - public Object visit(ASTAnyTypeDeclaration node, Object data) { + public Object visitJavaNode(JavaNode node, Object data) { + visitTypeDecl((ASTAnyTypeDeclaration) node, (RuleContext) data); + return null; + } + + private void visitTypeDecl(ASTAnyTypeDeclaration node, RuleContext data) { if (!MetricsUtil.supportsAll(node, NUMBER_OF_ACCESSORS, NUMBER_OF_PUBLIC_FIELDS, WEIGHED_METHOD_COUNT, WEIGHT_OF_CLASS)) { - return super.visit(node, data); + return; } boolean isDataClass = interfaceRevealsData(node) && classRevealsDataAndLacksComplexity(node); @@ -47,8 +57,6 @@ public class DataClassRule extends AbstractJavaMetricsRule { StringUtil.percentageString(woc, 3), nopa, noam, wmc, }); } - - return super.visit(node, 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 b0e57b01d3..a90bddf887 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 @@ -10,14 +10,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.internal.util.AssertionUtil; 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.JavaNode; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.NcssOption; -import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -29,7 +31,7 @@ import net.sourceforge.pmd.properties.PropertyFactory; * * @author Clément Fournier */ -public final class NcssCountRule extends AbstractJavaMetricsRule { +public final class NcssCountRule extends AbstractJavaRulechainRule { private static final PropertyDescriptor METHOD_REPORT_LEVEL_DESCRIPTOR = @@ -65,6 +67,7 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { public NcssCountRule() { + super(ASTMethodOrConstructorDeclaration.class, ASTAnyTypeDeclaration.class); definePropertyDescriptor(METHOD_REPORT_LEVEL_DESCRIPTOR); definePropertyDescriptor(CLASS_REPORT_LEVEL_DESCRIPTOR); definePropertyDescriptor(NCSS_OPTIONS_DESCRIPTOR); @@ -72,49 +75,55 @@ public final class NcssCountRule extends AbstractJavaMetricsRule { @Override - public Object visit(ASTCompilationUnit node, Object data) { - methodReportLevel = getProperty(METHOD_REPORT_LEVEL_DESCRIPTOR); - classReportLevel = getProperty(CLASS_REPORT_LEVEL_DESCRIPTOR); - ncssOptions = MetricOptions.ofOptions(getProperty(NCSS_OPTIONS_DESCRIPTOR)); + public Object visitJavaNode(JavaNode node, Object data) { + int methodReportLevel = getProperty(METHOD_REPORT_LEVEL_DESCRIPTOR); + int classReportLevel = getProperty(CLASS_REPORT_LEVEL_DESCRIPTOR); + MetricOptions ncssOptions = MetricOptions.ofOptions(getProperty(NCSS_OPTIONS_DESCRIPTOR)); - super.visit(node, data); + if (node instanceof ASTAnyTypeDeclaration) { + visitTypeDecl((ASTAnyTypeDeclaration) node, classReportLevel, ncssOptions, (RuleContext) data); + } else if (node instanceof ASTMethodOrConstructorDeclaration) { + visitMethod((ASTMethodOrConstructorDeclaration) node, methodReportLevel, ncssOptions, (RuleContext) data); + } else { + throw AssertionUtil.shouldNotReachHere("unreachable"); + } return data; } - @Override - public Object visit(ASTAnyTypeDeclaration node, Object data) { - - super.visit(node, data); + private void visitTypeDecl(ASTAnyTypeDeclaration node, + int level, + MetricOptions ncssOptions, + RuleContext data) { if (JavaMetrics.NCSS.supports(node)) { int classSize = MetricsUtil.computeMetric(JavaMetrics.NCSS, node, ncssOptions); int classHighest = (int) MetricsUtil.computeStatistics(JavaMetrics.NCSS, node.getOperations(), ncssOptions).getMax(); - if (classSize >= classReportLevel) { + if (classSize >= level) { String[] messageParams = {PrettyPrintingUtil.kindName(node), node.getSimpleName(), - classSize + " (Highest = " + classHighest + ")", }; + classSize + " (Highest = " + classHighest + ")",}; addViolation(data, node, messageParams); } } - return data; } - @Override - public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { + private void visitMethod(ASTMethodOrConstructorDeclaration node, + int level, + MetricOptions ncssOptions, + RuleContext data) { if (JavaMetrics.NCSS.supports(node)) { int methodSize = MetricsUtil.computeMetric(JavaMetrics.NCSS, node, ncssOptions); - if (methodSize >= methodReportLevel) { + if (methodSize >= level) { addViolation(data, node, new String[] { node instanceof ASTMethodDeclaration ? "method" : "constructor", - PrettyPrintingUtil.displaySignature(node), "" + methodSize, }); + PrettyPrintingUtil.displaySignature(node), "" + methodSize,}); } } - return data; } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DataClassTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DataClassTest.java index ff0a97b3ef..044eb74458 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DataClassTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/DataClassTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.design; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class DataClassTest extends PmdRuleTst { // no additional unit tests } 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 5fb27123d6..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 @@ -6,6 +6,5 @@ package net.sourceforge.pmd.lang.java.rule.design; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class NcssCountTest extends PmdRuleTst { } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/DataClass.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/DataClass.xml index f921a09b64..4add116b13 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/DataClass.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/DataClass.xml @@ -60,7 +60,7 @@ public class Property implements Comparable { // Woc = 10%, Noam = 6, Nopa = 0, ArgoUML data class 1 - The class 'Property' is suspected to be a Data Class (WOC=11.111%, NOPA=0, NOAM=6, WMC=9) + The class 'Property' is suspected to be a Data Class (WOC=14.286%, NOPA=0, NOAM=6, WMC=9) @@ -205,7 +205,7 @@ public class TestDescriptor { PMD data class 1 - The class 'TestDescriptor' is suspected to be a Data Class (WOC=13.043%, NOPA=0, NOAM=17, WMC=25) + The class 'TestDescriptor' is suspected to be a Data Class (WOC=15.000%, NOPA=0, NOAM=17, WMC=25) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NcssCount.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NcssCount.xml index 2123d86722..9aa09006e9 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NcssCount.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NcssCount.xml @@ -51,7 +51,7 @@ public class Foo extends Bar { } } - super(z); + super.f(z); } public void foo() { From 3e15b4af00cce822f1a035c882eafc7c159f153d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 3 Dec 2020 12:10:53 +0100 Subject: [PATCH 031/101] Update Npath complexity rule --- .../java/metrics/internal/CycloVisitor.java | 18 ++++--- .../metrics/internal/NpathBaseVisitor.java | 14 ++--- .../java/rule/design/NPathComplexityRule.java | 45 ++++------------ .../java/rule/design/NPathComplexityTest.java | 1 - .../java/rule/design/xml/NPathComplexity.xml | 52 +++++++++---------- 5 files changed, 49 insertions(+), 81 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloVisitor.java index a5bec1a34e..cf85f027b0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloVisitor.java @@ -194,12 +194,16 @@ public class CycloVisitor extends JavaVisitorBase { return 0; } - return expr.descendantsOrSelf() - .reduce(0, (acc, ifx) -> { - if (JavaAstUtils.isConditional(ifx)) { - return acc + 1; - } - return acc; - }); + if (expr instanceof ASTConditionalExpression) { + ASTConditionalExpression conditional = (ASTConditionalExpression) expr; + return booleanExpressionComplexity(conditional.getCondition()) + + booleanExpressionComplexity(conditional.getThenBranch()) + + booleanExpressionComplexity(conditional.getElseBranch()) + + 2; + } else { + return expr.descendantsOrSelf() + .filter(JavaAstUtils::isConditional) + .count(); + } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java index 2bc55dd851..ce181818cc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java @@ -80,17 +80,13 @@ public class NpathBaseVisitor extends JavaVisitorBase { public BigInteger visit(ASTIfStatement node, Void data) { // (npath of if + npath of else (or 1) + bool_comp of if) * npath of next - NodeStream statementChildren = node.children(ASTStatement.class); + int boolCompIf = CycloVisitor.booleanExpressionComplexity(node.getCondition()); - // add path for not taking if - BigInteger complexity = node.hasElse() ? BigInteger.ZERO : BigInteger.ONE; + BigInteger thenResult = node.getThenBranch().acceptVisitor(this, data); + ASTStatement elseBranch = node.getElseBranch(); + BigInteger elseResult = elseBranch != null ? elseBranch.acceptVisitor(this, data) : BigInteger.ONE; - for (ASTStatement element : statementChildren) { - complexity = complexity.add(element.acceptVisitor(this, data)); - } - - int boolCompIf = CycloVisitor.booleanExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); - return complexity.add(BigInteger.valueOf(boolCompIf)); + return thenResult.add(BigInteger.valueOf(boolCompIf)).add(elseResult); } 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 b1da86eaad..7fa535e437 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 @@ -7,14 +7,14 @@ package net.sourceforge.pmd.lang.java.rule.design; import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; import java.math.BigInteger; -import java.util.logging.Logger; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; +import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; +import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; -import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -26,52 +26,25 @@ import net.sourceforge.pmd.properties.PropertyFactory; * @author Clément Fournier * @author Jason Bennett */ -public class NPathComplexityRule extends AbstractJavaMetricsRule { - - private static final Logger LOG = Logger.getLogger(NPathComplexityRule.class.getName()); - - @Deprecated - private static final PropertyDescriptor MINIMUM_DESCRIPTOR - = PropertyFactory.doubleProperty("minimum").desc("Deprecated! Minimum reporting threshold") - .require(positive()).defaultValue(200d).build(); - +public class NPathComplexityRule extends AbstractJavaRulechainRule { private static final PropertyDescriptor REPORT_LEVEL_DESCRIPTOR = PropertyFactory.intProperty("reportLevel").desc("N-Path Complexity reporting threshold") .require(positive()).defaultValue(200).build(); - - private int reportLevel = 200; - - public NPathComplexityRule() { + super(ASTMethodOrConstructorDeclaration.class); definePropertyDescriptor(REPORT_LEVEL_DESCRIPTOR); - definePropertyDescriptor(MINIMUM_DESCRIPTOR); } @Override - public Object visit(ASTCompilationUnit node, Object data) { - reportLevel = getReportLevel(); - - super.visit(node, data); - return data; + public Object visitJavaNode(JavaNode node, Object data) { + return visitMethod((ASTMethodOrConstructorDeclaration) node, (RuleContext) data); } - - private int getReportLevel() { - double oldProp = getProperty(MINIMUM_DESCRIPTOR); - if (oldProp != MINIMUM_DESCRIPTOR.defaultValue()) { - LOG.warning("Rule NPathComplexity uses deprecated property 'minimum'. Future versions of PMD will remove support for this property. Please use 'reportLevel' instead!"); - return (int) oldProp; - } - - return getProperty(REPORT_LEVEL_DESCRIPTOR); - } - - - @Override - public final Object visit(ASTMethodOrConstructorDeclaration node, Object data) { + private Object visitMethod(ASTMethodOrConstructorDeclaration node, RuleContext data) { + int reportLevel = getProperty(REPORT_LEVEL_DESCRIPTOR); if (!JavaMetrics.NPATH.supports(node)) { return data; } 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 f9efc5aac8..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 @@ -6,6 +6,5 @@ package net.sourceforge.pmd.lang.java.rule.design; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class NPathComplexityTest extends PmdRuleTst { } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NPathComplexity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NPathComplexity.xml index 349bc22b27..8801f3f25f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NPathComplexity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NPathComplexity.xml @@ -74,15 +74,11 @@ public class Foo { int j = 0; switch (j) { // 5 - case 0: - case 1: - case 3: if (a || b) {} break; + case 0: case 1: case 2: case 3: case 4: break; } - switch (j) { // * 5 - case 0: - case 1: - case 3: if (a || b) {} break; + switch (j) { // 5 + case 0: case 1: case 2: case 3: case 4: break; } if (true || a && b); // * 4 @@ -142,6 +138,27 @@ class Foo { ]]> + + Switch stmt + 2 + 1 + + The method 'bar()' has an NPath complexity of 9, current threshold is 2 + + + + - - Backwards compatibility with minimum property - 300 - 0 - - - Switch arrow branch (#2625) 0 From 19aa28b2401f66ca6922b81a587eb70d6d81bea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 3 Dec 2020 12:14:45 +0100 Subject: [PATCH 032/101] Update Cyclo rule --- .ci/files/all-java.xml | 6 +- .../rule/design/CyclomaticComplexityRule.java | 63 +++---------------- .../rule/design/CyclomaticComplexityTest.java | 1 - .../rule/design/xml/CyclomaticComplexity.xml | 13 ---- 4 files changed, 11 insertions(+), 72 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index da63fd7deb..395a434515 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -133,7 +133,7 @@ - + @@ -147,8 +147,8 @@ - - + + 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 4b7a826eb1..0af56eaadb 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 @@ -9,10 +9,8 @@ import static net.sourceforge.pmd.properties.constraints.NumericConstraints.posi import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Logger; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; @@ -20,7 +18,7 @@ import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.CycloOption; -import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -33,17 +31,7 @@ import net.sourceforge.pmd.properties.PropertyFactory; * @author Clément Fournier, based on work by Alan Hohn and Donald A. Leckie * @version 6.0.0 */ -public class CyclomaticComplexityRule extends AbstractJavaRule { - - private static final Logger LOG = Logger.getLogger(CyclomaticComplexityRule.class.getName()); - - // Deprecated, kept for backwards compatibility (6.0.0) - @Deprecated - private static final PropertyDescriptor REPORT_LEVEL_DESCRIPTOR - = PropertyFactory.intProperty("reportLevel") - .desc("Deprecated! Cyclomatic Complexity reporting threshold") - .require(positive()).defaultValue(10).build(); - +public class CyclomaticComplexityRule extends AbstractJavaRulechainRule { private static final PropertyDescriptor CLASS_LEVEL_DESCRIPTOR = PropertyFactory.intProperty("classReportLevel") @@ -69,49 +57,12 @@ public class CyclomaticComplexityRule extends AbstractJavaRule { .emptyDefaultValue() .build(); - private int methodReportLevel; - private int classReportLevel; - private MetricOptions cycloOptions; - public CyclomaticComplexityRule() { + super(ASTMethodOrConstructorDeclaration.class, ASTAnyTypeDeclaration.class); definePropertyDescriptor(CLASS_LEVEL_DESCRIPTOR); definePropertyDescriptor(METHOD_LEVEL_DESCRIPTOR); definePropertyDescriptor(CYCLO_OPTIONS_DESCRIPTOR); - definePropertyDescriptor(REPORT_LEVEL_DESCRIPTOR); - } - - // Kept for backwards compatibility // TODO remove the property sometime - private void assignReportLevelsCompat() { - int methodLevel = getProperty(METHOD_LEVEL_DESCRIPTOR); - int classLevel = getProperty(CLASS_LEVEL_DESCRIPTOR); - int commonLevel = getProperty(REPORT_LEVEL_DESCRIPTOR); - - if (methodLevel == METHOD_LEVEL_DESCRIPTOR.defaultValue() - && classLevel == CLASS_LEVEL_DESCRIPTOR.defaultValue() - && commonLevel != REPORT_LEVEL_DESCRIPTOR.defaultValue()) { - LOG.warning("Rule CyclomaticComplexity uses deprecated property 'reportLevel'. " - + "Future versions of PMD will remove support for this property. " - + "Please use 'methodReportLevel' and 'classReportLevel' instead!"); - methodLevel = commonLevel; - classLevel = commonLevel * 8; - } - - methodReportLevel = methodLevel; - classReportLevel = classLevel; - } - - @Override - public Object visit(ASTCompilationUnit node, Object data) { - // methodReportLevel = getProperty(METHOD_LEVEL_DESCRIPTOR); - // classReportLevel = getProperty(CLASS_LEVEL_DESCRIPTOR); - assignReportLevelsCompat(); - - cycloOptions = MetricOptions.ofOptions(getProperty(CYCLO_OPTIONS_DESCRIPTOR)); - - - super.visit(node, data); - return data; } @@ -125,12 +76,12 @@ public class CyclomaticComplexityRule extends AbstractJavaRule { public Object visitTypeDecl(ASTAnyTypeDeclaration node, Object data) { - super.visitJavaNode(node, data); + MetricOptions cycloOptions = MetricOptions.ofOptions(getProperty(CYCLO_OPTIONS_DESCRIPTOR)); if (JavaMetrics.WEIGHED_METHOD_COUNT.supports(node)) { int classWmc = MetricsUtil.computeMetric(JavaMetrics.WEIGHED_METHOD_COUNT, node, cycloOptions); - if (classWmc >= classReportLevel) { + if (classWmc >= getProperty(CLASS_LEVEL_DESCRIPTOR)) { int classHighest = (int) MetricsUtil.computeStatistics(JavaMetrics.CYCLO, node.getOperations(), cycloOptions).getMax(); String[] messageParams = {PrettyPrintingUtil.kindName(node), @@ -158,9 +109,11 @@ public class CyclomaticComplexityRule extends AbstractJavaRule { } private void visitMethodLike(ASTMethodOrConstructorDeclaration node, Object data) { + MetricOptions cycloOptions = MetricOptions.ofOptions(getProperty(CYCLO_OPTIONS_DESCRIPTOR)); + if (JavaMetrics.CYCLO.supports(node)) { int cyclo = MetricsUtil.computeMetric(JavaMetrics.CYCLO, node, cycloOptions); - if (cyclo >= methodReportLevel) { + if (cyclo >= getProperty(METHOD_LEVEL_DESCRIPTOR)) { String opname = PrettyPrintingUtil.displaySignature(node); 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 6d340ae5ee..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 @@ -6,6 +6,5 @@ package net.sourceforge.pmd.lang.java.rule.design; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class CyclomaticComplexityTest extends PmdRuleTst { } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CyclomaticComplexity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CyclomaticComplexity.xml index 3a7c8fff48..cf0423eb7b 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CyclomaticComplexity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CyclomaticComplexity.xml @@ -436,17 +436,4 @@ public class Complicated { - - Test property 'reportLevel' changes methodReportLevel - 1 - 1 - - - - - Test property 'reportLevel' changes classReportLevel - 11 - 0 - - From afaf46c6fc3e597985bbdf73af8d260779dd01db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 3 Dec 2020 12:15:07 +0100 Subject: [PATCH 033/101] Update GodClass --- .ci/files/all-java.xml | 2 +- .../net/sourceforge/pmd/lang/java/rule/design/GodClassTest.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 395a434515..865df43955 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -132,7 +132,7 @@ - + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/GodClassTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/GodClassTest.java index 72c2ff8b19..6dbff09d61 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/GodClassTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/GodClassTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.design; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class GodClassTest extends PmdRuleTst { // no additional unit tests } From 768a24670f759eae3d0ba83a90d9ed06be223868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 3 Dec 2020 12:15:28 +0100 Subject: [PATCH 034/101] Remove old metrics abstract class --- .../java/rule/AbstractJavaMetricsRule.java | 72 ------------------- 1 file changed, 72 deletions(-) delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaMetricsRule.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaMetricsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaMetricsRule.java deleted file mode 100644 index df530f8e28..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaMetricsRule.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule; - -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.MethodLikeNode; - - -/** - * Java Rule with convenient visit methods to e.g. treat constructors and methods the same. - * - * @author Clément Fournier - * @deprecated Internal API - */ -@Deprecated -@InternalApi -public abstract class AbstractJavaMetricsRule extends AbstractJavaRule { - - @Override - public final Object visit(ASTClassOrInterfaceDeclaration node, Object data) { - return visit((ASTAnyTypeDeclaration) node, data); - } - - - @Override - public final Object visit(ASTAnnotationTypeDeclaration node, Object data) { - return visit((ASTAnyTypeDeclaration) node, data); - } - - - @Override - public final Object visit(ASTEnumDeclaration node, Object data) { - return visit((ASTAnyTypeDeclaration) node, data); - } - - - public Object visit(ASTAnyTypeDeclaration node, Object data) { - return visitJavaNode(node, data); - } - - - @Override - public final Object visit(ASTMethodDeclaration node, Object data) { - return visit((ASTMethodOrConstructorDeclaration) node, data); - } - - - @Override - public final Object visit(ASTConstructorDeclaration node, Object data) { - return visit((ASTMethodOrConstructorDeclaration) node, data); - } - - - public Object visit(ASTMethodOrConstructorDeclaration node, Object data) { - return visit((MethodLikeNode) node, data); - } - - - public Object visit(MethodLikeNode node, Object data) { - return visitJavaNode(node, data); - } - -} From 9fa85d8e597de4c595dececf179455d06dcd239b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 3 Dec 2020 12:15:51 +0100 Subject: [PATCH 035/101] Remove MethodLikeNode --- .../ASTMethodOrConstructorDeclaration.java | 4 +--- .../pmd/lang/java/ast/MethodLikeNode.java | 21 ------------------- 2 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/MethodLikeNode.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java index 8718b947b5..98890eaa3d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java @@ -26,12 +26,10 @@ import net.sourceforge.pmd.lang.java.types.JMethodSig; * * * @author Clément Fournier - * @see MethodLikeNode * @since 5.8.1 */ public interface ASTMethodOrConstructorDeclaration - extends MethodLikeNode, - AccessNode, + extends AccessNode, SignedNode, ASTBodyDeclaration, TypeParamOwnerNode, diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/MethodLikeNode.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/MethodLikeNode.java deleted file mode 100644 index 434c642147..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/MethodLikeNode.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.ast; - -/** - * Groups method, constructor and lambda declarations under a common type. - * - * @author Clément Fournier - * @since 6.1.0 - * @deprecated Lambda expressions should not be grouped with other kinds - * of method declarations, they have nothing in common. Giving them a - * qualified name is hacky and compiler-implementation-dependent. - * Ultimately this supertype is not useful and can go away. - */ -@Deprecated -public interface MethodLikeNode extends JavaNode { - - -} From 16a4aa3163061011b08564c5bda50db543e3f6e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 3 Dec 2020 12:17:36 +0100 Subject: [PATCH 036/101] Remove signatures --- .../pmd/lang/apex/ast/ASTMethod.java | 12 +- .../apex/metrics/ApexSignatureMatcher.java | 24 -- .../signature/ApexOperationSigMask.java | 65 ---- .../signature/ApexOperationSignature.java | 68 ----- .../apex/metrics/signature/ApexSignature.java | 56 ---- .../sourceforge/pmd/lang/ast/SignedNode.java | 31 -- .../sourceforge/pmd/lang/metrics/SigMask.java | 30 -- .../pmd/lang/metrics/Signature.java | 21 -- .../lang/java/ast/ASTFieldDeclaration.java | 15 +- .../ASTMethodOrConstructorDeclaration.java | 8 - ...bstractMethodOrConstructorDeclaration.java | 12 - .../multifile/signature/JavaFieldSigMask.java | 57 ---- .../signature/JavaFieldSignature.java | 77 ----- .../signature/JavaOperationSigMask.java | 81 ----- .../signature/JavaOperationSignature.java | 103 ------- .../java/multifile/signature/JavaSigMask.java | 63 ---- .../multifile/signature/JavaSignature.java | 61 ---- .../documentation/CommentRequiredRule.java | 4 +- .../pmd/lang/java/metrics/SigMaskTest.java | 282 ------------------ .../pmd/lang/java/metrics/SignatureTest.java | 270 ----------------- 20 files changed, 4 insertions(+), 1336 deletions(-) delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexSignatureMatcher.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSigMask.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSignature.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexSignature.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SignedNode.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/SigMask.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Signature.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSigMask.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSignature.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSigMask.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSigMask.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSignature.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/SigMaskTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/SignatureTest.java diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java index a781dc9fdd..57ebfe6a56 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java @@ -4,14 +4,9 @@ package net.sourceforge.pmd.lang.apex.ast; -import net.sourceforge.pmd.lang.apex.metrics.signature.ApexOperationSignature; -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.ast.SignedNode; - import apex.jorje.semantic.ast.member.Method; -public final class ASTMethod extends AbstractApexNode implements ApexQualifiableNode, - SignedNode, Node { +public final class ASTMethod extends AbstractApexNode implements ApexQualifiableNode { ASTMethod(Method method) { super(method); @@ -58,11 +53,6 @@ public final class ASTMethod extends AbstractApexNode implements ApexQua } - @Override - public ApexOperationSignature getSignature() { - return ApexOperationSignature.of(this); - } - /** * Returns true if this is a synthetic class initializer, inserted * by the parser. diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexSignatureMatcher.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexSignatureMatcher.java deleted file mode 100644 index aa45ea9c29..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/ApexSignatureMatcher.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics; - -import net.sourceforge.pmd.lang.apex.ast.ApexQualifiedName; -import net.sourceforge.pmd.lang.apex.metrics.signature.ApexOperationSigMask; - -/** - * @author Clément Fournier - */ -public interface ApexSignatureMatcher { - - /** - * Returns true if the signature of the operation designated by the qualified name is covered by the mask. - * - * @param qname The operation to test - * @param sigMask The signature mask to use - * - * @return True if the signature of the operation designated by the qualified name is covered by the mask - */ - boolean hasMatchingSig(ApexQualifiedName qname, ApexOperationSigMask sigMask); -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSigMask.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSigMask.java deleted file mode 100644 index be7326494d..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSigMask.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.signature; - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Set; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.apex.metrics.signature.ApexSignature.Visibility; - -/** - * @author Clément Fournier - */ -@Deprecated -@DeprecatedUntil700 -public class ApexOperationSigMask { - - private Set visMask = EnumSet.allOf(Visibility.class); - - - /** - * Sets the mask to cover all visibilities. - */ - public void coverAllVisibilities() { - visMask.addAll(Arrays.asList(Visibility.values())); - } - - - /** - * Restricts the visibilities covered by the mask to the parameters. - * - * @param visibilities The visibilities to cover - */ - public void restrictVisibilitiesTo(Visibility... visibilities) { - visMask.clear(); - visMask.addAll(Arrays.asList(visibilities)); - } - - - /** - * Forbid all mentioned visibilities. - * - * @param visibilities The visibilities to forbid - */ - public void forbid(Visibility... visibilities) { - visMask.removeAll(Arrays.asList(visibilities)); - } - - - /** - * Returns true if the parameter is covered by this mask. - * - * @param sig The signature to test. - * - * @return True if the parameter is covered by this mask - */ - public boolean covers(ApexOperationSignature sig) { - return visMask.contains(sig.visibility); - } - - -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSignature.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSignature.java deleted file mode 100644 index ed599719c6..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexOperationSignature.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.signature; - -import java.util.HashMap; -import java.util.Map; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.metrics.Signature; - -/** - * @author Clément Fournier - */ -@Deprecated -@DeprecatedUntil700 -public final class ApexOperationSignature extends ApexSignature implements Signature { - - private static final Map POOL = new HashMap<>(); - - - /** - * Create a signature using its visibility. - * - * @param visibility The visibility - */ - private ApexOperationSignature(Visibility visibility) { - super(visibility); - } - - - @Override - public int hashCode() { - return code(visibility); - } - - - @Override - public boolean equals(Object obj) { - return obj == this; - } - - - private static int code(Visibility visibility) { - return visibility.hashCode(); - } - - - /** - * Builds the signature of this node. - * - * @param node The method node - * - * @return The signature of the node - */ - public static ApexOperationSignature of(ASTMethod node) { - Visibility visibility = Visibility.get(node); - int code = code(visibility); - if (!POOL.containsKey(code)) { - POOL.put(code, new ApexOperationSignature(visibility)); - } - return POOL.get(code); - } - - -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexSignature.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexSignature.java deleted file mode 100644 index 18b7a75a4d..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/signature/ApexSignature.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.metrics.signature; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; - -/** - * Base class for apex field or method signatures. - * - * @author Clément Fournier - */ -@Deprecated -@DeprecatedUntil700 -public abstract class ApexSignature { - - /** Visibility of the field or method. */ - public final Visibility visibility; - - - /** Create a signature using its visibility. */ - protected ApexSignature(Visibility visibility) { - this.visibility = visibility; - } - - - /** Visibility of a field or method. */ - public enum Visibility { - PRIVATE, PUBLIC, PROTECTED, GLOBAL; - - - /** - * Finds out the visibility of a method node. - * - * @param method The method node - * - * @return The visibility of the method - */ - public static Visibility get(ASTMethod method) { - ASTModifierNode modifierNode = method.getFirstChildOfType(ASTModifierNode.class); - if (modifierNode.isPublic()) { - return PUBLIC; - } else if (modifierNode.isPrivate()) { - return PRIVATE; - } else if (modifierNode.isProtected()) { - return PROTECTED; - } else { - return GLOBAL; - } - } - } - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SignedNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SignedNode.java deleted file mode 100644 index b92723ae80..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SignedNode.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.ast; - - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.metrics.Signature; - -/** - * Nodes that can be described by a signature. - * - * @param The type of node - * - * @author Clément Fournier - */ -@Deprecated -@DeprecatedUntil700 -public interface SignedNode extends Node { - - /** - * Gets the signature of this node. - * - * @return The signature - */ - @Deprecated - @DeprecatedUntil700 - Signature getSignature(); - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/SigMask.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/SigMask.java deleted file mode 100644 index c17dd6aadf..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/SigMask.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.metrics; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; - -/** - * Generic signature mask. - * - * @param Type of signature this mask handles - * - * @author Clément Fournier - * @since 6.0.0 - */ -@Deprecated -@DeprecatedUntil700 -public interface SigMask> { - - /** - * Returns true if the parameter is covered by this mask. - * - * @param sig The signature to test. - * - * @return True if the parameter is covered by this mask - */ - boolean covers(T sig); - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Signature.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Signature.java deleted file mode 100644 index 547a14a277..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Signature.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.metrics; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.ast.SignedNode; - -/** - * Signature of a node. - * - * @param The type of node this signature signs - * - * @author Clément Fournier - * @since 6.0.0 - */ -@Deprecated -@DeprecatedUntil700 -public interface Signature> { -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java index ba2d8d8f67..93aa3cbc15 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java @@ -6,9 +6,7 @@ package net.sourceforge.pmd.lang.java.ast; import org.checkerframework.checker.nullness.qual.Nullable; -import net.sourceforge.pmd.lang.ast.SignedNode; import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSignature; import net.sourceforge.pmd.lang.rule.xpath.DeprecatedAttribute; @@ -26,15 +24,13 @@ import net.sourceforge.pmd.lang.rule.xpath.DeprecatedAttribute; * */ public final class ASTFieldDeclaration extends AbstractJavaNode - implements SignedNode, - Iterable, + implements Iterable, LeftRecursiveNode, AccessNode, ASTBodyDeclaration, InternalInterfaces.MultiVariableIdOwner, JavadocCommentOwner { - private JavaFieldSignature signature; ASTFieldDeclaration(int id) { super(id); @@ -72,15 +68,6 @@ public final class ASTFieldDeclaration extends AbstractJavaNode } - @Override - public JavaFieldSignature getSignature() { - if (signature == null) { - signature = JavaFieldSignature.buildFor(this); - } - - return signature; - } - /** * Returns the type node at the beginning of this field declaration. * The type of this node is not necessarily the type of the variables, diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java index 98890eaa3d..77b23f8acc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java @@ -7,9 +7,7 @@ package net.sourceforge.pmd.lang.java.ast; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import net.sourceforge.pmd.lang.ast.SignedNode; import net.sourceforge.pmd.lang.ast.impl.GenericNode; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature; import net.sourceforge.pmd.lang.java.symbols.JExecutableSymbol; import net.sourceforge.pmd.lang.java.types.JClassType; import net.sourceforge.pmd.lang.java.types.JMethodSig; @@ -30,7 +28,6 @@ import net.sourceforge.pmd.lang.java.types.JMethodSig; */ public interface ASTMethodOrConstructorDeclaration extends AccessNode, - SignedNode, ASTBodyDeclaration, TypeParamOwnerNode, GenericNode, @@ -57,11 +54,6 @@ public interface ASTMethodOrConstructorDeclaration String getName(); - @Override - JavaOperationSignature getSignature(); - - - /** * Returns true if this method is abstract, so doesn't * declare a body. Interface members are diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractMethodOrConstructorDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractMethodOrConstructorDeclaration.java index cb9ad2ea8d..fe2699fec1 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractMethodOrConstructorDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractMethodOrConstructorDeclaration.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.java.ast; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature; import net.sourceforge.pmd.lang.java.symbols.JExecutableSymbol; import net.sourceforge.pmd.lang.java.types.JMethodSig; @@ -15,7 +14,6 @@ abstract class AbstractMethodOrConstructorDeclaration { - - private boolean coverFinal = true; - private boolean coverStatic = true; - - /** Include final fields?. */ - public void coverFinal(boolean coverFinal) { - this.coverFinal = coverFinal; - } - - - public void coverFinal() { - this.coverFinal = true; - } - - - public void forbidFinal() { - this.coverFinal = false; - } - - - /** Include static fields?. */ - public void coverStatic(boolean coverStatic) { - this.coverStatic = coverStatic; - } - - - public void coverStatic() { - this.coverStatic = true; - } - - - public void forbidStatic() { - this.coverStatic = false; - } - - - @Override - public boolean covers(JavaFieldSignature sig) { - return super.covers(sig) && (coverFinal || !sig.isFinal) && (coverStatic || !sig.isStatic); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSignature.java deleted file mode 100644 index aacee3dcc0..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaFieldSignature.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.multifile.signature; - -import java.util.HashMap; -import java.util.Map; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; - -/** - * Signature for a field. - * - * @author Clément Fournier - */ -@Deprecated -@DeprecatedUntil700 -public final class JavaFieldSignature extends JavaSignature { - - private static final Map POOL = new HashMap<>(); - - public final boolean isStatic; - public final boolean isFinal; - - - private JavaFieldSignature(Visibility visibility, boolean isStatic, boolean isFinal) { - super(visibility); - this.isStatic = isStatic; - this.isFinal = isFinal; - } - - - @Override - public String toString() { - return "JavaFieldSignature{" - + "isStatic=" + isStatic - + ", isFinal=" + isFinal - + ", visibility=" + visibility - + '}'; - } - - - @Override - public boolean equals(Object o) { - return this == o; - } - - - @Override - public int hashCode() { - return code(visibility, isStatic, isFinal); - } - - - /** Used internally by the pooler. */ - private static int code(Visibility visibility, boolean isStatic, boolean isFinal) { - return visibility.hashCode() * 31 + (isStatic ? 1 : 0) * 2 + (isFinal ? 1 : 0); - } - - - /** - * Builds a field signature from its AST node. - * - * @param node The AST node of the field - * - * @return The signature of the field - */ - public static JavaFieldSignature buildFor(ASTFieldDeclaration node) { - int code = code(Visibility.get(node), node.isStatic(), node.isFinal()); - if (!POOL.containsKey(code)) { - POOL.put(code, new JavaFieldSignature(Visibility.get(node), node.isStatic(), node.isFinal())); - } - return POOL.get(code); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSigMask.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSigMask.java deleted file mode 100644 index 0ddda40809..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSigMask.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.multifile.signature; - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Set; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature.Role; - -/** - * Signature mask for an operation. Newly created masks cover any operation that is not abstract. - * - * @author Clément Fournier - */ -@Deprecated -@DeprecatedUntil700 -public final class JavaOperationSigMask extends JavaSigMask { - - private Set roleMask = EnumSet.allOf(Role.class); - private boolean coverAbstract = false; - - - /** - * Sets the mask to cover all roles. - */ - public void coverAllRoles() { - roleMask.addAll(Arrays.asList(JavaOperationSignature.Role.values())); - } - - - /** - * Restricts the roles covered by the mask to the parameters. - * - * @param roles The roles to cover - */ - public void restrictRolesTo(JavaOperationSignature.Role... roles) { - roleMask.clear(); - roleMask.addAll(Arrays.asList(roles)); - } - - - /** - * Forbid all mentioned roles. - * - * @param roles The roles to forbid - */ - public void forbid(JavaOperationSignature.Role... roles) { - roleMask.removeAll(Arrays.asList(roles)); - } - - - /** - * Forbid all mentioned visibilities. - * - * @param coverAbstract The visibilities to forbid - */ - public void coverAbstract(boolean coverAbstract) { - this.coverAbstract = coverAbstract; - } - - - public void coverAbstract() { - this.coverAbstract = true; - } - - - public void forbidAbstract() { - this.coverAbstract = false; - } - - - @Override - public boolean covers(JavaOperationSignature sig) { - return super.covers(sig) && roleMask.contains(sig.role) && (coverAbstract - || !sig.isAbstract); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java deleted file mode 100644 index 94328c4d39..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaOperationSignature.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.multifile.signature; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; - -/** - * Signature for an operation. - * - * @author Clément Fournier - */ -@Deprecated -@DeprecatedUntil700 -public final class JavaOperationSignature extends JavaSignature { - - private static final Map POOL = new ConcurrentHashMap<>(); - public final Role role; - public final boolean isAbstract; - - - private JavaOperationSignature(Visibility visibility, Role role, boolean isAbstract) { - super(visibility); - this.role = role; - this.isAbstract = isAbstract; - } - - - @Override - public boolean equals(Object o) { - return this == o; - } - - - @Override - public int hashCode() { - return code(visibility, role, isAbstract); - } - - - @Override - public String toString() { - return "JavaOperationSignature{" - + "role=" + role - + ", isAbstract=" + isAbstract - + ", visibility=" + visibility - + '}'; - } - - - /** Used internally by the pooler. */ - private static int code(Visibility visibility, Role role, boolean isAbstract) { - return visibility.hashCode() * 31 + role.hashCode() * 2 + (isAbstract ? 1 : 0); - } - - - /** - * Builds an operation signature from a method or constructor declaration. - * - * @param node The node - * - * @return The signature of the parameter - */ - public static JavaOperationSignature buildFor(ASTMethodOrConstructorDeclaration node) { - int code = code(Visibility.get(node), Role.get(node), node.isAbstract()); - if (!POOL.containsKey(code)) { - POOL.put(code, new JavaOperationSignature(Visibility.get(node), Role.get(node), node.isAbstract())); - } - return POOL.get(code); - } - - - /** - * Role of an operation. - */ - public enum Role { - GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC; - - - public static Role get(ASTMethodOrConstructorDeclaration node) { - return node instanceof ASTConstructorDeclaration ? CONSTRUCTOR : get((ASTMethodDeclaration) node); - } - - - private static Role get(ASTMethodDeclaration node) { - if (node.isStatic()) { - return STATIC; - } else if (JavaRuleUtil.isGetterOrSetter(node)) { - return GETTER_OR_SETTER; - } else { - return METHOD; - } - } - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSigMask.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSigMask.java deleted file mode 100644 index 0b1ae93a66..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSigMask.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.multifile.signature; - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Set; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaSignature.Visibility; -import net.sourceforge.pmd.lang.metrics.SigMask; - -/** - * Generic signature mask. - * - * @param The type of Signature to handle. - * - * @author Clément Fournier - */ -@Deprecated -@DeprecatedUntil700 -public abstract class JavaSigMask> implements SigMask { - - /** Visibility mask. */ - private Set visMask = EnumSet.allOf(Visibility.class); - - - /** - * Sets the mask to cover all visibilities. - */ - public void coverAllVisibilities() { - visMask.addAll(Arrays.asList(JavaSignature.Visibility.values())); - } - - - /** - * Restricts the visibilities covered by the mask to the parameters. - * - * @param visibilities The visibilities to cover - */ - public void restrictVisibilitiesTo(JavaSignature.Visibility... visibilities) { - visMask.clear(); - visMask.addAll(Arrays.asList(visibilities)); - } - - - /** - * Forbid all mentioned visibilities. - * - * @param visibilities The visibilities to forbid - */ - public void forbid(JavaSignature.Visibility... visibilities) { - visMask.removeAll(Arrays.asList(visibilities)); - } - - - @Override - public boolean covers(T sig) { - return visMask.contains(sig.visibility); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSignature.java deleted file mode 100644 index 95f77d093c..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/multifile/signature/JavaSignature.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.multifile.signature; - -import net.sourceforge.pmd.annotation.DeprecatedUntil700; -import net.sourceforge.pmd.lang.ast.SignedNode; -import net.sourceforge.pmd.lang.java.ast.AccessNode; -import net.sourceforge.pmd.lang.metrics.Signature; - -/** - * Generic signature. This class is extended by classes specific to operations and fields. - * - * @author Clément Fournier - */ -@Deprecated -@DeprecatedUntil700 -public abstract class JavaSignature> implements Signature { - - /** Visibility. */ - public final Visibility visibility; - - - /** - * Initialises the visibility. - * - * @param visibility The visibility of the signature - */ - protected JavaSignature(Visibility visibility) { - this.visibility = visibility; - } - - - /** - * The visibility of a node. TODO replace with {@link AccessNode.Visibility} - */ - public enum Visibility { - PUBLIC, PACKAGE, PROTECTED, PRIVATE; - - - /** - * Returns the Visibility enum key for a node. - * - * @param node A node - * - * @return The visibility enum key for a node - */ - public static Visibility get(AccessNode node) { - if (node.isPublic()) { - return PUBLIC; - } else if (node.isPackagePrivate()) { - return PACKAGE; - } else if (node.isProtected()) { - return PROTECTED; - } else { - return PRIVATE; - } - } - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java index 78cabc82e2..d29c502823 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java @@ -24,8 +24,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.JModifier; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavadocCommentOwner; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; import net.sourceforge.pmd.properties.PropertyBuilder.GenericPropertyBuilder; @@ -162,7 +162,7 @@ public class CommentRequiredRule extends AbstractJavaRule { public Object visit(ASTMethodDeclaration decl, Object data) { if (isAnnotatedOverride(decl)) { checkCommentMeetsRequirement(data, decl, OVERRIDE_CMT_DESCRIPTOR); - } else if (decl.getSignature().role == JavaOperationSignature.Role.GETTER_OR_SETTER) { + } else if (JavaRuleUtil.isGetterOrSetter(decl)) { checkCommentMeetsRequirement(data, decl, ACCESSOR_CMT_DESCRIPTOR); } else { checkMethodOrConstructorComment(decl, data); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/SigMaskTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/SigMaskTest.java deleted file mode 100644 index 8e09379079..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/SigMaskTest.java +++ /dev/null @@ -1,282 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.List; - -import org.junit.Test; - -import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSigMask; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSignature; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSigMask; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature.Role; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaSignature.Visibility; -import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; -import net.sourceforge.pmd.lang.metrics.SigMask; - -/** - * @author Clément Fournier - */ -public class SigMaskTest extends BaseNonParserTest { - - private static final String TEST_FIELDS = "class Bzaz{" - + "public String x;" - + "private int y;" - + "protected String z;" - + "int s;" - + "public final int t;" - + "private final int a;" - + "protected final double u;" - + "final long v;" - + "static int aa;" - + "static final int ab;" - + "private static int ac;" - + "protected static final int ad;" - + "public static int ag;" - + "}"; - - private static final String TEST_OPERATIONS = "abstract class Bzaz{ " - + "int x;" - + "int y;" - + "int z;" - // constructors - + "public Bzaz() {}" - + "private Bzaz(int x){}" - + "protected Bzaz(int x, String y){}" - // static - + "public static void main(String[] args){}" - + "protected static void makeFoo(){}" - + "private static void makeBar(){}" - // getters and setters - + "public int getX(){return 2;}" - + "int getY(){return 0;}" - + "protected void setY(int y){}" - + "private void setX(int x){}" - // methods - + "public void foo(){} " - + "void bar(){} " - + "protected void foo(int x){} " - + "private void rand(){}" - // abstract - + "protected abstract int getZ();" - + "abstract int abs2();" - + "public static abstract String abstr();" - + "abstract void setZ(int x);" - + "}"; - - /** - * Ensure any non-abstract method is covered by a newly created mask. - */ - @Test - public void testEmptyOperationMask() { - List nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST_OPERATIONS); - SigMask mask = new JavaOperationSigMask(); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - if (node.isAbstract()) { - assertFalse(mask.covers(JavaOperationSignature.buildFor(node))); - } else { - assertTrue(mask.covers(JavaOperationSignature.buildFor(node))); - } - } - } - - /** - * Ensure any field is covered by a newly created mask. - */ - @Test - public void testEmptyFieldMask() { - List nodes = getOrderedNodes(ASTFieldDeclaration.class, TEST_FIELDS); - SigMask mask = new JavaFieldSigMask(); - - for (ASTFieldDeclaration node : nodes) { - assertTrue(mask.covers(JavaFieldSignature.buildFor(node))); - } - } - - @Test - public void testFinalFields() { - List nodes = getOrderedNodes(ASTFieldDeclaration.class, TEST_FIELDS); - JavaFieldSigMask mask = new JavaFieldSigMask(); - mask.forbidFinal(); - - for (ASTFieldDeclaration node : nodes) { - if (node.isFinal()) { - assertFalse(mask.covers(JavaFieldSignature.buildFor(node))); - } else { - assertTrue(mask.covers(JavaFieldSignature.buildFor(node))); - } - } - } - - @Test - public void testStaticFields() { - List nodes = getOrderedNodes(ASTFieldDeclaration.class, TEST_FIELDS); - JavaFieldSigMask mask = new JavaFieldSigMask(); - mask.forbidStatic(); - - for (ASTFieldDeclaration node : nodes) { - if (node.isStatic()) { - assertFalse(mask.covers(JavaFieldSignature.buildFor(node))); - } else { - assertTrue(mask.covers(JavaFieldSignature.buildFor(node))); - } - } - } - - @Test - public void testFieldvisibility() { - List nodes = getOrderedNodes(ASTFieldDeclaration.class, TEST_FIELDS); - JavaFieldSigMask mask = new JavaFieldSigMask(); - - mask.restrictVisibilitiesTo(Visibility.PUBLIC); - - for (ASTFieldDeclaration node : nodes) { - if (node.isPublic()) { - assertTrue(mask.covers(JavaFieldSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaFieldSignature.buildFor(node))); - } - } - - mask.restrictVisibilitiesTo(Visibility.PRIVATE); - - for (ASTFieldDeclaration node : nodes) { - if (node.isPrivate()) { - assertTrue(mask.covers(JavaFieldSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaFieldSignature.buildFor(node))); - } - } - - mask.restrictVisibilitiesTo(Visibility.PACKAGE); - - for (ASTFieldDeclaration node : nodes) { - if (node.isPackagePrivate()) { - assertTrue(mask.covers(JavaFieldSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaFieldSignature.buildFor(node))); - } - } - - mask.restrictVisibilitiesTo(Visibility.PROTECTED); - - for (ASTFieldDeclaration node : nodes) { - if (node.isProtected()) { - assertTrue(mask.covers(JavaFieldSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaFieldSignature.buildFor(node))); - } - } - - } - - - @Test - public void testOperationVisibility() { - List nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST_OPERATIONS); - - JavaOperationSigMask mask = new JavaOperationSigMask(); - mask.coverAbstract(); - - mask.restrictVisibilitiesTo(Visibility.PUBLIC); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - if (node.isPublic()) { - assertTrue(mask.covers(JavaOperationSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaOperationSignature.buildFor(node))); - } - } - - mask.restrictVisibilitiesTo(Visibility.PRIVATE); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - if (node.isPrivate()) { - assertTrue(mask.covers(JavaOperationSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaOperationSignature.buildFor(node))); - } - } - - mask.restrictVisibilitiesTo(Visibility.PACKAGE); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - if (node.isPackagePrivate()) { - assertTrue(mask.covers(JavaOperationSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaOperationSignature.buildFor(node))); - } - } - - mask.restrictVisibilitiesTo(Visibility.PROTECTED); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - if (node.isProtected()) { - assertTrue(mask.covers(JavaOperationSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaOperationSignature.buildFor(node))); - } - } - } - - @Test - public void testOperationRoles() { - List nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST_OPERATIONS); - JavaOperationSigMask mask = new JavaOperationSigMask(); - mask.restrictRolesTo(Role.STATIC); - mask.coverAbstract(); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - if (node.isStatic()) { - assertTrue(mask.covers(JavaOperationSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaOperationSignature.buildFor(node))); - } - } - - mask.restrictRolesTo(Role.CONSTRUCTOR); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - if (node instanceof ASTConstructorDeclaration) { - assertTrue(mask.covers(JavaOperationSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaOperationSignature.buildFor(node))); - } - } - - mask.restrictRolesTo(Role.GETTER_OR_SETTER); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - if (node instanceof ASTMethodDeclaration - && ((ASTMethodDeclaration) node).getName().matches("(get|set).*")) { - assertTrue(mask.covers(JavaOperationSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaOperationSignature.buildFor(node))); - } - } - - mask.restrictRolesTo(Role.METHOD); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - if (node instanceof ASTMethodDeclaration - && !node.isStatic() - && !((ASTMethodDeclaration) node).getName().matches("(get|set).*")) { - assertTrue(mask.covers(JavaOperationSignature.buildFor(node))); - } else { - assertFalse(mask.covers(JavaOperationSignature.buildFor(node))); - } - } - - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/SignatureTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/SignatureTest.java deleted file mode 100644 index 0022641c44..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/SignatureTest.java +++ /dev/null @@ -1,270 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.metrics; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import net.sourceforge.pmd.lang.java.JavaParsingHelper; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; -import net.sourceforge.pmd.lang.java.metrics.testdata.GetterDetection; -import net.sourceforge.pmd.lang.java.metrics.testdata.SetterDetection; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSignature; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature.Role; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaSignature; -import net.sourceforge.pmd.lang.java.multifile.signature.JavaSignature.Visibility; -import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; - -/** - * Test class for {@link JavaSignature} and its subclasses. - * - * @author Clément Fournier - */ -public class SignatureTest extends BaseNonParserTest { - - // common to operation and field signatures - @Test - public void visibilityTest() { - final String TEST = "class Bzaz{ " - + "public int bar;" - + "String k;" - + "protected double d;" - + "private int i;" - + "protected int x;" - + "public Bzaz(){} " - + "void bar(){} " - + "protected void foo(int x){}" - + "private Bzaz(int y){}" - + "}"; - - - List operationDeclarations = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST); - List fieldDeclarations = getOrderedNodes(ASTFieldDeclaration.class, TEST); - List sigs = new ArrayList<>(); - - for (ASTMethodOrConstructorDeclaration node : operationDeclarations) { - sigs.add(JavaOperationSignature.buildFor(node)); - } - - // operations - assertEquals(Visibility.PUBLIC, sigs.get(0).visibility); - assertEquals(Visibility.PACKAGE, sigs.get(1).visibility); - assertEquals(Visibility.PROTECTED, sigs.get(2).visibility); - assertEquals(Visibility.PRIVATE, sigs.get(3).visibility); - - sigs.clear(); - for (ASTFieldDeclaration node : fieldDeclarations) { - sigs.add(JavaFieldSignature.buildFor(node)); - } - - // fields - assertEquals(Visibility.PUBLIC, sigs.get(0).visibility); - assertEquals(Visibility.PACKAGE, sigs.get(1).visibility); - assertEquals(Visibility.PROTECTED, sigs.get(2).visibility); - assertEquals(Visibility.PRIVATE, sigs.get(3).visibility); - } - - @Test - public void operationRoleTest() { - final String TEST = "class Bzaz{ int x; " - + "public static void foo(){} " - + "Bzaz(){} " - + "int getX(){return x;}" - + " void setX(int a){x=a;}" - + " public void doSomething(){}}"; - - - List nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST); - List sigs = new ArrayList<>(); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - sigs.add(JavaOperationSignature.buildFor(node)); - } - - assertEquals(Role.STATIC, sigs.get(0).role); - assertEquals(Role.CONSTRUCTOR, sigs.get(1).role); - assertEquals(Role.GETTER_OR_SETTER, sigs.get(2).role); - assertEquals(Role.GETTER_OR_SETTER, sigs.get(3).role); - assertEquals(Role.METHOD, sigs.get(4).role); - } - - @Test - public void testGetterDetection() { - ASTCompilationUnit compilationUnit = JavaParsingHelper.WITH_PROCESSING.parseClass(GetterDetection.class); - - compilationUnit.jjtAccept(new JavaParserVisitorAdapter() { - @Override - public Object visit(ASTMethodDeclaration node, Object data) { - assertEquals(Role.GETTER_OR_SETTER, Role.get(node)); - return data; - } - }, null); - } - - @Test - public void testSetterDetection() { - ASTCompilationUnit compilationUnit = JavaParsingHelper.WITH_PROCESSING.parseClass(SetterDetection.class); - - compilationUnit.jjtAccept(new JavaParserVisitorAdapter() { - @Override - public Object visit(ASTMethodDeclaration node, Object data) { - assertEquals(Role.GETTER_OR_SETTER, Role.get(node)); - return data; - } - }, null); - } - - - @Test - public void isAbstractOperationTest() { - final String TEST = "abstract class Bzaz{ int x; " - + "public static abstract void foo();" - + "protected abstract int bar(int x);" - + "int getX(){return x;}" - + "void setX(int a){x=a;}" - + "public void doSomething(){}}"; - - - List nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST); - List sigs = new ArrayList<>(); - - for (ASTMethodOrConstructorDeclaration node : nodes) { - sigs.add(JavaOperationSignature.buildFor(node)); - } - - - assertTrue(sigs.get(0).isAbstract); - assertTrue(sigs.get(1).isAbstract); - assertFalse(sigs.get(2).isAbstract); - assertFalse(sigs.get(3).isAbstract); - assertFalse(sigs.get(4).isAbstract); - } - - @Test - public void isFinalFieldTest() { - final String TEST = "class Bzaz{" - + "public String x;" - + "private int y;" - + "private final int a;" - + "protected final double u;" - + "final long v;" - + "}"; - - List nodes = getOrderedNodes(ASTFieldDeclaration.class, TEST); - List sigs = new ArrayList<>(); - - for (ASTFieldDeclaration node : nodes) { - sigs.add(JavaFieldSignature.buildFor(node)); - } - - assertFalse(sigs.get(0).isFinal); - assertFalse(sigs.get(1).isFinal); - assertTrue(sigs.get(2).isFinal); - assertTrue(sigs.get(3).isFinal); - assertTrue(sigs.get(4).isFinal); - } - - @Test - public void isStaticFieldTest() { - final String TEST = "class Bzaz{" - + "public final String x;" - + "private int y;" - + "private static int a;" - + "protected static final double u;" - + "static long v;" - + "}"; - - List nodes = getOrderedNodes(ASTFieldDeclaration.class, TEST); - List sigs = new ArrayList<>(); - - for (ASTFieldDeclaration node : nodes) { - sigs.add(JavaFieldSignature.buildFor(node)); - } - - assertFalse(sigs.get(0).isStatic); - assertFalse(sigs.get(1).isStatic); - assertTrue(sigs.get(2).isStatic); - assertTrue(sigs.get(3).isStatic); - assertTrue(sigs.get(4).isStatic); - } - - // Ensure only one instance of a signature is created. - @Test - public void operationPoolTest() { - final String TEST = "class Bzaz{ " - + "public static void foo(){} " - + "public static void az(){} " - + "public static int getX(){return x;}}"; - - final String TEST2 = "class Bzaz{ " - + "void foo(){} " - + "void az(){} " - + "int rand(){return x;}}"; - - - List nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST); - List nodes2 = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST2); - - List sigs = new ArrayList<>(); - List sigs2 = new ArrayList<>(); - - for (int i = 0; i < sigs.size(); i++) { - sigs.add(JavaOperationSignature.buildFor(nodes.get(i))); - sigs2.add(JavaOperationSignature.buildFor(nodes2.get(i))); - - } - - for (int i = 0; i < sigs.size() - 1; i++) { - assertTrue(sigs.get(i) == sigs.get(i + 1)); - assertTrue(sigs2.get(i) == sigs2.get(i + 1)); - } - } - - // Ensure only one instance of a signature is created. - @Test - public void fieldPoolTest() { - final String TEST = "class Bzaz {" - + "public int bar;" - + "public String k;" - + "public double d;" - + "}"; - - final String TEST2 = "class Foo {" - + "private final int i;" - + "private final int x;" - + "private final String k;" - + "}"; - - - List nodes = getOrderedNodes(ASTFieldDeclaration.class, TEST); - List nodes2 = getOrderedNodes(ASTFieldDeclaration.class, TEST2); - - List sigs = new ArrayList<>(); - List sigs2 = new ArrayList<>(); - - for (int i = 0; i < nodes.size(); i++) { - sigs.add(JavaFieldSignature.buildFor(nodes.get(i))); - sigs2.add(JavaFieldSignature.buildFor(nodes2.get(i))); - - } - - for (int i = 0; i < nodes.size() - 1; i++) { - assertTrue(sigs.get(i) == sigs.get(i + 1)); - assertTrue(sigs2.get(i) == sigs2.get(i + 1)); - } - } - -} From b5f2e3a2485b61514dde3a2c27626cfbe4dd341c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 3 Dec 2020 12:29:35 +0100 Subject: [PATCH 037/101] Cleanups --- .ci/files/all-java.xml | 2 +- .../java/metrics/internal/ClassFanOutVisitor.java | 14 +++++++------- ...moizerTest.java => MetricsMemoizationTest.java} | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) rename pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/{ProjectMemoizerTest.java => MetricsMemoizationTest.java} (97%) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 865df43955..0469c94133 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -142,7 +142,7 @@ - + diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutVisitor.java index 25aad2f2bb..3ee69e4b09 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/ClassFanOutVisitor.java @@ -12,7 +12,8 @@ import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.ClassFanOutOption; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; -import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol; +import net.sourceforge.pmd.lang.java.types.JClassType; +import net.sourceforge.pmd.lang.java.types.JTypeMirror; import net.sourceforge.pmd.lang.metrics.MetricOptions; @@ -53,14 +54,13 @@ public final class ClassFanOutVisitor extends JavaVisitorBase, } private void check(TypeNode node, Set classes) { - JTypeDeclSymbol symbol = node.getTypeMirror().getSymbol(); - if (!(symbol instanceof JClassSymbol) - || ((JClassSymbol) symbol).isPrimitive() - || ((JClassSymbol) symbol).isArray()) { + JTypeMirror typeMirror = node.getTypeMirror(); + if (!(typeMirror instanceof JClassType)) { return; } - if (shouldBeIncluded((JClassSymbol) symbol)) { - classes.add((JClassSymbol) symbol); + JClassSymbol symbol = ((JClassType) typeMirror).getSymbol(); + if (shouldBeIncluded(symbol)) { + classes.add(symbol); } } 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/MetricsMemoizationTest.java similarity index 97% rename from pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/ProjectMemoizerTest.java rename to pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/MetricsMemoizationTest.java index 2e8a976930..8000b1952c 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/MetricsMemoizationTest.java @@ -28,7 +28,7 @@ import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** * @author Clément Fournier */ -public class ProjectMemoizerTest extends BaseNonParserTest { +public class MetricsMemoizationTest extends BaseNonParserTest { private final Metric randomMetric = randomMetric(); From a37cabf9bccc4c835b1ba83864c6bebc04b6f3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 10 Dec 2020 21:54:53 +0100 Subject: [PATCH 038/101] Update docs --- docs/_data/xpath_funs.yml | 16 +- .../pmd/userdocs/extending/metrics_howto.md | 284 +----------------- .../sourceforge/pmd/lang/metrics/Metric.java | 34 ++- .../pmd/lang/java/metrics/JavaMetrics.java | 17 +- .../rule/xpath/internal/MetricFunction.java | 4 - 5 files changed, 59 insertions(+), 296 deletions(-) diff --git a/docs/_data/xpath_funs.yml b/docs/_data/xpath_funs.yml index c4f7f4c87c..b2a7beb5f5 100644 --- a/docs/_data/xpath_funs.yml +++ b/docs/_data/xpath_funs.yml @@ -65,12 +65,22 @@ langs: - name: metric returnType: "xs:decimal?" shortDescription: "Computes and returns the value of a metric" - description: "Returns the value of the metric as evaluated on the context node" - notes: "The context node must be a {% jdoc jast::ASTAnyTypeDeclaration %} or a {% jdoc jast::MethodLikeNode %}" + description: + Returns the value of the metric as evaluated on the context node. + If the metric cannot be computed on that node, returns an empty sequence + (which is falsy). + parameters: - name: "metricKey" type: "xs:string" - description: "The name of an enum constant in {% jdoc jmx::api.JavaOperationMetricKey %} or {% jdoc jmx::api.JavaClassMetricKey %}" + description: "The name of a metric in {% jdoc jmx::JavaMetrics %} (or an alias thereof)." + examples: + - code: "//ClassOrInterfaceDeclaration[metric('NCSS') > 200]" + outcome: "" + - code: "//MethodDeclaration[metric('CYCLO') > 10 and metric('NCSS') > 20]" + outcome: "" + - code: "//TypeParameter[metric('idontexist') > 50]" + outcome: "Error: no such metric" - name: hasAnnotation returnType: "xs:boolean" diff --git a/docs/pages/pmd/userdocs/extending/metrics_howto.md b/docs/pages/pmd/userdocs/extending/metrics_howto.md index 80ae0cf516..cb8f776424 100644 --- a/docs/pages/pmd/userdocs/extending/metrics_howto.md +++ b/docs/pages/pmd/userdocs/extending/metrics_howto.md @@ -15,287 +15,11 @@ author: Clément Fournier {% jdoc_nspace :jast java::lang.java.ast %} -## Using the metrics framework +In PMD's Metrics framework, a metric `Metric` is an operation that can be carried out on nodes of a certain type `N` and produces +a numeric result of type `R`. -{%include note.html content="The following explains how to use the Java metrics framework. The Apex framework -differs only by the name of its classes." %} - -In PMD's Metrics framework, a metric is an operation that can be carried out on nodes of a certain type and produces -a numeric result. In the Java framework, metrics can be computed on operation declaration nodes (constructor and -method declaration), and type declaration nodes (class, interface, enum, and annotation declarations). A metric -object in the framework can only handle either types or operations, but not both. - -PMD ships with a library of already implemented metrics. These metrics are referenced by {% jdoc coremx::MetricKey %} objects, -which are listed in two public enums: {% jdoc jmx::api.JavaClassMetricKey %} and {% jdoc jmx::api.JavaOperationMetricKey %}. -Metric keys wrap a metric, and know which type of node their metric can be computed on. That way, you cannot compute an operation metric on a class -declaration node. Metrics that can be computed on both operation and type declarations (e.g. NCSS) have one metric key in -each enum. - -## For XPath rules - -XPath rules can compute metrics using the `metric` function. This function takes a single **string argument**, -which is the name of the metric key as defined in `JavaClassMetricKey` or `JavaOperationMetricKey`. The metric - will be **computed on the context node**. - -The function will throw an exception in the following cases: -* The context node is neither an instance of {% jdoc jast::ASTAnyTypeDeclaration %} or {% jdoc jast::MethodLikeNode %}, that is, -it's not one of {% jdoc jast::ASTClassOrInterfaceDeclaration %}, {% jdoc jast::ASTEnumDeclaration}, -{% jdoc jast::ASTAnnotationDeclaration %}, {% jdoc jast::ASTMethodDeclaration %}, -{% jdoc jast::ASTConstructorDeclaration %}, or {% jdoc jast::ASTLambdaExpression %}. -* The metric key does not exist (the name is case insensitive) or is not defined for the type of the context node. - -{%include note.html - content="More advanced features of the API are not accessible yet, but may be supported in the future. - The API is thus subject to change." %} - -### Examples - -* `//ClassOrInterfaceDeclaration[metric('NCSS') > 200]` -* `//MethodDeclaration[metric('CYCLO') > 10 and metric('NCSS') > 20]` -* `//ClassOrInterfaceDeclaration[metric('CYCLO') > 50]`: IllegalArgumentException! - CYCLO's only defined for methods and constructors. - -## For Java Rules - -The static façade class {% jdoc jmx::JavaMetrics %} is the single entry point to compute metrics in the Java framework. - -This class provides the method `get` and its overloads. The following sections describes the interface of this class. - -### Basic usage - -The simplest overloads of `JavaMetrics.get` take two parameters: **a `MetricKey` and a node of the corresponding type.** -Say you want to write a rule to report methods that have a high cyclomatic complexity. In your rule's visitor, you -can get the value of Cyclo for a method node like so: -```java -public Object visit(ASTMethodDeclaration method, Object data) { - int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method); - if (cyclo > 10) { - // add violation - } - return data; -} -``` - -The same goes for class metrics: you select one among `JavaClassMetricKey`'s constants and pass it along with the node -to `JavaMetrics.get`. - -{%include tip.html - content="A specific base rule class (`AbstractJavaMetricsRule`) exists - to e.g. check constructors and method nodes completely alike. This comes - in handy for metrics, as they usually don't make the distinction" %} - -### Capability checking - -Metrics are not necessarily computable on any node of the type they handle. For example, Cyclo cannot be computed on -abstract methods. Metric keys provides a {% jdoc !a!coremx::MetricKey#supports(coreast::Node) %} boolean method -to find out if the metric can be computed on -the specified node. **If the metric cannot be computed on the given node, `JavaMetrics.get` will return `Double.NaN` .** -If you're concerned about that, you can condition your call on whether the node is supported or not: -```java -public Object visit(ASTMethodDeclaration method, Object data) { - if (JavaOperationMetricKey.CYCLO.supports(node)) { - int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method); - if (cyclo > 10) { - // add violation - } - return data; - } -} -``` - -### Metric options - -Some metrics define options that can be used to slightly modify the computation. You'll typically see these options -gathered inside an enum in the implementation class of the metric, for example `CycloMetric.CycloOption`. They're -also documented on the [index of metrics](pmd_java_metrics_index.html). - -To use options with a metric, you must first bundle them into a {% jdoc coremx::MetricOptions %} object. `MetricOptions` provides the -utility method `ofOptions` to get a `MetricOptions` bundle from a collection or with varargs parameters. You can then -pass this bundle as a parameter to `JavaMetrics.get`: -```java -public Object visit(ASTMethodDeclaration method, Object data) { - int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method, - MetricOptions.ofOptions(CycloOptions.IGNORE_BOOLEAN_PATHS)); - if (cyclo > 10) { - // add violation - } - return data; -} -``` - -The version of `MetricOptions.ofOptions` using a collection is useful when you're building a `MetricOptions` from eg -the value of an `EnumeratedMultiProperty`, which gives users control of the options they use. See -[CyclomaticComplexityRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java#L35) -for an example usage. - -### Result options - -The Metrics API also gives you the possibility to aggregate the result of an operation metric on all operations of a -class very simply. You can for example get the highest value of the metric over a class that way: -```java -public Object visit(ASTClassOrInterfaceDeclaration clazz, Object data) { - int highest = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, clazz, - ResultOption.HIGHEST); - if (highest > 10) { - // add violation - } - return data; -} -``` - -Notice that **we use an operation metric and a class node**. The `ResultOption` parameter controls what result will be -computed: you can choose among `HIGHEST`, `SUM` and `AVERAGE`. You can use metric options together with a result -option too. - -### Complete use case - -The following is a sample code for a rule reporting methods with a cyclomatic -complexity over 10 and classes with a total cyclo over 50. A metric option can be -user-configured with a rule property. More complete examples can be found in -[CyclomaticComplexityRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java#L35), -[NcssCountRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java#L30), -or [GodClassRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java#L24). - - -```java -public class CycloRule extends AbstractJavaMetricsRule { - - public static final BooleanProperty COUNT_BOOLEAN_PATHS - = BooleanProperty.named("countBooleanPaths") - .desc("Count boolean paths") - .defaultValue(true).build(); - - private static final MetricOptions options; - - public CycloRule() { - definePropertyDescriptor(COUNT_BOOLEAN_PATHS); - } - - @Override - public Object visit(ASTCompilationUnit node, Object data) { - options = getProperty(COUNT_BOOLEAN_PATHS) - ? MetricOptions.ofOptions(CycloOptions.IGNORE_BOOLEAN_PATHS) - : MetricOptions.emptyOptions(); - } - - @Override - public Object visit(ASTAnyTypeDeclaration clazz, Object data) { - int total = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, clazz, - options, ResultOption.SUM); - - if (total > 50) { - // add violation - } - - return data; - } - - @Override - public Object visit(ASTMethodDeclaration method, Object data) { - int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, method, - options); - if (cyclo > 10) { // this is safe if the node is not supported, as (Double.NaN > 10) == false - // add violation - } - return data; - } -} -``` - -## Available metrics - -There are already many metrics ready to use. We maintain the following documentation -pages to describe them all, including their usage and options: +PMD ships with a library of "standard" metrics. Like cyclomatic complexity measures. These are documented in the following pages: * [Java metrics](pmd_java_metrics_index.html) * [Apex metrics](pmd_apex_metrics_index.html) - -## Writing custom metrics - -You can use the framework to customize the existing metrics at will, or define -new ones quite easily. Here's some info to get you started. Again, the examples are for -the Java framework but it's symmetrical in the Apex framework. - -### The really short guide - -1. Determine whether your metric is an operation metric or a class metric and - **extend the correct base class** ({% jdoc jmx::AbstractJavaClassMetric %} or - {% jdoc jmx::AbstractJavaOperationMetric %}) -1. You're immediately prompted by your IDE to **implement the `computeFor` method**. - This method takes a node of the type you want to handle, a bundle of options, - and returns the result of the metric. -1. Optionally specify a predicate to check if a node can be handled by **overriding - the `supports` method**. -1. Optionally define options (implementing [`MetricOption`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOption.java)) - and handle them as you see fit in your `computeFor` method -1. **Create a metric key** using `MetricKeyUtil`'s `of` method, specifying a name - for your metric and an instance of your metric. You're done and can use your - metric key as if it were a standard one. - -### Best practices - -* **Metrics should be stateless**. In any case, instances of the same metric class - are considered `equals`. The same instance of your metric will be used to - compute the metric on the AST of different nodes so it should really be - "functionally pure". That rule also makes you keep it simple and understandable - which is nice. -* **Implementation patterns:** You can implement your `computeFor` method as you - like it. But most metrics in our library are implemented following a few - patterns you may want to look at: - * *Visitor metrics:* Those metrics use one or more AST visitor to compute their - value. That's especially good to implement metrics that count some kind of node, - e.g. [NPath complexity](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathMetric.java) - or [NCSS](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NcssMetric.java). - Additionally, it makes your metric more easily generalisable to other node types. - - * *Signature matching metrics:* That's even more straightforward when you want - to count the number of methods or fields that match a specific signature, e.g. - public static final fields. Basically a signature is an object that describes - a field or method, with info about its modifers and other node-specific info. - `AbstractJavaClassMetric` has a few methods that allow you to count signatures - directly, see e.g. the metrics [NOPA](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NopaMetric.java) - and [WOC](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/WocMetric.java). - - -### Capability checking - -You may have noticed that when you extend e.g. `AbstractJavaClassMetric`, the -`computeFor` method you're prompted to implement takes a node of type -`ASTAnyTypeDeclaration` as a parameter. That's not a concrete node type, but -an interface, implemented by several concrete node types. Basically that's done -so that class metrics are given the ability to be computed on any type -declaration, and operation metrics on constructors and methods. Here are the -concrete node types you can target with class and operation metrics, by language: - - -Language | Java | Apex | ------------|------|------| -Operation declaration|`ASTMethodOrConstructorDeclaration`
>: `ASTMethodDeclaration`, `ASTConstructorDeclaration`| `ASTMethod`* -Type declaration|`ASTAnyTypeDeclaration` >: `ASTEnumDeclaration`,
`ASTAnnotationDeclaration`, `ASTClassOrInterfaceDeclaration`| `ASTUserClassOrInterface` >: `ASTUserClass`, `ASTUserInterface` - -*Apex method metrics are also applied to triggers by default (see [#771](https://github.com/pmd/pmd/pull/771)). Finer capability checking is not available out of the box for now. - -What if you don't want such a generalisation? The `supports` method lets you -define a predicate to check that the node is supported by your metric. For example, -if your metric can only be computed on classes, you may override the default behaviour -like so: -```java -@Override -public boolean supports(ASTAnyTypeDeclaration node) { - return node.getTypeKind() == TypeKind.CLASS; -} -``` - -{%include tip.html - content="You can be sure that if your `supports` method returns `false` on a node, then - that node will never be passed as a parameter to `computeFor`. That allows you - to write your `computeFor` method without worrying about unsupported nodes." %} - -The `supports` method already has a default implementation in the abstract base -classes. Here's the default behaviour by language and type of metric: - -Language | Java | Apex | ------------|------|------| -Operation metrics| supports constructors and non abstract methods| supports any non abstract method (including triggers), except ``, ``, and `clone` -Type declaration|supports classes and enums|supports classes - +Usage and implementation documentation may be found in our Javadocs: {% jdoc coremx::Metric %} and {% jdoc coremx::MetricsUtil %}. In the Java module, XPath rules may additionally use the [pmd-java:metric](pmd_userdocs_extending_writing_xpath_rules.html#pmd-java-metric) function. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java index 3f9888b38e..d37c0f256e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java @@ -19,7 +19,29 @@ import net.sourceforge.pmd.util.DataMap.DataKey; /** * A named computation that can be carried out on some nodes. Example - * include complexity metrics. + * include complexity metrics, like cyclomatic complexity. + * + *

Use with {@link MetricsUtil}, for example, in the Java module: + *

{@code
+ *   if (JavaMetrics.CYCLO.supports(node)) {
+ *     int cyclo = MetricsUtil.computeMetric(JavaMetrics.CYCLO, node);
+ *     ...
+ *   }
+ * }
+ * + *

Note that the {@code supports} check is necessary (metrics cannot + * necessarily be computed on any node of the type they support). + * + *

Metrics support a concept of {@linkplain MetricOption options}, + * which can be passed to {@link Metric#compute(Metric, MetricOptions, Node) compute} + * or {@link MetricsUtil#computeMetric(Metric, Node, MetricOptions)}. + * + *

Metric instances are stateless by contract. + * + *

To implement your own metrics, use the factory method {@link #of(BiFunction, Function, String, String...) of}. + * Be aware though, that you cannot register a custom metric into a + * {@link LanguageMetricsProvider}, which means your metric will not be + * available from XPath. * * @param Type of nodes the metric can be computed on * @param Result type of the metric @@ -86,10 +108,11 @@ public interface Metric extends DataKey Return type of the metric @@ -136,7 +159,8 @@ public interface Metric extends DataKey ACCESS_TO_FOREIGN_DATA = Metric.of(JavaMetrics::computeAtfd, isJavaNode(), "Access To Foreign Data", "ATFD"); - - + /** + * {@link Metric#of(BiFunction, Function, String, String...)} + */ public static final Metric WEIGHT_OF_CLASS = Metric.of(JavaMetrics::computeWoc, asClass(it -> !it.isInterface()), "Weight Of Class", "WOC"); @@ -237,7 +239,9 @@ public final class JavaMetrics { } - /** Variants of NCSS. */ + /** + * Options for {@link #NCSS}. + */ public enum NcssOption implements MetricOption { /** Counts import and package statement. This makes the metric JavaNCSS compliant. */ COUNT_IMPORTS("countImports"); @@ -257,7 +261,9 @@ public final class JavaMetrics { } - /** Options for CYCLO. */ + /** + * Options for {@link #CYCLO}. + */ public enum CycloOption implements MetricOption { /** Do not count the paths in boolean expressions as decision points. */ IGNORE_BOOLEAN_PATHS("ignoreBooleanPaths"), @@ -307,6 +313,9 @@ public final class JavaMetrics { } + /** + * Options for {@link #FAN_OUT}. + */ public enum ClassFanOutOption implements MetricOption { /** Whether to include Classes in the java.lang package. */ INCLUDE_JAVA_LANG("includeJavaLang"); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java index adb6de5293..271238902d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java @@ -79,10 +79,6 @@ public final class MetricFunction extends BaseJavaXPathFunction { } - static String genericBadNodeMessage() { - return "Incorrect node type: the 'metric' function cannot be applied"; - } - private static double getMetric(Node n, String metricKeyName) throws XPathException { Metric metric = METRICS.getMetricWithName(metricKeyName); if (metric == null) { From e29e2f97a940962476b324186c388b356fd11477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 10 Dec 2020 22:00:09 +0100 Subject: [PATCH 039/101] Move documentation from website into javadocs --- docs/_data/sidebars/pmd_sidebar.yml | 12 - .../adding_new_metrics_framework.md | 46 --- .../pages/pmd/languages/apex_metrics_index.md | 71 ---- .../pages/pmd/languages/java_metrics_index.md | 346 ------------------ .../pmd/userdocs/extending/metrics_howto.md | 25 -- .../pmd/lang/apex/metrics/ApexMetrics.java | 56 ++- .../pmd/lang/metrics/package-info.java | 12 +- .../pmd/lang/java/metrics/JavaMetrics.java | 266 ++++++++++++-- 8 files changed, 303 insertions(+), 531 deletions(-) delete mode 100644 docs/pages/pmd/devdocs/major_contributions/adding_new_metrics_framework.md delete mode 100644 docs/pages/pmd/languages/apex_metrics_index.md delete mode 100644 docs/pages/pmd/languages/java_metrics_index.md delete mode 100644 docs/pages/pmd/userdocs/extending/metrics_howto.md diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 2bd5c4f803..f85e460304 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -94,9 +94,6 @@ entries: - title: Defining rule properties url: /pmd_userdocs_extending_defining_properties.html output: web, pdf - - title: Using and defining code metrics - url: /pmd_userdocs_extending_metrics_howto.html - output: web, pdf - title: Rule guidelines url: /pmd_userdocs_extending_rule_guidelines.html output: web, pdf @@ -358,12 +355,6 @@ entries: - title: JSP Support url: /pmd_languages_jsp.html output: web, pdf - - title: Java code metrics - url: /pmd_java_metrics_index.html - output: web, pdf - - title: Apex code metrics - url: /pmd_apex_metrics_index.html - output: web, pdf - title: Developer Documentation output: web, pdf folderitems: @@ -403,9 +394,6 @@ entries: - title: Adding a new CPD language url: /pmd_devdocs_major_adding_new_cpd_language.html output: web, pdf - - title: Adding metrics support to a language - url: /pmd_devdocs_major_adding_new_metrics_framework.html - output: web, pdf - title: Experimental features output: web, pdf subfolderitems: diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_new_metrics_framework.md b/docs/pages/pmd/devdocs/major_contributions/adding_new_metrics_framework.md deleted file mode 100644 index 384efa8ea2..0000000000 --- a/docs/pages/pmd/devdocs/major_contributions/adding_new_metrics_framework.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Adding support for metrics to a language -short_title: Implement a metrics framework -tags: [devdocs, extending, metrics] -summary: "PMD's Java module has an extensive framework for the calculation of metrics, which allows rule developers -to implement and use new code metrics very simply. Most of the functionality of this framework is abstracted in such -a way that any PMD supported language can implement such a framework without too much trouble. Here's how." -last_updated: February 2020 -permalink: pmd_devdocs_major_adding_new_metrics_framework.html -author: Clément Fournier ---- - -## Internal architecture of the metrics framework - -The framework is pretty simple. On a high level, a `Metric` describes some numeric computation on a node of type `N`. -You should wrap it into a `MetricKey`, so that it can be cached on nodes (implemented by {%jdoc core::lang.metrics.MetricsUtil %}). - -At the very least, a metrics framework has those two components and is just a convenient way to compute and memoize -metrics on a single file. The expressive power of metrics can be improved by implementing *signature matching* capabilities, -which allows a metric to count signatures matching a specific pattern (a mask) over a whole class. This was originally -designed to work across files, given a working usage resolution. However, making that work with incremental analysis is -harder than it looks, and has been rescheduled to another project. - -## Implementation of a new framework - -* Implement metrics (typically in an internal package) -* Create some public enums/ utility classes to expose metric keys -* Implement a {%jdoc core::lang.metrics.LanguageMetricsProvider %}, to expose your metrics to the designer -* Use your metric keys in rules with {%jdoc core::lang.metrics.MetricsUtil %} - -### Optional: Signature matching - -You can match the signature of anything: method, field, class, package... It depends on what's useful for you. -Suppose you want to be able to match signatures for nodes of type `N`. What you have to do then is the following: - -* Create a class implementing the interface `Signature`. Signatures describe basic information about the node, -which typically includes most of the modifiers they declare (eg visibility, abstract or virtual, etc.). -It's up to you to define the right level of detail, depending on the accuracy of the pattern matching required. -* Make type `N` implement `SignedNode`. This makes the node capable of giving its signature. Factory methods to -build a `Signature` from a `N` are a good idea. -* Create signature masks. A mask is an object that matches some signatures based on their features. For example, with - the Java framework, you can build a `JavaOperationSigMask` that matches all method signatures with visibility - `public`. A sigmask implements `SigMask`, where `S` is the type of signature your mask handles. -* Create utility methods in your abstract class metric class to count signatures matching a specific mask. -[Example](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractJavaClassMetric.java#L52) - diff --git a/docs/pages/pmd/languages/apex_metrics_index.md b/docs/pages/pmd/languages/apex_metrics_index.md deleted file mode 100644 index 6b0b62bf7b..0000000000 --- a/docs/pages/pmd/languages/apex_metrics_index.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: Index of Apex code metrics -tags: [extending, metrics] -summary: "Index of the code metrics available out of the box to Apex rule developers." -last_updated: July 20, 2017 -permalink: pmd_apex_metrics_index.html -toc: - minimumHeaders: 8 ---- -# Index of code metrics - -## Cyclomatic Complexity (CYCLO) - -*Operation metric.* Can be calculated on any non-abstract operation. - -### Description - -Number of independent paths through a block of code \[[Lanza05](#Lanza05)\]. -Formally, given that the control flow graph of the block has `n` vertices, `e` -edges and `p` connected components, the cyclomatic complexity of the block is -given by `CYCLO = e - n + 2p` \[[McCabe76](#McCabe76)\]. In practice it can be -calculated by counting control flow statements following the standard rules given -below. - -The standard version of the metric complies with McCabe's original definition: - -* Methods have a base complexity of 1. -* +1 for every control flow statement (`if`, `catch`, `throw`, `do`, - `while`, `for`, `break`, `continue`) and conditional expression (`?:`). -* `else`, `finally` and `default` don't count; -* +1 for every boolean operator (`&&`, `||`) in the guard condition of a control - flow statement. - -### Code examples - -```java -class Foo { - void baseCyclo() { // Cyclo = 1 - highCyclo(); - } - - void highCyclo() { // Cyclo = 10 - int x = 0, y = 2; - boolean a = false, b = true; - - if (a && (y == 1 ? b : true)) { // +3 - if (y == x) { // +1 - while (true) { // +1 - if (x++ < 20) { // +1 - break; // +1 - } - } - } else if (y == t && !d) { // +2 - x = a ? y : x; // +1 - } else { - x = 2; - } - } - } -} -``` - -## Weighted Method Count (WMC) - -*Class metric.* Can be computed on classes and enums. - -# References - -Lanza05: Lanza, Marinescu; Object-Oriented Metrics in Practice, 2005. - -McCabe76: McCabe, A Complexity Measure, in Proceedings of the 2nd ICSE (1976). diff --git a/docs/pages/pmd/languages/java_metrics_index.md b/docs/pages/pmd/languages/java_metrics_index.md deleted file mode 100644 index f2dad16f17..0000000000 --- a/docs/pages/pmd/languages/java_metrics_index.md +++ /dev/null @@ -1,346 +0,0 @@ ---- -title: Index of Java code metrics -tags: [extending, metrics] -summary: "Index of the code metrics available out of the box to Java rule developers." -last_updated: July 20, 2017 -permalink: pmd_java_metrics_index.html -toc: - minimumHeaders: 8 ---- -# Index of code metrics - -## Access to Foreign Data (ATFD) - -*Operation metric, class metric.* Can be computed on classes, enums and -concrete operations. - -### Description - -Number of usages of foreign attributes, both directly and through accessors. -High values of ATFD (> 3 for an operation) may suggest that the class or operation -breaks encapsulation by relying on the internal representation of the classes -it uses instead of the services they provide. - -ATFD can be used to detect God Classes and Feature Envy. \[[Lanza05](#Lanza05)\] - -## Class Fan Out Complexity (CLASS_FAN_OUT) - -*Operation metric, class metric.* Can be computed on classes, enums and -concrete operations. - -### Description -This counts the number of other classes a given class or operation relies on. -Classes from the package `java.lang` are ignored by default (can be changed via options). -Also primitives are not included into the count. - -### Code example - -```java -import java.util.*; -import java.io.IOException; - -public class Foo { // total 8 - public Set set = new HashSet(); // +2 - public Map map = new HashMap(); // +2 - public String string = ""; // from java.lang -> does not count by default - public Double number = 0.0; // from java.lang -> does not count by default - public int[] intArray = new int[3]; // primitive -> does not count - - @Deprecated // from java.lang -> does not count by default - @Override // from java.lang -> does not count by default - public void foo(List list) throws Exception { // +1 (Exception is from java.lang) - throw new IOException(); // +1 - } - - public int getMapSize() { - return map.size(); // +1 because it uses the Class from the 'map' field - } -} -``` - -### Options - -* Option `includeJavaLang`: Also include classes from the package `java.lang` - -## Cyclomatic Complexity (CYCLO) - -*Operation metric.* Can be calculated on any non-abstract operation. - -### Description - -Number of independent paths through a block of code \[[Lanza05](#Lanza05)\]. -Formally, given that the control flow graph of the block has `n` vertices, `e` -edges and `p` connected components, the cyclomatic complexity of the block is -given by `CYCLO = e - n + 2p` \[[McCabe76](#McCabe76)\]. In practice it can be -calculated by counting control flow statements following the standard rules given -below. - -The standard version of the metric complies with McCabe's original definition: - -* Methods have a base complexity of 1. -* +1 for every control flow statement (`if`, `case`, `catch`, `throw`, `do`, - `while`, `for`, `break`, `continue`) and conditional expression (`?:`) - \[[Sonarqube](#Sonarqube)\]. Notice switch cases count as one, but not the - switch itself: the point is that a switch should have the same complexity - value as the equivalent series of `if` statements. -* `else`, `finally` and `default` don't count; -* +1 for every boolean operator (`&&`, `||`) in the guard condition of a control - flow statement. That's because Java has short-circuit evaluation semantics for - boolean operators, which makes every boolean operator kind of a control flow - statement in itself. - -### Code examples - -```java -class Foo { - void baseCyclo() { // Cyclo = 1 - highCyclo(); - } - - void highCyclo() { // Cyclo = 10 - int x = 0, y = 2; - boolean a = false, b = true; - - if (a && (y == 1 ? b : true)) { // +3 - if (y == x) { // +1 - while (true) { // +1 - if (x++ < 20) { // +1 - break; // +1 - } - } - } else if (y == t && !d) { // +2 - x = a ? y : x; // +1 - } else { - x = 2; - } - } - } -} -``` -### Options - -* Option `CycloVersion#IGNORE_BOOLEAN_PATHS`: Boolean operators are not counted, - nor are empty fall-through cases in `switch` statements. You can use this - option to get results similar to those of the old `StdCyclomaticComplexityRule`, - which is to be replaced. -* Option `CycloVersion#CONSIDER_ASSERTS`: Assert statements are counted as if - they were `if (..) throw new AssertionError(..)`. Compatible with - `IGNORE_BOOLEAN_PATHS`. - -## Lines of Code (LoC) - -*Operation metric, class metric.* Can be calculated on any of those nodes. - -### Description - -Simply counts the number of lines of code the operation or class takes up in -the source. This metric doesn't discount comments or blank lines. See also -[NCSS](#non-commenting-source-statements-ncss). - - -## Non-commenting source statements (NCSS) - -*Operation metric, class metric.* Can be calculated on any of those nodes. - -### Description - -Number of statements in a class or operation. That's roughly equivalent to -counting the number of semicolons and opening braces in the program. Comments -and blank lines are ignored, and statements spread on multiple lines count as -only one (e.g. `int\n a;` counts a single statement). - -The standard version of the metric is based off JavaNCSS's version -\[[JavaNcss](#JavaNcss)\]: - -* +1 for any of the following statements: `if`, `else`, `while`, `do`, `for`, - `switch`, `break`, `continue`, `return`, `throw`, `synchronized`, `catch`, - `finally`. -* +1 for each assignment, variable declaration (except `for` loop initializers) - or statement expression. We count variables declared on the same line (e.g. - `int a, b, c;`) as a single statement. -* Contrary to Sonarqube, but as JavaNCSS, we count type declarations (class, - interface, enum, annotation), and method and field declarations - \[[Sonarqube](#Sonarqube)\]. -* Contrary to JavaNCSS, but as Sonarqube, we do not count package declaration - and import declarations as statements. This makes it easier to compare nested - classes to outer classes. Besides, it makes for class metric results that - actually represent the size of the class and not of the file. If you don't - like that behaviour, use the `COUNT_IMPORTS` option. - -### Code example -```java -import java.util.Collections; // +0 -import java.io.IOException; // +0 - -class Foo { // +1, total Ncss = 12 - - public void bigMethod() // +1 - throws IOException { - int x = 0, y = 2; // +1 - boolean a = false, b = true; // +1 - - if (a || b) { // +1 - try { // +1 - do { // +1 - x += 2; // +1 - } while (x < 12); - - System.exit(0); // +1 - } catch (IOException ioe) { // +1 - throw new PatheticFailException(ioe); // +1 - } - } else { - assert false; // +1 - } - } -} -``` - - -### Options - -* Option `NcssVersion#COUNT_IMPORTS`: Import and package statements are counted - as well. This version fully complies with JavaNCSS. - -## NPath complexity (NPath) - -*Operation metric.* Can be computed on any non-abstract operation. - -### Description - -Number of acyclic execution paths through a piece of code. This is related to -cyclomatic complexity, but the two metrics don't count the same thing: NPath -counts the number of distinct *full* paths from the beginning to the end of the -method, while Cyclo only counts the number of decision points. NPath is not -computed as simply as Cyclo. With NPath, two decision points appearing sequentially -have their complexity multiplied. - -The fact that NPath multiplies the complexity of statements makes it grow -exponentially: 10 `if` - `else` statements in a row would give an NPath of 1024, -while Cyclo would evaluate to 20. Methods with an NPath complexity over 200 are -generally considered too complex. - -We compute NPath recursively, with the following set of rules: -* An empty block has a complexity of 1. -* The complexity of a block is the product of the NPath complexity of its - statements, calculated as follows: - * The complexity of `for`, `do` and `while` statements is 1, plus the - complexity of the block, plus the complexity of the guard condition. - * The complexity of a cascading `if` statement (`if .. else if ..`) is the - number of `if` statements in the chain, plus the complexity of their guard - condition, plus the complexity of the unguarded `else` block (or 1 if there - is none). - * The complexity of a `switch` statement is the number of cases, plus the - complexity of each `case` block. It's equivalent to the complexity of the - equivalent cascade of `if` statements. - * The complexity of a ternary expression (`?:`) is the complexity of the guard - condition, plus the complexity of both expressions. It's equivalent to the - complexity of the equivalent `if .. else` construct. - * The complexity of a `try .. catch` statement is the complexity of the `try` - block, plus the complexity of each catch block. - * The complexity of a `return` statement is the complexity of the expression - (or 1 if there is none). - * All other statements have a complexity of 1 and are discarded from the product. - -### Code example - -```java -void fun(boolean a, boolean b, boolean c) { // NPath = 6 - - // block #0 - - if (a) { - // block #1 - } else { - // block #2 - } - - // block #3 - - if (b) { - // block #4 - } else if (c) { - // block #5 - } - - // block #6 -} -``` -After block 0, the control flow can either execute block 1 or 2 before jumping -to block 3. From block three, the control flow will again have the choice -between blocks 4 and 5 before jumping to block 6. The first `if` offers 2 -choices, the second offers 3, so the cyclomatic complexity of this method is -2 + 3 = 5. NPath, however, sees 2 * 3 = 6 full paths from the beginning to the end. - - -## Number Of Public Attributes (NOPA) -*Class metric.* Can be computed on classes. - -## Number Of Accessor Methods (NOAM) -*Class metric.* Can be computed on classes. - -## Tight Class Cohesion (TCC) - -*Class metric.* Can be computed on classes and enums. - -### Description - -The relative number of method pairs of a class that access in common at -least one attribute of the measured class. TCC only counts -direct attribute accesses, that is, only those attributes that are accessed in -the body of the method \[[BK95](#BK95)\]. - -TCC is taken to be a reliable cohesion metric for a class. High values (>70%) -indicate a class with one basic function, which is hard to break into subcomponents. -On the other hand, low values (<50%) may indicate that the class tries to do too much and -defines several unrelated services, which is undesirable. - -TCC can be used to detect God Classes and Brain Classes \[[Lanza05](#Lanza05)\]. - -## Weighted Method Count (WMC) - -*Class metric.* Can be computed on classes and enums. - -### Description - -Sum of the statistical complexity of the operations in the class. We use -[CYCLO](#cyclomatic-complexity-cyclo) to quantify the complexity of an operation -\[[Lanza05](#Lanza05)\]. - -### Options - -WMC uses the same options as CYCLO, which are provided to CYCLO when -computing it. - -## Weight Of Class (WOC) - -*Class metric.* Can be computed on classes. - -### Description - -Number of "functional" public methods divided by the total number of -public methods. Our definition of "functional method" excludes -constructors, getters, and setters. - -This metric tries to quantify whether the measured class' interface reveals -more data than behaviour. Low values (less than 30%) indicate that the class -reveals much more data than behaviour, which is a sign of poor encapsulation. - -This metric is used to detect Data Classes, in conjunction with [WMC](#weighted-method-count-wmc), -[NOPA](#number-of-public-attributes-nopa) and [NOAM](#number-of-accessor-methods-noam). - - - -# References - - -BK95: Bieman, Kang; Cohesion and reuse in an object-oriented system. -In Proceedings ACM Symposium on Software Reusability, 1995. - -Lanza05: Lanza, Marinescu; Object-Oriented Metrics in Practice, 2005. - -McCabe76: McCabe, A Complexity Measure, in Proceedings of the 2nd ICSE (1976). - -Sonarqube: [Sonarqube online documentation.](https://docs.sonarqube.org/display/SONAR/Metric+Definitions) - -JavaNcss: [JavaNCSS online documentation.](http://www.kclee.de/clemens/java/javancss/) diff --git a/docs/pages/pmd/userdocs/extending/metrics_howto.md b/docs/pages/pmd/userdocs/extending/metrics_howto.md deleted file mode 100644 index cb8f776424..0000000000 --- a/docs/pages/pmd/userdocs/extending/metrics_howto.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Using and defining code metrics for custom rules -tags: [extending, userdocs, metrics] -summary: "Since version 6.0.0, PMD is enhanced with the ability to compute code metrics on Java and Apex source (the so-called -Metrics Framework). This framework provides developers with a straightforward interface to use code metrics in their -rules, and to extend the framework with their own custom metrics." -last_updated: December 18, 2017 -permalink: pmd_userdocs_extending_metrics_howto.html -author: Clément Fournier ---- - -{% jdoc_nspace :coremx core::lang.metrics %} -{% jdoc_nspace :coreast core::lang.ast %} -{% jdoc_nspace :jmx java::lang.java.metrics %} -{% jdoc_nspace :jast java::lang.java.ast %} - - -In PMD's Metrics framework, a metric `Metric` is an operation that can be carried out on nodes of a certain type `N` and produces -a numeric result of type `R`. - -PMD ships with a library of "standard" metrics. Like cyclomatic complexity measures. These are documented in the following pages: -* [Java metrics](pmd_java_metrics_index.html) -* [Apex metrics](pmd_apex_metrics_index.html) - -Usage and implementation documentation may be found in our Javadocs: {% jdoc coremx::Metric %} and {% jdoc coremx::MetricsUtil %}. In the Java module, XPath rules may additionally use the [pmd-java:metric](pmd_userdocs_extending_writing_xpath_rules.html#pmd-java-metric) function. 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 1faaa15e88..c97979efff 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 @@ -23,7 +23,8 @@ import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** - * + * Built-in Apex metrics. See {@link Metric} and {@link MetricsUtil} + * for usage doc. */ public final class ApexMetrics { @SuppressWarnings({"unchecked", "rawtypes"}) @@ -31,6 +32,54 @@ public final class ApexMetrics { (Class) ApexNode.class; // this is a Class, the raw type + /** + * Number of independent paths through a block of code. + * Formally, given that the control flow graph of the block has n + * vertices, e edges and p connected components, the cyclomatic complexity + * of the block is given by {@code CYCLO = e - n + 2p}. In practice + * it can be calculated by counting control flow statements following + * the standard rules given below. + * + * + *

The standard version of the metric complies with McCabe’s original definition: + *

    + *
  • Methods have a base complexity of 1. + *
  • +1 for every control flow statement (if, catch, throw, do, while, for, break, continue) and conditional expression (?:). + *
  • else, finally and default do not count; + *
  • +1 for every boolean operator ({@code &&}, {@code ||}) in + * the guard condition of a control flow statement. That’s because + * Apex has short-circuit evaluation semantics for boolean operators, + * which makes every boolean operator kind of a control flow statement in itself. + *
+ * + *

Code example: + *

{@code
+     * class Foo {
+     *   void baseCyclo() {                // Cyclo = 1
+     *     highCyclo();
+     *   }
+     *
+     *   void highCyclo() {                // Cyclo = 10
+     *     int x = 0, y = 2;
+     *     boolean a = false, b = true;
+     *
+     *     if (a && (y == 1 ? b : true)) { // +3
+     *       if (y == x) {                 // +1
+     *         while (true) {              // +1
+     *           if (x++ < 20) {           // +1
+     *             break;                  // +1
+     *           }
+     *         }
+     *       } else if (y == t && !d) {    // +2
+     *         x = a ? y : x;              // +1
+     *       } else {
+     *         x = 2;
+     *       }
+     *     }
+     *   }
+     * }
+     * }
+ */ public static final Metric, Integer> CYCLO = Metric.of(ApexMetrics::computeCyclo, isRegularApexNode(), "Cyclomatic Complexity", "Cyclo"); @@ -40,6 +89,11 @@ public final class ApexMetrics { "Cognitive Complexity"); + /** + * Sum of the statistical complexity of the operations in the class. + * We use CYCLO to quantify the complexity of an operation. + * + */ public static final Metric, Integer> WEIGHED_METHOD_COUNT = Metric.of(ApexMetrics::computeWmc, filterMapNode(ASTUserClass.class, PredicateUtil.always()), "Weighed Method Count", "WMC"); 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 index 8f20baa9f4..ab4f4228ca 100644 --- 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 @@ -3,14 +3,14 @@ */ /** - * Language-independent framework to represent code metrics. If you want - * to compute code metrics in your rules, then you should find the language-specific + * Language-independent framework to represent code metrics. To find the build-in + * metrics for a language, find the language-specific * utility class containing {@link net.sourceforge.pmd.lang.metrics.Metric} * constants, eg in java, {@code JavaMetrics}. * - *

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. - * + *

See {@link net.sourceforge.pmd.lang.metrics.Metric} and {@link net.sourceforge.pmd.lang.metrics.MetricsUtil} + * for usage documentation. In some language modules, XPath rules may + * use metrics through an XPath function, e.g. pmd-java:metric + * function. */ package net.sourceforge.pmd.lang.metrics; 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 4f24f84442..600c9c90f5 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 @@ -12,7 +12,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; @@ -43,22 +42,228 @@ import net.sourceforge.pmd.lang.metrics.MetricOptions; import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** - * A collection of Java metrics. - * - * @see Online documentation + * Built-in Java metrics. See {@link Metric} and {@link MetricsUtil} + * for usage doc. */ @SuppressWarnings("PMD.UnusedFormalParameter") // #2838 public final class JavaMetrics { + /** + * Number of usages of foreign attributes, both directly and through accessors. + * High values of ATFD (> 3 for an operation) may suggest that the + * class or operation breaks encapsulation by relying on the internal + * representation of the classes it uses instead of the services they provide. + */ + public static final Metric ACCESS_TO_FOREIGN_DATA = + Metric.of(JavaMetrics::computeAtfd, isJavaNode(), + "Access To Foreign Data", "ATFD"); + + /** + * Number of independent paths through a block of code. + * Formally, given that the control flow graph of the block has n + * vertices, e edges and p connected components, the cyclomatic complexity + * of the block is given by {@code CYCLO = e - n + 2p}. In practice + * it can be calculated by counting control flow statements following + * the standard rules given below. + * + *

The standard version of the metric complies with McCabe’s original definition: + *

    + *
  • Methods have a base complexity of 1. + *
  • +1 for every control flow statement (if, case, catch, throw, + * do, while, for, break, continue) and conditional expression (?:). + * Notice switch cases count as one, but not the switch itself: the + * point is that a switch should have the same complexity value as + * the equivalent series of if statements. + *
  • else, finally and default do not count; + *
  • +1 for every boolean operator ({@code &&}, {@code ||}) in + * the guard condition of a control flow statement. That’s because + * Java has short-circuit evaluation semantics for boolean operators, + * which makes every boolean operator kind of a control flow statement in itself. + *
+ * + *

Code example: + *

{@code
+     * class Foo {
+     *   void baseCyclo() {                // Cyclo = 1
+     *     highCyclo();
+     *   }
+     *
+     *   void highCyclo() {                // Cyclo = 10
+     *     int x = 0, y = 2;
+     *     boolean a = false, b = true;
+     *
+     *     if (a && (y == 1 ? b : true)) { // +3
+     *       if (y == x) {                 // +1
+     *         while (true) {              // +1
+     *           if (x++ < 20) {           // +1
+     *             break;                  // +1
+     *           }
+     *         }
+     *       } else if (y == t && !d) {    // +2
+     *         x = a ? y : x;              // +1
+     *       } else {
+     *         x = 2;
+     *       }
+     *     }
+     *   }
+     * }
+     * }
+ * + * @see CycloOption + */ + public static final Metric CYCLO = + Metric.of(JavaMetrics::computeCyclo, asMethodOrCtor(), + "Cyclomatic Complexity", "Cyclo"); + + /** + * This counts the number of other classes a given class or operation + * relies on. Classes from the package {@code java.lang} are ignored + * by default (can be changed via options). Also primitives are not + * included into the count. + * + *

Code example: + *

{@code
+     * import java.util.*;
+     * import java.io.IOException;
+     *
+     * public class Foo { // total 8
+     *     public Set set = new HashSet(); // +2
+     *     public Map map = new HashMap(); // +2
+     *     public String string = ""; // from java.lang -> does not count by default
+     *     public Double number = 0.0; // from java.lang -> does not count by default
+     *     public int[] intArray = new int[3]; // primitive -> does not count
+     *
+     *     \@Deprecated // from java.lang -> does not count by default
+     *     public void foo(List list) throws Exception { // +1 (Exception is from java.lang)
+     *         throw new IOException(); // +1
+     *     }
+     *
+     *     public int getMapSize() {
+     *         return map.size(); // +1 because it uses the Class from the 'map' field
+     *     }
+     * }
+     * }
+ * + * @see ClassFanOutOption + */ + public static final Metric FAN_OUT = + Metric.of(JavaMetrics::computeFanOut, isJavaNode(), + "Fan-Out", "CFO"); + + /** + * Simply counts the number of lines of code the operation or class + * takes up in the source. This metric doesn’t discount comments or blank lines. + * See {@link #NCSS} for a less biased metric. + */ public static final Metric LINES_OF_CODE = Metric.of(JavaMetrics::computeLoc, isJavaNode(), "Lines of code", "LOC"); + /** + * Number of statements in a class or operation. That’s roughly + * equivalent to counting the number of semicolons and opening braces + * in the program. Comments and blank lines are ignored, and statements + * spread on multiple lines count as only one (e.g. {@code int\n a;} + * counts a single statement). + * + *

The standard version of the metric is based off [JavaNCSS](http://www.kclee.de/clemens/java/javancss/): + *

    + *
  • +1 for any of the following statements: {@code if}, {@code else}, + * {@code while}, {@code do}, {@code for}, {@code switch}, {@code break}, + * {@code continue}, {@code return}, {@code throw}, {@code synchronized}, + * {@code catch}, {@code finally}. + *
  • +1 for each assignment, variable declaration (except for loop initializers) + * or statement expression. We count variables declared on the same line (e.g. + * {@code int a, b, c;}) as a single statement. + *
  • Contrary to Sonarqube, but as JavaNCSS, we count type declarations (class, interface, enum, annotation), + * and method and field declarations. + *
  • Contrary to JavaNCSS, but as Sonarqube, we do not count package + * declaration and import declarations as statements. This makes it + * easier to compare nested classes to outer classes. Besides, it makes + * for class metric results that actually represent the size of the class + * and not of the file. If you don’t like that behaviour, use the {@link NcssOption#COUNT_IMPORTS} option. + *
+ * + *
{@code
+     * import java.util.Collections;       // +0
+     * import java.io.IOException;         // +0
+     *
+     * class Foo {                         // +1, total Ncss = 12
+     *
+     *   public void bigMethod()           // +1
+     *       throws IOException {
+     *     int x = 0, y = 2;               // +1
+     *     boolean a = false, b = true;    // +1
+     *
+     *     if (a || b) {                   // +1
+     *       try {                         // +1
+     *         do {                        // +1
+     *           x += 2;                   // +1
+     *         } while (x < 12);
+     *
+     *         System.exit(0);             // +1
+     *       } catch (IOException ioe) {   // +1
+     *         throw new PatheticFailException(ioe); // +1
+     *       }
+     *     } else {
+     *       assert false;                 // +1
+     *     }
+     *   }
+     * }
+     * }
+ */ public static final Metric NCSS = Metric.of(JavaMetrics::computeNcss, isJavaNode(), "Non-commenting source statements", "NCSS"); + /** + * Number of acyclic execution paths through a piece of code. This + * is related to cyclomatic complexity, but the two metrics don’t + * count the same thing: NPath counts the number of distinct full + * paths from the beginning to the end of the method, while Cyclo + * only counts the number of decision points. NPath is not computed + * as simply as {@link #CYCLO}. With NPath, two decision points appearing + * sequentially have their complexity multiplied. + * + *

The fact that NPath multiplies the complexity of statements makes + * it grow exponentially: 10 {@code if .. else} statements in a row + * would give an NPath of 1024, while Cyclo would evaluate to 20. + * Methods with an NPath complexity over 200 are generally considered + * too complex. + * + *

We compute NPath recursively, with the following set of rules: + *

    + *
  • An empty block has a complexity of 1. + *
  • The complexity of a block is the product of the NPath complexity + * of its statements, calculated as follows: + *
      + *
    • The complexity of for, do and while statements is 1, plus the + * complexity of the block, plus the complexity of the guard condition. + *
    • The complexity of a cascading if statement ({@code if .. else if ..}) + * is the number of if statements in the chain, plus the complexity of + * their guard condition, plus the complexity of the unguarded else block + * (or 1 if there is none). + *
    • The complexity of a switch statement is the number of cases, + * plus the complexity of each case block. It’s equivalent to the + * complexity of the equivalent cascade of if statements. + *
    • The complexity of a ternary expression ({@code ? :}) is the complexity + * of the guard condition, plus the complexity of both expressions. + * It’s equivalent to the complexity of the equivalent {@code if .. else} construct. + *
    • The complexity of a {@code try .. catch} statement is the complexity + * of the {@code try} block, plus the complexity of each catch block. + *
    • The complexity of a return statement is the complexity of the + * expression (or 1 if there is none). + *
    • All other statements have a complexity of 1 and are discarded + * from the product. + *
    + *
  • + *
+ */ + public static final Metric NPATH = + Metric.of(JavaMetrics::computeNpath, asMethodOrCtor(), + "NPath Complexity", "NPath"); + public static final Metric NUMBER_OF_ACCESSORS = Metric.of(JavaMetrics::computeNoam, asClass(always()), "Number of accessor methods", "NOAM"); @@ -67,38 +272,51 @@ public final class JavaMetrics { Metric.of(JavaMetrics::computeNopa, asClass(always()), "Number of public attributes", "NOPA"); + /** + * The relative number of method pairs of a class that access in common + * at least one attribute of the measured class. TCC only counts direct + * attribute accesses, that is, only those attributes that are accessed + * in the body of the method. + * + *

The value is a double between 0 and 1. + * + *

TCC is taken to be a reliable cohesion metric for a class. + * High values (>70%) indicate a class with one basic function, + * which is hard to break into subcomponents. On the other hand, low + * values (<50%) may indicate that the class tries to do too much + * and defines several unrelated services, which is undesirable. + */ public static final Metric TIGHT_CLASS_COHESION = Metric.of(JavaMetrics::computeTcc, asClass(it -> !it.isInterface()), "Tight Class Cohesion", "TCC"); - public static final Metric CYCLO = - Metric.of(JavaMetrics::computeCyclo, asMethodOrCtor(), - "Cyclomatic Complexity", "Cyclo"); - - public static final Metric NPATH = - Metric.of(JavaMetrics::computeNpath, asMethodOrCtor(), - "NPath Complexity", "NPath"); - + /** + * Sum of the statistical complexity of the operations in the class. + * We use CYCLO to quantify the complexity of an operation. + * + *

WMC uses the same options as CYCLO, which are provided to CYCLO when computing it ({@link CycloOption}). + */ public static final Metric WEIGHED_METHOD_COUNT = Metric.of(JavaMetrics::computeWmc, asClass(it -> !it.isInterface()), "Weighed Method Count", "WMC"); - public static final Metric ACCESS_TO_FOREIGN_DATA = - Metric.of(JavaMetrics::computeAtfd, isJavaNode(), - "Access To Foreign Data", "ATFD"); + /** - * {@link Metric#of(BiFunction, Function, String, String...)} + * Number of “functional” public methods divided by the total number + * of public methods. Our definition of “functional method” excludes + * constructors, getters, and setters. + * + *

The value is a double between 0 and 1. + * + *

This metric tries to quantify whether the measured class’ interface + * reveals more data than behaviour. Low values (less than 30%) indicate + * that the class reveals much more data than behaviour, which is a + * sign of poor encapsulation. */ public static final Metric WEIGHT_OF_CLASS = Metric.of(JavaMetrics::computeWoc, asClass(it -> !it.isInterface()), "Weight Of Class", "WOC"); - - public static final Metric FAN_OUT = - Metric.of(JavaMetrics::computeFanOut, isJavaNode(), - "Fan-Out", "CFO"); - - private JavaMetrics() { // utility class } @@ -267,7 +485,7 @@ public final class JavaMetrics { public enum CycloOption implements MetricOption { /** Do not count the paths in boolean expressions as decision points. */ IGNORE_BOOLEAN_PATHS("ignoreBooleanPaths"), - /** Consider assert statements. */ + /** Consider assert statements as if they were {@code if (..) throw new AssertionError(..)}. */ CONSIDER_ASSERT("considerAssert"); private final String vName; @@ -317,7 +535,7 @@ public final class JavaMetrics { * Options for {@link #FAN_OUT}. */ public enum ClassFanOutOption implements MetricOption { - /** Whether to include Classes in the java.lang package. */ + /** Whether to include classes in the {@code java.lang} package. */ INCLUDE_JAVA_LANG("includeJavaLang"); private final String vName; From 835be1f9bc974c68c625d45418ca3a07d8cfc7d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 1 Mar 2021 17:16:06 +0100 Subject: [PATCH 040/101] Update release notes --- docs/pages/7_0_0_release_notes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index a99d23c9d5..3fe7ee272e 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -188,11 +188,11 @@ The metrics framework has been made simpler and more general. For that reason, keeping around a hard distinction between "class metrics" and "operation metrics" is not useful. So in the Java framework for example, we removed the interfaces `JavaClassMetric`, `JavaOperationMetric`, abstract classes for those, `JavaClassMetricKey`, and `JavaOperationMetricKey`. Metric constants are now all inside the `JavaMetrics` utility class. The same was done in the Apex framework. - We don't really need abstract classes for metrics now. So `AbstractMetric` is also removed from core. There is a factory method on the `Metric` interface to create a metric easily. + We don't really need abstract classes for metrics now. So `AbstractMetric` is also removed from pmd-core. There is a factory method on the `Metric` interface to create a metric easily. -* This makes it so, that `LanguageMetricsProvider` does not need type parameters. It can just return a `Set>` to list available metrics. +* This makes it so, that {% jdoc core::lang.metrics.LanguageMetricsProvider %} does not need type parameters. It can just return a `Set>` to list available metrics. -* `Signature`s, their implementations, and the interface `SignedNode` have been deprecated until PMD 7. They don't carry their weight, and node streams allow replacing their usages very easily. +* {% jdoc_old core::lang.metrics.Signature %}s, their implementations, and the interface `SignedNode` have been removed. Node streams allow replacing their usages very easily. ### External Contributions From 37d4431cee666b31c53fbb3eed2f500c93ebf23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 1 Mar 2021 17:19:27 +0100 Subject: [PATCH 041/101] Make constants for sets of metrics --- .../pmd/lang/apex/ApexHandler.java | 11 ++++---- .../java/internal/JavaLanguageHandler.java | 28 ++++++++++--------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java index 4ff8536f29..ac4b290160 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexHandler.java @@ -42,14 +42,15 @@ public class ApexHandler extends AbstractPmdLanguageVersionHandler { private static class ApexMetricsProvider implements LanguageMetricsProvider { + private final Set> metrics = setOf( + ApexMetrics.COGNITIVE_COMPLEXITY, + ApexMetrics.CYCLO, + ApexMetrics.WEIGHED_METHOD_COUNT + ); @Override public Set> getMetrics() { - return setOf( - ApexMetrics.COGNITIVE_COMPLEXITY, - ApexMetrics.CYCLO, - ApexMetrics.WEIGHED_METHOD_COUNT - ); + return metrics; } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java index 47c7101a11..c90973e476 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageHandler.java @@ -87,21 +87,23 @@ public class JavaLanguageHandler extends AbstractPmdLanguageVersionHandler { public static class JavaMetricsProvider implements LanguageMetricsProvider { + private final Set> metrics = setOf( + JavaMetrics.ACCESS_TO_FOREIGN_DATA, + JavaMetrics.CYCLO, + JavaMetrics.NPATH, + JavaMetrics.NCSS, + JavaMetrics.LINES_OF_CODE, + JavaMetrics.FAN_OUT, + JavaMetrics.WEIGHED_METHOD_COUNT, + JavaMetrics.WEIGHT_OF_CLASS, + JavaMetrics.NUMBER_OF_ACCESSORS, + JavaMetrics.NUMBER_OF_PUBLIC_FIELDS, + JavaMetrics.TIGHT_CLASS_COHESION + ); + @Override public Set> getMetrics() { - return setOf( - JavaMetrics.ACCESS_TO_FOREIGN_DATA, - JavaMetrics.CYCLO, - JavaMetrics.NPATH, - JavaMetrics.NCSS, - JavaMetrics.LINES_OF_CODE, - JavaMetrics.FAN_OUT, - JavaMetrics.WEIGHED_METHOD_COUNT, - JavaMetrics.WEIGHT_OF_CLASS, - JavaMetrics.NUMBER_OF_ACCESSORS, - JavaMetrics.NUMBER_OF_PUBLIC_FIELDS, - JavaMetrics.TIGHT_CLASS_COHESION - ); + return metrics; } } } From 70e00a64fe67fa63cf04b0759efaf262eae0f193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 6 Mar 2021 13:17:51 +0100 Subject: [PATCH 042/101] Fix malformed code in tests --- .../pmd/lang/java/rule/design/xml/NPathComplexity.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NPathComplexity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NPathComplexity.xml index 8801f3f25f..f5da1cc4e4 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NPathComplexity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NPathComplexity.xml @@ -245,10 +245,10 @@ public class NPathTest { } var product = new Product(); var description = switch (language) { - case FR -> description.setFr(title); - case IT -> description.setIt(title); - case EN -> description.setEn(title); - default -> description.setDe(title); + case FR -> new Description.Fr(title); + case IT -> new Description.It(title); + case EN -> new Description.En(title); + default -> new Description.De(title); }; product.setDescription(description); product.setMagicNumber(3); From 7c80ae05a8333d99234e6aa1fe8cd8ae24c8a920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 6 Mar 2021 13:26:02 +0100 Subject: [PATCH 043/101] Code style --- .../pmd/lang/java/rule/design/NcssCountRule.java | 8 ++------ .../lang/java/rule/documentation/CommentRequiredRule.java | 1 - .../pmd/lang/java/rule/internal/JavaRuleUtil.java | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) 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 a90bddf887..bcb6461678 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 @@ -49,10 +49,6 @@ public final class NcssCountRule extends AbstractJavaRulechainRule { .build(); private static final PropertyDescriptor> NCSS_OPTIONS_DESCRIPTOR; - private int methodReportLevel; - private int classReportLevel; - private MetricOptions ncssOptions; - static { Map options = new HashMap<>(); @@ -103,7 +99,7 @@ public final class NcssCountRule extends AbstractJavaRulechainRule { if (classSize >= level) { String[] messageParams = {PrettyPrintingUtil.kindName(node), node.getSimpleName(), - classSize + " (Highest = " + classHighest + ")",}; + classSize + " (Highest = " + classHighest + ")", }; addViolation(data, node, messageParams); } @@ -121,7 +117,7 @@ public final class NcssCountRule extends AbstractJavaRulechainRule { if (methodSize >= level) { addViolation(data, node, new String[] { node instanceof ASTMethodDeclaration ? "method" : "constructor", - PrettyPrintingUtil.displaySignature(node), "" + methodSize,}); + PrettyPrintingUtil.displaySignature(node), "" + methodSize, }); } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java index e6f82954e7..b54c16a125 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java @@ -24,7 +24,6 @@ import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavadocCommentOwner; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.properties.PropertyBuilder.GenericPropertyBuilder; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java index 3318c98427..d933664b14 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java @@ -58,9 +58,9 @@ import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaTokenKinds; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.java.ast.UnaryOp; +import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind; import net.sourceforge.pmd.lang.java.types.JTypeMirror; -import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; import net.sourceforge.pmd.util.CollectionUtil; From 6488e1152307999fe01c7449bf4811a0803db5ca Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 26 Mar 2021 16:28:46 +0100 Subject: [PATCH 044/101] [java] Update rule UseStringBufferForStringAppends --- .ci/files/all-java.xml | 2 +- .../UseStringBufferForStringAppendsRule.java | 104 ++++-------------- .../UseStringBufferForStringAppendsTest.java | 1 - .../xml/UseStringBufferForStringAppends.xml | 33 +++--- 4 files changed, 42 insertions(+), 98 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 7d2af50fbc..0ee6cc9c50 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -314,7 +314,7 @@ - + diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java index ac91f98e46..d9d4ff4ef3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java @@ -4,30 +4,22 @@ package net.sourceforge.pmd.lang.java.rule.performance; -import java.util.Objects; - import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTArgumentList; -import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator; -import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; -import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; -import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression; +import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; +import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.AccessType; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTForStatement; +import net.sourceforge.pmd.lang.java.ast.ASTForeachStatement; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; -import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; -import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; +import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; -import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; -public class UseStringBufferForStringAppendsRule extends AbstractJavaRule { +public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRule { public UseStringBufferForStringAppendsRule() { - addRuleChainVisit(ASTVariableDeclaratorId.class); + super(ASTVariableDeclaratorId.class); } /** @@ -39,81 +31,31 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRule { @Override public Object visit(ASTVariableDeclaratorId node, Object data) { if (!TypeTestUtil.isA(String.class, node) || node.hasArrayType() - || node.getNthParent(3) instanceof ASTForStatement) { + || node.getNthParent(3) instanceof ASTForStatement + || node.getNthParent(3) instanceof ASTForeachStatement) { return data; } - // Remember how often we the variable has been used + // Remember how often the variable has been used int usageCounter = 0; - for (NameOccurrence no : node.getUsages()) { - Node name = no.getLocation(); - ASTStatementExpression statement = name.getFirstParentOfType(ASTStatementExpression.class); - if (statement == null) { - continue; - } - ASTArgumentList argList = name.getFirstParentOfType(ASTArgumentList.class); - if (argList != null && argList.getFirstParentOfType(ASTStatementExpression.class) == statement) { - // used in method call - continue; - } - ASTEqualityExpression equality = name.getFirstParentOfType(ASTEqualityExpression.class); - if (equality != null && equality.getFirstParentOfType(ASTStatementExpression.class) == statement) { - // used in condition - continue; - } + for (ASTNamedReferenceExpr usage : node.getLocalUsages()) { if ((node.getNthParent(2) instanceof ASTFieldDeclaration || node.getParent() instanceof ASTFormalParameter) - && isNotWithinLoop(name)) { + && isNotWithinLoop(usage)) { // ignore if the field or formal parameter is *not* used within loops continue; } - ASTConditionalExpression conditional = name.getFirstParentOfType(ASTConditionalExpression.class); - if (conditional != null) { - Node thirdParent = name.getNthParent(3); - Node fourthParent = name.getNthParent(4); - if ((Objects.equals(thirdParent, conditional) || Objects.equals(fourthParent, conditional)) - && conditional.getFirstParentOfType(ASTStatementExpression.class) == statement) { - // is used in ternary as only option (not appended to other - // string) - continue; - } - } - if (statement.getNumChildren() > 0 && statement.getChild(0) instanceof ASTPrimaryExpression) { - ASTName astName = statement.getChild(0).getFirstDescendantOfType(ASTName.class); - if (astName != null) { - ASTAssignmentOperator assignmentOperator = statement - .getFirstDescendantOfType(ASTAssignmentOperator.class); - if (astName.equals(name)) { - if (assignmentOperator != null && assignmentOperator.isCompound()) { - if (isWithinLoop(name)) { - // always report within a loop - addViolation(data, assignmentOperator); - } else { - usageCounter++; - if (usageCounter > 1) { - // only report, if it is not the first time - addViolation(data, assignmentOperator); - } - } - } - } else if (astName.hasImageEqualTo(name.getImage())) { - if (assignmentOperator != null && !assignmentOperator.isCompound()) { - if (isWithinLoop(name)) { - // always report within a loop - addViolation(data, assignmentOperator); - } else { - usageCounter++; - if (usageCounter > 1) { - // only report, if it is not the first time - addViolation(data, assignmentOperator); - } - } - } else if (assignmentOperator != null && assignmentOperator.isCompound() - && usageCounter >= 1) { - addViolation(data, assignmentOperator); - } + if (usage.getAccessType() == AccessType.WRITE) { + if (isWithinLoop(usage)) { + // always report within a loop + addViolation(data, usage); + } else { + usageCounter++; + if (usageCounter > 1) { + // only report, if it is not the first time + addViolation(data, usage); } } } @@ -122,9 +64,7 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRule { } private boolean isNotWithinLoop(Node name) { - return name.getFirstParentOfType(ASTForStatement.class) == null - && name.getFirstParentOfType(ASTWhileStatement.class) == null - && name.getFirstParentOfType(ASTDoStatement.class) == null; + return name.ancestors(ASTLoopStatement.class).isEmpty(); } private boolean isWithinLoop(Node name) { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsTest.java index 59ed609a76..b1ae669420 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.performance; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class UseStringBufferForStringAppendsTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml index 33a85af08c..d65a435515 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml @@ -6,15 +6,15 @@ failure case - 1 - 7 + 2 + 6,7 0 failure case, constructor - 1 - 6 + 2 + 5,6 static failure case - 1 - 6 + 2 + 5,6 #1340 UseStringBufferForStringAppends False Positive with ternary operator (used both in condition and options) 0 @@ -175,9 +179,10 @@ public class UseStringBuffer { #222 False positive when inverting ternary expression arguments 0 Date: Fri, 26 Mar 2021 17:11:40 +0100 Subject: [PATCH 045/101] Draft for java features page --- docs/_data/sidebars/pmd_sidebar.yml | 3 +++ docs/pages/pmd/languages/java.md | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 docs/pages/pmd/languages/java.md diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 190e130207..8e2100a18f 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -352,6 +352,9 @@ entries: - title: Language Specific Documentation output: web, pdf folderitems: + - title: Java Support + url: /pmd_languages_java.html + output: web, pdf - title: JSP Support url: /pmd_languages_jsp.html output: web, pdf diff --git a/docs/pages/pmd/languages/java.md b/docs/pages/pmd/languages/java.md new file mode 100644 index 0000000000..bbfd9381af --- /dev/null +++ b/docs/pages/pmd/languages/java.md @@ -0,0 +1,28 @@ +--- +title: Java support +permalink: pmd_languages_java.html +author: Clément Fournier +--- + +{% include warning.html content="WIP, todo for pmd 7" %} + +### Type and symbol resolution + +Java being a statically typed language, a Java program contains more information that just its syntax tree; for instance, every expression has a static type, and every method call is bound to a method overload statically (even if that overload is virtual). In PMD, much of this information is resolved from the AST by additional passes, which run after parsing, and before rules can inspect the tree. + +The semantic analysis roughly works like so: +1. The first passes resolve *symbols*, which are a model of the named entities that Java programs declare, like classes, methods, and variables. +2. Then, each name in the tree is resolved to a symbol, according to the language's scoping rules. This may modify the tree to remove *ambiguous names* (names which could be either a type, package, or variable). +3. The last pass resolves the types of expressions, which performs overload resolution on method calls, and type inference. + +TODO describe +* why we need auxclasspath +* how disambiguation can fail + +### Type and symbol APIs + +TODO describe APIs + +### Metrics framework + +TODO From 5c4fb5ae6ef714b69e04321317fba719d8e5ae9e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 26 Mar 2021 17:45:46 +0100 Subject: [PATCH 046/101] [java] Update rule UseIOStreamsWithApacheCommonsFileItem --- .ci/files/all-java.xml | 2 +- .../resources/category/java/performance.xml | 21 ++++--------------- ...OStreamsWithApacheCommonsFileItemTest.java | 1 - 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 7d2af50fbc..6aaddd7515 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -312,7 +312,7 @@ - + diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index 3dfebdf342..f8a611da15 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -1005,23 +1005,10 @@ and buffering. +//MethodCall + [@MethodName = 'get' or @MethodName = 'getString'] + [VariableAccess[pmd-java:typeIs('org.apache.commons.fileupload.FileItem')]] + ]]> diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UseIOStreamsWithApacheCommonsFileItemTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UseIOStreamsWithApacheCommonsFileItemTest.java index 8521904b7e..4eed642b53 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UseIOStreamsWithApacheCommonsFileItemTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UseIOStreamsWithApacheCommonsFileItemTest.java @@ -6,6 +6,5 @@ package net.sourceforge.pmd.lang.java.rule.performance; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class UseIOStreamsWithApacheCommonsFileItemTest extends PmdRuleTst { } From 08cc7f8c593bd4aeba8693ef6c8ee5eee773fa22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 27 Mar 2021 18:09:26 +0100 Subject: [PATCH 047/101] Remove useless suppression annotations --- .../java/net/sourceforge/pmd/lang/apex/metrics/ApexMetrics.java | 2 -- .../java/net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java | 1 - 2 files changed, 3 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 c97979efff..31807f709a 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 @@ -113,14 +113,12 @@ public final class ApexMetrics { return n -> n.asStream().filterIs(klass).filter(pred).first(); } - @SuppressWarnings("PMD.UnusedFormalParameter") private static int computeCyclo(ApexNode node, MetricOptions ignored) { MutableInt result = new MutableInt(1); node.acceptVisitor(new StandardCycloVisitor(), result); return result.getValue(); } - @SuppressWarnings("PMD.UnusedFormalParameter") private static int computeCognitiveComp(ApexNode node, MetricOptions ignored) { State state = new State(); node.acceptVisitor(CognitiveComplexityVisitor.INSTANCE, state); 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 600c9c90f5..5866ccacfa 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 @@ -45,7 +45,6 @@ import net.sourceforge.pmd.lang.metrics.MetricsUtil; * Built-in Java metrics. See {@link Metric} and {@link MetricsUtil} * for usage doc. */ -@SuppressWarnings("PMD.UnusedFormalParameter") // #2838 public final class JavaMetrics { /** From 0cb6e537f005762c3cab1ab38a3923d710c20738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 27 Mar 2021 18:12:10 +0100 Subject: [PATCH 048/101] Change parameters of Metric#compute to match order in MetricsUtil --- .../pmd/lang/metrics/LanguageMetricsProvider.java | 2 +- .../java/net/sourceforge/pmd/lang/metrics/Metric.java | 10 +++++----- .../lang/java/rule/xpath/internal/MetricFunction.java | 2 +- .../sourceforge/pmd/test/AbstractMetricTestRule.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) 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 def0787615..e2062af0de 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 @@ -53,7 +53,7 @@ public interface LanguageMetricsProvider { default Map, Number> computeAllMetricsFor(Node node) { Map, Number> results = new HashMap<>(); for (Metric metric : getMetrics()) { - @Nullable Number result = Metric.compute(metric, MetricOptions.emptyOptions(), node); + @Nullable Number result = Metric.compute(metric, node, MetricOptions.emptyOptions()); if (result != null) { results.put(metric, result); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java index d37c0f256e..92d4f1796d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/Metric.java @@ -33,7 +33,7 @@ import net.sourceforge.pmd.util.DataMap.DataKey; * necessarily be computed on any node of the type they support). * *

Metrics support a concept of {@linkplain MetricOption options}, - * which can be passed to {@link Metric#compute(Metric, MetricOptions, Node) compute} + * which can be passed to {@link Metric#compute(Metric, Node, MetricOptions) compute} * or {@link MetricsUtil#computeMetric(Metric, Node, MetricOptions)}. * *

Metric instances are stateless by contract. @@ -162,17 +162,17 @@ public interface Metric extends DataKey Type of nodes the metric supports * @param Return type + * @param metric Metric + * @param node Node + * @param options Options for the metric * * @return Null if the node is unsupported, otherwise the result of the metric. * * @throws NullPointerException if any of the parameters is null */ - static @Nullable R compute(Metric metric, MetricOptions options, Node node) { + static @Nullable R compute(Metric metric, Node node, MetricOptions options) { N n = metric.castIfSupported(node); if (n != null) { return metric.computeFor(n, options); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java index 271238902d..7514478979 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/xpath/internal/MetricFunction.java @@ -85,7 +85,7 @@ public final class MetricFunction extends BaseJavaXPathFunction { throw new XPathException(badMetricKeyMessage(metricKeyName)); } - Number computed = Metric.compute(metric, MetricOptions.emptyOptions(), n); + Number computed = Metric.compute(metric, n, MetricOptions.emptyOptions()); return computed == null ? Double.NaN : computed.doubleValue(); } diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java index 9aa2c782f5..4c18a4eb8b 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java @@ -85,7 +85,7 @@ public abstract class AbstractMetricTestRule> e if (reportOn(target)) { MetricOptions options = MetricOptions.ofOptions(getProperty(optionsDescriptor)); N reportLevel = parseReportLevel(getProperty(reportLevelDescriptor)); - N result = Metric.compute(metric, options, target); + N result = Metric.compute(metric, target, options); if (result != null && reportLevel.compareTo(result) <= 0) { addViolationWithMessage(ctx, target, violationMessage(target, result)); From e5c22963816b48f163cb9865776ad91eb10ad4e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 27 Mar 2021 18:15:22 +0100 Subject: [PATCH 049/101] Add more constraints to Nopa test --- .../sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml index 9456375fe1..e8d45b3625 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NopaTest.xml @@ -49,6 +49,11 @@ public class Foo { NOPA supports enums, interfaces or annotations 3 + + 'Foo' has value 1. + 'Foo$Bar' has value 1. + 'Foo$Tag' has value 1. + Date: Sat, 27 Mar 2021 18:17:09 +0100 Subject: [PATCH 050/101] Move file to java source root --- pmd-lang-test/pom.xml | 13 ++++++++++++- .../pmd/test/AbstractMetricTestRule.java | 0 2 files changed, 12 insertions(+), 1 deletion(-) rename pmd-lang-test/src/main/{kotlin => java}/net/sourceforge/pmd/test/AbstractMetricTestRule.java (100%) diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index e4212445ce..32dc5f267a 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -17,7 +17,6 @@ - ${project.basedir}/src/main/kotlin ${project.basedir}/src/test/resources @@ -40,9 +39,21 @@ compile process-sources + + + ${project.basedir}/src/main/java + ${project.basedir}/src/main/kotlin + + + + + org.apache.maven.plugins + maven-compiler-plugin + + org.apache.maven.plugins maven-javadoc-plugin diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java b/pmd-lang-test/src/main/java/net/sourceforge/pmd/test/AbstractMetricTestRule.java similarity index 100% rename from pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/AbstractMetricTestRule.java rename to pmd-lang-test/src/main/java/net/sourceforge/pmd/test/AbstractMetricTestRule.java From 93c04c4b1fb765678cdaf686bbf3f51e018f623f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 16:27:09 +0200 Subject: [PATCH 051/101] Refine definition of a getter --- .../metrics/internal/AtfdBaseVisitor.java | 7 +++-- .../lang/java/rule/internal/JavaRuleUtil.java | 30 +++++++++++++++++-- .../java/rule/internal/JavaRuleUtilTest.java | 21 +++++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java index 085e04cb43..e9850a7ab9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java @@ -8,7 +8,9 @@ import org.apache.commons.lang3.mutable.MutableInt; import net.sourceforge.pmd.lang.java.ast.ASTFieldAccess; import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; +import net.sourceforge.pmd.lang.java.ast.ASTThisExpression; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; +import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; @@ -38,8 +40,9 @@ public class AtfdBaseVisitor extends JavaVisitorBase { } private boolean isForeignMethod(ASTMethodCall node) { - return node.getMethodName().startsWith("set") - || node.getMethodName().startsWith("get"); + return JavaRuleUtil.isGetterOrSetterCall(node) // getter or setter + && node.getQualifier() != null // not called on this + && !(node.getQualifier() instanceof ASTThisExpression); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java index 8159851368..c15841acb2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java @@ -248,6 +248,30 @@ public final class JavaRuleUtil { || "_".equals(name); // before java 9 it's ok } + /** + * Returns true if the string has the given word as a strict prefix. + * There needs to be a camelcase word boundary after the prefix. + * + * + * startsWithCamelCaseWord("getter", "get") == false + * startsWithCamelCaseWord("get", "get") == false + * startsWithCamelCaseWord("getX", "get") == true + * + * + * @param camelCaseString A string + * @param prefixWord A prefix + */ + static boolean startsWithCamelCaseWord(String camelCaseString, String prefixWord) { + return camelCaseString.startsWith(prefixWord) + && camelCaseString.length() > prefixWord.length() + && Character.isUpperCase(camelCaseString.charAt(prefixWord.length())); + } + + public static boolean isGetterOrSetterCall(ASTMethodCall call) { + return call.getArguments().size() == 0 && startsWithCamelCaseWord(call.getMethodName(), "get") + || call.getArguments().size() > 0 && startsWithCamelCaseWord(call.getMethodName(), "set"); + } + public static boolean isGetterOrSetter(ASTMethodDeclaration node) { return isGetter(node) || isSetter(node); @@ -261,9 +285,9 @@ public final class JavaRuleUtil { } ASTAnyTypeDeclaration enclosing = node.getEnclosingType(); - if (node.getName().startsWith("get")) { + if (startsWithCamelCaseWord(node.getName(), "get")) { return hasField(enclosing, node.getName().substring(3)); - } else if (node.getName().startsWith("is")) { + } else if (startsWithCamelCaseWord(node.getName(), "is")) { return hasField(enclosing, node.getName().substring(2)); } @@ -279,7 +303,7 @@ public final class JavaRuleUtil { ASTAnyTypeDeclaration enclosing = node.getEnclosingType(); - if (node.getName().startsWith("set")) { + if (startsWithCamelCaseWord(node.getName(), "set")) { return hasField(enclosing, node.getName().substring(3)); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java new file mode 100644 index 0000000000..df3435c734 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java @@ -0,0 +1,21 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.internal; + +import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.startsWithCamelCaseWord; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class JavaRuleUtilTest { + + @Test + public void testCamelCaseWords() { + assertFalse(startsWithCamelCaseWord("getter", "get")); + assertFalse(startsWithCamelCaseWord("get", "get")); + assertTrue(startsWithCamelCaseWord("getX", "get")); + } + +} From eb43a3b251db26cc234edefd5529ed87afaa73ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 16:48:51 +0200 Subject: [PATCH 052/101] Refine atfd --- .../metrics/internal/AtfdBaseVisitor.java | 23 ++++-- .../java/rule/internal/JavaRuleUtilTest.java | 16 ++-- .../lang/java/metrics/impl/xml/AtfdTest.xml | 81 ++++++++++--------- 3 files changed, 72 insertions(+), 48 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java index e9850a7ab9..eaee259353 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/AtfdBaseVisitor.java @@ -6,8 +6,10 @@ package net.sourceforge.pmd.lang.java.metrics.internal; import org.apache.commons.lang3.mutable.MutableInt; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldAccess; import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; +import net.sourceforge.pmd.lang.java.ast.ASTSuperExpression; import net.sourceforge.pmd.lang.java.ast.ASTThisExpression; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; @@ -32,17 +34,28 @@ public class AtfdBaseVisitor extends JavaVisitorBase { @Override public Void visit(ASTFieldAccess node, MutableInt data) { - JFieldSymbol sym = node.getReferencedSym(); - if (sym != null && !sym.getEnclosingClass().equals(node.getEnclosingType().getSymbol())) { + if (isForeignField(node)) { data.increment(); } return visitChildren(node, data); } + private boolean isForeignField(ASTFieldAccess node) { + JFieldSymbol sym = node.getReferencedSym(); + if (sym == null || sym.isStatic()) { + return false; + } + ASTExpression qualifier = node.getQualifier(); + return !(qualifier instanceof ASTThisExpression + || qualifier instanceof ASTSuperExpression + || sym.getEnclosingClass().equals(node.getEnclosingType().getSymbol()) + ); + } + private boolean isForeignMethod(ASTMethodCall node) { - return JavaRuleUtil.isGetterOrSetterCall(node) // getter or setter - && node.getQualifier() != null // not called on this - && !(node.getQualifier() instanceof ASTThisExpression); + return JavaRuleUtil.isGetterOrSetterCall(node) + && node.getQualifier() != null + && !(node.getQualifier() instanceof ASTThisExpression); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java index df3435c734..577a3a5e47 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java @@ -5,17 +5,23 @@ package net.sourceforge.pmd.lang.java.rule.internal; import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.startsWithCamelCaseWord; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; -class JavaRuleUtilTest { +public class JavaRuleUtilTest { @Test public void testCamelCaseWords() { - assertFalse(startsWithCamelCaseWord("getter", "get")); - assertFalse(startsWithCamelCaseWord("get", "get")); - assertTrue(startsWithCamelCaseWord("getX", "get")); + assertFalse(startsWithCamelCaseWord("getter", "get"), "no word boundary"); + assertFalse(startsWithCamelCaseWord("get", "get"), "no following word"); + assertTrue(startsWithCamelCaseWord("getX", "get"), "ok prefix"); + assertFalse(startsWithCamelCaseWord("ge", "get"), "shorter word"); + + assertThrows(NullPointerException.class, () -> startsWithCamelCaseWord(null, "get")); + assertThrows(NullPointerException.class, () -> startsWithCamelCaseWord("fnei", null)); } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/AtfdTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/AtfdTest.xml index a895ce8a7d..ceee50eb9b 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/AtfdTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/AtfdTest.xml @@ -6,84 +6,73 @@ Full example 8 - 'StatementAndBraceFinder' has value 18. + 'StatementAndBraceFinder' has value 17. 'StatementAndBraceFinder#StatementAndBraceFinder(DataFlowHandler)' has value 0. 'StatementAndBraceFinder#buildDataFlowFor(JavaNode)' has value 4. 'StatementAndBraceFinder#tryToLog(String, NodeType, Node)' has value 2. @@ -222,4 +211,20 @@ public class Foo { } ]]> + + ATFD discounts static fields + 2 + + 'Foo' has value 0. + 'Foo#bar()' has value 0. + + + From 9bc8ea67cc036a49da8e48f6beaafcb22745bff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 17:08:19 +0200 Subject: [PATCH 053/101] Add some doc --- .../net/sourceforge/pmd/lang/java/metrics/JavaMetrics.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 5866ccacfa..fca3ee019d 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 @@ -49,7 +49,10 @@ public final class JavaMetrics { /** * Number of usages of foreign attributes, both directly and through accessors. - * High values of ATFD (> 3 for an operation) may suggest that the + * "Foreign" hier means "not belonging to {@code this}", although field accesses + * to fields declared in the enclosing class are not considered foreign. + * + *

High values of ATFD (> 3 for an operation) may suggest that the * class or operation breaks encapsulation by relying on the internal * representation of the classes it uses instead of the services they provide. */ From e8a16765b7ea6b0293b526049dd751360726ad5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 17:14:26 +0200 Subject: [PATCH 054/101] Unresolved types in tests --- .../net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml | 1 + .../pmd/lang/java/rule/design/xml/NPathComplexity.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml index 4483047805..7a61cf6ca5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml @@ -5,6 +5,7 @@ xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd"> Date: Sun, 28 Mar 2021 17:17:38 +0200 Subject: [PATCH 055/101] Make npath tests more unitary --- .../lang/java/metrics/impl/xml/NPathTest.xml | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml index 7a61cf6ca5..4ba6ee6bf2 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml @@ -424,7 +424,7 @@ public class Test { 6 1 - 'SOFExample#usefulMethod(List)' has value 256. + 'SOFExample#usefulMethod(List)' has value 16. @@ -461,7 +455,7 @@ public class SOFExample { 6 1 - 'SOFExample#usefulMethod(List)' has value 256. + 'SOFExample#usefulMethod(List)' has value 16. + + + + Some foreach + 6 + 1 + + 'SOFExample#usefulMethod(List)' has value 256. + + myCals) { for (MyCal myCal : myCals) { if(myCal.aTime == UNKNOWN) myCal.aTime = aTime; From 794b72307511f77dff46578645c26c67010c589b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 17:30:05 +0200 Subject: [PATCH 056/101] Fix npath not handling foreach loop --- .../metrics/internal/NpathBaseVisitor.java | 9 +++ .../lang/java/metrics/impl/xml/NPathTest.xml | 57 +++++++++++++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java index ce181818cc..8c9396796e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/NpathBaseVisitor.java @@ -11,6 +11,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTForStatement; +import net.sourceforge.pmd.lang.java.ast.ASTForeachStatement; import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; @@ -119,6 +120,14 @@ public class NpathBaseVisitor extends JavaVisitorBase { return nPathBody.add(BigInteger.valueOf(boolComp + 1)); } + @Override + public BigInteger visit(ASTForeachStatement node, Void data) { + // (npath of for + 1) * npath of next + + BigInteger nPathBody = node.getBody().acceptVisitor(this, data); + return nPathBody.add(BigInteger.ONE); + } + @Override public BigInteger visit(ASTReturnStatement node, Void data) { diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml index 4ba6ee6bf2..81d8c8769c 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml @@ -1,8 +1,8 @@ + xmlns="http://pmd.sourceforge.net/rule-tests" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd"> + ]]> @@ -458,7 +458,7 @@ public class SOFExample { 'SOFExample#usefulMethod(List)' has value 16. magicMap = new HashMap(); protected static final long UNKNOWN = 0L; @@ -508,7 +508,7 @@ public class SOFExample { 6 1 - 'SOFExample#usefulMethod(List)' has value 256. + 'SOFExample#usefulMethod(List)' has value 17. + + NPath foreach times other construct + 6 + 1 + + 'SOFExample#usefulMethod(List)' has value 272. + + magicMap = new HashMap(); + protected static final long UNKNOWN = 0L; + + private static final class MyCal { + + long aTime; + long bTime; + long cTime; + long dTime; + } + + public void usefulMethod(final List myCals) { + + final Date a = magicMap.get("a"); + final Date b = magicMap.get("b"); + final Date c = magicMap.get("c"); + final Date d = magicMap.get("d"); + + final long aTime = a == null ? UNKNOWN : a.getTime(); + final long bTime = b == null ? UNKNOWN : b.getTime(); + final long cTime = c == null ? UNKNOWN : c.getTime(); + final long dTime = d == null ? UNKNOWN : d.getTime(); + + for (MyCal myCal : myCals) { + if(myCal.aTime == UNKNOWN) myCal.aTime = aTime; + if(myCal.bTime == UNKNOWN) myCal.bTime = bTime; + if(myCal.cTime == UNKNOWN) myCal.cTime = cTime; + if(myCal.dTime == UNKNOWN) myCal.dTime = dTime; + } + + } + } + ]]> + + #1226 [java] NPath complexity false negative 0 From d5312011796ba8cf28efc05404b1d666d3028abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 17:44:34 +0200 Subject: [PATCH 057/101] Also recognize isX methods as getters --- .../sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java index c15841acb2..3488934283 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java @@ -268,7 +268,9 @@ public final class JavaRuleUtil { } public static boolean isGetterOrSetterCall(ASTMethodCall call) { - return call.getArguments().size() == 0 && startsWithCamelCaseWord(call.getMethodName(), "get") + return call.getArguments().size() == 0 + && (startsWithCamelCaseWord(call.getMethodName(), "get") + || startsWithCamelCaseWord(call.getMethodName(), "is")) || call.getArguments().size() > 0 && startsWithCamelCaseWord(call.getMethodName(), "set"); } From 415b4a49bf9bbf1de99f699cc33f3d1101b6d5d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 18:53:15 +0200 Subject: [PATCH 058/101] Update doc for some metrics rules --- .../pmd/lang/java/metrics/JavaMetrics.java | 4 +++ .../main/resources/category/java/design.xml | 29 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) 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 fca3ee019d..cd2c4357cd 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 @@ -44,6 +44,10 @@ import net.sourceforge.pmd.lang.metrics.MetricsUtil; /** * Built-in Java metrics. See {@link Metric} and {@link MetricsUtil} * for usage doc. + * + * @see "Michele Lanza and Radu Marinescu. Object-Oriented Metrics in Practice: + * Using Software Metrics to Characterize, Evaluate, and Improve the Design + * of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006." */ public final class JavaMetrics { diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index 411be40ab8..6304b84102 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -495,6 +495,18 @@ Refactoring a Data Class should focus on restoring a good data-behaviour proximi most cases, that means moving the operations defined on the data back into the class. In some other cases it may make sense to remove entirely the class and move the data into the former client classes. + +The rule uses metrics to implement its detection strategy. The violation message +gives information about the values of these metrics: +* WMC: a class complexity measure for a class, see {% jdoc java::lang.java.metrics.JavaMetrics#WEIGHED_METHOD_COUNT %} +* WOC: a 'non-triviality' measure for a class, see {% jdoc java::lang.java.metrics.JavaMetrics#WEIGHT_OF_CLASS %} +* NOPA: number of public attributes, see {% jdoc java::lang.java.metrics.JavaMetrics#NUMBER_OF_PUBLIC_FIELDS %} +* NOAM: number of public accessor methods, see {% jdoc java::lang.java.metrics.JavaMetrics#NUMBER_OF_ACCESSORS %} + +The rule identifies a god class by looking for classes which have all of the following properties: +* High NOPA + NOAM +* Low WOC +* Low WMC 3 @@ -753,11 +765,22 @@ are very big and overly complex. They should be split apart to be more object-or The rule uses the detection strategy described in "Object-Oriented Metrics in Practice". The violations are reported against the entire class. -See also the references: +The rule uses metrics to implement its detection strategy. The violation message +gives information about the values of these metrics: +* WMC: a class complexity measure, see {% jdoc java::lang.java.metrics.JavaMetrics#WEIGHED_METHOD_COUNT %} +* ATFD: a measure of how much data external data the class uses, see {% jdoc java::lang.java.metrics.JavaMetrics#ACCESS_TO_FOREIGN_DATA %} +* TCC: a measure of how tightly related the methods are, see {% jdoc java::lang.java.metrics.JavaMetrics#TIGHT_CLASS_COHESION %} -Michele Lanza and Radu Marinescu. Object-Oriented Metrics in Practice: +The rule identifies a god class by looking for classes which have all of the following properties: +* High WMC +* High ATFD +* Low TCC + +See also the reference: + +Michele Lanza and Radu Marinescu. *Object-Oriented Metrics in Practice: Using Software Metrics to Characterize, Evaluate, and Improve the Design -of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. +of Object-Oriented Systems.* Springer, Berlin, 1 edition, October 2006. Page 80. 3 From eb4fe19b5d2e237e5f0c93c52e8110d5e3ecb56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 19:07:44 +0200 Subject: [PATCH 059/101] Describe how to add a new metrics framework --- .../major_contributions/adding_new_language.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_new_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_new_language.md index f87d471aea..1ec23a6dd9 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_new_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_new_language.md @@ -146,3 +146,15 @@ This can be achieved with Rule Designer: * Add a syntax highlighter implementation to `net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting` (you could use Java as an example). * Register it in the `AvailableSyntaxHighlighters` enumeration. * Now build your implementation and place the `target/pmd-ui--SNAPSHOT.jar` to the `lib` directory inside your `pmd-bin-...` distribution (you have to delete old `pmd-ui-*.jar` from there). + +# Optional features + +## Metrics + +If you want to add support for computing metrics: +* Create a package `lang..metrics` +* Create a utility class `Metrics` +* Implement new metrics and add them as static constants. Be sure to document them. +* Implement {% jdoc core::lang.LanguageVersionHandler#getLanguageMetricsProvider() %}, to make the metrics available in the designer. + +See {% jdoc java::lang.java.metrics.JavaMetrics %} for an example. From 783772a351dc2d2a7f6bbda05fef1f5bbcad9d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 19:11:47 +0200 Subject: [PATCH 060/101] Doc in java page --- docs/pages/pmd/languages/java.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/pages/pmd/languages/java.md b/docs/pages/pmd/languages/java.md index bbfd9381af..58dfcb13d7 100644 --- a/docs/pages/pmd/languages/java.md +++ b/docs/pages/pmd/languages/java.md @@ -25,4 +25,20 @@ TODO describe APIs ### Metrics framework -TODO +In order to use code metrics in Java, use the metrics constants in {% jdoc java::lang.java.metrics.JavaMetrics %}, +together with {% jdoc core::lang.metrics.MetricsUtil %}. For instance: + +```java +@Override +public Object visit(ASTMethodDeclaration node, Object data) { + if (JavaMetrics.NCSS.supports(node)) { + int methodSize = MetricsUtil.computeMetric(JavaMetrics.NCSS, node, ncssOptions); + if (methodSize >= level) { + addViolation(data, node); + } + } + return null; +} +``` + +The Javadocs are the reference documentation. From 045720399f2d2162fed5335e70e1492b7a8104f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 19:24:07 +0200 Subject: [PATCH 061/101] Use jekyll tags properly, create apex page placeholder --- docs/_data/sidebars/pmd_sidebar.yml | 9 ++++++--- docs/_data/tags.yml | 2 +- docs/pages/pmd/languages/apex.md | 10 ++++++++++ docs/pages/pmd/languages/java.md | 3 +++ docs/pages/pmd/languages/jsp.md | 2 ++ docs/pages/pmd/languages/plsql.md | 4 +++- .../pages/pmd/userdocs/extending/writing_java_rules.md | 3 +-- docs/pages/tags/tag_languages.md | 2 +- 8 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 docs/pages/pmd/languages/apex.md diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 8e2100a18f..7bda470a8a 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -349,13 +349,16 @@ entries: - title: Performance output: web, pdf url: /pmd_rules_xsl_performance.html - - title: Language Specific Documentation + - title: Language-Specific Documentation output: web, pdf folderitems: - - title: Java Support + - title: Apex + url: /pmd_languages_apex.html + output: web, pdf + - title: Java url: /pmd_languages_java.html output: web, pdf - - title: JSP Support + - title: JSP url: /pmd_languages_jsp.html output: web, pdf - title: PLSQL diff --git a/docs/_data/tags.yml b/docs/_data/tags.yml index 0fe60c394a..88d01cea93 100644 --- a/docs/_data/tags.yml +++ b/docs/_data/tags.yml @@ -9,4 +9,4 @@ allowed-tags: - metrics # About using metrics, and metrics indices - tools # About tools and integrations, Maven, gradle, etc. - devdocs # About PMD internals, contributing, building, projects - - languages + - languages # Language-specific documentation pages diff --git a/docs/pages/pmd/languages/apex.md b/docs/pages/pmd/languages/apex.md new file mode 100644 index 0000000000..f6ff6b50cc --- /dev/null +++ b/docs/pages/pmd/languages/apex.md @@ -0,0 +1,10 @@ +--- +title: Apex support +permalink: pmd_languages_apex.html +author: Clément Fournier +last_updated: March 2021 (7.0.0) +tags: [languages] +summary: "Apex-specific features and guidance" +--- + +{% include warning.html content="Todo for pmd 7" %} diff --git a/docs/pages/pmd/languages/java.md b/docs/pages/pmd/languages/java.md index 58dfcb13d7..cbe060e53b 100644 --- a/docs/pages/pmd/languages/java.md +++ b/docs/pages/pmd/languages/java.md @@ -2,6 +2,9 @@ title: Java support permalink: pmd_languages_java.html author: Clément Fournier +last_updated: March 2021 (7.0.0) +tags: [languages] +summary: "Java-specific features and guidance" --- {% include warning.html content="WIP, todo for pmd 7" %} diff --git a/docs/pages/pmd/languages/jsp.md b/docs/pages/pmd/languages/jsp.md index 771f7af06a..31b4995e54 100644 --- a/docs/pages/pmd/languages/jsp.md +++ b/docs/pages/pmd/languages/jsp.md @@ -2,6 +2,8 @@ title: JSP Support permalink: pmd_languages_jsp.html author: Pieter Vanraemdonck +tags: [languages] +summary: "JSP-specific features and guidance" --- ## What is currently supported and what is not diff --git a/docs/pages/pmd/languages/plsql.md b/docs/pages/pmd/languages/plsql.md index fc6b6d7bb2..38f22bab03 100644 --- a/docs/pages/pmd/languages/plsql.md +++ b/docs/pages/pmd/languages/plsql.md @@ -1,7 +1,9 @@ --- -title: PLSQL +title: PLSQL Support permalink: pmd_languages_plsql.html last_updated: March 2021 (6.33.0) +tags: [languages] +summary: "PLSQL-specific features and guidance" --- ## Parsing Exclusions diff --git a/docs/pages/pmd/userdocs/extending/writing_java_rules.md b/docs/pages/pmd/userdocs/extending/writing_java_rules.md index 82b9a4941b..14619958b7 100644 --- a/docs/pages/pmd/userdocs/extending/writing_java_rules.md +++ b/docs/pages/pmd/userdocs/extending/writing_java_rules.md @@ -27,6 +27,7 @@ your rule as you add test cases. In this page we'll talk about rules for the Java language, but the process is very similar for other languages. +{% include note.html content="[Please find an index of language-specific documentation here](tag_languages.html)" %} ## Basics @@ -133,8 +134,6 @@ The start method is called exactly once per file. - - ## Rule lifecycle reference ### Construction diff --git a/docs/pages/tags/tag_languages.md b/docs/pages/tags/tag_languages.md index 886d150173..c074dbcc09 100644 --- a/docs/pages/tags/tag_languages.md +++ b/docs/pages/tags/tag_languages.md @@ -1,5 +1,5 @@ --- -title: "Supported Lanugages" +title: "Supported Languages" tagName: languages search: exclude permalink: tag_languages.html From 77c05afd55705a67f48324f19a3f6b26c3ac7265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 19:57:58 +0200 Subject: [PATCH 062/101] Update JUnit4SuitesShouldUseSuiteAnnotation --- .../resources/category/java/bestpractices.xml | 5 ++-- ...it4SuitesShouldUseSuiteAnnotationTest.java | 1 - .../JUnit4SuitesShouldUseSuiteAnnotation.xml | 27 ++++++++++++++----- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 79c171144b..7e1cfad363 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -620,9 +620,8 @@ through the @RunWith(Suite.class) annotation. diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnit4SuitesShouldUseSuiteAnnotationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnit4SuitesShouldUseSuiteAnnotationTest.java index 3d125ff28a..7c48d95ab2 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnit4SuitesShouldUseSuiteAnnotationTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnit4SuitesShouldUseSuiteAnnotationTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class JUnit4SuitesShouldUseSuiteAnnotationTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4SuitesShouldUseSuiteAnnotation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4SuitesShouldUseSuiteAnnotation.xml index 0affb504ca..c48ed3ebef 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4SuitesShouldUseSuiteAnnotation.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4SuitesShouldUseSuiteAnnotation.xml @@ -8,14 +8,17 @@ Contains suite 1 @@ -25,10 +28,15 @@ public class Foo extends TestCase{ Contains JUnit4TestAdapter suite 0 - Uses propper suite + Uses proper suite 0 Date: Sun, 28 Mar 2021 22:19:16 +0200 Subject: [PATCH 063/101] Update JUnit4TestShouldUseAfterAnnotation --- .../src/main/resources/category/java/bestpractices.xml | 5 ++--- .../JUnit4TestShouldUseAfterAnnotationTest.java | 1 - .../xml/JUnit4TestShouldUseAfterAnnotation.xml | 7 ++++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 7e1cfad363..ba5fc857bb 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -659,9 +659,8 @@ JUnit 5 introduced @AfterEach and @AfterAll annotations to execute methods after Contains tearDown 1 - Contains @tearDown + Contains @After tearDown 0 Renamed tearDown 0 Date: Sun, 28 Mar 2021 22:23:02 +0200 Subject: [PATCH 064/101] Update JUnit4TestShouldUseBeforeAnnotation --- .../resources/category/java/bestpractices.xml | 5 ++--- .../JUnit4TestShouldUseBeforeAnnotationTest.java | 1 - .../xml/JUnit4TestShouldUseAfterAnnotation.xml | 7 +++++++ .../xml/JUnit4TestShouldUseBeforeAnnotation.xml | 15 +++++++++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index ba5fc857bb..4b6f279adb 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -701,9 +701,8 @@ JUnit 5 introduced @BeforeEach and @BeforeAll annotations to execute methods bef @@ -79,6 +81,9 @@ public class Foo { public void tearDown() { //... } + @Test + public void someTest() {} + } ]]> @@ -94,6 +99,8 @@ public class Foo { public void tearDown() { //... } + @Test + public void someTest() {} } ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml index ee7e4369c2..156fed7dbb 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml @@ -8,6 +8,7 @@ Contains setUp 1 Contains @setUp 0 Renamed setup 0 #1400 False positive with JUnit4TestShouldUseBeforeAnnotation 0 @@ -72,6 +81,8 @@ public class Foo { public void setUp(Method m) { //... } + @Test + public void someTest() {} } ]]> @@ -87,6 +98,8 @@ public class Foo { public void setUp() { //... } + @Test + public void someTest() {} } ]]> @@ -102,6 +115,8 @@ public class Foo { public void setUp() { //... } + @Test + public void someTest() {} } ]]> From 765de83cac81b1b1cf88a0a89ff7b1a752e11f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 22:28:21 +0200 Subject: [PATCH 065/101] Update JUnit4TestShouldUseTestAnnotation --- .../resources/category/java/bestpractices.xml | 24 ++++++++++--------- ...JUnit4TestShouldUseTestAnnotationTest.java | 1 - .../xml/JUnit4TestShouldUseTestAnnotation.xml | 8 +++++-- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 4b6f279adb..16ec72bede 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -743,17 +743,19 @@ In JUnit 5, one of the following annotations should be used for tests: @Test, @R diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnit4TestShouldUseTestAnnotationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnit4TestShouldUseTestAnnotationTest.java index 23dd354ec1..f348ab0b04 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnit4TestShouldUseTestAnnotationTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/JUnit4TestShouldUseTestAnnotationTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class JUnit4TestShouldUseTestAnnotationTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseTestAnnotation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseTestAnnotation.xml index 50481ad196..b00844daba 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseTestAnnotation.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseTestAnnotation.xml @@ -9,7 +9,7 @@ 1 0 0 1 2 Date: Sun, 28 Mar 2021 22:30:51 +0200 Subject: [PATCH 066/101] Update ci file --- .ci/files/all-java.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 7d2af50fbc..3cb85a7150 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -27,10 +27,10 @@ - - - - + + + + From ea244062b96c8e5d7f9ca7b27afcb257bedf1d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 22:36:50 +0200 Subject: [PATCH 067/101] Reduce FPs by checking we're a junit 4 class --- .../resources/category/java/bestpractices.xml | 9 ++++-- .../JUnit4TestShouldUseAfterAnnotation.xml | 26 +++++++++++++++++ .../JUnit4TestShouldUseBeforeAnnotation.xml | 29 +++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 16ec72bede..f59a802dab 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -659,12 +659,14 @@ JUnit 5 introduced @AfterEach and @AfterAll annotations to execute methods after @@ -701,12 +703,15 @@ JUnit 5 introduced @BeforeEach and @BeforeAll annotations to execute methods bef diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml index bb486ea4de..a46bbd5924 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseAfterAnnotation.xml @@ -104,4 +104,30 @@ public class Foo { } ]]> + + Contains tearDown, not a junit 4 test + 0 + + + + Contains tearDown with different signature + 0 + + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml index 156fed7dbb..f4e52a2625 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/JUnit4TestShouldUseBeforeAnnotation.xml @@ -120,4 +120,33 @@ public class Foo { } ]]> + + Contains setUp, not a junit 4 test + 0 + + + + Contains setUp with different signature + 0 + + From 1a3fea8cdbeef88affcb55b6e2daf1f0df20f768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 22:49:45 +0200 Subject: [PATCH 068/101] Update LooseCoupling --- .ci/files/all-java.xml | 2 +- .../rule/bestpractices/LooseCouplingRule.java | 48 +++++++++++-------- .../rule/bestpractices/LooseCouplingTest.java | 1 - 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 7d2af50fbc..7143c09fc5 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -36,7 +36,7 @@ - + diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java index 4478957657..a8d84328b1 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java @@ -7,36 +7,44 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import java.util.Collection; import java.util.Map; -import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.java.ast.ASTBlock; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; -import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; +import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTResultType; +import net.sourceforge.pmd.lang.java.ast.ASTMethodReference; import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; -public class LooseCouplingRule extends AbstractJavaRule { +public class LooseCouplingRule extends AbstractJavaRulechainRule { + + public LooseCouplingRule() { + super(ASTClassOrInterfaceType.class); + } @Override public Object visit(ASTClassOrInterfaceType node, Object data) { - if (methodHasOverride(node)) { - return data; + if (isConcreteCollectionType(node) + && !isInOverriddenMethodSignature(node) + && !(node.getParent() instanceof ASTConstructorCall + || node.getParent() instanceof ASTMethodReference)) { + addViolation(data, node, node.getSimpleName()); } - Node parent = node.getNthParent(3); - boolean isType = (TypeTestUtil.isA(Collection.class, node) || TypeTestUtil.isA(Map.class, node)) - && !(node.getType() != null && node.getType().isInterface()); - - if (isType && (parent instanceof ASTFieldDeclaration || parent instanceof ASTFormalParameter - || parent instanceof ASTResultType)) { - addViolation(data, node, node.getImage()); - } - return data; + return null; } - private boolean methodHasOverride(JavaNode node) { - ASTMethodDeclaration method = node.ancestors(ASTMethodDeclaration.class).first(); - return method != null && method.isAnnotationPresent(Override.class); + private boolean isConcreteCollectionType(ASTClassOrInterfaceType node) { + return (TypeTestUtil.isA(Collection.class, node) || TypeTestUtil.isA(Map.class, node)) + && !node.getTypeMirror().isInterface(); + } + + private static boolean isInOverriddenMethodSignature(JavaNode node) { + JavaNode ancestor = node.ancestors().map(NodeStream.asInstanceOf(ASTMethodDeclaration.class, ASTBlock.class)).first(); + if (ancestor instanceof ASTMethodDeclaration) { + // then it's in a signature and not the body + return ((ASTMethodDeclaration) ancestor).isOverridden(); + } + return false; } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingTest.java index 421b22f18e..25382d7ae0 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class LooseCouplingTest extends PmdRuleTst { // no additional unit tests } From 33f232aa8d2a4ff2c834439cbaa52592a4ab2656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 28 Mar 2021 23:47:12 +0200 Subject: [PATCH 069/101] Update ReplaceEnumerationWithIterator --- .ci/files/all-java.xml | 2 +- pmd-java/src/main/resources/category/java/bestpractices.xml | 2 +- .../rule/bestpractices/ReplaceEnumerationWithIteratorTest.java | 1 - .../rule/bestpractices/xml/ReplaceEnumerationWithIterator.xml | 1 + 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index c8e5d901ae..0384daa41f 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -41,7 +41,7 @@ - + diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 79c171144b..06a35e69a0 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -1109,7 +1109,7 @@ Consider replacing Enumeration usages with the newer java.util.Iterator diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceEnumerationWithIteratorTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceEnumerationWithIteratorTest.java index ea3d9377c9..fea13ff280 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceEnumerationWithIteratorTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceEnumerationWithIteratorTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class ReplaceEnumerationWithIteratorTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceEnumerationWithIterator.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceEnumerationWithIterator.xml index 90602fc2d0..1477cf4c4e 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceEnumerationWithIterator.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceEnumerationWithIterator.xml @@ -8,6 +8,7 @@ bad, implementing Enumeration 1 Date: Sun, 28 Mar 2021 23:53:49 +0200 Subject: [PATCH 070/101] Update ReplaceHashtableWithMap and ReplaceVectorWithList --- .ci/files/all-java.xml | 4 ++-- .../src/main/resources/category/java/bestpractices.xml | 8 ++++++-- .../rule/bestpractices/ReplaceHashtableWithMapTest.java | 1 - .../rule/bestpractices/ReplaceVectorWithListTest.java | 1 - .../rule/bestpractices/xml/ReplaceHashtableWithMap.xml | 2 +- .../java/rule/bestpractices/xml/ReplaceVectorWithList.xml | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 0384daa41f..32705f46da 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -42,8 +42,8 @@ - - + + diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 06a35e69a0..bd25671038 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -1141,7 +1141,9 @@ Consider replacing Hashtable usage with the newer java.util.Map if thread safety 3 - //Type/ReferenceType/ClassOrInterfaceType[@Image='Hashtable'] + @@ -1167,7 +1169,9 @@ Consider replacing Vector usages with the newer java.util.ArrayList if expensive 3 - //Type/ReferenceType/ClassOrInterfaceType[@Image='Vector'] + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceHashtableWithMapTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceHashtableWithMapTest.java index 0c378ddcfc..d1a6337efa 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceHashtableWithMapTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceHashtableWithMapTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class ReplaceHashtableWithMapTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceVectorWithListTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceVectorWithListTest.java index 10f7043142..d6f5b31eb4 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceVectorWithListTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ReplaceVectorWithListTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class ReplaceVectorWithListTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceHashtableWithMap.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceHashtableWithMap.xml index a4ff525da8..58147cad22 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceHashtableWithMap.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/ReplaceHashtableWithMap.xml @@ -6,7 +6,7 @@ bad, local variable of type Hashtable - 1 + 2 bad, local variable of type Vector - 1 + 2 Date: Mon, 29 Mar 2021 00:07:11 +0200 Subject: [PATCH 071/101] Fix FPs of LooseCoupling --- .../rule/bestpractices/LooseCouplingRule.java | 20 ++++++- .../rule/bestpractices/xml/LooseCoupling.xml | 59 +++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java index a8d84328b1..bb7adc630a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java @@ -6,13 +6,16 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import java.util.Collection; import java.util.Map; +import java.util.Properties; import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; +import net.sourceforge.pmd.lang.java.ast.ASTArrayType; import net.sourceforge.pmd.lang.java.ast.ASTBlock; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodReference; +import net.sourceforge.pmd.lang.java.ast.ASTTypeExpression; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; @@ -27,13 +30,24 @@ public class LooseCouplingRule extends AbstractJavaRulechainRule { public Object visit(ASTClassOrInterfaceType node, Object data) { if (isConcreteCollectionType(node) && !isInOverriddenMethodSignature(node) - && !(node.getParent() instanceof ASTConstructorCall - || node.getParent() instanceof ASTMethodReference)) { + && !isInAllowedSyntacticCtx(node) + && !isAllowedType(node)) { addViolation(data, node, node.getSimpleName()); } return null; } + private boolean isInAllowedSyntacticCtx(ASTClassOrInterfaceType node) { + return node.getParent() instanceof ASTConstructorCall + || node.getParent() instanceof ASTTypeExpression + || node.getParent() instanceof ASTArrayType && node.getParent().getParent() instanceof ASTArrayAllocation; + } + + private boolean isAllowedType(ASTClassOrInterfaceType node) { + return TypeTestUtil.isA(Properties.class, node); + } + + private boolean isConcreteCollectionType(ASTClassOrInterfaceType node) { return (TypeTestUtil.isA(Collection.class, node) || TypeTestUtil.isA(Map.class, node)) && !node.getTypeMirror().isInterface(); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml index 2434052cc6..71b879f8c5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml @@ -135,6 +135,65 @@ import java.util.LinkedHashMap; public class Test { @Override public LinkedHashMap findGetters() {} +} + ]]> + + + FP with method reference + 0 + + + + FP with instanceof + 0 + + + + FP with static method call + 0 + + + + FP with array creation + 0 + From 6e6ca68192c4af546622b359a74dd5fde10b7b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 29 Mar 2021 00:19:06 +0200 Subject: [PATCH 072/101] Add new property to LooseCoupling for list of exceptions to the rule This is because I saw a lot of them being things like ImmutableList, which are project-specific --- docs/pages/7_0_0_release_notes.md | 1 + .../rule/bestpractices/LooseCouplingRule.java | 18 ++++++++-- .../rule/bestpractices/xml/LooseCoupling.xml | 36 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index dbbd0e70c0..6e19bb4a10 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -83,6 +83,7 @@ The default version is always ES6. not necessary are allowed, if they separate expressions of different precedence. The other property `ignoreBalancing` (default: true) is similar, in that it allows parentheses that help reading and understanding the expressions. +* The rule {% rule "java/bestpractices/LooseCoupling" %} has a new property to allow some types to be coupled to (`allowedTypes`). #### Removed Rules diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java index bb7adc630a..1f0f3e3bde 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java @@ -5,8 +5,8 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import java.util.Collection; +import java.util.List; import java.util.Map; -import java.util.Properties; import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; @@ -19,11 +19,20 @@ import net.sourceforge.pmd.lang.java.ast.ASTTypeExpression; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; public class LooseCouplingRule extends AbstractJavaRulechainRule { + private static final PropertyDescriptor> ALLOWED_TYPES = + PropertyFactory.stringListProperty("allowedTypes") + .desc("Exceptions to the rule") + .defaultValues("java.util.Properties") + .build(); + public LooseCouplingRule() { super(ASTClassOrInterfaceType.class); + definePropertyDescriptor(ALLOWED_TYPES); } @Override @@ -44,7 +53,12 @@ public class LooseCouplingRule extends AbstractJavaRulechainRule { } private boolean isAllowedType(ASTClassOrInterfaceType node) { - return TypeTestUtil.isA(Properties.class, node); + for (String allowed : getProperty(ALLOWED_TYPES)) { + if (TypeTestUtil.isA(allowed, node)) { + return true; + } + } + return false; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml index 71b879f8c5..b0e32bbce6 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml @@ -194,6 +194,42 @@ public class MyMap implements Map { class Foo { final Map[] map = new MyMap[5]; // ok +} + ]]> + + + FP with j.util.Properties + 0 + + + + Exception list, no exception + 1 + + + + Exception list + mine.O + 0 + From 65064ffdc7a797491aba5a6a77d3f65e32e7c62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 29 Mar 2021 00:36:58 +0200 Subject: [PATCH 073/101] Update rule doc --- .../src/main/resources/category/java/bestpractices.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 79c171144b..512789df51 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -935,9 +935,12 @@ class Foo { class="net.sourceforge.pmd.lang.java.rule.bestpractices.LooseCouplingRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#loosecoupling"> -The use of implementation types (i.e., HashSet) as object references limits your ability to use alternate -implementations in the future as requirements change. Whenever available, referencing objects -by their interface types (i.e, Set) provides much more flexibility. +Excessive coupling to implementation types (e.g., `HashSet`) limits your ability to use alternate +implementations in the future as requirements change. Whenever available, declare variables +and parameters using a more general type (e.g, `Set`). + +This rule reports uses of concrete collection types. User-defined types that should be treated +the same as interfaces can be configured with the property `allowedTypes`. 3 From 9f087b6f3b103d029ccb9538d1ecc4b6ac4b2e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 29 Mar 2021 00:39:20 +0200 Subject: [PATCH 074/101] Ignore class literals (#2464) --- .../java/rule/bestpractices/LooseCouplingRule.java | 9 ++++++--- .../java/rule/bestpractices/xml/LooseCoupling.xml | 11 +++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java index 1f0f3e3bde..49f3c464e6 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java @@ -12,6 +12,7 @@ import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; import net.sourceforge.pmd.lang.java.ast.ASTArrayType; import net.sourceforge.pmd.lang.java.ast.ASTBlock; +import net.sourceforge.pmd.lang.java.ast.ASTClassLiteral; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; @@ -47,9 +48,11 @@ public class LooseCouplingRule extends AbstractJavaRulechainRule { } private boolean isInAllowedSyntacticCtx(ASTClassOrInterfaceType node) { - return node.getParent() instanceof ASTConstructorCall - || node.getParent() instanceof ASTTypeExpression - || node.getParent() instanceof ASTArrayType && node.getParent().getParent() instanceof ASTArrayAllocation; + JavaNode parent = node.getParent(); + return parent instanceof ASTConstructorCall + || parent instanceof ASTTypeExpression + || parent instanceof ASTClassLiteral + || parent instanceof ASTArrayType && parent.getParent() instanceof ASTArrayAllocation; } private boolean isAllowedType(ASTClassOrInterfaceType node) { diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml index b0e32bbce6..f24d813638 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml @@ -230,6 +230,17 @@ import java.util.List; class O implements List { final O map = new O(); +} + ]]> + + + #2464 class literals + 0 + From b741cdc65f75085b63394048554399ecd4ff0094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 29 Mar 2021 00:44:51 +0200 Subject: [PATCH 075/101] Update pmd 7 release notes --- docs/pages/7_0_0_release_notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 6e19bb4a10..6e4bc930f1 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -134,10 +134,12 @@ The following previously deprecated rules have been finally removed: * [#1998](https://github.com/pmd/pmd/issues/1998): \[java] AccessorClassGeneration false-negative: subclass calls private constructor * [#2130](https://github.com/pmd/pmd/issues/2130): \[java] UnusedLocalVariable: false-negative with array * [#2147](https://github.com/pmd/pmd/issues/2147): \[java] JUnitTestsShouldIncludeAssert - false positives with lambdas and static methods + * [#2464](https://github.com/pmd/pmd/issues/2464): \[java] LooseCoupling must ignore class literals: ArrayList.class * [#2542](https://github.com/pmd/pmd/issues/2542): \[java] UseCollectionIsEmpty can not detect the case `foo.bar().size()` * [#2796](https://github.com/pmd/pmd/issue/2796): \[java] UnusedAssignment false positive with call chains * [#2797](https://github.com/pmd/pmd/issues/2797): \[java] MissingOverride long-standing issues * [#2806](https://github.com/pmd/pmd/issues/2806): \[java] SwitchStmtsShouldHaveDefault false-positive with Java 14 switch non-fallthrough branches + * [#2822](https://github.com/pmd/pmd/issues/2822): \[java] LooseCoupling rule: Extend to cover user defined implementations and interfaces * [#2883](https://github.com/pmd/pmd/issues/2883): \[java] JUnitAssertionsShouldIncludeMessage false positive with method call * [#2890](https://github.com/pmd/pmd/issues/2890): \[java] UnusedPrivateMethod false positive with generics * java-codestyle From 891ed33a01aa83780ac7c59418ee171d8580118a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 29 Mar 2021 16:39:13 +0200 Subject: [PATCH 076/101] Allow AbstractMap.SimpleEntry --- .../java/rule/bestpractices/LooseCouplingRule.java | 7 ++++--- .../java/rule/bestpractices/xml/LooseCoupling.xml | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java index 49f3c464e6..7fb8219623 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java @@ -49,9 +49,10 @@ public class LooseCouplingRule extends AbstractJavaRulechainRule { private boolean isInAllowedSyntacticCtx(ASTClassOrInterfaceType node) { JavaNode parent = node.getParent(); - return parent instanceof ASTConstructorCall - || parent instanceof ASTTypeExpression - || parent instanceof ASTClassLiteral + return parent instanceof ASTConstructorCall // new ArrayList<>() + || parent instanceof ASTTypeExpression // instanceof, method reference + || parent instanceof ASTClassLiteral // ArrayList.class + || parent instanceof ASTClassOrInterfaceType // AbstractMap.SimpleEntry || parent instanceof ASTArrayType && parent.getParent() instanceof ASTArrayAllocation; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml index f24d813638..d7aed00ec7 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml @@ -241,6 +241,18 @@ import java.util.ArrayList; class Foo { final Object o = ArrayList.class; +} + ]]> + + + Inner class selection + 0 + ("", ""); } ]]> From 882b76f74f779483b8e8edbdd2d93c9db4663ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 29 Mar 2021 16:40:26 +0200 Subject: [PATCH 077/101] Allow cast --- .../pmd/lang/java/rule/bestpractices/LooseCouplingRule.java | 2 ++ .../pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java index 7fb8219623..3a43650dde 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java @@ -12,6 +12,7 @@ import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; import net.sourceforge.pmd.lang.java.ast.ASTArrayType; import net.sourceforge.pmd.lang.java.ast.ASTBlock; +import net.sourceforge.pmd.lang.java.ast.ASTCastExpression; import net.sourceforge.pmd.lang.java.ast.ASTClassLiteral; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; @@ -51,6 +52,7 @@ public class LooseCouplingRule extends AbstractJavaRulechainRule { JavaNode parent = node.getParent(); return parent instanceof ASTConstructorCall // new ArrayList<>() || parent instanceof ASTTypeExpression // instanceof, method reference + || parent instanceof ASTCastExpression // if we allow instanceof, we should allow cast || parent instanceof ASTClassLiteral // ArrayList.class || parent instanceof ASTClassOrInterfaceType // AbstractMap.SimpleEntry || parent instanceof ASTArrayType && parent.getParent() instanceof ASTArrayAllocation; diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml index d7aed00ec7..6b91f33266 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml @@ -151,7 +151,7 @@ public class Test { ]]> - FP with instanceof + FP with instanceof and cast 0 Date: Tue, 30 Mar 2021 19:33:10 +0200 Subject: [PATCH 078/101] [doc] Fix dead links in doc/ruledoc --- docs/pages/release_notes_old.md | 2 +- pmd-java/src/main/resources/category/java/design.xml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/pages/release_notes_old.md b/docs/pages/release_notes_old.md index 9cfbf3c035..9c710da04f 100644 --- a/docs/pages/release_notes_old.md +++ b/docs/pages/release_notes_old.md @@ -1913,7 +1913,7 @@ For the changes, see [PMD Designer Changelog](https://github.com/pmd/pmd-designe #### Java Metrics * The new metric "Class Fan Out Complexity" has been added. See - [Java Metrics Documentation](pmd_java_metrics_index.html#class-fan-out-complexity-class_fan_out) for details. + [Java Metrics Documentation](https://pmd.github.io/pmd-6.19.0/pmd_java_metrics_index.html#class-fan-out-complexity-class_fan_out) for details. #### Modified Rules diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index 6304b84102..9f469f0adc 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -435,7 +435,7 @@ in a single method makes its behaviour hard to read and change. Cyclomatic complexity assesses the complexity of a method by counting the number of decision points in a method, plus one for the method entry. Decision points are places where the control flow jumps to another place in the program. As such, they include all control flow statements, such as `if`, `while`, `for`, and `case`. For more -details on the calculation, see the documentation of the [Cyclo metric](pmd_java_metrics_index.html#cyclomatic-complexity-cyclo). +details on the calculation, see the documentation {% jdoc java::lang.java.metrics.JavaMetrics#CYCLO %}. Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote high complexity, and 11+ is very high complexity. By default, this rule reports methods with a complexity >= 10. @@ -929,8 +929,8 @@ public class Bar { This rule uses the NCSS (Non-Commenting Source Statements) metric to determine the number of lines of code in a class, method or constructor. NCSS ignores comments, blank lines, and only counts actual -statements. For more details on the calculation, see the documentation of -the [NCSS metric](pmd_java_metrics_index.html#non-commenting-source-statements-ncss). +statements. For more details on the calculation, see the documentation +{% jdoc java::lang.java.metrics.JavaMetrics#NCSS %}. 3 @@ -975,7 +975,7 @@ The NPath complexity of a method is the number of acyclic execution paths throug While cyclomatic complexity counts the number of decision points in a method, NPath counts the number of full paths from the beginning to the end of the block of the method. That metric grows exponentially, as it multiplies the complexity of statements in the same block. For more details on the calculation, see the -documentation of the [NPath metric](pmd_java_metrics_index.html#npath-complexity-npath). +documentation {% jdoc java::lang.java.metrics.JavaMetrics#NPATH %}. A threshold of 200 is generally considered the point where measures should be taken to reduce complexity and increase readability. From c7d249fbf791fb1531fa9b7a4ebf495017096fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 30 Mar 2021 02:26:56 +0200 Subject: [PATCH 079/101] Delete unused class --- .../java/symbols/internal/asm/SigVisitor.java | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SigVisitor.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SigVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SigVisitor.java deleted file mode 100644 index 9f6ad757bb..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SigVisitor.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.symbols.internal.asm; - -import org.objectweb.asm.signature.SignatureVisitor; - -/** - * - */ -public class SigVisitor extends SignatureVisitor { - - public SigVisitor() { - super(AsmSymbolResolver.ASM_API_V); - } - -} From 480bec5db9f86a5e6bb7dec6062279c54b9ef8c0 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 1 Apr 2021 09:02:03 +0200 Subject: [PATCH 080/101] [java] UseStringBufferForStringAppends - fix fp with multiple simple assignments Refs #3171 --- .../UseStringBufferForStringAppendsRule.java | 46 ++++++++++++++++--- .../xml/UseStringBufferForStringAppends.xml | 44 ++++++++++++++++++ 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java index d9d4ff4ef3..a015b6bc29 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java @@ -4,16 +4,22 @@ package net.sourceforge.pmd.lang.java.rule.performance; +import java.util.List; + import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.AccessType; +import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTForStatement; import net.sourceforge.pmd.lang.java.ast.ASTForeachStatement; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; +import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; +import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRule { @@ -36,8 +42,10 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu return data; } - // Remember how often the variable has been used + // Remember how often the variable has been used (assigned a new value or used on the right hand side) int usageCounter = 0; + // Remember how often the variable has been appended + int appendedCounter = 0; for (ASTNamedReferenceExpr usage : node.getLocalUsages()) { if ((node.getNthParent(2) instanceof ASTFieldDeclaration @@ -47,13 +55,39 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu continue; } + boolean isAppend = false; + if (usage.getParent() instanceof ASTAssignmentExpression) { + ASTAssignmentExpression assignment = (ASTAssignmentExpression) usage.getParent(); + // it is either a compound (a += x) + isAppend = assignment.isCompound(); + + if (!isAppend) { + List symbolsOnTheRight = assignment.descendants(ASTInfixExpression.class) + .filter(e -> e.getOperator() == BinaryOp.ADD) + .children(ASTNamedReferenceExpr.class) + .toList(ASTNamedReferenceExpr::getReferencedSym); + // or maybe a append in some way (a = a + x) + isAppend = symbolsOnTheRight.contains(usage.getReferencedSym()); + } + } + if (usage.getAccessType() == AccessType.WRITE) { - if (isWithinLoop(usage)) { - // always report within a loop - addViolation(data, usage); - } else { + if (isAppend) { + // variable is appended + appendedCounter++; + // and used usageCounter++; - if (usageCounter > 1) { + } else { + // reset counters, if it is a assignment with a new value + usageCounter = 1; + appendedCounter = 0; + } + + if (appendedCounter > 0) { + if (isWithinLoop(usage)) { + // always report appends within a loop + addViolation(data, usage); + } else if (usageCounter > 1) { // only report, if it is not the first time addViolation(data, usage); } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml index d65a435515..a6038ed448 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml @@ -540,6 +540,50 @@ public class UseStringBufferForStringAppendsFP { String s2 = "a"; s2 += s1; } +} + ]]> + + + + False positive with simple assignment instead of compound + 0 + messages = new ArrayList<>(); + for (String m : messages) { + checkMessage = m; // FP here + checkMessage = "a"; // FP here + checkMessage = "b"; // FP here + final MessageFormat formatter = new MessageFormat(m, Locale.ROOT); + checkMessage = formatter.format(null); // FP here + int lastDotIndex = checkMessage.lastIndexOf('.'); + checkMessage = checkMessage.substring(lastDotIndex + 1, checkMessage.length()); // FP here + } + return checkMessage; + } +} + ]]> + + + + False positive with simple assignment in for-loop + 0 + From cff45648a91b855583a5f1a8b7c3b2e09b414fdc Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 1 Apr 2021 09:29:53 +0200 Subject: [PATCH 081/101] [java] UseIOStreamsWithApacheCommons: fix FN with method call returning file item --- .../main/resources/category/java/performance.xml | 2 +- .../UseIOStreamsWithApacheCommonsFileItem.xml | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index f8a611da15..1ef48e2ef6 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -1007,7 +1007,7 @@ and buffering. diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseIOStreamsWithApacheCommonsFileItem.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseIOStreamsWithApacheCommonsFileItem.xml index fe72dc7c7e..9fe4d19ffe 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseIOStreamsWithApacheCommonsFileItem.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseIOStreamsWithApacheCommonsFileItem.xml @@ -138,6 +138,22 @@ public class Foo { return ""; } } +} + ]]> + + + + False negative with method call returning file item + 1 + From 6865c692ea7d651b67c0a73923188831c0ac1336 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 1 Apr 2021 11:01:47 +0200 Subject: [PATCH 082/101] [java] UseStringBufferForStringAppends - fix more false positives Refs #3171 --- .../UseStringBufferForStringAppendsRule.java | 52 +++++++++---------- .../xml/UseStringBufferForStringAppends.xml | 10 ++++ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java index a015b6bc29..295ec35826 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.java.rule.performance; +import java.util.ArrayList; import java.util.List; import net.sourceforge.pmd.lang.ast.Node; @@ -42,10 +43,10 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu return data; } - // Remember how often the variable has been used (assigned a new value or used on the right hand side) + // Remember how often the variable has been used on the right hand side int usageCounter = 0; - // Remember how often the variable has been appended - int appendedCounter = 0; + + List possibleViolations = new ArrayList<>(); for (ASTNamedReferenceExpr usage : node.getLocalUsages()) { if ((node.getNthParent(2) instanceof ASTFieldDeclaration @@ -55,45 +56,40 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu continue; } - boolean isAppend = false; if (usage.getParent() instanceof ASTAssignmentExpression) { ASTAssignmentExpression assignment = (ASTAssignmentExpression) usage.getParent(); // it is either a compound (a += x) - isAppend = assignment.isCompound(); - - if (!isAppend) { - List symbolsOnTheRight = assignment.descendants(ASTInfixExpression.class) - .filter(e -> e.getOperator() == BinaryOp.ADD) - .children(ASTNamedReferenceExpr.class) - .toList(ASTNamedReferenceExpr::getReferencedSym); - // or maybe a append in some way (a = a + x) - isAppend = symbolsOnTheRight.contains(usage.getReferencedSym()); + if (assignment.isCompound()) { + usageCounter++; } + + List symbolsOnTheRight = assignment.descendants(ASTInfixExpression.class) + .filter(e -> e.getOperator() == BinaryOp.ADD) + .children(ASTNamedReferenceExpr.class) + .toList(ASTNamedReferenceExpr::getReferencedSym); + // or maybe a append in some way (a = a + x) + // or a combination (a += a + x) + usageCounter += symbolsOnTheRight.stream().filter(e -> e.equals(usage.getReferencedSym())).count(); } if (usage.getAccessType() == AccessType.WRITE) { - if (isAppend) { - // variable is appended - appendedCounter++; - // and used - usageCounter++; - } else { - // reset counters, if it is a assignment with a new value - usageCounter = 1; - appendedCounter = 0; - } - - if (appendedCounter > 0) { + if (usageCounter > 0) { if (isWithinLoop(usage)) { // always report appends within a loop addViolation(data, usage); - } else if (usageCounter > 1) { - // only report, if it is not the first time - addViolation(data, usage); + } else { + possibleViolations.add(usage); } } } } + + // only report, if it is used more than once + // then all usage locations are reported + if (usageCounter > 1) { + possibleViolations.forEach(v -> addViolation(data, v)); + } + return data; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml index a6038ed448..ad57014c7f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml @@ -584,6 +584,16 @@ public class USeStringBufferForStringAppendsFP { } } private String extract(String s) { return s; } + + private void logMessage(int lineNumber, String message) { + String msg; + msg = message; + if (lineNumber >= 10) { + msg = "TEST" + msg; // FP here + } + log(lineNumber, msg); + } + private void log(int lineNumber, String msg) { } } ]]> From bcde125ada66492ccbff53fe16b65387cf329a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 1 Apr 2021 15:31:24 +0200 Subject: [PATCH 083/101] Fix fp with extends clause --- .../java/rule/bestpractices/LooseCouplingRule.java | 2 ++ .../java/rule/bestpractices/xml/LooseCoupling.xml | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java index 3a43650dde..6e23ccd93f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java @@ -16,6 +16,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTCastExpression; import net.sourceforge.pmd.lang.java.ast.ASTClassLiteral; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; +import net.sourceforge.pmd.lang.java.ast.ASTExtendsList; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTTypeExpression; import net.sourceforge.pmd.lang.java.ast.JavaNode; @@ -55,6 +56,7 @@ public class LooseCouplingRule extends AbstractJavaRulechainRule { || parent instanceof ASTCastExpression // if we allow instanceof, we should allow cast || parent instanceof ASTClassLiteral // ArrayList.class || parent instanceof ASTClassOrInterfaceType // AbstractMap.SimpleEntry + || parent instanceof ASTExtendsList // extends AbstractMap<...> || parent instanceof ASTArrayType && parent.getParent() instanceof ASTArrayAllocation; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml index 6b91f33266..2eb1ca0e01 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml @@ -253,6 +253,17 @@ import java.util.AbstractMap; class Foo { final Object o = new AbstractMap.SimpleEntry<>("", ""); +} + ]]> + + + Extends clause + 0 + { + } ]]> From 86c24760ab5df3b17f26530b368b0e3a3c1bf9b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 1 Apr 2021 15:34:34 +0200 Subject: [PATCH 084/101] Fix fp with this/super qualifier --- .../rule/bestpractices/LooseCouplingRule.java | 4 ++++ .../rule/bestpractices/xml/LooseCoupling.xml | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java index 6e23ccd93f..67b3e3704b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/LooseCouplingRule.java @@ -18,6 +18,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTExtendsList; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTSuperExpression; +import net.sourceforge.pmd.lang.java.ast.ASTThisExpression; import net.sourceforge.pmd.lang.java.ast.ASTTypeExpression; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; @@ -57,6 +59,8 @@ public class LooseCouplingRule extends AbstractJavaRulechainRule { || parent instanceof ASTClassLiteral // ArrayList.class || parent instanceof ASTClassOrInterfaceType // AbstractMap.SimpleEntry || parent instanceof ASTExtendsList // extends AbstractMap<...> + || parent instanceof ASTThisExpression // Enclosing.this + || parent instanceof ASTSuperExpression // Enclosing.super || parent instanceof ASTArrayType && parent.getParent() instanceof ASTArrayAllocation; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml index 2eb1ca0e01..3901ae1697 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/LooseCoupling.xml @@ -264,6 +264,28 @@ import java.util.AbstractMap; class Foo extends AbstractMap { +} + ]]> + + + This/super qualifier + 0 + From c6b8147ec1c94129ec754878a02584284c5d59f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 1 Apr 2021 19:06:02 +0200 Subject: [PATCH 085/101] Fix some javadoc warnings --- .../src/main/java/net/sourceforge/pmd/lang/ast/NodeStream.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/NodeStream.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/NodeStream.java index 68161495c4..931536b857 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/NodeStream.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/NodeStream.java @@ -58,7 +58,7 @@ import net.sourceforge.pmd.lang.ast.internal.StreamImpl; * {@linkplain #followingSiblings() .followingSiblings}() // the stream here contains only the siblings, not the original node * {@linkplain #take(int) .take}(1) // the stream here contains only the first sibling, if it exists * {@linkplain #filterIs(Class) .filterIs}(ASTNumericLiteral.class) - * {@linkplain #filter(Predicate) .filter}(it -> !it.isFloatingPoint() && it.getValueAsInt() == 0) + * {@linkplain #filter(Predicate) .filter}(it -> !it.isFloatingPoint() && it.getValueAsInt() == 0) * {@linkplain #nonEmpty() .nonEmpty}(); // If the stream is non empty here, then all the pipeline matched * * @@ -1079,7 +1079,6 @@ public interface NodeStream<@NonNull T extends Node> extends Iterable<@NonNull T * * @param c1 First type to test * @param rest Other types to test - * @param Input type (this method does not care about it) * @param Output type * * @see #firstNonNull(Function) From b6f2172171047fc3b4baae987f4b5cb4e664f469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 1 Apr 2021 19:09:15 +0200 Subject: [PATCH 086/101] Add nullable annot --- .../main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java index 7aef0067b7..deab5552d8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java @@ -11,6 +11,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.util.CollectionUtil; +import org.checkerframework.checker.nullness.qual.Nullable; /** * Represents the operator of an {@linkplain ASTInfixExpression infix expression}. @@ -176,7 +177,7 @@ public enum BinaryOp implements InternalInterfaces.OperatorLike { * for {@code <=}, returns {@code >}. Returns null if this is another kind * of operator. */ - public BinaryOp getComplement() { + public @Nullable BinaryOp getComplement() { switch (this) { case CONDITIONAL_OR: return CONDITIONAL_AND; case CONDITIONAL_AND: return CONDITIONAL_OR; From 6c667f570e89c7c2de5474e8e49950e263264d60 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 2 Apr 2021 11:10:10 +0200 Subject: [PATCH 087/101] [java] UseStringBufferForStringAppends - fix more fp with simple assignments Refs #3171 --- .../UseStringBufferForStringAppendsRule.java | 20 ++++++++++--------- .../xml/UseStringBufferForStringAppends.xml | 19 +++++++++++++++++- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java index 295ec35826..493a882528 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java @@ -56,6 +56,7 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu continue; } + boolean isSimpleAssignment = false; if (usage.getParent() instanceof ASTAssignmentExpression) { ASTAssignmentExpression assignment = (ASTAssignmentExpression) usage.getParent(); // it is either a compound (a += x) @@ -69,17 +70,18 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu .toList(ASTNamedReferenceExpr::getReferencedSym); // or maybe a append in some way (a = a + x) // or a combination (a += a + x) - usageCounter += symbolsOnTheRight.stream().filter(e -> e.equals(usage.getReferencedSym())).count(); + long usageOnRightHandSide = symbolsOnTheRight.stream().filter(e -> e.equals(usage.getReferencedSym())).count(); + usageCounter += usageOnRightHandSide; + + isSimpleAssignment = !assignment.isCompound() && usageOnRightHandSide == 0; } - if (usage.getAccessType() == AccessType.WRITE) { - if (usageCounter > 0) { - if (isWithinLoop(usage)) { - // always report appends within a loop - addViolation(data, usage); - } else { - possibleViolations.add(usage); - } + if (usage.getAccessType() == AccessType.WRITE && !isSimpleAssignment) { + if (isWithinLoop(usage)) { + // always report appends within a loop + addViolation(data, usage); + } else { + possibleViolations.add(usage); } } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml index ad57014c7f..f30009740b 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml @@ -574,7 +574,7 @@ public class UseStringBufferForStringAppendsFP { 0 + + + + False positive for assignments + 2 + 5,6 + From 89d04f1d0252b95604c4cb38f003d38bf22bcf01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 2 Apr 2021 15:07:59 +0200 Subject: [PATCH 088/101] Fix duplicate import --- .../main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java | 1 - 1 file changed, 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java index deab5552d8..bd06111562 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java @@ -11,7 +11,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.util.CollectionUtil; -import org.checkerframework.checker.nullness.qual.Nullable; /** * Represents the operator of an {@linkplain ASTInfixExpression infix expression}. From 3903f5a4f384595bd8c3b58de8c928506182afd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 2 Apr 2021 16:00:37 +0200 Subject: [PATCH 089/101] Forcibly disable InsufficientStringBufferDeclarationRule This is to avoid errors in CI, like in #3187. This is just a hack, we should fix pmd-regression-tester, or live with it until we have ported all rules. This may not be enough, maybe another rule will take its place and crash everything. --- .../InsufficientStringBufferDeclarationRule.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java index d858e8bd1a..de7b25d5ab 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java @@ -15,6 +15,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTAdditiveExpression; import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression; import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement; import net.sourceforge.pmd.lang.java.ast.ASTCastExpression; +import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; @@ -55,7 +56,10 @@ public class InsufficientStringBufferDeclarationRule extends AbstractJavaRule { public static final int DEFAULT_BUFFER_SIZE = 16; public InsufficientStringBufferDeclarationRule() { - addRuleChainVisit(ASTVariableDeclaratorId.class); + // addRuleChainVisit(ASTVariableDeclaratorId.class); + // fixme this was added to disable the rule and prevent errors in CI + // remove line below and uncomment line above + addRuleChainVisit(ASTCompilationUnit.class); } @Override From b16e80c65fab759a030c2e583908b2d8d1045a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 2 Apr 2021 17:16:24 +0200 Subject: [PATCH 090/101] Fix unresolved references in tests --- .../lang/java/rule/design/xml/DataClass.xml | 2 + .../lang/java/rule/design/xml/NcssCount.xml | 15 +++++--- .../documentation/xml/CommentRequired.xml | 37 ++++++++++++------- .../xml/CloneMethodMustImplementCloneable.xml | 5 ++- .../rule/errorprone/xml/EmptyFinallyBlock.xml | 2 +- .../rule/errorprone/xml/EmptyTryBlock.xml | 12 +++++- .../java/rule/errorprone/xml/EqualsNull.xml | 13 ++++--- .../rule/errorprone/xml/JUnitStaticSuite.xml | 7 ++++ .../xml/TestClassWithoutTestCases.xml | 1 + .../xml/UselessOperationOnImmutable.xml | 6 ++- .../multithreading/xml/DoNotUseThreads.xml | 1 + .../xml/DoubleCheckedLocking.xml | 4 +- .../xml/UseNotifyAllInsteadOfNotify.xml | 8 +++- .../performance/xml/AvoidUsingShortType.xml | 8 +++- .../xml/ConsecutiveAppendsShouldReuse.xml | 12 ++---- .../xml/InefficientStringBuffering.xml | 12 ++++-- .../performance/xml/SimplifyStartsWith.xml | 12 +++--- .../performance/xml/StringInstantiation.xml | 5 ++- .../rule/performance/xml/StringToString.xml | 18 ++++----- .../xml/UseArrayListInsteadOfVector.xml | 1 + .../rule/performance/xml/UseIndexOfChar.xml | 8 ++-- .../rule/security/xml/HardCodedCryptoKey.xml | 11 +++--- .../rule/security/xml/InsecureCryptoIv.xml | 2 + 23 files changed, 130 insertions(+), 72 deletions(-) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/DataClass.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/DataClass.xml index 4add116b13..8abe253f1c 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/DataClass.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/DataClass.xml @@ -5,6 +5,7 @@ xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd"> 10 4 - The class 'Foo' has a NCSS line count of 65 (Highest = 20). + The class 'Foo' has a NCSS line count of 66 (Highest = 21). The constructor 'Foo(int)' has a NCSS line count of 13. The method 'foo()' has a NCSS line count of 14. - The method 'main(String)' has a NCSS line count of 20. + The method 'main(String)' has a NCSS line count of 21. @@ -140,10 +144,10 @@ public class Foo extends Bar { countImports 4 - The class 'Foo' has a NCSS line count of 68 (Highest = 20). + The class 'Foo' has a NCSS line count of 72 (Highest = 21). The constructor 'Foo(int)' has a NCSS line count of 13. The method 'foo()' has a NCSS line count of 14. - The method 'main(String)' has a NCSS line count of 20. + The method 'main(String)' has a NCSS line count of 21. @@ -184,6 +188,7 @@ public class Foo { #1434 CommentRequired raises violation on serialVersionUID field 0 3 @@ -155,7 +156,7 @@ public class CommentRequired implements Serializable { 3 @@ -166,8 +167,9 @@ public class CommentRequired implements Serializable { 0 #1684 comment required on serialPersistentFields of wrong type 1 - 5 + 6 #1684 comment required on serialPersistentFields of wrong visibility 1 - 5 + 7 #1684 comment required on serialPersistentFields not static 1 - 5 + 7 #1684 comment required on serialPersistentFields not final 1 - 5 + 7 #1684 serialPersistentFields comment required Required 1 - 5 + 7 ok, extends superclass AND implements cloneable 0 #1534 [java] CloneMethodMustImplementCloneable: ClassCastException with Annotation (java8) 0 implements @Readonly List<@Readonly T> {} ]]> @@ -201,7 +204,7 @@ class CloneableClass implements TestInterface { 0 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EmptyFinallyBlock.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EmptyFinallyBlock.xml index 97d9fefaf3..6bd7624f01 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EmptyFinallyBlock.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EmptyFinallyBlock.xml @@ -50,7 +50,7 @@ public class EmptyFinallyBlock3 { public class EmptyFinallyBlock4 { public void foo() { try { - } catch (IOException e ){ + } catch (java.io.IOException e){ } catch (Exception e ) { } catch (Throwable t ) { } finally{ diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EmptyTryBlock.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EmptyTryBlock.xml index 3814229345..ac74441716 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EmptyTryBlock.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EmptyTryBlock.xml @@ -54,13 +54,21 @@ public class EmptyTryBlock3 { #432 false positive for empty try-with-resource 0 target.request(mediaTypes).delete(), DELETE, new ExpectedResponse(status, required))) { + try (ClientResponse response = get()) { // false positive } } } - ]]> + ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EqualsNull.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EqualsNull.xml index bdeb1894fb..4cc24992b9 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EqualsNull.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/EqualsNull.xml @@ -9,7 +9,7 @@ 1 0 1 0 0 1 0 1 0 Not a JUnit test (nonstatic is bad) 0 0 0 getSolution() { List result = new ArrayList(); @@ -168,6 +171,7 @@ public class Foo { 1 4 Generics 0 Bar foo() { /* blah */} +public class Foo { + public static Foo foo() { /* blah */} } ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/multithreading/xml/UseNotifyAllInsteadOfNotify.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/multithreading/xml/UseNotifyAllInsteadOfNotify.xml index a5c7622583..b64925f97b 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/multithreading/xml/UseNotifyAllInsteadOfNotify.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/multithreading/xml/UseNotifyAllInsteadOfNotify.xml @@ -73,6 +73,7 @@ public class Foo { 0 0 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidUsingShortType.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidUsingShortType.xml index d7739caf7a..95eecb27da 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidUsingShortType.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidUsingShortType.xml @@ -63,6 +63,7 @@ public class TypeNameWithshort #1449 false positive when casting a variable to short 0 short as method parameter with @Override 0 0 0 0 2, Consecutive appends with reuse, should be ok 0 0 0 2 2 0 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/InefficientStringBuffering.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/InefficientStringBuffering.xml index dea5e40e83..0e7147f5f4 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/InefficientStringBuffering.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/InefficientStringBuffering.xml @@ -71,8 +71,8 @@ public class Foo { case where concatenation is not a child of a BlockStatement, but instead is a child of an ExplicitConstructorInvocation 0 concatenating method + int 0 JTextArea.append 0 3109408, false + with adding two integers in constructor 0 0 0 #1392 SimplifyStartsWith false-negative 1 - 6 + 5 Not a new String 0 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/StringToString.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/StringToString.xml index 3642768b5c..871e545d46 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/StringToString.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/StringToString.xml @@ -114,15 +114,15 @@ public class Foo { #959 StringToString False Positive 0 @@ -133,7 +133,7 @@ public class Foo { 0 msg) { } + private void log(java.util.function.Supplier msg) { } public void run() { String abc = "abc"; log(abc::toString); // fails rule @@ -206,15 +206,15 @@ public class Foo { getString().toString(), object false-positive test 0 10 5,6,7 TEST0 0 #1211 PMD is failing with NPE for rule UseIndexOfChar while analyzing Jdk 8 Lambda expression 0 optionalResult = null; - services.stream() + int getLastSeen() { return 0; } + public void bar(List foos) { + Optional optionalResult = foos.stream() .filter(s -> s.getLastSeen() > 0) .findFirst(); } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/security/xml/HardCodedCryptoKey.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/security/xml/HardCodedCryptoKey.xml index 148506962e..9a7a976ca4 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/security/xml/HardCodedCryptoKey.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/security/xml/HardCodedCryptoKey.xml @@ -25,9 +25,9 @@ public class Foo { 0 0 Date: Fri, 2 Apr 2021 23:46:30 +0200 Subject: [PATCH 091/101] Fix PrettyPrintingUtil::displaySignature with extra dimensions --- .../java/ast/internal/PrettyPrintingUtil.java | 5 ++++ .../ast/internal/PrettyPrintingUtilTest.java | 24 +++++++++++++++++++ .../lang/java/metrics/impl/xml/LocTest.xml | 2 +- .../lang/java/metrics/impl/xml/NcssTest.xml | 4 ++-- .../lang/java/rule/design/xml/NcssCount.xml | 4 ++-- 5 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtilTest.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java index def163cf40..e5d3aed293 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java @@ -12,6 +12,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters; +import net.sourceforge.pmd.lang.java.ast.ASTList; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType; @@ -44,6 +45,10 @@ public final class PrettyPrintingUtil { first = false; prettyPrintTypeNode(param.getTypeNode(), sb); + int extraDimensions = ASTList.sizeOrZero(param.getVarId().getExtraDimensions()); + while (extraDimensions-- > 0) { + sb.append("[]"); + } } sb.append(')'); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtilTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtilTest.java new file mode 100644 index 0000000000..d9dda43384 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtilTest.java @@ -0,0 +1,24 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast.internal; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; +import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; + +public class PrettyPrintingUtilTest extends BaseNonParserTest { + + @Test + void displaySignatureTestWithExtraDimensions() { + ASTCompilationUnit root = java.parse("class A { public void foo(String[] a[]) {} "); + ASTMethodDeclaration m = root.descendants(ASTMethodDeclaration.class).firstOrThrow(); + + assertEquals("foo(String[][])", PrettyPrintingUtil.displaySignature(m)); + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/LocTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/LocTest.xml index 5365271dcd..618c4f0af0 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/LocTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/LocTest.xml @@ -71,7 +71,7 @@ public class Foo { 'Foo' has value 58. 'Foo#foo()' has value 1. - 'Foo#main(String)' has value 40. + 'Foo#main(String[])' has value 40. diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml index 265b73d68f..fabd73fecd 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NcssTest.xml @@ -130,7 +130,7 @@ public class Foo extends Bar { 'com.company.money.Foo#Foo()' has value 2. 'com.company.money.Foo#Foo(int)' has value 13. 'com.company.money.Foo#foo()' has value 14. - 'com.company.money.Foo#main(String)' has value 21. + 'com.company.money.Foo#main(String[])' has value 21. @@ -145,7 +145,7 @@ public class Foo extends Bar { 'com.company.money.Foo#Foo()' has value 2. 'com.company.money.Foo#Foo(int)' has value 13. 'com.company.money.Foo#foo()' has value 14. - 'com.company.money.Foo#main(String)' has value 21. + 'com.company.money.Foo#main(String[])' has value 21. diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NcssCount.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NcssCount.xml index 5daee1a3bd..33fbcf4ab3 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NcssCount.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/NcssCount.xml @@ -132,7 +132,7 @@ public class Foo extends Bar { The class 'Foo' has a NCSS line count of 66 (Highest = 21). The constructor 'Foo(int)' has a NCSS line count of 13. The method 'foo()' has a NCSS line count of 14. - The method 'main(String)' has a NCSS line count of 21. + The method 'main(String[])' has a NCSS line count of 21. @@ -147,7 +147,7 @@ public class Foo extends Bar { The class 'Foo' has a NCSS line count of 72 (Highest = 21). The constructor 'Foo(int)' has a NCSS line count of 13. The method 'foo()' has a NCSS line count of 14. - The method 'main(String)' has a NCSS line count of 21. + The method 'main(String[])' has a NCSS line count of 21. From 363aeb05a7ac81c246fe4073f4a95cb844bb812a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 3 Apr 2021 00:19:21 +0200 Subject: [PATCH 092/101] Remove more unresolved references --- .../UnnecessaryFullyQualifiedNameTest.java | 11 +- .../Container.java | 12 + .../MyClass.java | 9 + .../bestpractices/xml/UnusedPrivateMethod.xml | 303 +++++++----------- .../xml/UnnecessaryAnnotationValueElement.xml | 6 + .../codestyle/xml/UnnecessaryConstructor.xml | 2 +- .../xml/UnnecessaryFullyQualifiedName.xml | 45 ++- .../xml/UnnecessaryLocalBeforeReturn.xml | 29 +- .../rule/codestyle/xml/UselessParentheses.xml | 69 ++-- .../codestyle/xml/UselessQualifiedThis.xml | 22 +- .../design/xml/SimplifyBooleanReturns.xml | 4 + 11 files changed, 250 insertions(+), 262 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/unnecessaryfullyqualifiedname/Container.java create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/unnecessaryfullyqualifiedname/MyClass.java diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameTest.java index 151748731b..c4670b7a95 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameTest.java @@ -25,6 +25,7 @@ public class UnnecessaryFullyQualifiedNameTest extends PmdRuleTst { // #1546 part 1 UnnecessaryFullyQualifiedName doesn't take into consideration conflict resolution // #1546 part 2 UnnecessaryFullyQualifiedName doesn't take into consideration conflict resolution public static class PhonyMockito { + public static final int TWO = 2; public static T mock(Class clazz) { @@ -32,9 +33,13 @@ public class UnnecessaryFullyQualifiedNameTest extends PmdRuleTst { } } - public static class PhonyPowerMockito { - public static T mock(Class clazz) { - return null; + static class Container { + + public static class PhonyMockito { + + public static T mock(Class clazz) { + return null; + } } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/unnecessaryfullyqualifiedname/Container.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/unnecessaryfullyqualifiedname/Container.java new file mode 100644 index 0000000000..98891eacc9 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/unnecessaryfullyqualifiedname/Container.java @@ -0,0 +1,12 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.codestyle.unnecessaryfullyqualifiedname; + + +public class Container { + public static class MyClass { + + } +} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/unnecessaryfullyqualifiedname/MyClass.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/unnecessaryfullyqualifiedname/MyClass.java new file mode 100644 index 0000000000..4945c55977 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/unnecessaryfullyqualifiedname/MyClass.java @@ -0,0 +1,9 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.codestyle.unnecessaryfullyqualifiedname; + + +public class MyClass { +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml index f6b869b292..dc0ab2332e 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml @@ -221,7 +221,7 @@ public class Foo { foo("hi"); } private void foo(String y) {} - public void foo(List y) {} + public void foo(Integer y) {} } ]]> @@ -231,7 +231,7 @@ public class Foo { 1 7 - Avoid unused private methods such as 'foo(List)'. + Avoid unused private methods such as 'foo(Integer)'. @@ -351,12 +351,12 @@ public class PMDFalsePositiveTest { 0 @@ -422,8 +422,9 @@ public class Foo { #1228 UnusedPrivateMethod returns false positives (1) 0 @@ -443,10 +444,13 @@ public class Foo { #1228 UnusedPrivateMethod returns false positives (2) 0 #1228 UnusedPrivateMethod returns false positives (3) 0 @@ -509,36 +511,14 @@ public class Foo { #1228 UnusedPrivateMethod returns false positives (4) 0 @@ -548,9 +528,10 @@ public class Foo { #1228 UnusedPrivateMethod returns false positives (5a) 0 @@ -568,10 +548,11 @@ public class Foo extends MultiActionController { #1228 UnusedPrivateMethod returns false positives (5b) 0 @@ -865,66 +845,25 @@ public class Foo { #1228 UnusedPrivateMethod returns false positives (7) 0 = 0) { - Enumeration e = node.children(); - while (e.hasMoreElements()) { - TreeNode n = (TreeNode) e.nextElement(); - TreePath path = parent.pathByAddingChild(n); - visitAll(tree, path, expand); // line 37 - } - } - if (expand) { - tree.expandPath(parent); - } else { - tree.collapsePath(parent); - } - } - public static void main(String[] args) { - EventQueue.invokeLater(new Runnable() { - @Override public void run() { - createAndShowGUI(); + visitAll(tree, true); // line 14 } }); + return p; } - public static void createAndShowGUI() { - JFrame f = new JFrame(); - f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - f.getContentPane().add(new Bar().makeUI()); - f.setSize(320, 240); - f.setLocationRelativeTo(null); - f.setVisible(true); - } + private static void visitAll(JTree tree, boolean expand) { } } ]]> @@ -933,17 +872,17 @@ public class Bar { #1234 Unused private methods still giving false positives in 5.1.3 snapshot 0 > bliCodeCache; public List getBliCodeByFiscalYear(int fiscalYear) { List records = bliCodeCache.get(fiscalYear); if (records == null) { - logger.info("No BLI Code records cached for year : " + fiscalYear + ". Caching now."); records = this.selectBLICodeByFiscalYear(fiscalYear); bliCodeCache.put(fiscalYear, records); } - if (records == null) { - logger.error("Could not load BLI Code DATA. No records retrieved."); - } return records; } @@ -953,14 +892,7 @@ public class Foo { * @return an List of BLI Codes */ private List selectBLICodeByFiscalYear(int fy) { - - List result = new ArrayList(); - try { - result = spiStripFieldService.getBliCodeList(fy); - } catch (ServiceException se) { - logger.error("Error getting BLI Code DATA: " + se.getMessage(), se); - } - return result; + return null; } } ]]> @@ -1226,22 +1158,19 @@ public class TestPrivate { #1261 False positive "Avoid unused private methods" with Generics 4 0 , X extends Map> void createLedgerAndChangeHistory(T oldObject, X updatedObject, boolean isChildLedgerEntry) throws ServiceException { - Map.Entry entry = new Map.Entry(); + public , X extends Map> void createLedgerAndChangeHistory(T oldObject, X updatedObject, boolean isChildLedgerEntry) { - try { - if (oldObject instanceof BudgetPackage || oldObject instanceof SpiEntity) { - setTotals(oldObject); - } - // do other stuff - } catch (ServiceException e) { + if (oldObject instanceof TestPrivate) { + setTotals(oldObject); } + // do other stuff } - private void setTotals(X ledgerable) throws ServiceException { + private void setTotals(X ledgerable) { // do stuff } } @@ -1404,17 +1333,17 @@ public class UnusedPrivateMethodWithEnum { 0 #1395 UnusedPrivateMethod false positive for array element method call 0 0 actual - = Combiners.mapMerge(mapOf(annPurse5, bobPurse7), mapOf(bobPurse9, calPurse10), ADDITION); - assertEquals(mapOf(annPurse5, bobPurse16, calPurse10), actual); +import my.Combiners; + +public class Purse { + + Purse annPurse5, bobPurse7, bobPurse9, calPurse10, bobPurse16; + + public void mapMergeShouldReturnTheUnionWhenGivenDifferentSetsWithSomeCommonValues() { + Combiners.mapMerge(mapOf(annPurse5, bobPurse7), mapOf(bobPurse9, calPurse10)); } + private static Map mapOf(final Purse... values) { return mapOf2(Purse::getOwner, values); } + private static Map mapOf2(final Function keyMapper, final V... values) { return Stream.of(values).collect(Collectors.toMap(keyMapper, Function.identity())); } + + String getOwner() { return "me"; } + + static class Combiners { + + static Map mapMerge(Map m1, Map m2) { + return m2; + } + } } ]]> @@ -1501,51 +1448,29 @@ public class Something { #1405 UnusedPrivateMethod false positive? 0 - getProductImageUrls(final ApparelStyleVariantProductModel product, final String format) { + getProductImageUrls(final Blabla product, final String format) { return getImageUrlsListForVariant(product, format); } - private List getImageUrlsListForVariant(final VariantProductModel variant, final String format) { - final SortedMap imageUrls = getImageUrlsMapForVariant(variant, format); - return new ArrayList(imageUrls.values()); + private List getImageUrlsListForVariant(final Sup variant, final String format) { } } ]]> - - #1412 UnusedPrivateMethod false positive: Issue #1403 not completely solved - 0 - (); - annPurse5 = new Purse(ANN, 5); - bobPurse7 = new Purse(BOB, 7); - } - @Test public void mapMergeShouldReturnTheUnionWhenGivenDifferentSetsWithSomeCommonValues() { - final Map actual - = Combiners.mapMerge(mapOf(annPurse5, bobPurse7), mapOf(bobPurse9, calPurse10), ADDITION); - assertEquals(mapOf(annPurse5, bobPurse16, calPurse10), actual); - } - private static Map mapOf(final Purse... values) { - return mapOf(Purse::getOwner, values); - } - private static Map mapOf(final Function keyMapper, final V... values) { - return Stream.of(values).collect(Collectors.toMap(keyMapper, Function.identity())); - } -} - ]]> - #521 UnusedPrivateMethod returns false positives with primitive data type in map argument 0 map = new LinkedHashMap<>(); @@ -1580,8 +1505,9 @@ class Foo { test(); } - private void test(@AnnotatedUsage Foo this) { + private void test(@Annotated Foo this) { } + @interface Annotated {} } ]]> @@ -1658,6 +1584,7 @@ public class UnusedPrivateMethodFP { 0 UnusedPrivateMethod false positive #2890 0 optionIndexes, MenuEntry[] entries, int index1, int index2) { - MenuEntry entry1 = entries[index1], - entry2 = entries[index2]; - entries[index1] = entry2; - entries[index2] = entry1; + public void swap(Map> optionIndexes, Object[] entries, int index1, int index2) { - client.setMenuEntries(entries); - - // Update optionIndexes - String option1 = Text.removeTags(entry1.getOption()).toLowerCase(), - option2 = Text.removeTags(entry2.getOption()).toLowerCase(); - - List list1 = optionIndexes.get(option1), - list2 = optionIndexes.get(option2); - - // call remove(Object) instead of remove(int) - list1.remove((Integer) index1); - list2.remove((Integer) index2); + List list1 = optionIndexes.get("option1"), + list2 = optionIndexes.get("option2"); sortedInsert(list1, index2); sortedInsert(list2, index1); @@ -1753,11 +1669,6 @@ public class UnusedPrivateMethodFP { } private static void testNoChangeOnFlip(CharSequence chars) { - for (int index = 0; index < chars.length(); index++) { - char expected = chars.charAt(index); - char actual = CharacterUtils.flipCase(expected); - assertEquals("Unexpected flipped value", expected, actual); - } } } ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryAnnotationValueElement.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryAnnotationValueElement.xml index 22f9ce88f4..a0e5124306 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryAnnotationValueElement.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryAnnotationValueElement.xml @@ -17,6 +17,7 @@ public class Foo { return; } } +@interface TestClassAnnotation { String value(); } ]]> @@ -33,6 +34,7 @@ public class Foo { return; } } +@interface TestMemberAnnotation { String value(); } ]]> @@ -49,6 +51,7 @@ public class Foo { return; } } +@interface TestMethodAnnotation { String value(); } ]]> @@ -65,6 +68,7 @@ public class Foo { return; } } +@interface TestMethodAnnotation { String value(); } ]]> @@ -81,6 +85,7 @@ public class Foo { return; } } +@interface TestMethodAnnotation { String value(); } ]]> @@ -97,6 +102,7 @@ public class Foo { return; } } +@interface TestMethodAnnotation { String value(); } ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryConstructor.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryConstructor.xml index 3d14e79550..1754836837 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryConstructor.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryConstructor.xml @@ -51,7 +51,7 @@ public class Foo { 0 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml index a456bce072..e59544b468 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryFullyQualifiedName.xml @@ -286,7 +286,7 @@ public class Test {} #1404 Java8 'Unnecessary use of fully qualified name' in Streams Collector 1 - 18 + 15 Unnecessary qualifier 'Collectors': 'toList' is already in scope @@ -294,21 +294,18 @@ public class Test {} // https://github.com/FenixEdu/fenixedu-learning/blob/master/src/main/java/org/fenixedu/learning/domain/executionCourse/components/InitialPageComponent.java#L50 import java.util.Comparator; import java.util.List; +import java.util.ArrayList; +import java.util.Map; import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; -public class InitialPageComponent extends BaseExecutionCourseComponent { - public void handle(Page page, TemplateContext componentContext, TemplateContext globalContext) { - ExecutionCourse executionCourse = ((ExecutionCourseSite) page.getSite()).getExecutionCourse(); - globalContext.put( - "professorships", - executionCourse - .getProfessorshipsSet() - .stream() - .sorted(Comparator.comparing(Professorship::isResponsibleFor).reversed() - .thenComparing(Professorship.COMPARATOR_BY_PERSON_NAME)) - .collect(Collectors.toList())); +public class InitialPageComponent { + public void handle(Map> globalContext) { + List lst = new ArrayList<>(); + globalContext.put("professorships", + lst.stream().sorted(Comparator.comparingInt(String::length).reversed() + .collect(Collectors.toList()))); } } ]]> @@ -338,10 +335,10 @@ public class UnnecessaryFullyQualifiedName { @@ -352,10 +349,10 @@ public class Foo { @@ -388,13 +385,12 @@ final class Test { #1114 - Star import overwritten by explicit import is not correctly handled 0 @@ -724,7 +720,7 @@ public class SomeClass { package ohio; public class InnerClass { - public void method1() throws RuntimeException, RE, + public void method1() throws RuntimeException, java.lang.RuntimeException { } } @@ -818,7 +814,7 @@ class Assert { Just the Map prefix is a violation 1 - 6 + 7 Unnecessary qualifier 'java.util': 'Map' is already in scope because it is imported in this file @@ -826,8 +822,9 @@ class Assert { package a; import java.util.Map; + import java.util.Set; - class A { + class A { public Set> entrySet() {return null;} } ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryLocalBeforeReturn.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryLocalBeforeReturn.xml index 1afde48b6d..82b7df07dc 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryLocalBeforeReturn.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryLocalBeforeReturn.xml @@ -147,16 +147,11 @@ public class Foo { #933 UnnecessaryLocalBeforeReturn false positive for SuppressWarnings annotation 0 > T findEventTypeValueByName(Class entityClass, String eventTypeName, String eventTypeValueName) { - Criteria criteria = this.session.createCriteria(entityClass) - .add(Restrictions.eq(UserVisibleEventTypeValue_.internalName, eventTypeValueName)) - .createCriteria(UserVisibleEventTypeValue_.type) - .add(Restrictions.eq(UserVisibleEventType_.name, eventTypeName)) - .setCacheable(true); - +public class TestCase { + T getSomeT() { return null; } + private static T findEventTypeValueByName(TestCase unchecked) { @SuppressWarnings("unchecked") - T result = (T) criteria.uniqueResult(); + T result = (T) unchecked.getSomeT(); return result; } } @@ -167,6 +162,9 @@ public class UnnecessaryLocalBeforeReturnCase { #282 UnnecessaryLocalBeforeReturn false positive when cloning Maps 0 customerErrors = new ConcurrentHashMap<>(); @@ -188,7 +186,7 @@ public class CustomerErrorCollector { #310 UnnecessaryLocalBeforeReturn enhancement is overly restrictive -- method order matters 0 @@ -211,7 +213,7 @@ public class UnnecessaryLocalBeforeReturnFP { 2 3,10 @@ -264,6 +270,7 @@ public class ObjectCreator { FP with captured method reference 0 create() { final Object o = new Object(); // captured by the method ref diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UselessParentheses.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UselessParentheses.xml index c9ebf7383a..de3cf18adc 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UselessParentheses.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UselessParentheses.xml @@ -134,8 +134,12 @@ public class Foo { false negatives false 8 - 4,6,10,15,16,17,18,19 + 8,10,14,19,20,21,22,23 = 0) // and here ? name.substring(colonIndex + 1) : name; } - public void viewerModelChanged(ViewerModelEvent e) { + public void viewerModelChanged() { int startOffset = (unresolved1 + unresolved2) - 1; // here, the parenthesized expr has unresolved type startOffset = (unresolved1 + 1) - 1; // here, the parenthesized expr has resolved type startOffset = (1 + unresolved1) - 1; @@ -221,13 +225,16 @@ public class Test { 0 @@ -237,9 +244,11 @@ public class Test { #1111 False positive: Useless parentheses 0 @@ -248,8 +257,9 @@ return (absolute ? amount.abs() : amount).toString(); 0 > 1); + int getX() { return 0; } + public void foo(Test e) { + xCoord = e.getX() - (1 >> 1); } } ]]> @@ -326,7 +336,7 @@ class ExampleClass { eGood = (a > b) + c; eGood = (a <= b) + c; eGood = (a >= b) + c; - eGood = (a instanceof b) + c; + eGood = (a instanceof String) + c; eGood = (a == b) + c; eGood = (a != b) + c; eGood = (a & b) + c; @@ -357,17 +367,19 @@ public class Example { 2 3,7 @@ -377,6 +389,8 @@ public class Useless { 0 0 0 From controversial/UnnecessaryParentheses: #537 Trivial case with additive expression 1 From controversial/UnnecessaryParentheses: #537 Trivial case with additive expression modified 0 1 @@ -470,9 +492,11 @@ public class Foo { 0 @@ -532,6 +556,7 @@ public class Test { [java] False positive "UselessParentheses" for parentheses that contain assignment #1285 0 0 @@ -102,8 +105,11 @@ public class Foo { #1422 UselessQualifiedThis: False positive with Java 8 Function 0 handleApiAggregateException(final ApiAggregateException e) { + public final List handleApiAggregateException(final ApiError e) { return e.getCauses().stream().map( ApiExceptionCtrlAdvice::toApiError ).collect(Collectors.toList()); @@ -111,8 +117,14 @@ public class ApiExceptionCtrlAdvice { private static ApiError toApiError(final Throwable e) { return new ApiError() .withException(e.getClass().getName()) - .withCause(Optional.ofNullable(e.getCause()).map(Throwable::getClass).map(Class::getName).orElse(EMPTY)) - .withMessage(Optional.ofNullable(e.getMessage()).orElse(EMPTY)); + .withCause(Optional.ofNullable(e.getCause()).map(Throwable::getClass).map(Class::getName).orElse("")) + .withMessage(Optional.ofNullable(e.getMessage()).orElse("")); + } + class ApiError { + List getCauses() {return List.of(); } + ApiError withException(String s) { return this; } + ApiError withCause(String s) { return this; } + ApiError withMessage(String s) { return this; } } } ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanReturns.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanReturns.xml index a46c5a7175..18d9cb33c9 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanReturns.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanReturns.xml @@ -74,6 +74,7 @@ public class Foo { 1 myObjectList; public boolean exists(Object obj) { if (myObjectList.contains(obj)) { return true; @@ -89,6 +90,7 @@ public class SimplifyBooleanReturns { 1 myObjectList; public boolean exists(Object obj) { if (myObjectList.contains(obj)) return true; @@ -102,6 +104,7 @@ public class SimplifyBooleanReturns { 1 myObjectList; public boolean exists(Object obj) { if (myObjectList.contains(obj)) return obj != null; @@ -115,6 +118,7 @@ public class SimplifyBooleanReturns { 1 myObjectList; public boolean exists(Object obj) { if (myObjectList.contains(obj)) return obj.getClass().equals(String.class); From b70ded59cabe436bbbc74b4331c5b38de5999c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 3 Apr 2021 02:43:17 +0200 Subject: [PATCH 093/101] Checkstyle --- .../pmd/lang/java/ast/internal/PrettyPrintingUtilTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtilTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtilTest.java index d9dda43384..c28a42ca8d 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtilTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtilTest.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.java.ast.internal; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; From 6671963ea222b230edd622360a8b8b2a3e703882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 3 Apr 2021 04:58:44 +0200 Subject: [PATCH 094/101] Remove some kotlin warnings --- .../sourceforge/pmd/lang/java/ast/NodeParsingCtx.kt | 12 +++++++----- .../symbols/table/internal/MemberInheritanceTest.kt | 1 + .../symbols/table/internal/TypeParamScopingTest.kt | 2 +- .../pmd/lang/java/symbols/table/internal/Utils.kt | 4 ++-- .../java/symbols/table/internal/VarScopingTest.kt | 1 + .../sourceforge/pmd/lang/java/types/SubtypingTest.kt | 2 +- .../lang/java/types/internal/infer/AnonCtorsTest.kt | 1 + .../java/types/internal/infer/LambdaInferenceTest.kt | 1 + .../types/internal/infer/MethodRefInferenceTest.kt | 4 +--- .../pmd/lang/java/types/internal/infer/StressTest.kt | 2 +- 10 files changed, 17 insertions(+), 13 deletions(-) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/NodeParsingCtx.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/NodeParsingCtx.kt index 3a11287703..adbecd7183 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/NodeParsingCtx.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/NodeParsingCtx.kt @@ -83,7 +83,8 @@ object ExpressionParsingCtx : NodeParsingCtx("expression") { override fun retrieveNode(acu: ASTCompilationUnit): ASTExpression = StatementParsingCtx.retrieveNode(acu) - .getFirstDescendantOfType(ASTExpression::class.java)!! + .descendants(ASTExpression::class.java) + .firstOrThrow() } object StatementParsingCtx : NodeParsingCtx("statement") { @@ -94,7 +95,8 @@ object StatementParsingCtx : NodeParsingCtx("statement") { override fun retrieveNode(acu: ASTCompilationUnit): ASTStatement = TypeBodyParsingCtx.retrieveNode(acu) - .getFirstDescendantOfType(ASTBlock::class.java).getChild(0) + .descendants(ASTBlock::class.java) + .firstOrThrow().getChild(0) } object TypeBodyParsingCtx : NodeParsingCtx("body declaration") { @@ -113,7 +115,7 @@ $construct } override fun retrieveNode(acu: ASTCompilationUnit): ASTBodyDeclaration = - acu.typeDeclarations.firstOrThrow().getFirstDescendantOfType(ASTBodyDeclaration::class.java) + acu.typeDeclarations.firstOrThrow().getDeclarations().firstOrThrow() } object TopLevelTypeDeclarationParsingCtx : NodeParsingCtx("top-level declaration") { @@ -123,7 +125,7 @@ object TopLevelTypeDeclarationParsingCtx : NodeParsingCtx $construct """.trimIndent() - override fun retrieveNode(acu: ASTCompilationUnit): ASTAnyTypeDeclaration = acu.getFirstDescendantOfType(ASTAnyTypeDeclaration::class.java)!! + override fun retrieveNode(acu: ASTCompilationUnit): ASTAnyTypeDeclaration = acu.typeDeclarations.firstOrThrow() } object TypeParsingCtx : NodeParsingCtx("type") { @@ -144,7 +146,7 @@ object AnnotationParsingCtx : NodeParsingCtx("annotation") { override fun retrieveNode(acu: ASTCompilationUnit): ASTAnnotation = StatementParsingCtx.retrieveNode(acu) - .getFirstDescendantOfType(ASTAnnotation::class.java)!! + .descendants(ASTAnnotation::class.java).firstOrThrow() } object TypeParametersParsingCtx : NodeParsingCtx("type parameters") { diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/MemberInheritanceTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/MemberInheritanceTest.kt index 2467637f01..908c56d47e 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/MemberInheritanceTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/MemberInheritanceTest.kt @@ -19,6 +19,7 @@ import net.sourceforge.pmd.lang.java.types.JClassType import net.sourceforge.pmd.lang.java.types.JVariableSig import net.sourceforge.pmd.lang.java.types.typeDsl +@Suppress("UNUSED_VARIABLE") class MemberInheritanceTest : ParserTestSpec({ parserTest("Test problem with values scope in enum") { diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/TypeParamScopingTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/TypeParamScopingTest.kt index 332bbad049..0b7e39dc9f 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/TypeParamScopingTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/TypeParamScopingTest.kt @@ -155,7 +155,7 @@ class TypeParamScopingTest : ParserTestSpec({ """) // type parameters - val (x, t, t2, y2) = acu.descendants(ASTTypeParameter::class.java).toList() + val (x, _, t2, _) = acu.descendants(ASTTypeParameter::class.java).toList() // parameters val (pt, px) = acu.descendants(ASTFormalParameter::class.java).map { it.typeNode }.toList() diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/Utils.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/Utils.kt index 118d154526..7dfe9f0479 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/Utils.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/Utils.kt @@ -31,11 +31,11 @@ inline fun JSymbolTable.shouldResolveVarTo(simpleN } infix fun JavaNode.shouldResolveToField(fieldId: ASTVariableDeclaratorId): JFieldSymbol = - symbolTable.shouldResolveVarTo(fieldId.variableName, fieldId.symbol as JFieldSymbol) + symbolTable.shouldResolveVarTo(fieldId.name, fieldId.symbol as JFieldSymbol) infix fun JavaNode.shouldResolveToLocal(localId: ASTVariableDeclaratorId): JLocalVariableSymbol = - symbolTable.shouldResolveVarTo(localId.variableName, localId.symbol as JLocalVariableSymbol) + symbolTable.shouldResolveVarTo(localId.name, localId.symbol as JLocalVariableSymbol) inline fun JSymbolTable.shouldResolveVarTo(simpleName: String): T = diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/VarScopingTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/VarScopingTest.kt index 95919d8843..b38e96703a 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/VarScopingTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/VarScopingTest.kt @@ -16,6 +16,7 @@ import net.sourceforge.pmd.lang.java.symbols.JFormalParamSymbol import net.sourceforge.pmd.lang.java.symbols.JLocalVariableSymbol import java.lang.reflect.Modifier +@Suppress("UNUSED_VARIABLE") class VarScopingTest : ProcessorTestSpec({ parserTest("Shadowing of variables") { diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/SubtypingTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/SubtypingTest.kt index 2ccb8e2340..e68829ae27 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/SubtypingTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/SubtypingTest.kt @@ -139,7 +139,7 @@ class SubtypingTest : FunSpec({ test("Test capture variable subtyping") { - val (k, f, c) = ParserTestCtx().makeDummyTVars("K", "F", "C") + val (k, f) = ParserTestCtx().makeDummyTVars("K", "F") val wild = `?` `super` k val superList = capture(List::class[wild]) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/AnonCtorsTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/AnonCtorsTest.kt index 29fcec8816..4fddf25782 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/AnonCtorsTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/AnonCtorsTest.kt @@ -14,6 +14,7 @@ import net.sourceforge.pmd.lang.java.types.* /** * @author Clément Fournier */ +@Suppress("UNUSED_VARIABLE") class AnonCtorsTest : ProcessorTestSpec({ diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/LambdaInferenceTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/LambdaInferenceTest.kt index cae1d44d62..2efbe3e02b 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/LambdaInferenceTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/LambdaInferenceTest.kt @@ -17,6 +17,7 @@ import java.util.function.DoubleConsumer import java.util.function.Supplier import kotlin.test.assertEquals +@Suppress("UNUSED_VARIABLE") class LambdaInferenceTest : ProcessorTestSpec({ diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/MethodRefInferenceTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/MethodRefInferenceTest.kt index 5b79f1a18b..a68789e7f3 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/MethodRefInferenceTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/MethodRefInferenceTest.kt @@ -16,9 +16,7 @@ import java.util.function.* import java.util.stream.Collector import java.util.function.Function as JavaFunction -/** - * - */ +@Suppress("UNUSED_VARIABLE") class MethodRefInferenceTest : ProcessorTestSpec({ diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/StressTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/StressTest.kt index 12152b90ac..35c47a0522 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/StressTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/StressTest.kt @@ -230,7 +230,7 @@ class StressTest : ProcessorTestSpec({ acu.descendants(ASTLocalVariableDeclaration::class.java) .map { it.varIds[0]!! } - .filter { it.variableName.startsWith("asList") } + .filter { it.name.startsWith("asList") } .map { it.initializer!! } .forEachIndexed { i, expr -> val t = measureTimeMillis { From 6680b54577ba5692c94bd6196cf1622b30bfd4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 3 Apr 2021 19:11:21 +0200 Subject: [PATCH 095/101] Remove intermediary list --- .../UseStringBufferForStringAppendsRule.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java index 493a882528..2f4a5de4da 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java @@ -20,7 +20,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRule { @@ -64,13 +63,17 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu usageCounter++; } - List symbolsOnTheRight = assignment.descendants(ASTInfixExpression.class) - .filter(e -> e.getOperator() == BinaryOp.ADD) - .children(ASTNamedReferenceExpr.class) - .toList(ASTNamedReferenceExpr::getReferencedSym); + int usageOnRightHandSide = + assignment.getRightOperand() + .descendantsOrSelf() + .filterIs(ASTInfixExpression.class) + .filter(e -> e.getOperator() == BinaryOp.ADD) + .children(ASTNamedReferenceExpr.class) + .filterMatching(ASTNamedReferenceExpr::getReferencedSym, node.getSymbol()) + .count(); + // or maybe a append in some way (a = a + x) // or a combination (a += a + x) - long usageOnRightHandSide = symbolsOnTheRight.stream().filter(e -> e.equals(usage.getReferencedSym())).count(); usageCounter += usageOnRightHandSide; isSimpleAssignment = !assignment.isCompound() && usageOnRightHandSide == 0; From bdd19af1f7ca55592276f79856781439c62b3295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 3 Apr 2021 20:59:53 +0200 Subject: [PATCH 096/101] Remove some magic numbers --- .../java/ast/ASTVariableDeclaratorId.java | 31 ++++++++++++++++--- .../UseStringBufferForStringAppendsRule.java | 13 ++------ .../pmd/lang/java/symbols/JFieldSymbol.java | 4 +++ .../lang/java/symbols/JVariableSymbol.java | 9 ++++++ 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java index 41659a2f0e..3e5fd8214b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.java @@ -188,10 +188,31 @@ public final class ASTVariableDeclaratorId extends AbstractTypedSymbolDeclarator /** - * Returns true if this node declares a local variable. + * Returns true if this node declares a local variable from within + * a regular {@link ASTLocalVariableDeclaration}. */ public boolean isLocalVariable() { - return getNthParent(2) instanceof ASTLocalVariableDeclaration; + return getNthParent(2) instanceof ASTLocalVariableDeclaration + && !isResourceDeclaration() + && !isForeachVariable(); + } + + /** + * Returns true if this node is a variable declared in a + * {@linkplain ASTForeachStatement foreach loop}. + */ + public boolean isForeachVariable() { + // Foreach/LocalVarDecl/VarDeclarator/VarDeclId + return getNthParent(3) instanceof ASTForeachStatement; + } + + /** + * Returns true if this node is a variable declared in the init clause + * of a {@linkplain ASTForStatement for loop}. + */ + public boolean isForLoopVariable() { + // For/ForInit/LocalVarDecl/VarDeclarator/VarDeclId + return getNthParent(3) instanceof ASTForInit; } @@ -206,8 +227,10 @@ public final class ASTVariableDeclaratorId extends AbstractTypedSymbolDeclarator /** - * Returns true if this node declares a field. - * TODO should this return true if this is an enum constant? + * Returns true if this node declares a field from a regular + * {@link ASTFieldDeclaration}. This returns false for enum + * constants (use {@link JVariableSymbol#isField() getSymbol().isField()} + * if you want that). */ public boolean isField() { return getNthParent(2) instanceof ASTFieldDeclaration; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java index 2f4a5de4da..ce76450649 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java @@ -11,10 +11,6 @@ import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.AccessType; import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression; -import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTForStatement; -import net.sourceforge.pmd.lang.java.ast.ASTForeachStatement; -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; @@ -36,9 +32,7 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu */ @Override public Object visit(ASTVariableDeclaratorId node, Object data) { - if (!TypeTestUtil.isA(String.class, node) || node.hasArrayType() - || node.getNthParent(3) instanceof ASTForStatement - || node.getNthParent(3) instanceof ASTForeachStatement) { + if (!TypeTestUtil.isA(String.class, node) || node.isForeachVariable()) { return data; } @@ -48,9 +42,8 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu List possibleViolations = new ArrayList<>(); for (ASTNamedReferenceExpr usage : node.getLocalUsages()) { - if ((node.getNthParent(2) instanceof ASTFieldDeclaration - || node.getParent() instanceof ASTFormalParameter) - && isNotWithinLoop(usage)) { + if ((node.isField() || node.isFormalParameter()) + && isNotWithinLoop(usage)) { // ignore if the field or formal parameter is *not* used within loops continue; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JFieldSymbol.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JFieldSymbol.java index 2b34afd0c2..969a48c6a4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JFieldSymbol.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JFieldSymbol.java @@ -17,6 +17,10 @@ import org.checkerframework.checker.nullness.qual.Nullable; */ public interface JFieldSymbol extends JAccessibleElementSymbol, JVariableSymbol { + @Override + default boolean isField() { + return true; + } /** Returns true if this field is an enum constant. */ boolean isEnumConstant(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JVariableSymbol.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JVariableSymbol.java index 2b407ea2f6..93b0e7e2fb 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JVariableSymbol.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JVariableSymbol.java @@ -18,6 +18,15 @@ import net.sourceforge.pmd.lang.java.types.Substitution; */ public interface JVariableSymbol extends BoundToNode { + /** + * Returns true if this is a field symbol. + * + * @see JFieldSymbol + */ + default boolean isField() { + return false; + } + /** * Returns true if this declaration is declared final. * This takes implicit modifiers into account. From 7b87d69b85375500c1522edb8ac8ed9489fcad23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 3 Apr 2021 22:55:39 +0200 Subject: [PATCH 097/101] Fix pmd-lang-test project import --- pmd-lang-test/pom.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index 32dc5f267a..3f1e9bd3e8 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -27,6 +27,26 @@ + + org.codehaus.mojo + build-helper-maven-plugin + + + add-kotlin-sources + + + + add-source + + + + ${project.basedir}/src/main/kotlin + + + + + + kotlin-maven-plugin From 173806b6872d11312ef3b527846b10c9adf550f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 3 Apr 2021 23:01:54 +0200 Subject: [PATCH 098/101] Fix some compiler warnings --- .../sourceforge/pmd/cpd/test/CpdTextComparisonTest.kt | 9 +++++---- .../pmd/lang/ast/test/AstMatcherDslAdapter.kt | 2 +- .../sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt | 8 +++++--- .../net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt | 4 ++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/cpd/test/CpdTextComparisonTest.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/cpd/test/CpdTextComparisonTest.kt index 8335f58b12..9ea953c086 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/cpd/test/CpdTextComparisonTest.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/cpd/test/CpdTextComparisonTest.kt @@ -65,23 +65,23 @@ abstract class CpdTextComparisonTest( private fun StringBuilder.format(tokens: Tokens) { - appendHeader().appendln() + appendHeader().appendLine() var curLine = -1 for (token in tokens.iterator()) { if (token === TokenEntry.EOF) { - append("EOF").appendln() + append("EOF").appendLine() continue } if (curLine != token.beginLine) { curLine = token.beginLine - append('L').append(curLine).appendln() + append('L').append(curLine).appendLine() } - formatLine(token).appendln() + formatLine(token).appendLine() } } @@ -105,6 +105,7 @@ abstract class CpdTextComparisonTest( private fun StringBuilder.formatLine(escapedImage: String, bcol: Any, ecol: Any): StringBuilder { var colStart = length colStart = append(Indent).append(escapedImage).padCol(colStart, Col0Width) + @Suppress("UNUSED_VALUE") colStart = append(Indent).append(bcol).padCol(colStart, Col1Width) return append(ecol) } diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt index 6610034e4a..82b7c5a2ae 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt @@ -14,7 +14,7 @@ import io.kotest.matchers.should as ktShould /** An adapter for [baseShouldMatchSubtree]. */ object NodeTreeLikeAdapter : DoublyLinkedTreeLikeAdapter { - override fun getChildren(node: Node): List = node.findChildrenOfType(Node::class.java) + override fun getChildren(node: Node): List = node.children().toList() override fun nodeName(type: Class): String = type.simpleName.removePrefix("AST") diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt index cf7a3c8723..6e4453d7e1 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt @@ -221,8 +221,10 @@ abstract class BaseParsingHelper, T : RootNode */ @JvmOverloads fun executeRule(rule: Rule, code: String, filename: String = "testfile.${language.extensions[0]}"): Report { - val p = PMD() - p.configuration.suppressMarker = this.params.suppressMarker + val config = PMDConfiguration().apply { + suppressMarker = params.suppressMarker + } + val processor = SourceCodeProcessor(config) val ctx = RuleContext() val report = Report() ctx.report = report @@ -231,7 +233,7 @@ abstract class BaseParsingHelper, T : RootNode val rules = RuleSet.forSingleRule(rule) try { - p.sourceCodeProcessor.processSourceCode(StringReader(code), RuleSets(rules), ctx) + processor.processSourceCode(StringReader(code), RuleSets(rules), ctx) } catch (e: PMDException) { throw e.cause!! } diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt index d147e39cbb..97d93b5319 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt @@ -24,8 +24,8 @@ fun Node.safeGetChild(i: Int): Node? = when { else -> null } -inline fun Node.getDescendantsOfType(): List = findDescendantsOfType(T::class.java) -inline fun Node.getFirstDescendantOfType(): T = getFirstDescendantOfType(T::class.java) +inline fun Node.getDescendantsOfType(): List = descendants(T::class.java).toList() +inline fun Node.getFirstDescendantOfType(): T = descendants(T::class.java).firstOrThrow() val Node.textRange: TextRange get() = TextRange(beginPosition, endPosition) From 875793f99adbad1a7a2fbd179c355e0188d7fc84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 3 Apr 2021 23:10:04 +0200 Subject: [PATCH 099/101] Update reference files --- .../sourceforge/pmd/lang/java/ast/Bug1429.txt | 8 +- .../pmd/lang/java/ast/GitHubBug207.txt | 2 +- .../pmd/lang/java/ast/GitHubBug309.txt | 6 +- .../pmd/lang/java/ast/LambdaBug1333.txt | 8 +- .../pmd/lang/java/ast/LambdaBug1470.txt | 10 +- .../pmd/lang/java/ast/LambdaBug206.txt | 2 +- .../pmd/lang/java/ast/ParserCornerCases.txt | 46 +++--- .../pmd/lang/java/ast/ParserCornerCases17.txt | 90 +++++------ .../pmd/lang/java/ast/ParserCornerCases18.txt | 152 +++++++++--------- .../pmd/lang/java/ast/SwitchStatements.txt | 2 +- .../lang/java/ast/SwitchWithFallthrough.txt | 2 +- .../java15/NonSealedIdentifier.txt | 8 +- .../ast/jdkversiontests/java15/TextBlocks.txt | 38 ++--- .../java15p/LocalInterfacesAndEnums.txt | 2 +- .../jdkversiontests/java15p/LocalRecords.txt | 34 ++-- .../java15p/PatternMatchingInstanceof.txt | 14 +- .../ast/jdkversiontests/java15p/Records.txt | 24 +-- .../LocalClassAndInterfaceDeclarations.txt | 6 +- .../jdkversiontests/java16/LocalRecords.txt | 32 ++-- .../java16/NonSealedIdentifier.txt | 8 +- .../java16/PatternMatchingInstanceof.txt | 20 +-- .../java/ast/jdkversiontests/java16/Point.txt | 8 +- .../ast/jdkversiontests/java16/Records.txt | 24 +-- 23 files changed, 273 insertions(+), 273 deletions(-) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/Bug1429.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/Bug1429.txt index b1a0d5889e..72e047cce7 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/Bug1429.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/Bug1429.txt @@ -51,13 +51,13 @@ | +- FormalParameter[@EffectiveVisibility = "local", @Final = "true", @Varargs = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{final}", @ExplicitModifiers = "{final}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "obj", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "obj", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] +- Block[@Size = "5", @containsComment = "false"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "true", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{final}", @ExplicitModifiers = "{final}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "key"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "key", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "key", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- CastExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "obj", @Name = "obj", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -65,7 +65,7 @@ | +- ModifierList[@EffectiveModifiers = "{final}", @ExplicitModifiers = "{final}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "value"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "value", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "value", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- MethodCall[@CompileTimeConstant = "false", @Image = "get", @MethodName = "get", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "attributes", @Name = "attributes", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- ThisExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -76,7 +76,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "result"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "key", @Name = "key", @ParenthesisDepth = "0", @Parenthesized = "false"] +- IfStatement[@Else = "false"] | +- MethodCall[@CompileTimeConstant = "false", @Image = "isNotEmpty", @MethodName = "isNotEmpty", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/GitHubBug207.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/GitHubBug207.txt index fa77d84a93..faf90f79cb 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/GitHubBug207.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/GitHubBug207.txt @@ -11,7 +11,7 @@ | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Context"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "context", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "context", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] +- Block[@Size = "1", @containsComment = "false"] +- ReturnStatement[] +- MethodCall[@CompileTimeConstant = "false", @Image = "map", @MethodName = "map", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/GitHubBug309.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/GitHubBug309.txt index 1e725f6c78..aa88cf19c6 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/GitHubBug309.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/GitHubBug309.txt @@ -13,13 +13,13 @@ | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- ArrayDimensions[@Size = "1"] | | +- ArrayTypeDim[@Varargs = "false"] - | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] +- Block[@Size = "2", @containsComment = "true"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Runnable"] | +- VariableDeclarator[@Initializer = "true", @Name = "r11"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r11", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r11", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- MethodReference[@CompileTimeConstant = "false", @ConstructorReference = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Main"] @@ -34,7 +34,7 @@ | +- ArrayDimensions[@Size = "1"] | +- ArrayTypeDim[@Varargs = "false"] +- VariableDeclarator[@Initializer = "true", @Name = "r13"] - +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r13", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r13", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] +- MethodReference[@CompileTimeConstant = "false", @ConstructorReference = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false"] +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- ArrayType[@ArrayDepth = "1"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug1333.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug1333.txt index 6b0dba57b9..b3566b207f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug1333.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug1333.txt @@ -6,7 +6,7 @@ | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Logger"] | +- VariableDeclarator[@Initializer = "true", @Name = "LOG"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "LOG", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "LOG", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | +- MethodCall[@CompileTimeConstant = "false", @Image = "getLogger", @MethodName = "getLogger", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- AmbiguousName[@CompileTimeConstant = "false", @Image = "LoggerFactory", @Name = "LoggerFactory", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- ArgumentList[@Size = "1"] @@ -24,7 +24,7 @@ | +- LambdaParameterList[@Size = "1"] | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "path", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "path", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | +- MethodCall[@CompileTimeConstant = "false", @Image = "deleteDirectory", @MethodName = "deleteDirectory", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- ArgumentList[@Size = "1"] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "path", @Name = "path", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -38,7 +38,7 @@ | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | +- WildcardType[@LowerBound = "true", @UpperBound = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "consumer", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "consumer", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "1", @containsComment = "false"] | +- ExpressionStatement[] | +- MethodCall[@CompileTimeConstant = "false", @Image = "debug", @MethodName = "debug", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -54,7 +54,7 @@ | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "path", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "path", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] +- Block[@Size = "1", @containsComment = "false"] +- ExpressionStatement[] +- MethodCall[@CompileTimeConstant = "false", @Image = "debug", @MethodName = "debug", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug1470.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug1470.txt index 3440c33b32..466bfb43f2 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug1470.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug1470.txt @@ -10,7 +10,7 @@ | +- ModifierList[@EffectiveModifiers = "{private}", @ExplicitModifiers = "{private}"] | +- PrimitiveType[@Kind = "boolean"] | +- VariableDeclarator[@Initializer = "false", @Name = "stuff"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "stuff", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "stuff", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "public", @Image = "testSuper", @Name = "testSuper", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "false"] | +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Observable"] @@ -32,7 +32,7 @@ | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- WildcardType[@LowerBound = "true", @UpperBound = "false"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "subscriber", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "subscriber", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | +- Block[@Size = "1", @containsComment = "false"] | | +- ExpressionStatement[] | | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -43,7 +43,7 @@ | +- LambdaParameterList[@Size = "1"] | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "authToken", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "authToken", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | +- BooleanLiteral[@CompileTimeConstant = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @True = "false"] +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "public", @Image = "testSuper2", @Name = "testSuper2", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "false"] +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] @@ -62,7 +62,7 @@ | +- LambdaParameterList[@Size = "1"] | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "subscriber", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "subscriber", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | +- Block[@Size = "1", @containsComment = "false"] | +- ExpressionStatement[] | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -73,5 +73,5 @@ +- LambdaParameterList[@Size = "1"] | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "authToken", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "authToken", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] +- BooleanLiteral[@CompileTimeConstant = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @True = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug206.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug206.txt index bfb637711d..465ce1a000 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug206.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/LambdaBug206.txt @@ -10,7 +10,7 @@ | +- TypeArguments[@Diamond = "false", @Size = "1"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] +- VariableDeclarator[@Initializer = "true", @Name = "interner"] - +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "public", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "interner", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "public"] + +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "public", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "interner", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "public"] +- MethodCall[@CompileTimeConstant = "false", @Image = "withInitial", @MethodName = "withInitial", @ParenthesisDepth = "0", @Parenthesized = "false"] +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ThreadLocal"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases.txt index 6fc2e4a168..3845925d8a 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases.txt @@ -16,7 +16,7 @@ | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Class"] | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "V"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "clazz", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "clazz", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "0", @containsComment = "false"] | +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Image = "doStuff", @Name = "doStuff", @Overridden = "false", @Varargs = "false", @Visibility = "package", @Void = "false"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] @@ -27,7 +27,7 @@ | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "T"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "1", @containsComment = "false"] | +- ReturnStatement[] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -71,7 +71,7 @@ | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Outer"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "2", @containsComment = "false"] | +- ExplicitConstructorInvocation[@ArgumentCount = "0", @MethodName = "new", @Qualified = "true", @Super = "true", @This = "false"] | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -100,7 +100,7 @@ | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "int"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "1", @containsComment = "false"] | | +- ExplicitConstructorInvocation[@ArgumentCount = "2", @MethodName = "new", @Qualified = "false", @Super = "false", @This = "true"] | | +- TypeArguments[@Diamond = "false", @Size = "1"] @@ -116,11 +116,11 @@ | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | +- PrimitiveType[@Kind = "int"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "int"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "1", @containsComment = "false"] | | +- ExplicitConstructorInvocation[@ArgumentCount = "1", @MethodName = "new", @Qualified = "false", @Super = "true", @This = "false"] | | +- TypeArguments[@Diamond = "false", @Size = "1"] @@ -134,7 +134,7 @@ | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "title", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "title", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "1", @containsComment = "false"] | | +- ExplicitConstructorInvocation[@ArgumentCount = "0", @MethodName = "new", @Qualified = "false", @Super = "false", @This = "true"] | | +- ArgumentList[@Size = "0"] @@ -147,7 +147,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "o"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "doStuff", @MethodName = "doStuff", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- SuperExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- TypeArguments[@Diamond = "false", @Size = "1"] @@ -158,7 +158,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "v"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "v", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "v", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "thisGeneric", @MethodName = "thisGeneric", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- ThisExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- TypeArguments[@Diamond = "false", @Size = "1"] @@ -174,7 +174,7 @@ | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "X"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "1", @containsComment = "false"] | | +- ReturnStatement[] | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "x", @Name = "x", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -216,7 +216,7 @@ | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "obj", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "obj", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "0", @containsComment = "false"] +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "PmdTestChild", @CanonicalName = "PmdTestChild", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "true", @Record = "false", @RegularClass = "true", @SimpleName = "PmdTestChild", @TopLevel = "true", @Visibility = "package"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] @@ -244,7 +244,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] | | +- VariableDeclarator[@Initializer = "true", @Name = "memoryMonitor"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "memoryMonitor", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "memoryMonitor", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NullLiteral[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- IfStatement[@Else = "false"] | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "==", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -266,7 +266,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "false", @Name = "name"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "name", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "name", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "SimpleBeanUser", @CanonicalName = "SimpleBeanUser", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "true", @Record = "false", @RegularClass = "true", @SimpleName = "SimpleBeanUser", @TopLevel = "true", @Visibility = "package"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceBody[@Size = "2"] @@ -276,7 +276,7 @@ | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "SimpleBean"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "0", @containsComment = "false"] | +- ConstructorDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "package", @Image = "SimpleBeanUser", @Name = "SimpleBeanUser", @Varargs = "false", @Visibility = "package", @containsComment = "false"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] @@ -338,7 +338,7 @@ | | | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "unchecked", @Empty = "false", @Image = "\"unchecked\"", @Length = "9", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] | | | +- PrimitiveType[@Kind = "int"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "i"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "true", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "0.0", @ValueAsFloat = "0.0", @ValueAsInt = "0", @ValueAsLong = "0"] | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "<", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "i", @Name = "i", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -359,7 +359,7 @@ | | | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "unchecked", @Empty = "false", @Image = "\"unchecked\"", @Length = "9", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Iterator"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "it"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "it", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "true", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "it", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "iterator", @MethodName = "iterator", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "values", @MethodName = "values", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- AmbiguousName[@CompileTimeConstant = "false", @Image = "Fachabteilung", @Name = "Fachabteilung", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -375,7 +375,7 @@ | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "l"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "l", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "l", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ArrayList"] | | | +- TypeArguments[@Diamond = "false", @Size = "1"] @@ -391,7 +391,7 @@ | | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "unchecked", @Empty = "false", @Image = "\"unchecked\"", @Length = "9", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "false", @Name = "s"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "l", @Name = "l", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- Block[@Size = "0", @containsComment = "false"] +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "FooBlock", @CanonicalName = "FooBlock", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "true", @Record = "false", @RegularClass = "true", @SimpleName = "FooBlock", @TopLevel = "true", @Visibility = "package"] @@ -406,7 +406,7 @@ | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "FooBlock"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "0", @containsComment = "false"] +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "Foo", @CanonicalName = "Foo", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "true", @Record = "false", @RegularClass = "true", @SimpleName = "Foo", @TopLevel = "true", @Visibility = "package"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] @@ -432,13 +432,13 @@ | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "object", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "object", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "2", @containsComment = "false"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "fish"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "fish", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "fish", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "salmon", @Empty = "false", @Image = "\"salmon\"", @Length = "6", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] | +- ReturnStatement[] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "fish", @Name = "fish", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -475,7 +475,7 @@ | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "E"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "wrapped"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "anonymous", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "wrapped", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "anonymous", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "wrapped", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "iterator", @MethodName = "iterator", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- SuperExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ImmutableSet"] @@ -541,7 +541,7 @@ | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | +- WildcardType[@LowerBound = "false", @UpperBound = "false"] | +- VariableDeclarator[@Initializer = "true", @Name = "c"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "c", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "c", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- ClassLiteral[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- PrimitiveType[@Kind = "int"] +- ExpressionStatement[] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases17.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases17.txt index 938c095456..c86f1fbbac 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases17.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases17.txt @@ -28,7 +28,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "byte"] | | +- VariableDeclarator[@Initializer = "true", @Name = "aByte"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "aByte", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "aByte", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- CastExpression[@CompileTimeConstant = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- PrimitiveType[@Kind = "byte"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b00100001", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "33.0", @ValueAsFloat = "33.0", @ValueAsInt = "33", @ValueAsLong = "33"] @@ -36,7 +36,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "short"] | | +- VariableDeclarator[@Initializer = "true", @Name = "aShort"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "aShort", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "aShort", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- CastExpression[@CompileTimeConstant = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- PrimitiveType[@Kind = "short"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b1010000101000101", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "41285.0", @ValueAsFloat = "41285.0", @ValueAsInt = "41285", @ValueAsLong = "41285"] @@ -44,25 +44,25 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "anInt1"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "anInt1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "anInt1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b10100001010001011010000101000101", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "2.705695045E9", @ValueAsFloat = "2.70569498E9", @ValueAsInt = "-1589272251", @ValueAsLong = "2705695045"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "anInt2"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "anInt2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "anInt2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b101", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "5.0", @ValueAsFloat = "5.0", @ValueAsInt = "5", @ValueAsLong = "5"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "anInt3"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "anInt3", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "anInt3", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0B101", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "5.0", @ValueAsFloat = "5.0", @ValueAsInt = "5", @ValueAsLong = "5"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "long"] | | +- VariableDeclarator[@Initializer = "true", @Name = "aLong"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "aLong", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "aLong", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b1010000101000101101000010100010110100001010001011010000101000101L", @IntLiteral = "false", @Integral = "true", @LongLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "-6.8258723397796086E18", @ValueAsFloat = "-6.8258721E18", @ValueAsInt = "-1589272251", @ValueAsLong = "-6825872339779608251"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] @@ -71,7 +71,7 @@ | | | +- ArrayDimensions[@Size = "1"] | | | +- ArrayTypeDim[@Varargs = "false"] | | +- VariableDeclarator[@Initializer = "true", @Name = "phases"] - | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "phases", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "phases", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ArrayInitializer[@CompileTimeConstant = "false", @Length = "8", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b00110001", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "49.0", @ValueAsFloat = "49.0", @ValueAsInt = "49", @ValueAsLong = "49"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b01100010", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "98.0", @ValueAsFloat = "98.0", @ValueAsInt = "98", @ValueAsLong = "98"] @@ -85,7 +85,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "instruction"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "instruction", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "instruction", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "0.0", @ValueAsFloat = "0.0", @ValueAsInt = "0", @ValueAsLong = "0"] | +- IfStatement[@Else = "false"] | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "==", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -98,7 +98,7 @@ | | +- ModifierList[@EffectiveModifiers = "{final}", @ExplicitModifiers = "{final}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "register"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "register", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "register", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "&", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "instruction", @Name = "instruction", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b00001111", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "15.0", @ValueAsFloat = "15.0", @ValueAsInt = "15", @ValueAsLong = "15"] @@ -153,91 +153,91 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "long"] | | +- VariableDeclarator[@Initializer = "true", @Name = "creditCardNumber"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "creditCardNumber", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "creditCardNumber", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "1234_5678_9012_3456L", @IntLiteral = "false", @Integral = "true", @LongLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "1.234567890123456E15", @ValueAsFloat = "1.23456795E15", @ValueAsInt = "1015724736", @ValueAsLong = "1234567890123456"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "long"] | | +- VariableDeclarator[@Initializer = "true", @Name = "socialSecurityNumber"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "socialSecurityNumber", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "socialSecurityNumber", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "999_99_9999L", @IntLiteral = "false", @Integral = "true", @LongLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "9.99999999E8", @ValueAsFloat = "1.0E9", @ValueAsInt = "999999999", @ValueAsLong = "999999999"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "float"] | | +- VariableDeclarator[@Initializer = "true", @Name = "pi"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "pi", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "pi", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "true", @Image = "3.14_15F", @IntLiteral = "false", @Integral = "false", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.1415", @ValueAsFloat = "3.1415", @ValueAsInt = "3", @ValueAsLong = "3"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "long"] | | +- VariableDeclarator[@Initializer = "true", @Name = "hexBytes"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "hexBytes", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "hexBytes", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "16", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0xFF_EC_DE_5E", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "4.293713502E9", @ValueAsFloat = "4.29371341E9", @ValueAsInt = "-1253794", @ValueAsLong = "4293713502"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "long"] | | +- VariableDeclarator[@Initializer = "true", @Name = "hexWords"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "hexWords", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "hexWords", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "16", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0xCAFE_BABE", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.405691582E9", @ValueAsFloat = "3.40569165E9", @ValueAsInt = "-889275714", @ValueAsLong = "3405691582"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "long"] | | +- VariableDeclarator[@Initializer = "true", @Name = "maxLong"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "maxLong", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "maxLong", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "16", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0x7fff_ffff_ffff_ffffL", @IntLiteral = "false", @Integral = "true", @LongLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "9.223372036854776E18", @ValueAsFloat = "9.223372E18", @ValueAsInt = "-1", @ValueAsLong = "9223372036854775807"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "byte"] | | +- VariableDeclarator[@Initializer = "true", @Name = "nybbles"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "nybbles", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "nybbles", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b0010_0101", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "37.0", @ValueAsFloat = "37.0", @ValueAsInt = "37", @ValueAsLong = "37"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "long"] | | +- VariableDeclarator[@Initializer = "true", @Name = "bytes"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "bytes", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "bytes", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "2", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0b11010010_01101001_10010100_10010010", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.530134674E9", @ValueAsFloat = "3.53013478E9", @ValueAsInt = "-764832622", @ValueAsLong = "3530134674"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "_52"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "_52", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "_52", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "1", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "x1"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "_52", @Name = "_52", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "x2"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "5_2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "52.0", @ValueAsFloat = "52.0", @ValueAsInt = "52", @ValueAsLong = "52"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "x4"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x4", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x4", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "5_______2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "52.0", @ValueAsFloat = "52.0", @ValueAsInt = "52", @ValueAsLong = "52"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "x7"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x7", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x7", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "16", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0x5_2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "82.0", @ValueAsFloat = "82.0", @ValueAsInt = "82", @ValueAsLong = "82"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "x9"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x9", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x9", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- NumericLiteral[@Base = "8", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0_52", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "42.0", @ValueAsFloat = "42.0", @ValueAsInt = "42", @ValueAsLong = "42"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- PrimitiveType[@Kind = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "x10"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x10", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x10", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- NumericLiteral[@Base = "8", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "05_2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "42.0", @ValueAsFloat = "42.0", @ValueAsInt = "42", @ValueAsLong = "42"] +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "public", @Image = "stringsInSwitchStatements", @Name = "stringsInSwitchStatements", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "false"] | +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] @@ -248,13 +248,13 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "dayOfWeekArg"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "dayOfWeekArg", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "dayOfWeekArg", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "Wednesday", @Empty = "false", @Image = "\"Wednesday\"", @Length = "9", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "false", @Name = "typeOfDay"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "typeOfDay", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "typeOfDay", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- SwitchStatement[@DefaultCase = "true", @ExhaustiveEnumSwitch = "false"] | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "dayOfWeekArg", @Name = "dayOfWeekArg", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- SwitchFallthroughBranch[@Default = "false"] @@ -322,7 +322,7 @@ | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "T"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "t", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "t", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "0", @containsComment = "false"] +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "public", @Image = "typeInferenceForGenericInstanceCreation", @Name = "typeInferenceForGenericInstanceCreation", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "true"] | +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] @@ -338,7 +338,7 @@ | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "myMap"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "myMap", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "myMap", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "HashMap"] | | | +- TypeArguments[@Diamond = "true", @Size = "0"] @@ -349,7 +349,7 @@ | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "list"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "list", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "list", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ArrayList"] | | | +- TypeArguments[@Diamond = "true", @Size = "0"] @@ -366,7 +366,7 @@ | | | +- WildcardType[@LowerBound = "false", @UpperBound = "true"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "list2"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "list2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "list2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ArrayList"] | | | +- TypeArguments[@Diamond = "true", @Size = "0"] @@ -382,7 +382,7 @@ | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] | +- VariableDeclarator[@Initializer = "true", @Name = "myObject"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "myObject", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "myObject", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "MyClass"] | | +- TypeArguments[@Diamond = "true", @Size = "0"] @@ -399,7 +399,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "path"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "path", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "path", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "/foo", @Empty = "false", @Image = "\"/foo\"", @Length = "4", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] | +- TryStatement[@TryWithResources = "true"] | | +- ResourceList[@Size = "1", @TrailingSemiColon = "false"] @@ -408,7 +408,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{final}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "BufferedReader"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "br"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "br", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "br", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "BufferedReader"] | | | +- ArgumentList[@Size = "1"] @@ -421,7 +421,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "first"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "first", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "first", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "readLine", @MethodName = "readLine", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "br", @Name = "br", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- ArgumentList[@Size = "0"] @@ -429,19 +429,19 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "outputFileName"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "outputFileName", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "outputFileName", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "/foo-out", @Empty = "false", @Image = "\"/foo-out\"", @Length = "8", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "zipFileName"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "zipFileName", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "zipFileName", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "/foo.zip", @Empty = "false", @Image = "\"/foo.zip\"", @Length = "8", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Charset"] | | +- VariableDeclarator[@Initializer = "true", @Name = "charset"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "charset", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "charset", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "forName", @MethodName = "forName", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Charset"] @@ -451,7 +451,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Path"] | | +- VariableDeclarator[@Initializer = "true", @Name = "outputFilePath"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "outputFilePath", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "outputFilePath", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "get", @MethodName = "get", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Paths"] @@ -464,7 +464,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{final}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "ZipFile"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "zf"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "zf", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "zf", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "ZipFile"] | | | +- ArgumentList[@Size = "1"] @@ -474,7 +474,7 @@ | | +- ModifierList[@EffectiveModifiers = "{final}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "BufferedWriter"] | | +- VariableDeclarator[@Initializer = "true", @Name = "writer"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "writer", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "writer", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "newBufferedWriter", @MethodName = "newBufferedWriter", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Files"] @@ -491,7 +491,7 @@ | | | +- WildcardType[@LowerBound = "false", @UpperBound = "true"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ZipEntry"] | | +- VariableDeclarator[@Initializer = "true", @Name = "entries"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "entries", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "true", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "entries", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "entries", @MethodName = "entries", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "zf", @Name = "zf", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- ArgumentList[@Size = "0"] @@ -503,7 +503,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "newLine"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "newLine", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "newLine", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "getProperty", @MethodName = "getProperty", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] @@ -513,7 +513,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "zipEntryName"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "zipEntryName", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "zipEntryName", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "getName", @MethodName = "getName", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- CastExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "1", @Parenthesized = "true"] @@ -560,7 +560,7 @@ | | +- UnionType[] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "IOException"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "SQLException"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "true", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "ex", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "true", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "ex", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | +- Block[@Size = "2", @containsComment = "false"] | +- ExpressionStatement[] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "printStackTrace", @MethodName = "printStackTrace", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -577,7 +577,7 @@ +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] +- PrimitiveType[@Kind = "int"] +- VariableDeclarator[@Initializer = "true", @Name = "initialSizeGlobal"] - +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "initialSizeGlobal", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "initialSizeGlobal", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] +- CastExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] +- PrimitiveType[@Kind = "int"] +- InfixExpression[@CompileTimeConstant = "false", @Operator = "*", @ParenthesisDepth = "1", @Parenthesized = "true"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases18.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases18.txt index ec89aa68e5..72fae9f1d4 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases18.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases18.txt @@ -21,13 +21,13 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "FileFilter"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "java"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "java", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "java", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "false", @CompileTimeConstant = "false", @ExpressionBody = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "1"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "false", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "File"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "endsWith", @MethodName = "endsWith", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "getName", @MethodName = "getName", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -38,12 +38,12 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "FileFilter"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "java2"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "java2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "java2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "false", @CompileTimeConstant = "false", @ExpressionBody = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "1"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "endsWith", @MethodName = "endsWith", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "getName", @MethodName = "getName", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -54,12 +54,12 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "FileFilter"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "java3"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "java3", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "java3", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "false", @CompileTimeConstant = "false", @ExpressionBody = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "1"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "endsWith", @MethodName = "endsWith", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "getName", @MethodName = "getName", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -70,12 +70,12 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "FileFilter"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "java4"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "java4", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "java4", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "false", @CompileTimeConstant = "false", @ExpressionBody = "true", @ParenthesisDepth = "1", @Parenthesized = "true"] | | | +- LambdaParameterList[@Size = "1"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "endsWith", @MethodName = "endsWith", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "getName", @MethodName = "getName", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -97,7 +97,7 @@ | | | +- LambdaParameterList[@Size = "1"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- Block[@Size = "1", @containsComment = "false"] | | | +- ExpressionStatement[] | | | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -115,7 +115,7 @@ | | | | +- ArrayDimensions[@Size = "1"] | | | | +- ArrayTypeDim[@Varargs = "false"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "filters"] - | | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "filters", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "filters", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- ArrayAllocation[@ArrayDepth = "1", @CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ArrayType[@ArrayDepth = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "FileFilter"] @@ -126,7 +126,7 @@ | | | | +- LambdaParameterList[@Size = "1"] | | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "exists", @MethodName = "exists", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- ArgumentList[@Size = "0"] @@ -134,7 +134,7 @@ | | | | +- LambdaParameterList[@Size = "1"] | | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "canRead", @MethodName = "canRead", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- ArgumentList[@Size = "0"] @@ -142,7 +142,7 @@ | | | +- LambdaParameterList[@Size = "1"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "startsWith", @MethodName = "startsWith", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "getName", @MethodName = "getName", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -162,7 +162,7 @@ | | | | +- LambdaParameterList[@Size = "1"] | | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "exists", @MethodName = "exists", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- ArgumentList[@Size = "0"] @@ -170,7 +170,7 @@ | | | | +- LambdaParameterList[@Size = "1"] | | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "canRead", @MethodName = "canRead", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- ArgumentList[@Size = "0"] @@ -178,7 +178,7 @@ | | | +- LambdaParameterList[@Size = "1"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "f", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "startsWith", @MethodName = "startsWith", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "getName", @MethodName = "getName", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "f", @Name = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -189,7 +189,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "user"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "user", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "user", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "doPrivileged", @MethodName = "doPrivileged", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ArgumentList[@Size = "1"] | | | +- LambdaExpression[@BlockBody = "false", @CompileTimeConstant = "false", @ExpressionBody = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -205,7 +205,7 @@ | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "c"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "c", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "c", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "false", @CompileTimeConstant = "false", @ExpressionBody = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "0"] | | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "done", @Empty = "false", @Image = "\"done\"", @Length = "4", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] @@ -213,7 +213,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Runnable"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "r"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "true", @CompileTimeConstant = "false", @ExpressionBody = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "0"] | | | +- Block[@Size = "1", @containsComment = "false"] @@ -230,7 +230,7 @@ | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Runnable"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "sup"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sup", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sup", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "false", @CompileTimeConstant = "false", @ExpressionBody = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "0"] | | | +- LambdaExpression[@BlockBody = "true", @CompileTimeConstant = "false", @ExpressionBody = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -247,7 +247,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "boolean"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "flag"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "flag", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "flag", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- InfixExpression[@CompileTimeConstant = "true", @Operator = ">", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "1", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "2.0", @ValueAsFloat = "2.0", @ValueAsInt = "2", @ValueAsLong = "2"] @@ -257,7 +257,7 @@ | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "c2"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "c2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "c2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- ConditionalExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "flag", @Name = "flag", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaExpression[@BlockBody = "false", @CompileTimeConstant = "false", @ExpressionBody = "true", @ParenthesisDepth = "1", @Parenthesized = "true"] @@ -270,7 +270,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "o"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- CastExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Runnable"] | | | +- LambdaExpression[@BlockBody = "true", @CompileTimeConstant = "false", @ExpressionBody = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -296,15 +296,15 @@ | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "comparer"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "comparer", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "comparer", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "false", @CompileTimeConstant = "false", @ExpressionBody = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "2"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "compareToIgnoreCase", @MethodName = "compareToIgnoreCase", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "s1", @Name = "s1", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ArgumentList[@Size = "1"] @@ -316,10 +316,10 @@ | | | +- LambdaParameterList[@Size = "2"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "compareToIgnoreCase", @MethodName = "compareToIgnoreCase", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "s1", @Name = "s1", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ArgumentList[@Size = "1"] @@ -328,7 +328,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Button"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "button"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "button", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "button", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Button"] | | | +- ArgumentList[@Size = "0"] @@ -340,7 +340,7 @@ | | | +- LambdaParameterList[@Size = "1"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "e", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "e", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "out", @Name = "out", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -353,7 +353,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "int"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "initialSizeGlobal"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "initialSizeGlobal", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "initialSizeGlobal", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- CastExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- PrimitiveType[@Kind = "int"] | | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "*", @ParenthesisDepth = "1", @Parenthesized = "true"] @@ -370,17 +370,17 @@ | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "lambda2"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "lambda2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "lambda2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "true", @CompileTimeConstant = "false", @ExpressionBody = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "2"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "false", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "false", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | | +- Block[@Size = "1", @containsComment = "false"] | | | +- ExpressionStatement[] | | | +- UnaryExpression[@CompileTimeConstant = "false", @Operator = "++", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -392,15 +392,15 @@ | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "lambda2a"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "lambda2a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "lambda2a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "true", @CompileTimeConstant = "false", @ExpressionBody = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "2"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- Block[@Size = "1", @containsComment = "false"] | | | +- ExpressionStatement[] | | | +- UnaryExpression[@CompileTimeConstant = "false", @Operator = "++", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -413,21 +413,21 @@ | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Double"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "lambda3"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "lambda3", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "lambda3", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- LambdaExpression[@BlockBody = "true", @CompileTimeConstant = "false", @ExpressionBody = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- LambdaParameterList[@Size = "3"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "false", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "false", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "false", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Double"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "d", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "d", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | | +- Block[@Size = "1", @containsComment = "false"] | | | +- ExpressionStatement[] | | | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "true", @Operator = "+=", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -441,18 +441,18 @@ | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Double"] | | +- VariableDeclarator[@Initializer = "true", @Name = "lambda3a"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "lambda3a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "lambda3a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- LambdaExpression[@BlockBody = "true", @CompileTimeConstant = "false", @ExpressionBody = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- LambdaParameterList[@Size = "3"] | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "d", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "d", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | +- Block[@Size = "1", @containsComment = "false"] | | +- ExpressionStatement[] | | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "true", @Operator = "+=", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -474,20 +474,20 @@ | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "A"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "B"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "C"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "c", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "c", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- FieldDeclaration[@EffectiveVisibility = "package", @Visibility = "package"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Runnable"] | | +- VariableDeclarator[@Initializer = "true", @Name = "r1"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "r1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "r1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | +- LambdaExpression[@BlockBody = "true", @CompileTimeConstant = "false", @ExpressionBody = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- LambdaParameterList[@Size = "0"] | | +- Block[@Size = "1", @containsComment = "false"] @@ -523,7 +523,7 @@ | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "PrivilegedAction"] | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "action", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "action", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "1", @containsComment = "false"] | | +- ReturnStatement[] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "run", @MethodName = "run", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -539,7 +539,7 @@ | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "FileFilter"] | | | | +- ArrayDimensions[@Size = "1"] | | | | +- ArrayTypeDim[@Varargs = "false"] - | | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "filters", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "filters", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "0", @containsComment = "false"] | +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "public", @Image = "comparingByKey", @Name = "comparingByKey", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "false"] | | +- ModifierList[@EffectiveModifiers = "{public, static}", @ExplicitModifiers = "{public, static}"] @@ -572,10 +572,10 @@ | | +- LambdaParameterList[@Size = "2"] | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "c1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "c1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "c2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "c2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "compareTo", @MethodName = "compareTo", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "getKey", @MethodName = "getKey", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "c1", @Name = "c1", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -593,7 +593,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Runnable"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "r"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- MethodReference[@CompileTimeConstant = "false", @ConstructorReference = "false", @MethodName = "toDoLater", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ParserCornerCases18"] @@ -602,14 +602,14 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Runnable"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "r1"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- MethodReference[@CompileTimeConstant = "false", @ConstructorReference = "false", @MethodName = "toDoLater", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ThisExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ParserCornerCases18"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "pc"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "pc", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "pc", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ParserCornerCases18"] | | | +- ArgumentList[@Size = "0"] @@ -617,7 +617,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Runnable"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "r11"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r11", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r11", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- MethodReference[@CompileTimeConstant = "false", @ConstructorReference = "false", @MethodName = "toDoLater", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "pc", @Name = "pc", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] @@ -626,14 +626,14 @@ | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "s"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- MethodReference[@CompileTimeConstant = "false", @ConstructorReference = "false", @MethodName = "toString", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- SuperExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Runnable"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "r2"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- MethodReference[@CompileTimeConstant = "false", @ConstructorReference = "false", @MethodName = "staticMethod", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ParserCornerCases18"] @@ -646,7 +646,7 @@ | | | | +- ArrayDimensions[@Size = "1"] | | | | +- ArrayTypeDim[@Varargs = "false"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "arrayMaker"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "arrayMaker", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "arrayMaker", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- MethodReference[@CompileTimeConstant = "false", @ConstructorReference = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ArrayType[@ArrayDepth = "1"] @@ -660,7 +660,7 @@ | | | +- ArrayDimensions[@Size = "1"] | | | +- ArrayTypeDim[@Varargs = "false"] | | +- VariableDeclarator[@Initializer = "true", @Name = "array"] - | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "array", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "array", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "apply", @MethodName = "apply", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "arrayMaker", @Name = "arrayMaker", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- ArgumentList[@Size = "1"] @@ -675,7 +675,7 @@ | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] | | | +- VariableDeclarator[@Initializer = "false", @Name = "theFunction"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "theFunction", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "theFunction", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | +- ConstructorDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "public", @Image = "PmdTest", @Name = "PmdTest", @Varargs = "false", @Visibility = "public", @containsComment = "false"] | | | +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] | | | +- FormalParameters[@Size = "0"] @@ -692,7 +692,7 @@ | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "int"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "1", @containsComment = "false"] | | +- ReturnStatement[] | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "i", @Name = "i", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -719,7 +719,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "myString"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "myString", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "myString", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- CastExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | | +- Annotation[@SimpleName = "NonNull"] @@ -729,7 +729,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] | | +- VariableDeclarator[@Initializer = "true", @Name = "o"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "o", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "MyObject"] | | | +- Annotation[@SimpleName = "Interned"] @@ -780,16 +780,16 @@ | | | | +- LambdaParameterList[@Size = "2"] | | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- Block[@Size = "3", @containsComment = "false"] | | | | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | | +- PrimitiveType[@Kind = "int"] | | | | | +- VariableDeclarator[@Initializer = "true", @Name = "x"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "-", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "hashCode", @MethodName = "hashCode", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "a", @Name = "a", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -832,17 +832,17 @@ | | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "false", @Visibility = "package"] | | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] - | | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "false", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Integer"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "b", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "package"] | | | | +- Block[@Size = "3", @containsComment = "false"] | | | | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | | +- PrimitiveType[@Kind = "int"] | | | | | +- VariableDeclarator[@Initializer = "true", @Name = "x"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "-", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "hashCode", @MethodName = "hashCode", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "a", @Name = "a", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -880,7 +880,7 @@ | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Request"] | | | +- VariableDeclarator[@Initializer = "true", @Name = "request"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "request", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "request", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Request"] | | | +- ArgumentList[@Size = "0"] @@ -975,7 +975,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] | | +- VariableDeclarator[@Initializer = "true", @Name = "x"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "x", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ArrayAllocation[@ArrayDepth = "3", @CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- ArrayType[@ArrayDepth = "3"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] @@ -1008,7 +1008,7 @@ | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "other", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "other", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "0", @containsComment = "false"] | +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Image = "methodWithReceiverParameterWithAnnotation", @Name = "methodWithReceiverParameterWithAnnotation", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "true"] | | +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] @@ -1021,7 +1021,7 @@ | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "other", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "other", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "0", @containsComment = "false"] | +- AnnotationTypeDeclaration[@Abstract = "true", @Annotation = "true", @Anonymous = "false", @BinaryName = "ParserCornerCases18$AnnotatedUsage", @CanonicalName = "ParserCornerCases18.AnnotatedUsage", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Interface = "true", @Local = "false", @Nested = "true", @PackageName = "", @Record = "false", @RegularClass = "false", @SimpleName = "AnnotatedUsage", @TopLevel = "false", @Visibility = "public"] | | +- ModifierList[@EffectiveModifiers = "{public, abstract, static}", @ExplicitModifiers = "{public}"] @@ -1065,7 +1065,7 @@ | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "1", @containsComment = "false"] | +- ForStatement[] | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "&&", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchStatements.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchStatements.txt index 1f72870a4c..e96bc21556 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchStatements.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchStatements.txt @@ -11,7 +11,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- PrimitiveType[@Kind = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "a"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "1", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] +- SwitchStatement[@DefaultCase = "true", @ExhaustiveEnumSwitch = "false"] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "a", @Name = "a", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchWithFallthrough.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchWithFallthrough.txt index b1ee693f3a..5b8a9f2616 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchWithFallthrough.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchWithFallthrough.txt @@ -11,7 +11,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- PrimitiveType[@Kind = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "a"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "a", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "1", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] +- SwitchStatement[@DefaultCase = "true", @ExhaustiveEnumSwitch = "false"] +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "a", @Name = "a", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.txt index 5c167a3f52..106f76235f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.txt @@ -12,25 +12,25 @@ | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- ArrayDimensions[@Size = "1"] | | +- ArrayTypeDim[@Varargs = "false"] - | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] +- Block[@Size = "5", @containsComment = "false"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- PrimitiveType[@Kind = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "result"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "0.0", @ValueAsFloat = "0.0", @ValueAsInt = "0", @ValueAsLong = "0"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- PrimitiveType[@Kind = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "non"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "non", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "non", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "1", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- PrimitiveType[@Kind = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "sealed"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sealed", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sealed", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "2.0", @ValueAsFloat = "2.0", @ValueAsInt = "2", @ValueAsLong = "2"] +- ExpressionStatement[] | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.txt index 63e3d9eac1..43373e7005 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.txt @@ -14,7 +14,7 @@ | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- ArrayDimensions[@Size = "1"] | | +- ArrayTypeDim[@Varargs = "false"] - | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] +- ThrowsList[@Size = "1"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Exception"] +- Block[@Size = "25", @containsComment = "false"] @@ -22,7 +22,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "html"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "html", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "html", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "\n \n

Hello, world

\n \n\n", @Empty = "false", @Image = "\"\"\"\n \n \n

Hello, world

\n \n \n \"\"\"", @Length = "66", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- ExpressionStatement[] | +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -35,7 +35,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "query"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "query", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "query", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\nWHERE `CITY` = \'INDIANAPOLIS\'\nORDER BY `EMP_ID`, `LAST_NAME`;\n", @Empty = "false", @Image = "\"\"\"\n SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n WHERE `CITY` = \'INDIANAPOLIS\'\n ORDER BY `EMP_ID`, `LAST_NAME`;\n \"\"\"", @Length = "110", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- ExpressionStatement[] | +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -48,7 +48,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ScriptEngine"] | +- VariableDeclarator[@Initializer = "true", @Name = "engine"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "engine", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "engine", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- MethodCall[@CompileTimeConstant = "false", @Image = "getEngineByName", @MethodName = "getEngineByName", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "ScriptEngineManager"] @@ -59,7 +59,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] | +- VariableDeclarator[@Initializer = "true", @Name = "obj"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "obj", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "obj", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- MethodCall[@CompileTimeConstant = "false", @Image = "eval", @MethodName = "eval", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "engine", @Name = "engine", @ParenthesisDepth = "0", @Parenthesized = "false"] | +- ArgumentList[@Size = "1"] @@ -68,7 +68,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "htmlWithEscapes"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "htmlWithEscapes", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "htmlWithEscapes", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "\r\n \r\n

Hello, world

\r\n \r\n\r\n", @Empty = "false", @Image = "\"\"\"\n \\r\n \\r\n

Hello, world

\\r\n \\r\n \\r\n \"\"\"", @Length = "71", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- ExpressionStatement[] | +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -81,61 +81,61 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "season"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "season", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "season", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "winter", @Empty = "false", @Image = "\"\"\"\n winter\"\"\"", @Length = "6", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "period"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "period", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "period", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "winter\n", @Empty = "false", @Image = "\"\"\"\n winter\n \"\"\"", @Length = "7", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "greeting"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "greeting", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "greeting", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "Hi, \"Bob\"\n", @Empty = "false", @Image = "\"\"\"\n Hi, \"Bob\"\n \"\"\"", @Length = "10", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "salutation"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "salutation", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "salutation", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "Hi,\n \"Bob\"\n", @Empty = "false", @Image = "\"\"\"\n Hi,\n \"Bob\"\n \"\"\"", @Length = "11", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "empty"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "empty", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "empty", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "", @Empty = "true", @Image = "\"\"\"\n \"\"\"", @Length = "0", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "quote"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "quote", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "quote", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "\"\n", @Empty = "false", @Image = "\"\"\"\n \"\n \"\"\"", @Length = "2", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "backslash"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "backslash", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "backslash", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "\\\n", @Empty = "false", @Image = "\"\"\"\n \\\\\n \"\"\"", @Length = "2", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "normalStringLiteral"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "normalStringLiteral", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "normalStringLiteral", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "test", @Empty = "false", @Image = "\"test\"", @Length = "4", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "code"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "code", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "code", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "String text = \"\"\"\n A text block inside a text block\n\"\"\";\n", @Empty = "false", @Image = "\"\"\"\n String text = \\\"\"\"\n A text block inside a text block\n \\\"\"\";\n \"\"\"", @Length = "60", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "text"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "text", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "text", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", @Empty = "false", @Image = "\"\"\"\n Lorem ipsum dolor sit amet, consectetur adipiscing \\\n elit, sed do eiusmod tempor incididunt ut labore \\\n et dolore magna aliqua.\\\n \"\"\"", @Length = "123", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- ExpressionStatement[] | +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -148,7 +148,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "colors"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "colors", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "colors", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "red \ngreen \nblue \n", @Empty = "false", @Image = "\"\"\"\n red \\s\n green\\s\n blue \\s\n \"\"\"", @Length = "21", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- ExpressionStatement[] | +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -161,7 +161,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "emptyLine"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "emptyLine", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "emptyLine", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "\ntest\n", @Empty = "false", @Image = "\"\"\"\n\ntest\n\"\"\"", @Length = "6", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- ExpressionStatement[] | +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -178,7 +178,7 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "bs"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "bs", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "bs", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "\\test\n", @Empty = "false", @Image = "\"\"\"\n \\\\test\n \"\"\"", @Length = "6", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "true"] +- ExpressionStatement[] +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/LocalInterfacesAndEnums.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/LocalInterfacesAndEnums.txt index 29f6076142..ffaabf91a1 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/LocalInterfacesAndEnums.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/LocalInterfacesAndEnums.txt @@ -18,4 +18,4 @@ +- EnumBody[@SeparatorSemi = "false", @Size = "1", @TrailingComma = "false"] +- EnumConstant[@AnonymousClass = "false", @EffectiveVisibility = "local", @Image = "A", @MethodName = "new", @Name = "A", @Visibility = "public"] +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{}"] - +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "A", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "public"] + +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "A", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "public"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/LocalRecords.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/LocalRecords.txt index 3f722122aa..a291d1b972 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/LocalRecords.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/LocalRecords.txt @@ -14,11 +14,11 @@ | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Merchant"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchant", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchant", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "month", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "month", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "1", @containsComment = "false"] | +- ReturnStatement[] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "month", @Name = "month", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -33,11 +33,11 @@ | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "List"] | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Merchant"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchants", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchants", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "month", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "month", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- Block[@Size = "2", @containsComment = "false"] | +- LocalClassStatement[] | | +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "LocalRecords$1MerchantSales", @CanonicalName = null, @EffectiveVisibility = "local", @Enum = "false", @Final = "true", @Interface = "false", @Local = "true", @Nested = "false", @PackageName = "", @Record = "true", @RegularClass = "false", @SimpleName = "MerchantSales", @TopLevel = "false", @Visibility = "local"] @@ -46,11 +46,11 @@ | | | +- RecordComponent[@EffectiveVisibility = "local", @Varargs = "false", @Visibility = "private"] | | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Merchant"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchant", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchant", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | | | +- RecordComponent[@EffectiveVisibility = "local", @Varargs = "false", @Visibility = "private"] | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "double"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "sales", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "sales", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | | +- RecordBody[@Size = "0"] | +- ReturnStatement[] | +- MethodCall[@CompileTimeConstant = "false", @Image = "collect", @MethodName = "collect", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -65,7 +65,7 @@ | | | | +- LambdaParameterList[@Size = "1"] | | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "merchant", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "merchant", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "MerchantSales"] | | | | +- ArgumentList[@Size = "2"] @@ -79,10 +79,10 @@ | | | +- LambdaParameterList[@Size = "2"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "m1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "m1", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- LambdaParameter[@EffectiveVisibility = "package", @Final = "false", @TypeInferred = "true", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "m2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "true", @LocalVariable = "false", @Name = "m2", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "package"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "compare", @MethodName = "compare", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Double"] @@ -114,7 +114,7 @@ | | | +- RecordComponent[@EffectiveVisibility = "local", @Varargs = "false", @Visibility = "private"] | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | | +- RecordBody[@Size = "0"] | +- LocalClassStatement[] | | +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "LocalRecords$1MyRecord2", @CanonicalName = null, @EffectiveVisibility = "local", @Enum = "false", @Final = "true", @Interface = "false", @Local = "true", @Nested = "false", @PackageName = "", @Record = "true", @RegularClass = "false", @SimpleName = "MyRecord2", @TopLevel = "false", @Visibility = "local"] @@ -123,7 +123,7 @@ | | | +- RecordComponent[@EffectiveVisibility = "local", @Varargs = "false", @Visibility = "private"] | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | | +- RecordBody[@Size = "0"] | +- LocalClassStatement[] | | +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "LocalRecords$1MyRecord3", @CanonicalName = null, @EffectiveVisibility = "local", @Enum = "false", @Final = "true", @Interface = "false", @Local = "true", @Nested = "false", @PackageName = "", @Record = "true", @RegularClass = "false", @SimpleName = "MyRecord3", @TopLevel = "false", @Visibility = "local"] @@ -134,7 +134,7 @@ | | | +- RecordComponent[@EffectiveVisibility = "local", @Varargs = "false", @Visibility = "private"] | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | | +- RecordBody[@Size = "0"] | +- LocalClassStatement[] | +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "LocalRecords$1MyRecord4", @CanonicalName = null, @EffectiveVisibility = "local", @Enum = "false", @Final = "true", @Interface = "false", @Local = "true", @Nested = "false", @PackageName = "", @Record = "true", @RegularClass = "false", @SimpleName = "MyRecord4", @TopLevel = "false", @Visibility = "local"] @@ -145,7 +145,7 @@ | | +- RecordComponent[@EffectiveVisibility = "local", @Varargs = "false", @Visibility = "private"] | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | +- RecordBody[@Size = "0"] +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "package", @Image = "statementThatStartsWithRecordAsRegularIdent", @Name = "statementThatStartsWithRecordAsRegularIdent", @Overridden = "false", @Varargs = "false", @Visibility = "package", @Void = "true"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] @@ -159,7 +159,7 @@ | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "record"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "record", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "record", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "HashMap"] | | | +- TypeArguments[@Diamond = "true", @Size = "0"] @@ -188,19 +188,19 @@ | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- PrimitiveType[@Kind = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "result"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "0", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "0.0", @ValueAsFloat = "0.0", @ValueAsInt = "0", @ValueAsLong = "0"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- PrimitiveType[@Kind = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "non"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "non", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "non", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "1", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | +- PrimitiveType[@Kind = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "sealed"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sealed", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sealed", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "2.0", @ValueAsFloat = "2.0", @ValueAsInt = "2", @ValueAsLong = "2"] +- ExpressionStatement[] | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/PatternMatchingInstanceof.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/PatternMatchingInstanceof.txt index a17cd22307..13049f62f5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/PatternMatchingInstanceof.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/PatternMatchingInstanceof.txt @@ -6,7 +6,7 @@ | +- ModifierList[@EffectiveModifiers = "{private}", @ExplicitModifiers = "{private}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "s"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "other string", @Empty = "false", @Image = "\"other string\"", @Length = "12", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "public", @Image = "test", @Name = "test", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "true"] | +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] @@ -17,7 +17,7 @@ | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Object"] | | +- VariableDeclarator[@Initializer = "true", @Name = "obj"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "obj", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "obj", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "abc", @Empty = "false", @Image = "\"abc\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] | +- IfStatement[@Else = "true"] | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "instanceof", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -26,7 +26,7 @@ | | | +- TypePattern[@EffectiveVisibility = "package", @Visibility = "package"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "1", @containsComment = "true"] | | | +- ExpressionStatement[] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -59,7 +59,7 @@ | | | +- TypePattern[@EffectiveVisibility = "package", @Visibility = "package"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "1", @containsComment = "true"] | | | +- ExpressionStatement[] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -92,7 +92,7 @@ | | | | +- TypePattern[@EffectiveVisibility = "package", @Visibility = "package"] | | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = ">", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "length", @MethodName = "length", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -118,7 +118,7 @@ | | | +- TypePattern[@EffectiveVisibility = "package", @Visibility = "package"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @PatternBinding = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = ">", @ParenthesisDepth = "0", @Parenthesized = "false"] | | +- MethodCall[@CompileTimeConstant = "false", @Image = "length", @MethodName = "length", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -146,7 +146,7 @@ | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- ArrayDimensions[@Size = "1"] | | +- ArrayTypeDim[@Varargs = "false"] - | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] +- Block[@Size = "1", @containsComment = "false"] +- ExpressionStatement[] +- MethodCall[@CompileTimeConstant = "false", @Image = "test", @MethodName = "test", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/Records.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/Records.txt index f4aa3093ff..82eaf57bfa 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/Records.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/Records.txt @@ -35,13 +35,13 @@ | | +- RecordComponent[@EffectiveVisibility = "private", @Varargs = "false", @Visibility = "private"] | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "int"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "real", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "real", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | | +- RecordComponent[@EffectiveVisibility = "private", @Varargs = "false", @Visibility = "private"] | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | | +- Annotation[@SimpleName = "Deprecated"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Deprecated"] | | +- PrimitiveType[@Kind = "int"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "imaginary", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "imaginary", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | +- RecordBody[@Size = "3"] | +- ConstructorDeclaration[@Abstract = "false", @Arity = "2", @EffectiveVisibility = "public", @Image = "MyComplex", @Name = "MyComplex", @Varargs = "false", @Visibility = "public", @containsComment = "false"] | | +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] @@ -53,11 +53,11 @@ | | | | | +- Annotation[@SimpleName = "MyAnnotation"] | | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "MyAnnotation"] | | | | +- PrimitiveType[@Kind = "int"] - | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "real", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "real", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "int"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "imaginary", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "imaginary", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- Block[@Size = "3", @containsComment = "false"] | | +- IfStatement[@Else = "false"] | | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = ">", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -84,7 +84,7 @@ | | | +- RecordComponent[@EffectiveVisibility = "private", @Varargs = "false", @Visibility = "private"] | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "int"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | | +- RecordBody[@Size = "0"] | +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "Records$MyComplex$NestedClass", @CanonicalName = "Records.MyComplex.NestedClass", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "false", @Record = "false", @RegularClass = "true", @SimpleName = "NestedClass", @TopLevel = "false", @Visibility = "public"] | +- ModifierList[@EffectiveModifiers = "{public, static}", @ExplicitModifiers = "{public, static}"] @@ -95,11 +95,11 @@ | | +- RecordComponent[@EffectiveVisibility = "private", @Varargs = "false", @Visibility = "private"] | | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | | +- PrimitiveType[@Kind = "int"] - | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "lo", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "lo", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | | +- RecordComponent[@EffectiveVisibility = "private", @Varargs = "false", @Visibility = "private"] | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | +- PrimitiveType[@Kind = "int"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "hi", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "hi", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | +- RecordBody[@Size = "2"] | +- CompactConstructorDeclaration[@EffectiveVisibility = "public", @Image = "Range", @Visibility = "public"] | | +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] @@ -141,7 +141,7 @@ | | | +- ArrayTypeDim[@Varargs = "true"] | | | +- Annotation[@SimpleName = "Nullable"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Nullable"] - | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | +- RecordBody[@Size = "0"] +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "Records$ArrayRec", @CanonicalName = "Records.ArrayRec", @EffectiveVisibility = "public", @Enum = "false", @Final = "true", @Interface = "false", @Local = "false", @Nested = "true", @PackageName = "", @Record = "true", @RegularClass = "false", @SimpleName = "ArrayRec", @TopLevel = "false", @Visibility = "public"] | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{public}"] @@ -152,7 +152,7 @@ | | | +- PrimitiveType[@Kind = "int"] | | | +- ArrayDimensions[@Size = "1"] | | | +- ArrayTypeDim[@Varargs = "false"] - | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | +- VariableDeclaratorId[@ArrayType = "true", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | +- RecordBody[@Size = "0"] +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "Records$EmptyRec", @CanonicalName = "Records.EmptyRec", @EffectiveVisibility = "public", @Enum = "false", @Final = "true", @Interface = "false", @Local = "false", @Nested = "true", @PackageName = "", @Record = "true", @RegularClass = "false", @SimpleName = "EmptyRec", @TopLevel = "false", @Visibility = "public"] | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{public}"] @@ -183,7 +183,7 @@ | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "r"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "EmptyRec"] | | | +- TypeArguments[@Diamond = "true", @Size = "0"] @@ -212,11 +212,11 @@ | +- RecordComponent[@EffectiveVisibility = "private", @Varargs = "false", @Visibility = "private"] | | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "firstName", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "firstName", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] | +- RecordComponent[@EffectiveVisibility = "private", @Varargs = "false", @Visibility = "private"] | +- ModifierList[@EffectiveModifiers = "{private, final}", @ExplicitModifiers = "{}"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] - | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "lastName", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "lastName", @PatternBinding = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] +- ImplementsList[@Size = "2"] | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Person"] | +- ClassOrInterfaceType[@FullyQualified = "true", @SimpleName = "Serializable"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/LocalClassAndInterfaceDeclarations.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/LocalClassAndInterfaceDeclarations.txt index 9d9e74af58..028afebc29 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/LocalClassAndInterfaceDeclarations.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/LocalClassAndInterfaceDeclarations.txt @@ -12,13 +12,13 @@ | | +- ModifierList[] | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] | | +- VariableDeclarator[@Initializer = "true", @Name = "constantField"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @FormalParameter = "false", @Image = "constantField", @LambdaParameter = "false", @LocalVariable = "false", @Name = "constantField", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @Transient = "false", @TypeInferred = "false", @VariableName = "constantField", @Visibility = "package", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "constantField", @LambdaParameter = "false", @LocalVariable = "false", @Name = "constantField", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @Transient = "false", @TypeInferred = "false", @VariableName = "constantField", @Visibility = "package", @Volatile = "false"] | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "1", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] | +- FieldDeclaration[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @Transient = "false", @VariableName = "staticField", @Visibility = "package", @Volatile = "false"] | | +- ModifierList[] | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] | | +- VariableDeclarator[@Initializer = "false", @Name = "staticField"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @FormalParameter = "false", @Image = "staticField", @LambdaParameter = "false", @LocalVariable = "false", @Name = "staticField", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @Transient = "false", @TypeInferred = "false", @VariableName = "staticField", @Visibility = "package", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "staticField", @LambdaParameter = "false", @LocalVariable = "false", @Name = "staticField", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @Transient = "false", @TypeInferred = "false", @VariableName = "staticField", @Visibility = "package", @Volatile = "false"] | +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "local", @Final = "false", @Image = "staticMethod", @MethodName = "staticMethod", @Name = "staticMethod", @Native = "false", @Overridden = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @Transient = "false", @Varargs = "false", @Visibility = "package", @Void = "true", @Volatile = "false"] | +- ModifierList[] | +- VoidType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "void"] @@ -34,4 +34,4 @@ +- EnumBody[@SeparatorSemi = "false", @Size = "1", @TrailingComma = "false"] +- EnumConstant[@Abstract = "false", @AnonymousClass = "false", @EffectiveVisibility = "local", @Final = "true", @Image = "A", @MethodName = "new", @Name = "A", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Visibility = "public", @Volatile = "false"] +- ModifierList[] - +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "A", @LambdaParameter = "false", @LocalVariable = "false", @Name = "A", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @VariableName = "A", @Visibility = "public", @Volatile = "false"] + +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "A", @LambdaParameter = "false", @LocalVariable = "false", @Name = "A", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "true", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @VariableName = "A", @Visibility = "public", @Volatile = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/LocalRecords.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/LocalRecords.txt index 5700a87b79..c3f2151af4 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/LocalRecords.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/LocalRecords.txt @@ -14,11 +14,11 @@ | | +- FormalParameter[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "local", @Volatile = "false"] | | | +- ModifierList[] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Merchant", @TypeImage = "Merchant"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "merchant", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchant", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "merchant", @Visibility = "local", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "merchant", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchant", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "merchant", @Visibility = "local", @Volatile = "false"] | | +- FormalParameter[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "local", @Volatile = "false"] | | +- ModifierList[] | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "month", @LambdaParameter = "false", @LocalVariable = "false", @Name = "month", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "month", @Visibility = "local", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "month", @LambdaParameter = "false", @LocalVariable = "false", @Name = "month", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "month", @Visibility = "local", @Volatile = "false"] | +- Block[@Size = "1", @containsComment = "false"] | +- ReturnStatement[] | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "month", @Name = "month", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -33,11 +33,11 @@ | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "List", @TypeImage = "List"] | | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Merchant", @TypeImage = "Merchant"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "merchants", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchants", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "merchants", @Visibility = "local", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "merchants", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchants", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "merchants", @Visibility = "local", @Volatile = "false"] | | +- FormalParameter[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "local", @Volatile = "false"] | | +- ModifierList[] | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "month", @LambdaParameter = "false", @LocalVariable = "false", @Name = "month", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "month", @Visibility = "local", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "month", @LambdaParameter = "false", @LocalVariable = "false", @Name = "month", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "month", @Visibility = "local", @Volatile = "false"] | +- Block[@Size = "2", @containsComment = "false"] | +- LocalClassStatement[] | | +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "LocalRecords$1MerchantSales", @CanonicalName = null, @EffectiveVisibility = "local", @Enum = "false", @Final = "true", @Image = "MerchantSales", @Interface = "false", @Local = "true", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Record = "true", @RegularClass = "false", @SimpleName = "MerchantSales", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "local", @Volatile = "false"] @@ -46,11 +46,11 @@ | | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "local", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | | | +- ModifierList[] | | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Merchant", @TypeImage = "Merchant"] - | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "merchant", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchant", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "merchant", @Visibility = "private", @Volatile = "false"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "merchant", @LambdaParameter = "false", @LocalVariable = "false", @Name = "merchant", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "merchant", @Visibility = "private", @Volatile = "false"] | | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "local", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | | +- ModifierList[] | | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "double", @PrimitiveType = "true", @TypeImage = "double"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "sales", @LambdaParameter = "false", @LocalVariable = "false", @Name = "sales", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "sales", @Visibility = "private", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "sales", @LambdaParameter = "false", @LocalVariable = "false", @Name = "sales", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "sales", @Visibility = "private", @Volatile = "false"] | | +- RecordBody[@Size = "0"] | +- ReturnStatement[] | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "collect", @MethodName = "collect", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -65,7 +65,7 @@ | | | | +- LambdaParameterList[@Size = "1"] | | | | | +- LambdaParameter[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @Visibility = "package", @Volatile = "false"] | | | | | +- ModifierList[] - | | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "merchant", @LambdaParameter = "true", @LocalVariable = "false", @Name = "merchant", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @VariableName = "merchant", @Visibility = "package", @Volatile = "false"] + | | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "merchant", @LambdaParameter = "true", @LocalVariable = "false", @Name = "merchant", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @VariableName = "merchant", @Visibility = "package", @Volatile = "false"] | | | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @Expression = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "MerchantSales", @TypeImage = "MerchantSales"] | | | | +- ArgumentList[@Size = "2"] @@ -79,10 +79,10 @@ | | | +- LambdaParameterList[@Size = "2"] | | | | +- LambdaParameter[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @Visibility = "package", @Volatile = "false"] | | | | | +- ModifierList[] - | | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "m1", @LambdaParameter = "true", @LocalVariable = "false", @Name = "m1", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @VariableName = "m1", @Visibility = "package", @Volatile = "false"] + | | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "m1", @LambdaParameter = "true", @LocalVariable = "false", @Name = "m1", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @VariableName = "m1", @Visibility = "package", @Volatile = "false"] | | | | +- LambdaParameter[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @Visibility = "package", @Volatile = "false"] | | | | +- ModifierList[] - | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "m2", @LambdaParameter = "true", @LocalVariable = "false", @Name = "m2", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @VariableName = "m2", @Visibility = "package", @Volatile = "false"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "m2", @LambdaParameter = "true", @LocalVariable = "false", @Name = "m2", @Native = "false", @PackagePrivate = "true", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "true", @VariableName = "m2", @Visibility = "package", @Volatile = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "compare", @MethodName = "compare", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- TypeExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Double", @TypeImage = "Double"] @@ -114,7 +114,7 @@ | | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "local", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | | +- ModifierList[] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] | | +- RecordBody[@Size = "0"] | +- LocalClassStatement[] | | +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "LocalRecords$1MyRecord2", @CanonicalName = null, @EffectiveVisibility = "local", @Enum = "false", @Final = "true", @Image = "MyRecord2", @Interface = "false", @Local = "true", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Record = "true", @RegularClass = "false", @SimpleName = "MyRecord2", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "local", @Volatile = "false"] @@ -123,7 +123,7 @@ | | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "local", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | | +- ModifierList[] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] | | +- RecordBody[@Size = "0"] | +- LocalClassStatement[] | | +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "LocalRecords$1MyRecord3", @CanonicalName = null, @EffectiveVisibility = "local", @Enum = "false", @Final = "true", @Image = "MyRecord3", @Interface = "false", @Local = "true", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Record = "true", @RegularClass = "false", @SimpleName = "MyRecord3", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "local", @Volatile = "false"] @@ -134,7 +134,7 @@ | | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "local", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | | +- ModifierList[] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] | | +- RecordBody[@Size = "0"] | +- LocalClassStatement[] | +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "LocalRecords$1MyRecord4", @CanonicalName = null, @EffectiveVisibility = "local", @Enum = "false", @Final = "true", @Image = "MyRecord4", @Interface = "false", @Local = "true", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Record = "true", @RegularClass = "false", @SimpleName = "MyRecord4", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "local", @Volatile = "false"] @@ -145,7 +145,7 @@ | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "local", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | +- ModifierList[] | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] | +- RecordBody[@Size = "0"] +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "package", @Final = "false", @Image = "methodWithLocalClass", @MethodName = "methodWithLocalClass", @Name = "methodWithLocalClass", @Native = "false", @Overridden = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "package", @Void = "true", @Volatile = "false"] | +- ModifierList[] @@ -165,19 +165,19 @@ | +- ModifierList[] | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "result"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "result", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "result", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "result", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "result", @Visibility = "local", @Volatile = "false"] | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "0", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "0.0", @ValueAsFloat = "0.0", @ValueAsInt = "0", @ValueAsLong = "0"] +- LocalVariableDeclaration[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @Visibility = "local", @Volatile = "false"] | +- ModifierList[] | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "non"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "non", @LambdaParameter = "false", @LocalVariable = "true", @Name = "non", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "non", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "non", @LambdaParameter = "false", @LocalVariable = "true", @Name = "non", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "non", @Visibility = "local", @Volatile = "false"] | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "1", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] +- LocalVariableDeclaration[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @Visibility = "local", @Volatile = "false"] | +- ModifierList[] | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "sealed"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "sealed", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sealed", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "sealed", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "sealed", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sealed", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "sealed", @Visibility = "local", @Volatile = "false"] | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "2.0", @ValueAsFloat = "2.0", @ValueAsInt = "2", @ValueAsLong = "2"] +- ExpressionStatement[] | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Expression = "true", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/NonSealedIdentifier.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/NonSealedIdentifier.txt index 9f15096158..65baa4d53a 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/NonSealedIdentifier.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/NonSealedIdentifier.txt @@ -12,25 +12,25 @@ | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] | | +- ArrayDimensions[@Size = "1"] | | +- ArrayTypeDim[@Varargs = "false"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "args", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "args", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "args", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "args", @Visibility = "local", @Volatile = "false"] +- Block[@Size = "5", @containsComment = "false"] +- LocalVariableDeclaration[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @Visibility = "local", @Volatile = "false"] | +- ModifierList[] | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "result"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "result", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "result", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "result", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "result", @Visibility = "local", @Volatile = "false"] | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "0", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "0.0", @ValueAsFloat = "0.0", @ValueAsInt = "0", @ValueAsLong = "0"] +- LocalVariableDeclaration[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @Visibility = "local", @Volatile = "false"] | +- ModifierList[] | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "non"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "non", @LambdaParameter = "false", @LocalVariable = "true", @Name = "non", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "non", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "non", @LambdaParameter = "false", @LocalVariable = "true", @Name = "non", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "non", @Visibility = "local", @Volatile = "false"] | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "1", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] +- LocalVariableDeclaration[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @Visibility = "local", @Volatile = "false"] | +- ModifierList[] | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] | +- VariableDeclarator[@Initializer = "true", @Name = "sealed"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "sealed", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sealed", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "sealed", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "sealed", @LambdaParameter = "false", @LocalVariable = "true", @Name = "sealed", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "sealed", @Visibility = "local", @Volatile = "false"] | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "2.0", @ValueAsFloat = "2.0", @ValueAsInt = "2", @ValueAsLong = "2"] +- ExpressionStatement[] | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Expression = "true", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.txt index 7d8ed2d92a..6d7b131bad 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.txt @@ -6,7 +6,7 @@ | +- ModifierList[] | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] | +- VariableDeclarator[@Initializer = "true", @Name = "s"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "private", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "private", @Volatile = "false"] | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "other string", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"other string\"", @IntLiteral = "false", @Length = "12", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "public", @Final = "false", @Image = "test", @MethodName = "test", @Name = "test", @Native = "false", @Overridden = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "public", @Void = "true", @Volatile = "false"] | +- ModifierList[] @@ -17,7 +17,7 @@ | | +- ModifierList[] | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Object", @TypeImage = "Object"] | | +- VariableDeclarator[@Initializer = "true", @Name = "obj"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "obj", @LambdaParameter = "false", @LocalVariable = "true", @Name = "obj", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "obj", @Visibility = "local", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "obj", @LambdaParameter = "false", @LocalVariable = "true", @Name = "obj", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "obj", @Visibility = "local", @Volatile = "false"] | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "abc", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"abc\"", @IntLiteral = "false", @Length = "3", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] | +- IfStatement[@Else = "true"] | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "instanceof", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -26,7 +26,7 @@ | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] | | | +- ModifierList[] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] | | +- Block[@Size = "3", @containsComment = "false"] | | | +- ExpressionStatement[] | | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -78,7 +78,7 @@ | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] | | | +- ModifierList[] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] | | +- Block[@Size = "1", @containsComment = "true"] | | | +- ExpressionStatement[] | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -111,7 +111,7 @@ | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] | | | | +- ModifierList[] | | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = ">", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "length", @MethodName = "length", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -137,7 +137,7 @@ | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] | | | | +- ModifierList[] | | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = ">", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "length", @MethodName = "length", @ParenthesisDepth = "0", @Parenthesized = "false"] | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -162,7 +162,7 @@ | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "true", @Native = "false", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] | | | +- ModifierList[] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] | | +- Block[@Size = "1", @containsComment = "true"] | | | +- ExpressionStatement[] | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -196,7 +196,7 @@ | | | | +- Annotation[@AnnotationName = "Deprecated", @SimpleName = "Deprecated"] | | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Deprecated", @TypeImage = "Deprecated"] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] | | +- Block[@Size = "1", @containsComment = "true"] | | | +- ExpressionStatement[] | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -230,7 +230,7 @@ | | | +- Annotation[@AnnotationName = "Deprecated", @SimpleName = "Deprecated"] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Deprecated", @TypeImage = "Deprecated"] | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @Native = "false", @PackagePrivate = "false", @PatternBinding = "true", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "s", @Visibility = "local", @Volatile = "false"] | +- Block[@Size = "1", @containsComment = "true"] | | +- ExpressionStatement[] | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -265,7 +265,7 @@ | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] | | +- ArrayDimensions[@Size = "1"] | | +- ArrayTypeDim[@Varargs = "false"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "args", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "args", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "args", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "args", @Visibility = "local", @Volatile = "false"] +- Block[@Size = "1", @containsComment = "false"] +- ExpressionStatement[] +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test", @MethodName = "test", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/Point.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/Point.txt index ef0e18aba6..75bc648eba 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/Point.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/Point.txt @@ -5,11 +5,11 @@ | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "private", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | +- ModifierList[] | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "x", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "x", @Visibility = "private", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "x", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "x", @Visibility = "private", @Volatile = "false"] | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "private", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | +- ModifierList[] | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "y", @LambdaParameter = "false", @LocalVariable = "false", @Name = "y", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "y", @Visibility = "private", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "y", @LambdaParameter = "false", @LocalVariable = "false", @Name = "y", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "y", @Visibility = "private", @Volatile = "false"] +- RecordBody[@Size = "1"] +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Final = "false", @Image = "main", @MethodName = "main", @Name = "main", @Native = "false", @Overridden = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "true", @Transient = "false", @Varargs = "false", @Visibility = "public", @Void = "true", @Volatile = "false"] +- ModifierList[] @@ -21,13 +21,13 @@ | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] | | +- ArrayDimensions[@Size = "1"] | | +- ArrayTypeDim[@Varargs = "false"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "args", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "args", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "args", @LambdaParameter = "false", @LocalVariable = "false", @Name = "args", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "args", @Visibility = "local", @Volatile = "false"] +- Block[@Size = "2", @containsComment = "false"] +- LocalVariableDeclaration[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @Visibility = "local", @Volatile = "false"] | +- ModifierList[] | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Point", @TypeImage = "Point"] | +- VariableDeclarator[@Initializer = "true", @Name = "p"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "p", @LambdaParameter = "false", @LocalVariable = "true", @Name = "p", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "p", @Visibility = "local", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "p", @LambdaParameter = "false", @LocalVariable = "true", @Name = "p", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "p", @Visibility = "local", @Volatile = "false"] | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @Expression = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Point", @TypeImage = "Point"] | +- ArgumentList[@Size = "2"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/Records.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/Records.txt index 95f1b1ce16..afa0dfb675 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/Records.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/Records.txt @@ -35,13 +35,13 @@ | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "private", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | | +- ModifierList[] | | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "real", @LambdaParameter = "false", @LocalVariable = "false", @Name = "real", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "real", @Visibility = "private", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "real", @LambdaParameter = "false", @LocalVariable = "false", @Name = "real", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "real", @Visibility = "private", @Volatile = "false"] | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "private", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | +- ModifierList[] | | | +- Annotation[@AnnotationName = "Deprecated", @SimpleName = "Deprecated"] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Deprecated", @TypeImage = "Deprecated"] | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "imaginary", @LambdaParameter = "false", @LocalVariable = "false", @Name = "imaginary", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "imaginary", @Visibility = "private", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "imaginary", @LambdaParameter = "false", @LocalVariable = "false", @Name = "imaginary", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "imaginary", @Visibility = "private", @Volatile = "false"] | +- RecordBody[@Size = "3"] | +- ConstructorDeclaration[@Abstract = "false", @Arity = "2", @EffectiveVisibility = "public", @Final = "false", @Image = "MyComplex", @Name = "MyComplex", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "public", @Volatile = "false", @containsComment = "false"] | | +- ModifierList[] @@ -53,11 +53,11 @@ | | | | | +- Annotation[@AnnotationName = "MyAnnotation", @SimpleName = "MyAnnotation"] | | | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "MyAnnotation", @TypeImage = "MyAnnotation"] | | | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "real", @LambdaParameter = "false", @LocalVariable = "false", @Name = "real", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "real", @Visibility = "local", @Volatile = "false"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "real", @LambdaParameter = "false", @LocalVariable = "false", @Name = "real", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "real", @Visibility = "local", @Volatile = "false"] | | | +- FormalParameter[@Abstract = "false", @EffectiveVisibility = "local", @Final = "false", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "local", @Volatile = "false"] | | | +- ModifierList[] | | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "true", @Image = "imaginary", @LambdaParameter = "false", @LocalVariable = "false", @Name = "imaginary", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "imaginary", @Visibility = "local", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "imaginary", @LambdaParameter = "false", @LocalVariable = "false", @Name = "imaginary", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "imaginary", @Visibility = "local", @Volatile = "false"] | | +- Block[@Size = "3", @containsComment = "false"] | | +- IfStatement[@Else = "false"] | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = ">", @ParenthesisDepth = "0", @Parenthesized = "false"] @@ -84,7 +84,7 @@ | | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "private", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | | +- ModifierList[] | | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "a", @Visibility = "private", @Volatile = "false"] | | +- RecordBody[@Size = "0"] | +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "Records$MyComplex$NestedClass", @CanonicalName = "Records.MyComplex.NestedClass", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Image = "NestedClass", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "false", @RegularClass = "true", @SimpleName = "NestedClass", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "public", @Volatile = "false"] | +- ModifierList[] @@ -95,11 +95,11 @@ | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "private", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | | +- ModifierList[] | | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "lo", @LambdaParameter = "false", @LocalVariable = "false", @Name = "lo", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "lo", @Visibility = "private", @Volatile = "false"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "lo", @LambdaParameter = "false", @LocalVariable = "false", @Name = "lo", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "lo", @Visibility = "private", @Volatile = "false"] | | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "private", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | +- ModifierList[] | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "hi", @LambdaParameter = "false", @LocalVariable = "false", @Name = "hi", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "hi", @Visibility = "private", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "hi", @LambdaParameter = "false", @LocalVariable = "false", @Name = "hi", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "hi", @Visibility = "private", @Volatile = "false"] | +- RecordBody[@Size = "2"] | +- CompactConstructorDeclaration[@Abstract = "false", @EffectiveVisibility = "public", @Final = "false", @Image = "Range", @Native = "false", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @Transient = "false", @Visibility = "public", @Volatile = "false"] | | +- ModifierList[] @@ -141,7 +141,7 @@ | | | +- ArrayTypeDim[@Varargs = "true"] | | | +- Annotation[@AnnotationName = "Nullable", @SimpleName = "Nullable"] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Nullable", @TypeImage = "Nullable"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "x", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "x", @Visibility = "private", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "x", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "x", @Visibility = "private", @Volatile = "false"] | +- RecordBody[@Size = "0"] +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "Records$ArrayRec", @CanonicalName = "Records.ArrayRec", @EffectiveVisibility = "public", @Enum = "false", @Final = "true", @Image = "ArrayRec", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "true", @RegularClass = "false", @SimpleName = "ArrayRec", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "public", @Volatile = "false"] | +- ModifierList[] @@ -152,7 +152,7 @@ | | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] | | | +- ArrayDimensions[@Size = "1"] | | | +- ArrayTypeDim[@Varargs = "false"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "x", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "x", @Visibility = "private", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "x", @LambdaParameter = "false", @LocalVariable = "false", @Name = "x", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "x", @Visibility = "private", @Volatile = "false"] | +- RecordBody[@Size = "0"] +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "Records$EmptyRec", @CanonicalName = "Records.EmptyRec", @EffectiveVisibility = "public", @Enum = "false", @Final = "true", @Image = "EmptyRec", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "true", @RegularClass = "false", @SimpleName = "EmptyRec", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "public", @Volatile = "false"] | +- ModifierList[] @@ -183,7 +183,7 @@ | | | +- TypeArguments[@Diamond = "false", @Size = "1"] | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] | | +- VariableDeclarator[@Initializer = "true", @Name = "r"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @FormalParameter = "false", @Image = "r", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "r", @Visibility = "local", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "r", @LambdaParameter = "false", @LocalVariable = "true", @Name = "r", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "false", @Protected = "false", @Public = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "r", @Visibility = "local", @Volatile = "false"] | | +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "true", @Expression = "true", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "EmptyRec", @TypeImage = "EmptyRec"] | | | +- TypeArguments[@Diamond = "true", @Size = "0"] @@ -212,11 +212,11 @@ | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "private", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | | +- ModifierList[] | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "firstName", @LambdaParameter = "false", @LocalVariable = "false", @Name = "firstName", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "firstName", @Visibility = "private", @Volatile = "false"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "firstName", @LambdaParameter = "false", @LocalVariable = "false", @Name = "firstName", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "firstName", @Visibility = "private", @Volatile = "false"] | +- RecordComponent[@Abstract = "false", @EffectiveVisibility = "private", @Final = "true", @Native = "false", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @Varargs = "false", @Visibility = "private", @Volatile = "false"] | +- ModifierList[] | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] - | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @FormalParameter = "false", @Image = "lastName", @LambdaParameter = "false", @LocalVariable = "false", @Name = "lastName", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "lastName", @Visibility = "private", @Volatile = "false"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "lastName", @LambdaParameter = "false", @LocalVariable = "false", @Name = "lastName", @Native = "false", @PackagePrivate = "false", @PatternBinding = "false", @Private = "true", @Protected = "false", @Public = "false", @RecordComponent = "true", @ResourceDeclaration = "false", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @Transient = "false", @TypeInferred = "false", @VariableName = "lastName", @Visibility = "private", @Volatile = "false"] +- ImplementsList[@Size = "2"] | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Person", @TypeImage = "Person"] | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "true", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Serializable", @TypeImage = "Serializable"] From d2649850736417c0129fa0f24ac8f9b09f214991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 3 Apr 2021 23:14:21 +0200 Subject: [PATCH 100/101] Add manual tests --- .../pmd/lang/java/ast/ASTStatementsTest.kt | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTStatementsTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTStatementsTest.kt index de5d089369..8a3566e8a0 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTStatementsTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTStatementsTest.kt @@ -6,6 +6,8 @@ package net.sourceforge.pmd.lang.java.ast import net.sourceforge.pmd.lang.ast.test.shouldBe +import net.sourceforge.pmd.lang.java.types.JPrimitiveType +import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind.INT class ASTStatementsTest : ParserTestSpec({ @@ -24,7 +26,11 @@ class ASTStatementsTest : ParserTestSpec({ it::getTypeNode shouldBe classType("Integer") fromChild { - variableId("i") + variableId("i") { + it::isLocalVariable shouldBe false + it::isForLoopVariable shouldBe false + it::isForeachVariable shouldBe true + } } } @@ -85,7 +91,18 @@ class ASTStatementsTest : ParserTestSpec({ "for (int i = 0; i < 2; i++);" should parseAs { forLoop { it::getInit shouldBe forInit { - localVarDecl() + localVarDecl { + localVarModifiers() + primitiveType(INT) + varDeclarator { + variableId("i") { + it::isLocalVariable shouldBe true // different from foreach too + it::isForLoopVariable shouldBe true + it::isForeachVariable shouldBe false + } + int(0) + } + } } it::getCondition shouldBe infixExpr(BinaryOp.LT) { variableAccess("i") From fcfadbdd969dadbd1156d8cd43072ae00d0c1e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 4 Apr 2021 15:42:29 +0200 Subject: [PATCH 101/101] Add a 'flatten operands' op for concatenations --- .../pmd/lang/java/ast/BinaryOp.java | 11 +++++++ .../lang/java/rule/internal/JavaRuleUtil.java | 29 ++++++++++++++++ .../UseStringBufferForStringAppendsRule.java | 14 +++----- .../java/ast/ConstantExpressionsTests.java | 4 +-- .../java/rule/internal/JavaRuleUtilTest.java | 33 +++++++++++++++++-- .../java/symboltable/BaseNonParserTest.java | 12 +++++++ .../xml/UseStringBufferForStringAppends.xml | 20 +++++++++++ 7 files changed, 109 insertions(+), 14 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java index bd06111562..e93e0f1d50 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java @@ -205,4 +205,15 @@ public enum BinaryOp implements InternalInterfaces.OperatorLike { } return false; } + + /** + * Tests if the node is an {@link ASTInfixExpression} with the given operator. + */ + public static boolean isInfixExprWithOperator(@Nullable JavaNode e, BinaryOp operator) { + if (e instanceof ASTInfixExpression) { + ASTInfixExpression infix = (ASTInfixExpression) e; + return operator == infix.getOperator(); + } + return false; + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java index 3488934283..a8fa56323c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java @@ -10,6 +10,7 @@ import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectStreamField; import java.lang.reflect.Modifier; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -681,4 +682,32 @@ public final class JavaRuleUtil { } return false; } + + /** + * Return a node stream containing all the operands of an addition expression. + * For instance, {@code a+b+c} will be parsed as a tree with two levels. + * This method will return a flat node stream containing {@code a, b, c}. + * + * @param e An expression, if it is not a string concatenation expression, + * then returns an empty node stream. + */ + public static NodeStream flattenOperands(ASTExpression e) { + List result = new ArrayList<>(); + flattenOperandsRec(e, result); + return NodeStream.fromIterable(result); + } + + private static void flattenOperandsRec(ASTExpression e, List result) { + if (isStringConcatExpression(e)) { + ASTInfixExpression infix = (ASTInfixExpression) e; + flattenOperandsRec(infix.getLeftOperand(), result); + flattenOperandsRec(infix.getRightOperand(), result); + } else { + result.add(e); + } + } + + private static boolean isStringConcatExpression(ASTExpression e) { + return BinaryOp.isInfixExprWithOperator(e, BinaryOp.ADD) && TypeTestUtil.isA(String.class, e); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java index ce76450649..cd4140bff7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UseStringBufferForStringAppendsRule.java @@ -11,11 +11,10 @@ import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.AccessType; import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression; -import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; +import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRule { @@ -57,13 +56,10 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu } int usageOnRightHandSide = - assignment.getRightOperand() - .descendantsOrSelf() - .filterIs(ASTInfixExpression.class) - .filter(e -> e.getOperator() == BinaryOp.ADD) - .children(ASTNamedReferenceExpr.class) - .filterMatching(ASTNamedReferenceExpr::getReferencedSym, node.getSymbol()) - .count(); + JavaRuleUtil.flattenOperands(assignment.getRightOperand()) + .filterIs(ASTNamedReferenceExpr.class) + .filterMatching(ASTNamedReferenceExpr::getReferencedSym, node.getSymbol()) + .count(); // or maybe a append in some way (a = a + x) // or a combination (a += a + x) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ConstantExpressionsTests.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ConstantExpressionsTests.java index 3a11e59817..318c693a83 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ConstantExpressionsTests.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ConstantExpressionsTests.java @@ -17,9 +17,7 @@ public class ConstantExpressionsTests extends BaseNonParserTest { private Executable isConst(String expr, Object value) { return () -> { - ASTCompilationUnit ast = java.parse("class Foo {{ Object o = (" + expr + "); }}"); - - ASTExpression e = ast.descendants(ASTExpression.class).crossFindBoundaries().firstOrThrow(); + ASTExpression e = parseExpr(expr); assertEquals(value, e.getConstValue(), "Constant value of '" + expr + "'"); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java index 577a3a5e47..46b04d7202 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtilTest.java @@ -5,13 +5,20 @@ package net.sourceforge.pmd.lang.java.rule.internal; import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.startsWithCamelCaseWord; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; +import org.junit.Test; -public class JavaRuleUtilTest { +import net.sourceforge.pmd.lang.java.ast.ASTExpression; +import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; +import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; +import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; + +public class JavaRuleUtilTest extends BaseNonParserTest { @Test public void testCamelCaseWords() { @@ -24,4 +31,26 @@ public class JavaRuleUtilTest { assertThrows(NullPointerException.class, () -> startsWithCamelCaseWord("fnei", null)); } + @Test + public void testFlattenConcatOperands() { + ASTExpression e = parseExpr("s1+s2+s3"); + + assertTrue(JavaRuleUtil.isStringConcatExpr(e)); + assertEquals(e.descendants(ASTVariableAccess.class).toList(), + JavaRuleUtil.flattenOperands(e).toList()); + } + + @Test + public void testFlattenConcatOperandsRespectsTyping() { + ASTInfixExpression e = (ASTInfixExpression) parseExpr("i+j+s2+s3"); + assertTrue(JavaRuleUtil.isStringConcatExpr(e)); + ASTInfixExpression left = (ASTInfixExpression) e.getLeftOperand(); + assertTrue(JavaRuleUtil.isStringConcatExpr(left)); + + // This is (i+j) + // vvvvvvvvvvvvvvvvvvvvv + assertEquals(listOf(left.getLeftOperand(), left.getRightOperand(), e.getRightOperand()), + JavaRuleUtil.flattenOperands(e).toList()); + } + } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/BaseNonParserTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/BaseNonParserTest.java index d59fc4e543..67ee741d4a 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/BaseNonParserTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/BaseNonParserTest.java @@ -9,6 +9,7 @@ import java.util.List; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.JavaParsingHelper; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; /** * Base class for tests that usually need processing stages to run when @@ -27,4 +28,15 @@ public abstract class BaseNonParserTest { protected List getOrderedNodes(Class target, String code) { return JavaParsingHelper.WITH_PROCESSING.getNodes(target, code); } + + /** + * Parse and return an expression. Some variables are predeclared. + */ + protected ASTExpression parseExpr(String expr) { + ASTCompilationUnit ast = java.parse("class Foo {{ " + + "String s1,s2,s3; " + + "int i,j,k; " + + "Object o = (" + expr + "); }}"); + return ast.descendants(ASTExpression.class).crossFindBoundaries().firstOrThrow(); + } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml index f30009740b..ff2216eab2 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseStringBufferForStringAppends.xml @@ -544,6 +544,26 @@ public class UseStringBufferForStringAppendsFP { ]]>
+ + FP if variable is overwritten with dependent value + 0 + + + False positive with simple assignment instead of compound 0