From e7456c13413c29455d84d693fc3436b191e05261 Mon Sep 17 00:00:00 2001 From: Bailey Tjiong Date: Fri, 25 Feb 2022 19:01:18 +0100 Subject: [PATCH 01/89] Add an editme button at the bottom --- docs/_layouts/page.html | 8 ++++++++ docs/pages/pmd/devdocs/building.md | 9 +++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/_layouts/page.html b/docs/_layouts/page.html index 67a238ca90..9db879f3fc 100644 --- a/docs/_layouts/page.html +++ b/docs/_layouts/page.html @@ -63,6 +63,14 @@ layout: default {% endif %} + {% if site.github_editme_path %} + This documentation is written in markdown. If there is something missing or can be improved, edit this page on github and create a PR: + {% unless page.editmepath == false %} + Edit me + {% endunless %} + {% endif %} + + {% include disqus.html %} diff --git a/docs/pages/pmd/devdocs/building.md b/docs/pages/pmd/devdocs/building.md index 97196f2179..75d342bdf8 100644 --- a/docs/pages/pmd/devdocs/building.md +++ b/docs/pages/pmd/devdocs/building.md @@ -84,9 +84,6 @@ Now the source and binary distribution zip files can be found in the folder `pmd **Notes:** -* The rules that have already been written are specified in the `src/main/resources/rulesets/` directories of -the specific languages, e.g. `pmd-java/src/main/resources/rulesets`. -They’re also in the jar file that’s included with both the source and binary distributions. - -A paucity of detail, I’m sure you’d agree. If you think this document can be improved, -please post [here](http://sourceforge.net/p/pmd/discussion/188192) and let me know how. Thanks! +- The rules that have already been written are specified in the `src/main/resources/rulesets/` directories of + the specific languages, e.g. `pmd-java/src/main/resources/rulesets`. + They’re also in the jar file that’s included with both the source and binary distributions. From 6bdce79bdd118a9c82358774a0569c0d0705220c Mon Sep 17 00:00:00 2001 From: Bailey Tjiong Date: Fri, 25 Feb 2022 21:50:24 +0100 Subject: [PATCH 02/89] Add small edit button to section heading line --- docs/_layouts/page.html | 18 ++++++++++++------ docs/css/customstyles.css | 4 ++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/_layouts/page.html b/docs/_layouts/page.html index 9db879f3fc..8ae8f8d2fe 100644 --- a/docs/_layouts/page.html +++ b/docs/_layouts/page.html @@ -33,11 +33,8 @@ layout: default {% if page.summary %}
{{page.summary}}
{% endif %} - -
- - - {% if site.github_editme_path %} + + {% if site.github_editme_path %} {% assign editmepath = page.path %} {% if page.editmepath %} @@ -49,6 +46,8 @@ layout: default {% endif %} +
+ {{content}}
@@ -64,9 +63,16 @@ layout: default
{% if site.github_editme_path %} - This documentation is written in markdown. If there is something missing or can be improved, edit this page on github and create a PR: + This documentation is written in markdown. If there is something missing or can be improved, edit this page on github and create a PR: {% unless page.editmepath == false %} Edit me + {% endunless %} {% endif %} diff --git a/docs/css/customstyles.css b/docs/css/customstyles.css index 45885d182b..2aa3a5b69d 100644 --- a/docs/css/customstyles.css +++ b/docs/css/customstyles.css @@ -1246,3 +1246,7 @@ h4.panel-title { width: 100px; height: 100px; } + +.post-content h2 { + display: inline-block; +} \ No newline at end of file From 9d60958ec5afe8e49b018c3397071cbc2630773e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 3 Mar 2022 19:04:53 +0100 Subject: [PATCH 03/89] [apex] Add designer bindings to display main attributes --- .../pmd/lang/apex/ApexHandler.java | 7 ++ .../apex/internal/ApexDesignerBindings.java | 64 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/internal/ApexDesignerBindings.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 e8113f20df..efe2edd338 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 @@ -17,6 +17,7 @@ import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.ast.DumpFacade; +import net.sourceforge.pmd.lang.apex.internal.ApexDesignerBindings; import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics; import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey; import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey; @@ -25,6 +26,7 @@ import net.sourceforge.pmd.lang.apex.rule.ApexRuleViolationFactory; import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider; import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider; import net.sourceforge.pmd.lang.rule.RuleViolationFactory; +import net.sourceforge.pmd.util.designerbindings.DesignerBindings; /** @@ -69,6 +71,11 @@ public class ApexHandler extends AbstractLanguageVersionHandler { return myMetricsProvider; } + @Override + public DesignerBindings getDesignerBindings() { + return ApexDesignerBindings.INSTANCE; + } + private static class ApexMetricsProvider extends AbstractLanguageMetricsProvider, ASTMethod> { @SuppressWarnings("unchecked") diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/internal/ApexDesignerBindings.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/internal/ApexDesignerBindings.java new file mode 100644 index 0000000000..80dcb9bd65 --- /dev/null +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/internal/ApexDesignerBindings.java @@ -0,0 +1,64 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.internal; + +import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration; +import net.sourceforge.pmd.lang.apex.ast.ASTMethod; +import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; +import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; +import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration; +import net.sourceforge.pmd.lang.apex.ast.ApexNode; +import net.sourceforge.pmd.lang.apex.ast.ApexParserVisitorAdapter; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.Attribute; +import net.sourceforge.pmd.util.designerbindings.DesignerBindings.DefaultDesignerBindings; + +public class ApexDesignerBindings extends DefaultDesignerBindings { + + public static final ApexDesignerBindings INSTANCE = new ApexDesignerBindings(); + + @Override + public Attribute getMainAttribute(Node node) { + if (node instanceof ApexNode) { + Attribute attr = (Attribute) ((ApexNode) node).jjtAccept(MainAttrVisitor.INSTANCE, null); + if (attr != null) { + return attr; + } + } + + return super.getMainAttribute(node); + } + + @Override + public TreeIconId getIcon(Node node) { + if (node instanceof ASTFieldDeclaration) { + return TreeIconId.FIELD; + } else if (node instanceof ASTUserClass) { + return TreeIconId.CLASS; + } else if (node instanceof ASTMethod) { + return TreeIconId.METHOD; + } else if (node instanceof ASTVariableDeclaration) { + return TreeIconId.VARIABLE; + } + return super.getIcon(node); + } + + + private static final class MainAttrVisitor extends ApexParserVisitorAdapter { + + private static final MainAttrVisitor INSTANCE = new MainAttrVisitor(); + + @Override + public Object visit(ApexNode node, Object data) { + return null; // don't recurse + } + + @Override + public Object visit(ASTMethodCallExpression node, Object data) { + return new Attribute(node, "MethodName", node.getMethodName()); + } + } + +} From e63858269bf8fb25111e5ae853926c7b6ada718d Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 3 Mar 2022 21:55:56 +0100 Subject: [PATCH 04/89] [test] Fix AbstractRuleSetFactoryTest - check category/.../ as well --- .../sourceforge/pmd/AbstractRuleSetFactoryTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java index 814a349387..a1aa1327d5 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java @@ -286,10 +286,17 @@ public abstract class AbstractRuleSetFactoryTest { } private List getRuleSetFileNames(String language) throws IOException, RuleSetNotFoundException { + List ruleSetFileNames = new ArrayList<>(); + ruleSetFileNames.addAll(getRuleSetFileNames(language, "rulesets/" + language + "/rulesets.properties")); + ruleSetFileNames.addAll(getRuleSetFileNames(language, "category/" + language + "/categories.properties")); + return ruleSetFileNames; + } + + private List getRuleSetFileNames(String language, String propertiesPath) throws IOException, RuleSetNotFoundException { List ruleSetFileNames = new ArrayList<>(); try { Properties properties = new Properties(); - try (InputStream is = new ResourceLoader().loadClassPathResourceAsStreamOrThrow("rulesets/" + language + "/rulesets.properties")) { + try (InputStream is = new ResourceLoader().loadClassPathResourceAsStreamOrThrow(propertiesPath)) { properties.load(is); } String fileNames = properties.getProperty("rulesets.filenames"); @@ -304,6 +311,8 @@ public abstract class AbstractRuleSetFactoryTest { } return ruleSetFileNames; } + + private RuleSet loadRuleSetByFileName(String ruleSetFileName) throws RuleSetNotFoundException { RuleSetFactory rsf = RulesetsFactoryUtils.defaultFactory(); From b825f7f9c98b62f4c5e912c65f87b601f0f46c03 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 3 Mar 2022 22:00:58 +0100 Subject: [PATCH 05/89] [modelica] Rename rules and fix rulesets --- docs/pages/release_notes.md | 5 ++ pmd-modelica/pom.xml | 6 +++ .../rule/AmbiguousResolutionRule.java | 25 +++------ .../rule/ConnectUsingNonConnector.java | 50 +++--------------- .../AmbiguousResolutionRule.java | 27 ++++++++++ .../ConnectUsingNonConnectorRule.java | 51 +++++++++++++++++++ .../category/modelica/bestpractices.xml | 7 ++- 7 files changed, 108 insertions(+), 63 deletions(-) create mode 100644 pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/bestpractices/AmbiguousResolutionRule.java create mode 100644 pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/bestpractices/ConnectUsingNonConnectorRule.java diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8b6e8ffc93..89a2e399e1 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -65,6 +65,11 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is * {% jdoc !!core::PMDConfiguration#prependClasspath(java.lang.String) %} is deprecated in favour of {% jdoc core::PMDConfiguration#prependAuxClasspath(java.lang.String) %}. +* In modelica, the rule classes {% jdoc modelica::lang.modelica.rule.AmbiguousResolutionRule %} + and {% jdoc modelica::lang.modelica.rule.ConnectUsingNonConnector %} have been deprecated, + since they didn't comply to the usual rule class naming conventions yet. + The replacements are in the subpackage `bestpractices`. + #### Experimental APIs * Together with the [new programmatic API](#new-programmatic-api) the interface diff --git a/pmd-modelica/pom.xml b/pmd-modelica/pom.xml index 063371ff4f..3b94ff1440 100644 --- a/pmd-modelica/pom.xml +++ b/pmd-modelica/pom.xml @@ -12,6 +12,12 @@ + + + ${basedir}/src/main/resources + true + + maven-resources-plugin diff --git a/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/AmbiguousResolutionRule.java b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/AmbiguousResolutionRule.java index fcc1213d47..05e2d2302a 100644 --- a/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/AmbiguousResolutionRule.java +++ b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/AmbiguousResolutionRule.java @@ -1,26 +1,13 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ + package net.sourceforge.pmd.lang.modelica.rule; -import net.sourceforge.pmd.lang.modelica.ast.ASTName; -import net.sourceforge.pmd.lang.modelica.resolver.ResolutionResult; -import net.sourceforge.pmd.lang.modelica.resolver.ResolvableEntity; +/** + * @deprecated Use {@link net.sourceforge.pmd.lang.modelica.rule.bestpractices.AmbiguousResolutionRule} + */ +public class AmbiguousResolutionRule extends net.sourceforge.pmd.lang.modelica.rule.bestpractices.AmbiguousResolutionRule { -public class AmbiguousResolutionRule extends AbstractModelicaRule { - @Override - public Object visit(ASTName node, Object data) { - ResolutionResult candidates = node.getResolutionCandidates(); - if (candidates.isClashed()) { - StringBuilder sb = new StringBuilder(); - sb.append("Candidate resolutions: "); - for (ResolvableEntity candidate: candidates.getBestCandidates()) { - sb.append(candidate.getDescriptiveName()); - sb.append(", "); - } - addViolation(data, node, sb.substring(0, sb.length() - 2)); - } - return super.visit(node, data); - } } diff --git a/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/ConnectUsingNonConnector.java b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/ConnectUsingNonConnector.java index af444d5ba7..8698df8b36 100644 --- a/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/ConnectUsingNonConnector.java +++ b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/ConnectUsingNonConnector.java @@ -1,50 +1,16 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ + package net.sourceforge.pmd.lang.modelica.rule; -import net.sourceforge.pmd.lang.modelica.ast.ASTComponentReference; -import net.sourceforge.pmd.lang.modelica.ast.ASTConnectClause; -import net.sourceforge.pmd.lang.modelica.resolver.ModelicaClassSpecialization; -import net.sourceforge.pmd.lang.modelica.resolver.ModelicaClassType; -import net.sourceforge.pmd.lang.modelica.resolver.ModelicaComponentDeclaration; -import net.sourceforge.pmd.lang.modelica.resolver.ResolutionResult; -import net.sourceforge.pmd.lang.modelica.resolver.ResolvableEntity; +import net.sourceforge.pmd.lang.modelica.rule.bestpractices.ConnectUsingNonConnectorRule; -public class ConnectUsingNonConnector extends AbstractModelicaRule { - private void reportIfViolated(ASTComponentReference ref, Object data) { - ResolutionResult resolution = ref.getResolutionCandidates(); - if (!resolution.isUnresolved()) { // no false positive if not resolved at all - ResolvableEntity firstDecl = resolution.getBestCandidates().get(0); - if (firstDecl instanceof ModelicaComponentDeclaration) { - ModelicaComponentDeclaration componentDecl = (ModelicaComponentDeclaration) firstDecl; - ResolutionResult componentTypes = componentDecl.getTypeCandidates(); - if (!componentTypes.isUnresolved()) { - if (componentTypes.getBestCandidates().get(0) instanceof ModelicaClassType) { - ModelicaClassType classDecl = (ModelicaClassType) componentTypes.getBestCandidates().get(0); - ModelicaClassSpecialization restriction = classDecl.getSpecialization(); - if (!classDecl.isConnectorLike()) { - addViolation(data, ref, restriction.toString()); - } - } else { - addViolation(data, ref, firstDecl.getDescriptiveName()); - } - } - } else { - addViolation(data, ref, firstDecl.getDescriptiveName()); - } - } - } +/** + * @deprecated Use {@link ConnectUsingNonConnectorRule} + */ +@Deprecated +public class ConnectUsingNonConnector extends ConnectUsingNonConnectorRule { - @Override - public Object visit(ASTConnectClause node, Object data) { - ASTComponentReference lhs = (ASTComponentReference) node.getChild(0); - ASTComponentReference rhs = (ASTComponentReference) node.getChild(1); - - reportIfViolated(lhs, data); - reportIfViolated(rhs, data); - - return super.visit(node, data); - } } diff --git a/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/bestpractices/AmbiguousResolutionRule.java b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/bestpractices/AmbiguousResolutionRule.java new file mode 100644 index 0000000000..724018ca62 --- /dev/null +++ b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/bestpractices/AmbiguousResolutionRule.java @@ -0,0 +1,27 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.modelica.rule.bestpractices; + +import net.sourceforge.pmd.lang.modelica.ast.ASTName; +import net.sourceforge.pmd.lang.modelica.resolver.ResolutionResult; +import net.sourceforge.pmd.lang.modelica.resolver.ResolvableEntity; +import net.sourceforge.pmd.lang.modelica.rule.AbstractModelicaRule; + +public class AmbiguousResolutionRule extends AbstractModelicaRule { + @Override + public Object visit(ASTName node, Object data) { + ResolutionResult candidates = node.getResolutionCandidates(); + if (candidates.isClashed()) { + StringBuilder sb = new StringBuilder(); + sb.append("Candidate resolutions: "); + for (ResolvableEntity candidate: candidates.getBestCandidates()) { + sb.append(candidate.getDescriptiveName()); + sb.append(", "); + } + addViolation(data, node, sb.substring(0, sb.length() - 2)); + } + return super.visit(node, data); + } +} diff --git a/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/bestpractices/ConnectUsingNonConnectorRule.java b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/bestpractices/ConnectUsingNonConnectorRule.java new file mode 100644 index 0000000000..5712bca82f --- /dev/null +++ b/pmd-modelica/src/main/java/net/sourceforge/pmd/lang/modelica/rule/bestpractices/ConnectUsingNonConnectorRule.java @@ -0,0 +1,51 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.modelica.rule.bestpractices; + +import net.sourceforge.pmd.lang.modelica.ast.ASTComponentReference; +import net.sourceforge.pmd.lang.modelica.ast.ASTConnectClause; +import net.sourceforge.pmd.lang.modelica.resolver.ModelicaClassSpecialization; +import net.sourceforge.pmd.lang.modelica.resolver.ModelicaClassType; +import net.sourceforge.pmd.lang.modelica.resolver.ModelicaComponentDeclaration; +import net.sourceforge.pmd.lang.modelica.resolver.ResolutionResult; +import net.sourceforge.pmd.lang.modelica.resolver.ResolvableEntity; +import net.sourceforge.pmd.lang.modelica.rule.AbstractModelicaRule; + +public class ConnectUsingNonConnectorRule extends AbstractModelicaRule { + private void reportIfViolated(ASTComponentReference ref, Object data) { + ResolutionResult resolution = ref.getResolutionCandidates(); + if (!resolution.isUnresolved()) { // no false positive if not resolved at all + ResolvableEntity firstDecl = resolution.getBestCandidates().get(0); + if (firstDecl instanceof ModelicaComponentDeclaration) { + ModelicaComponentDeclaration componentDecl = (ModelicaComponentDeclaration) firstDecl; + ResolutionResult componentTypes = componentDecl.getTypeCandidates(); + if (!componentTypes.isUnresolved()) { + if (componentTypes.getBestCandidates().get(0) instanceof ModelicaClassType) { + ModelicaClassType classDecl = (ModelicaClassType) componentTypes.getBestCandidates().get(0); + ModelicaClassSpecialization restriction = classDecl.getSpecialization(); + if (!classDecl.isConnectorLike()) { + addViolation(data, ref, restriction.toString()); + } + } else { + addViolation(data, ref, firstDecl.getDescriptiveName()); + } + } + } else { + addViolation(data, ref, firstDecl.getDescriptiveName()); + } + } + } + + @Override + public Object visit(ASTConnectClause node, Object data) { + ASTComponentReference lhs = (ASTComponentReference) node.getChild(0); + ASTComponentReference rhs = (ASTComponentReference) node.getChild(1); + + reportIfViolated(lhs, data); + reportIfViolated(rhs, data); + + return super.visit(node, data); + } +} diff --git a/pmd-modelica/src/main/resources/category/modelica/bestpractices.xml b/pmd-modelica/src/main/resources/category/modelica/bestpractices.xml index fb1bcfde9e..bb896cca2d 100644 --- a/pmd-modelica/src/main/resources/category/modelica/bestpractices.xml +++ b/pmd-modelica/src/main/resources/category/modelica/bestpractices.xml @@ -10,6 +10,7 @@ Rules which enforce generally accepted best practices. @@ -41,9 +42,10 @@ end SomeOtherName /* should be SomeName */; + class="net.sourceforge.pmd.lang.modelica.rule.bestpractices.ConnectUsingNonConnectorRule"> Modelica specification requires passing connectors to the `connect` clause, while some implementations tolerate using it on plain variables, etc.. @@ -75,8 +77,9 @@ end Example; + class="net.sourceforge.pmd.lang.modelica.rule.bestpractices.AmbiguousResolutionRule"> There is multiple candidates for this type resolution. While generally this is not an error, this may indicate a bug. From 9bab5b659f37811b9627d93e50481d8dd8cdc8c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 6 Mar 2022 11:41:49 +0100 Subject: [PATCH 06/89] Fix issue with simple name containing dollar --- .../java/symbols/internal/asm/ClassStub.java | 8 ++++- .../testdata/deep/ClassWithDollar$.java | 13 ++++++++ .../java/symbols/internal/asm/NamesTest.kt | 13 +++++++- .../table/internal/HeaderScopesTest.kt | 32 +++++++++++++++++-- 4 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 pmd-java/src/test/java/javasymbols/testdata/deep/ClassWithDollar$.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java index 2c012c423e..36947a016c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java @@ -441,6 +441,7 @@ final class ClassStub implements JClassSymbol, AsmStub { static class Names { + private static final Pattern INNER_DELIMITER = Pattern.compile("\\$(?=\\w)"); final String binaryName; final String canonicalName; final String packageName; @@ -451,7 +452,12 @@ final class ClassStub implements JClassSymbol, AsmStub { binaryName = internalName.replace('/', '.'); packageName = binaryName.substring(0, packageEnd); - canonicalName = binaryName.replace('$', '.'); + if (binaryName.indexOf('$') >= 0) { // contains a dollar + canonicalName = INNER_DELIMITER.matcher(binaryName).replaceAll("."); + } else { + // fast path + canonicalName = binaryName; + } int lastDot = canonicalName.lastIndexOf('.'); simpleName = canonicalName.substring(lastDot + 1); diff --git a/pmd-java/src/test/java/javasymbols/testdata/deep/ClassWithDollar$.java b/pmd-java/src/test/java/javasymbols/testdata/deep/ClassWithDollar$.java new file mode 100644 index 0000000000..f3d21ed8c7 --- /dev/null +++ b/pmd-java/src/test/java/javasymbols/testdata/deep/ClassWithDollar$.java @@ -0,0 +1,13 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package javasymbols.testdata.deep; + +/** + * @author Clément Fournier + */ +public class ClassWithDollar$ { + + public static final Object MODULE$ = null; +} diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt index 0912a6c1fd..ae28a7390a 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt @@ -6,8 +6,9 @@ package net.sourceforge.pmd.lang.java.symbols.internal.asm import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe +import net.sourceforge.pmd.lang.ast.test.IntelliMarker -class NamesTest : FunSpec({ +class NamesTest : IntelliMarker, FunSpec({ test("Test inner class names") { @@ -40,4 +41,14 @@ class NamesTest : FunSpec({ AsmSymbolResolver.hasCanonicalName("a/b/C\$D") shouldBe true } + test("Test names with trailing dollar") { + + val names = ClassStub.Names("javasymbols/testdata/deep/ClassWithDollar\$") + + names.binaryName shouldBe "javasymbols.testdata.deep.ClassWithDollar\$" + names.canonicalName shouldBe "javasymbols.testdata.deep.ClassWithDollar\$" + names.simpleName shouldBe "ClassWithDollar\$" + names.packageName shouldBe "javasymbols.testdata.deep" + } + }) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt index 07b6d51346..5bff9ca925 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.collections.haveSize import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder import io.kotest.matchers.maps.shouldBeEmpty import io.kotest.matchers.maps.shouldContain +import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe @@ -19,7 +20,7 @@ import javasymbols.testdata.StaticNameCollision import javasymbols.testdata.StaticsSuper import net.sourceforge.pmd.lang.ast.test.shouldBe import net.sourceforge.pmd.lang.ast.test.shouldBeA -import net.sourceforge.pmd.lang.java.ast.ProcessorTestSpec +import net.sourceforge.pmd.lang.java.ast.* import net.sourceforge.pmd.lang.java.symbols.JClassSymbol import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol @@ -29,8 +30,7 @@ import net.sourceforge.pmd.lang.java.symbols.table.JSymbolTable import net.sourceforge.pmd.lang.java.symbols.table.ScopeInfo import net.sourceforge.pmd.lang.java.symbols.table.ScopeInfo.* import net.sourceforge.pmd.lang.java.symbols.table.coreimpl.ShadowChain -import net.sourceforge.pmd.lang.java.types.JClassType -import net.sourceforge.pmd.lang.java.types.JTypeMirror +import net.sourceforge.pmd.lang.java.types.* /** * Tests the scopes that dominate the whole compilation unit. @@ -328,6 +328,32 @@ class HeaderScopesTest : ProcessorTestSpec({ "java.lang.Exception" ) } + + parserTest("Import of an unconventional name with dollar") { + + assertNoSemanticErrorsOrWarnings() + + val acu = parser.parse( + """ + + import javasymbols.testdata.deep.ClassWithDollar${'$'}; + + public class Foo { + public void visit() { + var mod = ClassWithDollar${'$'}.MODULE${'$'}; + } + } + """ + ) + + val moduleAccess = acu.descendants(ASTFieldAccess::class.java).first().shouldNotBeNull() + with (acu.typeDsl) { + moduleAccess shouldHaveType ts.OBJECT + moduleAccess.qualifier.shouldBeA { + it shouldHaveType ts.rawType(ts.getClassSymbol("javasymbols.testdata.deep.ClassWithDollar\$")) + } + } + } }) From 1f008958e8befe4416925d7f33fe7b7c9facd652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 6 Mar 2022 13:54:03 +0100 Subject: [PATCH 07/89] Add tests, require parsing to know simple/cano name --- .../symbols/internal/SymbolToStrings.java | 6 - .../internal/asm/AsmSymbolResolver.java | 30 ++-- .../java/symbols/internal/asm/ClassStub.java | 131 +++++++++++++++--- .../internal/asm/ClassStubBuilder.java | 30 +++- .../java/symbols/internal/asm/Loader.java | 23 ++- .../internal/asm/SoftClassReference.java | 11 +- .../deep/Another$ClassWith$Dollar.java | 23 +++ .../symbols/internal/asm/AsmLoaderTest.kt | 77 +++++++--- .../internal/asm/BrokenClasspathTest.kt | 5 +- .../java/symbols/internal/asm/NamesTest.kt | 18 ++- .../table/internal/HeaderScopesTest.kt | 2 +- 11 files changed, 257 insertions(+), 99 deletions(-) create mode 100644 pmd-java/src/test/java/javasymbols/testdata/deep/Another$ClassWith$Dollar.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/SymbolToStrings.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/SymbolToStrings.java index 8e24d277fe..a039cce6d5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/SymbolToStrings.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/SymbolToStrings.java @@ -61,12 +61,6 @@ public class SymbolToStrings { String kind; if (sym.isUnresolved()) { kind = "unresolved"; - } else if (sym.isEnum()) { - kind = "enum"; - } else if (sym.isAnnotation()) { - kind = "annot"; - } else if (sym.isRecord()) { - kind = "record"; } else { kind = "class"; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java index a0b5d4d72e..3fd801d932 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java @@ -53,12 +53,7 @@ public class AsmSymbolResolver implements SymbolResolver { String internalName = getInternalName(binaryName); SoftClassReference found = knownStubs.computeIfAbsent(internalName, iname -> { - if (!hasCanonicalName(internalName)) { - // if the class is anonymous/local, give up - return failed; - } - - @Nullable URL url = getUrlOfInternalName(internalName); + @Nullable URL url = getUrlOfInternalName(iname); if (url == null) { return failed; } @@ -66,7 +61,16 @@ public class AsmSymbolResolver implements SymbolResolver { return new SoftClassReference(this, iname, new UrlLoader(url), ClassStub.UNKNOWN_ARITY); }); - return found == failed ? null : found.get(); // NOPMD CompareObjectsWithEquals + if (found == failed) { // NOPMD CompareObjectsWithEquals + return null; + } + ClassStub stub = found.get(); + if (!stub.hasCanonicalName()) { + knownStubs.put(internalName, failed); + return null; + } + + return stub; } SignatureParser getSigParser() { @@ -112,21 +116,15 @@ public class AsmSymbolResolver implements SymbolResolver { These methods return an unresolved symbol if the url is not found. */ - @Nullable JClassSymbol resolveFromInternalNameCannotFail(@Nullable String internalName) { + @Nullable ClassStub resolveFromInternalNameCannotFail(@Nullable String internalName) { if (internalName == null) { return null; } - return resolveFromInternalNameCannotFail(internalName, 0); - } - - // this is for inner + parent classes - void registerKnown(@NonNull String internalName, ClassStub innerClass) { - SoftClassReference softRef = new SoftClassReference(this, innerClass, internalName); - knownStubs.put(internalName, softRef); + return resolveFromInternalNameCannotFail(internalName, ClassStub.UNKNOWN_ARITY); } @SuppressWarnings("PMD.CompareObjectsWithEquals") // SoftClassReference - @NonNull JClassSymbol resolveFromInternalNameCannotFail(@NonNull String internalName, int observedArity) { + @NonNull ClassStub resolveFromInternalNameCannotFail(@NonNull String internalName, int observedArity) { return knownStubs.compute(internalName, (iname, prev) -> { if (prev != failed && prev != null) { return prev; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java index 36947a016c..ca3d30ddd0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; @@ -43,10 +44,9 @@ final class ClassStub implements JClassSymbol, AsmStub { static final int UNKNOWN_ARITY = 0; private final AsmSymbolResolver resolver; - private final String internalName; private final Loader loader; - private Names names; // lazy (doesn't need parsing) + private final Names names; // all the following are lazy and depend on the parse lock @@ -75,10 +75,15 @@ final class ClassStub implements JClassSymbol, AsmStub { assert isValidInternalName(internalName) : internalName; this.resolver = resolver; - this.internalName = internalName; + this.names = new Names(internalName); this.loader = loader; this.parseLock = new ParseLock() { + // note to devs: to debug the parsing logic you might have + // to replace the implementation of toString temporarily, + // otherwise an IDE could call toString just to show the item + // in the debugger view (which could cause parsing of the class file). + @Override protected boolean doParse() throws IOException { try (InputStream instream = loader.getInputStream()) { @@ -108,6 +113,16 @@ final class ClassStub implements JClassSymbol, AsmStub { fields = Collections.unmodifiableList(fields); memberClasses = Collections.unmodifiableList(memberClasses); enumConstantNames = enumConstantNames == null ? null : Collections.unmodifiableSet(enumConstantNames); + + if (enclosingInfo == EnclosingInfo.NO_ENCLOSING) { + if (names.canonicalName == null || names.simpleName == null) { + // This happens if the simple name contains dollars, + // in which case we might have an enclosing class, and + // we can only tell now (no enclosingInfo) that that's + // not the case. + names.finishOuterClass(); + } + } } @Override @@ -134,6 +149,15 @@ final class ClassStub implements JClassSymbol, AsmStub { this.signature = new LazyClassSignature(this, signature, superName, interfaces); } + /** + * Called if this is an inner class (their simple name cannot be + * derived from splitting the internal/binary name on dollars, as + * the simple name may itself contain dollars). + */ + void setSimpleName(String simpleName) { + this.names.simpleName = simpleName; + } + void setModifiers(int accessFlags, boolean fromClassInfo) { /* A different set of modifiers is contained in the ClassInfo @@ -328,13 +352,10 @@ final class ClassStub implements JClassSymbol, AsmStub { // public String getInternalName() { - return internalName; + return getNames().internalName; } private Names getNames() { - if (names == null) { - this.names = new Names(internalName); - } return names; } @@ -343,10 +364,44 @@ final class ClassStub implements JClassSymbol, AsmStub { return getNames().binaryName; } - @Nullable + boolean hasCanonicalName() { + if (names.canonicalName != null) { + return true; + } + parseLock.ensureParsed(); + if (isAnonymousClass() || isLocalClass()) { + return false; + } + JClassSymbol enclosing = getEnclosingClass(); + return enclosing == null // top-level class + || enclosing instanceof ClassStub + && ((ClassStub) enclosing).hasCanonicalName(); + } + @Override public String getCanonicalName() { - return getNames().canonicalName; + String canoName = names.canonicalName; + if (canoName == null) { + parseLock.ensureParsed(); + canoName = names.canonicalName; + if (canoName != null) { + return canoName; + } + JClassSymbol enclosing = getEnclosingClass(); + if (enclosing == null) { + canoName = names.packageName + '.' + getSimpleName(); + names.canonicalName = canoName; + return canoName; + } + String outerName = enclosing.getCanonicalName(); + if (outerName == null) { + return null; // should not happen + } + canoName = outerName + '.' + getSimpleName(); + names.canonicalName = canoName; + return canoName; + } + return canoName; } @Override @@ -356,7 +411,12 @@ final class ClassStub implements JClassSymbol, AsmStub { @Override public @NonNull String getSimpleName() { - return getNames().simpleName; + String mySimpleName = names.simpleName; + if (mySimpleName == null) { + parseLock.ensureParsed(); + return Objects.requireNonNull(names.simpleName); + } + return mySimpleName; } @Override @@ -428,7 +488,7 @@ final class ClassStub implements JClassSymbol, AsmStub { @Override public boolean isLocalClass() { - return false; // local classes are not reachable, technically someone can try to fetch them + return enclosingInfo.isLocal(); } @Override @@ -441,26 +501,48 @@ final class ClassStub implements JClassSymbol, AsmStub { static class Names { - private static final Pattern INNER_DELIMITER = Pattern.compile("\\$(?=\\w)"); final String binaryName; - final String canonicalName; + final String internalName; final String packageName; - final String simpleName; + /** If null, the class requires parsing to find out the actual canonical name. */ + @Nullable String canonicalName; + /** If null, the class requires parsing to find out the actual simple name. */ + @Nullable String simpleName; Names(String internalName) { - int packageEnd = Integer.max(0, internalName.lastIndexOf('/')); + assert isValidInternalName(internalName) : internalName; + int packageEnd = internalName.lastIndexOf('/'); - binaryName = internalName.replace('/', '.'); - packageName = binaryName.substring(0, packageEnd); - if (binaryName.indexOf('$') >= 0) { // contains a dollar - canonicalName = INNER_DELIMITER.matcher(binaryName).replaceAll("."); + this.internalName = internalName; + this.binaryName = internalName.replace('/', '.'); + if (packageEnd == -1) { + this.packageName = ""; } else { - // fast path - canonicalName = binaryName; + this.packageName = binaryName.substring(0, packageEnd); } - int lastDot = canonicalName.lastIndexOf('.'); - simpleName = canonicalName.substring(lastDot + 1); + if (binaryName.indexOf('$', packageEnd + 1) >= 0) { + // Contains a dollar in class name (after package) + // Requires parsing to find out the actual simple name, + // this might be an inner class, or simply a class with + // a dollar in its name. + + // ASSUMPTION: all JVM languages use the $ convention + // to separate inner classes. Java compilers do so but + // not necessarily true of all compilers/languages. + this.canonicalName = null; + this.simpleName = null; + } else { + // fast path + this.canonicalName = binaryName; + this.simpleName = binaryName.substring(packageEnd + 1); + } + } + + public void finishOuterClass() { + int packageEnd = internalName.lastIndexOf('/'); + this.simpleName = binaryName.substring(packageEnd + 1); // if -1, start from 0 + this.canonicalName = binaryName; } } @@ -478,6 +560,9 @@ final class ClassStub implements JClassSymbol, AsmStub { this.methodDescriptor = methodDescriptor; } + boolean isLocal() { + return methodName != null || methodDescriptor != null; + } public @Nullable JClassSymbol getEnclosingClass() { return stub; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStubBuilder.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStubBuilder.java index aaa1be5fe1..555fb1695d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStubBuilder.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStubBuilder.java @@ -9,10 +9,14 @@ import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; - -import net.sourceforge.pmd.lang.java.symbols.internal.asm.Loader.NoUrlLoader; +import org.objectweb.asm.Type; +/** + * Populates a {@link ClassStub} by reading a class file. Some info is + * known by the ClassStub without parsing (like its internal name), so + * we defer parsing until later. The class should be parsed only once. + */ class ClassStubBuilder extends ClassVisitor { private final ClassStub myStub; @@ -48,18 +52,30 @@ class ClassStubBuilder extends ClassVisitor { return null; } + /** + * Visits information about an inner class. This inner class is not necessarily a member of the + * class being visited. + * + *

Spec: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.6 + * + * @param innerInternalName the internal name of an inner class (see {@link Type#getInternalName()}). + * @param outerName the internal name of the class to which the inner class belongs (see {@link + * Type#getInternalName()}). May be {@literal null} for not member classes. + * @param innerSimpleName the (simple) name of the inner class inside its enclosing class. May be + * {@literal null} for anonymous inner classes. + * @param access the access flags of the inner class as originally + * declared in the enclosing class. + */ @Override public void visitInnerClass(String innerInternalName, @Nullable String outerName, @Nullable String innerSimpleName, int access) { if (myInternalName.equals(outerName) && innerSimpleName != null) { // not anonymous - ClassStub member = new ClassStub(myStub.getResolver(), - innerInternalName, - new NoUrlLoader(myStub.getResolver(), innerInternalName), - ClassStub.UNKNOWN_ARITY); - resolver.registerKnown(innerInternalName, member); + ClassStub member = resolver.resolveFromInternalNameCannotFail(innerInternalName, ClassStub.UNKNOWN_ARITY); member.setModifiers(access, false); myStub.addMemberClass(member); } else if (myInternalName.equals(innerInternalName) && outerName != null) { // then it's specifying the enclosing class + // (myStub is the inner class) + myStub.setSimpleName(innerSimpleName); myStub.setModifiers(access, false); myStub.setOuterClass(outerName, null, null); isInnerNonStaticClass = (Opcodes.ACC_STATIC & access) == 0; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/Loader.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/Loader.java index 84cf0ce5a8..a44cc6bc03 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/Loader.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/Loader.java @@ -27,6 +27,12 @@ abstract class Loader { @Nullable InputStream getInputStream() { return null; } + + @Override + public String toString() { + return "(failed loader)"; + } + } static class UrlLoader extends Loader { @@ -44,23 +50,10 @@ abstract class Loader { InputStream getInputStream() throws IOException { return url.openStream(); } - } - - static class NoUrlLoader extends Loader { - - private final AsmSymbolResolver resolver; - private final String internalName; - - NoUrlLoader(AsmSymbolResolver resolver, String internalName) { - this.resolver = resolver; - this.internalName = internalName; - } @Override - @Nullable - InputStream getInputStream() throws IOException { - URL url = resolver.getUrlOfInternalName(internalName); - return url != null ? url.openStream() : null; + public String toString() { + return "(URL loader)"; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SoftClassReference.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SoftClassReference.java index d644168b3d..6d0dd1ede3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SoftClassReference.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SoftClassReference.java @@ -9,6 +9,9 @@ import java.lang.ref.SoftReference; import org.checkerframework.checker.nullness.qual.NonNull; +/** + * A soft reference over a (possibly loaded class stub). + */ final class SoftClassReference { private final Loader loader; @@ -24,14 +27,6 @@ final class SoftClassReference { this.observedArity = observedArity; } - SoftClassReference(AsmSymbolResolver resolver, ClassStub stub, String internalName) { - this.resolver = resolver; - this.loader = stub.getLoader(); - this.internalName = internalName; - this.observedArity = 0; - this.ref = new SoftReference<>(stub); - } - @SuppressWarnings("PMD.AssignmentInOperand") @NonNull ClassStub get() { ClassStub c; diff --git a/pmd-java/src/test/java/javasymbols/testdata/deep/Another$ClassWith$Dollar.java b/pmd-java/src/test/java/javasymbols/testdata/deep/Another$ClassWith$Dollar.java new file mode 100644 index 0000000000..f31e0c90c7 --- /dev/null +++ b/pmd-java/src/test/java/javasymbols/testdata/deep/Another$ClassWith$Dollar.java @@ -0,0 +1,23 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package javasymbols.testdata.deep; + +/** + * @author Clément Fournier + */ +public class Another$ClassWith$Dollar { + + public static class AnInner$ClassWithDollar { + + public static class ADeeper$ClassWithDollar { + + } + } + + // looks like an anonymous class but isn't. + public static class DollarsAndNumbers$0 { + + } +} diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt index 1d95f30beb..7ff24deef3 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt @@ -7,14 +7,18 @@ package net.sourceforge.pmd.lang.java.symbols.internal.asm import io.kotest.core.spec.style.FunSpec import io.kotest.inspectors.forExactly import io.kotest.matchers.collections.shouldBeEmpty -import io.kotest.matchers.collections.shouldBeSingleton import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder import io.kotest.matchers.collections.shouldHaveSize +import io.kotest.matchers.nulls.shouldBeNull +import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeSameInstanceAs import javasymbols.testdata.Enums import javasymbols.testdata.NestedClasses import javasymbols.testdata.Statics +import javasymbols.testdata.deep.`Another$ClassWith$Dollar` import javasymbols.testdata.impls.GenericClass +import net.sourceforge.pmd.lang.ast.test.IntelliMarker import net.sourceforge.pmd.lang.ast.test.shouldBe import net.sourceforge.pmd.lang.java.types.testTypeSystem import org.objectweb.asm.Opcodes @@ -23,15 +27,13 @@ import kotlin.test.assertSame /** * @author Clément Fournier */ -class AsmLoaderTest : FunSpec({ +class AsmLoaderTest : IntelliMarker, FunSpec({ // TODO tests: // self-referential typevar bound : class C> // self-referential superclass : class C extends Sup implements I> - // methods with synthetic parameters (ctors of inner classes) // access flags - // method reference with static ctdecl & zero formal parameters (asInstanceMethod) val contextClasspath = Classpath { Thread.currentThread().contextClassLoader.getResource(it) } @@ -50,11 +52,11 @@ class AsmLoaderTest : FunSpec({ } val ts = testTypeSystem - val symLoader = AsmSymbolResolver(ts, contextClasspath) + fun symLoader() = AsmSymbolResolver(ts, contextClasspath) test("Generic class") { - val loaded = symLoader.resolveClassFromBinaryName(GenericClass::class.java.name)!! + val loaded = symLoader().resolveClassFromBinaryName(GenericClass::class.java.name)!! loaded::getTypeParameterCount shouldBe 2 loaded.typeParameters.let { tparams -> @@ -76,6 +78,7 @@ class AsmLoaderTest : FunSpec({ val outerName = NestedClasses::class.java.name + val symLoader = symLoader() val outer = symLoader.resolveClassFromBinaryName(outerName)!! val inner = symLoader.resolveClassFromBinaryName("$outerName\$Inner")!! val iinner = symLoader.resolveClassFromBinaryName("$outerName\$Inner\$IInner")!! @@ -85,13 +88,13 @@ class AsmLoaderTest : FunSpec({ inner.declaredClasses.shouldContainExactlyInAnyOrder(iinner) iinner.declaredClasses.shouldBeEmpty() - iinner.enclosingClass.shouldBe(inner) - inner.enclosingClass.shouldBe(outer) - outer.enclosingClass.shouldBe(null) + iinner.enclosingClass.shouldBeSameInstanceAs(inner) + inner.enclosingClass.shouldBeSameInstanceAs(outer) + outer.enclosingClass.shouldBeNull() - iinner.enclosingMethod.shouldBe(null) - inner.enclosingMethod.shouldBe(null) - outer.enclosingMethod.shouldBe(null) + iinner.enclosingMethod.shouldBeNull() + inner.enclosingMethod.shouldBeNull() + outer.enclosingMethod.shouldBeNull() } @@ -99,16 +102,54 @@ class AsmLoaderTest : FunSpec({ val outerName = Statics::class.java.name - val inner = symLoader.resolveClassFromBinaryName("$outerName\$ProtectedStatic")!! + val inner = symLoader().resolveClassFromBinaryName("$outerName\$ProtectedStatic")!! inner.modifiers shouldBe (Opcodes.ACC_PROTECTED or Opcodes.ACC_STATIC) } + test("Inner names with dollars") { + + val outerName = `Another$ClassWith$Dollar`::class.java.name + + val inner = symLoader().resolveClassFromBinaryName("$outerName\$AnInner\$ClassWithDollar")!! + + inner.simpleName shouldBe "AnInner\$ClassWithDollar" + inner.canonicalName shouldBe "javasymbols.testdata.deep.Another\$ClassWith\$Dollar.AnInner\$ClassWithDollar" + } + + test("Deeper inner names with dollars") { + + val outerName = `Another$ClassWith$Dollar`::class.java.name + + val symLoader = symLoader() + val deeper = symLoader.resolveClassFromBinaryName("$outerName\$AnInner\$ClassWithDollar\$ADeeper\$ClassWithDollar")!! + + deeper.simpleName shouldBe "ADeeper\$ClassWithDollar" + deeper.canonicalName shouldBe "javasymbols.testdata.deep.Another\$ClassWith\$Dollar.AnInner\$ClassWithDollar.ADeeper\$ClassWithDollar" + + symLoader.resolveClassFromCanonicalName(deeper.canonicalName!!) shouldBeSameInstanceAs deeper + } + + test("Simple name that looks like an anonymous name but isn't") { + + val klass = `Another$ClassWith$Dollar`.`DollarsAndNumbers$0`::class.java + val binaryName = klass.name + + val symLoader = symLoader() + val deeper = symLoader.resolveClassFromBinaryName(binaryName).shouldNotBeNull() + + deeper.simpleName shouldBe "DollarsAndNumbers\$0" + deeper.canonicalName shouldBe klass.canonicalName!! + deeper.binaryName shouldBe binaryName + + symLoader.resolveClassFromCanonicalName(deeper.canonicalName!!) shouldBeSameInstanceAs deeper + } + test("Inner class constructors reflect no parameter for the enclosing instance") { val outerName = NestedClasses::class.java.name - val inner = symLoader.resolveClassFromBinaryName("$outerName\$Inner")!! + val inner = symLoader().resolveClassFromBinaryName("$outerName\$Inner")!! inner.modifiers shouldBe Opcodes.ACC_PUBLIC @@ -124,6 +165,7 @@ class AsmLoaderTest : FunSpec({ val outerName = Statics::class.java.name + val symLoader = symLoader() val inner = symLoader.resolveClassFromCanonicalName("$outerName.ProtectedStatic")!! val second = symLoader.resolveClassFromBinaryName("$outerName\$ProtectedStatic")!! @@ -132,6 +174,7 @@ class AsmLoaderTest : FunSpec({ test("Unresolved class should have object as superclass") { + val symLoader = symLoader() val inner = symLoader.resolveFromInternalNameCannotFail("does/not/exist")!! val second = symLoader.resolveFromInternalNameCannotFail("does/not/exist")!! @@ -144,13 +187,13 @@ class AsmLoaderTest : FunSpec({ val outerName = Enums::class.java.name - val emptyEnum = symLoader.resolveClassFromBinaryName("$outerName\$Empty")!! + val emptyEnum = symLoader().resolveClassFromBinaryName("$outerName\$Empty")!! emptyEnum::getEnumConstantNames shouldBe emptySet() - val withConstants = symLoader.resolveClassFromBinaryName("$outerName\$SomeConstants")!! + val withConstants = symLoader().resolveClassFromBinaryName("$outerName\$SomeConstants")!! withConstants::getEnumConstantNames shouldBe setOf("A", "B") - val notAnEnum = symLoader.resolveClassFromBinaryName(outerName)!! + val notAnEnum = symLoader().resolveClassFromBinaryName(outerName)!! notAnEnum::getEnumConstantNames shouldBe null } }) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/BrokenClasspathTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/BrokenClasspathTest.kt index b8d979fee4..85f988420c 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/BrokenClasspathTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/BrokenClasspathTest.kt @@ -10,6 +10,7 @@ import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe import net.sourceforge.pmd.lang.ast.test.shouldBe +import net.sourceforge.pmd.lang.java.symbols.JClassSymbol import net.sourceforge.pmd.lang.java.types.JClassType import net.sourceforge.pmd.lang.java.types.TypeOps import net.sourceforge.pmd.lang.java.types.TypeSystem @@ -73,6 +74,6 @@ class BrokenClasspathTest : FunSpec({ }) -fun TypeSystem.createUnresolvedAsmSymbol(binaryName: String) = +fun TypeSystem.createUnresolvedAsmSymbol(binaryName: String): JClassSymbol = AsmSymbolResolver(this, Classpath.contextClasspath()) - .resolveFromInternalNameCannotFail(binaryName.replace('.', '/')) + .resolveFromInternalNameCannotFail(binaryName.replace('.', '/'))!! diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt index ae28a7390a..8b2c6f459e 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt @@ -15,8 +15,8 @@ class NamesTest : IntelliMarker, FunSpec({ val names = ClassStub.Names("java/text/NumberFormat\$Style") names.binaryName shouldBe "java.text.NumberFormat\$Style" - names.canonicalName shouldBe "java.text.NumberFormat.Style" - names.simpleName shouldBe "Style" + names.canonicalName shouldBe null + names.simpleName shouldBe null names.packageName shouldBe "java.text" } @@ -46,9 +46,19 @@ class NamesTest : IntelliMarker, FunSpec({ val names = ClassStub.Names("javasymbols/testdata/deep/ClassWithDollar\$") names.binaryName shouldBe "javasymbols.testdata.deep.ClassWithDollar\$" - names.canonicalName shouldBe "javasymbols.testdata.deep.ClassWithDollar\$" - names.simpleName shouldBe "ClassWithDollar\$" + names.canonicalName shouldBe null + names.simpleName shouldBe null names.packageName shouldBe "javasymbols.testdata.deep" } + test("Test names dollar in package name") { + + val names = ClassStub.Names("\$javasymbols\$/test\$data/de\$ep/ClassWithDollar\$") + + names.binaryName shouldBe "\$javasymbols\$.test\$data.de\$ep.ClassWithDollar\$" + names.packageName shouldBe "\$javasymbols\$.test\$data.de\$ep" + names.canonicalName shouldBe null + names.simpleName shouldBe null + } + }) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt index 5bff9ca925..1d76df1cd6 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt @@ -329,7 +329,7 @@ class HeaderScopesTest : ProcessorTestSpec({ ) } - parserTest("Import of an unconventional name with dollar") { + parserTest("f:Import of an unconventional name with dollar") { assertNoSemanticErrorsOrWarnings() From e97e2cde27649c8f9d355550c336d61fe41e74f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 6 Mar 2022 13:58:17 +0100 Subject: [PATCH 08/89] Remove SoftClassReference They were `get` immediately, and it's unclear what happens if a reference is GCed and reparsed later (it may set fields of existing enclosing classes). --- .../internal/asm/AsmSymbolResolver.java | 26 +++++------ .../internal/asm/SoftClassReference.java | 44 ------------------- 2 files changed, 12 insertions(+), 58 deletions(-) delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SoftClassReference.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java index 3fd801d932..976aae10e0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java @@ -31,19 +31,19 @@ public class AsmSymbolResolver implements SymbolResolver { private final Classpath classLoader; private final SignatureParser typeLoader; - private final ConcurrentMap knownStubs = new ConcurrentHashMap<>(); + private final ConcurrentMap knownStubs = new ConcurrentHashMap<>(); /** * Sentinel for when we fail finding a URL. This allows using a single map, * instead of caching failure cases separately. */ - private final SoftClassReference failed; + private final ClassStub failed; public AsmSymbolResolver(TypeSystem ts, Classpath classLoader) { this.ts = ts; this.classLoader = classLoader; this.typeLoader = new SignatureParser(this); - this.failed = new SoftClassReference(this, "/*failed-lookup*/", FailedLoader.INSTANCE, 0); + this.failed = new ClassStub(this, "/*failed-lookup*/", FailedLoader.INSTANCE, 0); } @Override @@ -52,25 +52,23 @@ public class AsmSymbolResolver implements SymbolResolver { String internalName = getInternalName(binaryName); - SoftClassReference found = knownStubs.computeIfAbsent(internalName, iname -> { + ClassStub found = knownStubs.computeIfAbsent(internalName, iname -> { @Nullable URL url = getUrlOfInternalName(iname); if (url == null) { return failed; } - return new SoftClassReference(this, iname, new UrlLoader(url), ClassStub.UNKNOWN_ARITY); + return new ClassStub(this, iname, new UrlLoader(url), ClassStub.UNKNOWN_ARITY); }); - if (found == failed) { // NOPMD CompareObjectsWithEquals - return null; - } - ClassStub stub = found.get(); - if (!stub.hasCanonicalName()) { + if (!found.hasCanonicalName()) { + // note: this check needs to be done outside of computeIfAbsent + // to prevent recursive updates of the knownStubs map. knownStubs.put(internalName, failed); - return null; + found = failed; } - return stub; + return found == failed ? null : found; // NOPMD CompareObjectsWithEquals } SignatureParser getSigParser() { @@ -131,7 +129,7 @@ public class AsmSymbolResolver implements SymbolResolver { } @Nullable URL url = getUrlOfInternalName(iname); Loader loader = url == null ? FailedLoader.INSTANCE : new UrlLoader(url); - return new SoftClassReference(this, iname, loader, observedArity); - }).get(); + return new ClassStub(this, iname, loader, observedArity); + }); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SoftClassReference.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SoftClassReference.java deleted file mode 100644 index 6d0dd1ede3..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/SoftClassReference.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symbols.internal.asm; - - -import java.lang.ref.SoftReference; - -import org.checkerframework.checker.nullness.qual.NonNull; - -/** - * A soft reference over a (possibly loaded class stub). - */ -final class SoftClassReference { - - private final Loader loader; - private final String internalName; - private final int observedArity; - private final AsmSymbolResolver resolver; - private SoftReference ref; - - SoftClassReference(AsmSymbolResolver resolver, String internalName, Loader loader, int observedArity) { - this.resolver = resolver; - this.loader = loader; - this.internalName = internalName; - this.observedArity = observedArity; - } - - @SuppressWarnings("PMD.AssignmentInOperand") - @NonNull ClassStub get() { - ClassStub c; - if (ref == null || (c = ref.get()) == null) { // SUPPRESS CHECKSTYLE NOW - c = new ClassStub(resolver, internalName, loader, observedArity); - ref = new SoftReference<>(c); - } - return c; - } - - @Override - public String toString() { - return internalName + " " + loader; - } -} From 7f31dc9e630b292de53aa6554aa5bb71fd7e36d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 6 Mar 2022 14:13:53 +0100 Subject: [PATCH 09/89] Test local classes --- .../java/symbols/internal/asm/ClassStub.java | 5 ++- .../testdata/deep/AClassWithLocals.java | 37 +++++++++++++++++++ .../symbols/internal/asm/AsmLoaderTest.kt | 18 +++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 pmd-java/src/test/java/javasymbols/testdata/deep/AClassWithLocals.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java index ca3d30ddd0..3f3e18b622 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java @@ -364,6 +364,9 @@ final class ClassStub implements JClassSymbol, AsmStub { return getNames().binaryName; } + /** + * Simpler check than computing the canonical name. + */ boolean hasCanonicalName() { if (names.canonicalName != null) { return true; @@ -395,7 +398,7 @@ final class ClassStub implements JClassSymbol, AsmStub { } String outerName = enclosing.getCanonicalName(); if (outerName == null) { - return null; // should not happen + return null; } canoName = outerName + '.' + getSimpleName(); names.canonicalName = canoName; diff --git a/pmd-java/src/test/java/javasymbols/testdata/deep/AClassWithLocals.java b/pmd-java/src/test/java/javasymbols/testdata/deep/AClassWithLocals.java new file mode 100644 index 0000000000..f62b0df6e8 --- /dev/null +++ b/pmd-java/src/test/java/javasymbols/testdata/deep/AClassWithLocals.java @@ -0,0 +1,37 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package javasymbols.testdata.deep; + +/** + * @author Clément Fournier + */ +public class AClassWithLocals { + + private static Object foo0 = new Object() {}; // AClassWithLocals$0 + private final Object foo1 = new Object() { + class Member {} // AClassWithLocals$1$Member + }; // AClassWithLocals$1 + + public AClassWithLocals() { + class Local { // AClassWithLocals$0Local + + } + new Object() {}; // // AClassWithLocals$2 + } + + static { + class Local { // AClassWithLocals$1Local + + } + new Object() {}; // // AClassWithLocals$3 + } + + void method() { + class Local { // AClassWithLocals$2Local + + } + new Object() {}; // // AClassWithLocals$4 + } +} diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt index 7ff24deef3..ac0d363060 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt @@ -16,6 +16,7 @@ import io.kotest.matchers.types.shouldBeSameInstanceAs import javasymbols.testdata.Enums import javasymbols.testdata.NestedClasses import javasymbols.testdata.Statics +import javasymbols.testdata.deep.AClassWithLocals import javasymbols.testdata.deep.`Another$ClassWith$Dollar` import javasymbols.testdata.impls.GenericClass import net.sourceforge.pmd.lang.ast.test.IntelliMarker @@ -117,6 +118,23 @@ class AsmLoaderTest : IntelliMarker, FunSpec({ inner.canonicalName shouldBe "javasymbols.testdata.deep.Another\$ClassWith\$Dollar.AnInner\$ClassWithDollar" } + test("Local classes") { + + val outerClass = AClassWithLocals::class.java + val outerName = AClassWithLocals::class.java.name + + val symLoader = symLoader() + val outer = symLoader.resolveClassFromBinaryName(outerName).shouldNotBeNull() + + outer.simpleName shouldBe outerClass.simpleName + outer.canonicalName shouldBe outerClass.canonicalName!! + + outer.declaredClasses.shouldBeEmpty() + + symLoader.resolveClassFromBinaryName("$outerName$0").shouldBeNull() + symLoader.resolveClassFromBinaryName("$outerName$0Local").shouldBeNull() + } + test("Deeper inner names with dollars") { val outerName = `Another$ClassWith$Dollar`::class.java.name From e3fd2782a32369d11498e7b546761c027e85e7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 6 Mar 2022 14:16:36 +0100 Subject: [PATCH 10/89] Cleanup --- .../symbols/internal/SymbolToStrings.java | 6 ++ .../java/symbols/internal/asm/ClassStub.java | 55 +++++++++++++------ .../symbols/internal/asm/AsmLoaderTest.kt | 5 ++ .../table/internal/HeaderScopesTest.kt | 2 +- 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/SymbolToStrings.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/SymbolToStrings.java index a039cce6d5..8e24d277fe 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/SymbolToStrings.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/SymbolToStrings.java @@ -61,6 +61,12 @@ public class SymbolToStrings { String kind; if (sym.isUnresolved()) { kind = "unresolved"; + } else if (sym.isEnum()) { + kind = "enum"; + } else if (sym.isAnnotation()) { + kind = "annot"; + } else if (sym.isRecord()) { + kind = "record"; } else { kind = "class"; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java index 3f3e18b622..05d78ffda4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java @@ -114,7 +114,7 @@ final class ClassStub implements JClassSymbol, AsmStub { memberClasses = Collections.unmodifiableList(memberClasses); enumConstantNames = enumConstantNames == null ? null : Collections.unmodifiableSet(enumConstantNames); - if (enclosingInfo == EnclosingInfo.NO_ENCLOSING) { + if (EnclosingInfo.NO_ENCLOSING.equals(enclosingInfo)) { if (names.canonicalName == null || names.simpleName == null) { // This happens if the simple name contains dollars, // in which case we might have an enclosing class, and @@ -385,28 +385,28 @@ final class ClassStub implements JClassSymbol, AsmStub { public String getCanonicalName() { String canoName = names.canonicalName; if (canoName == null) { - parseLock.ensureParsed(); - canoName = names.canonicalName; - if (canoName != null) { - return canoName; - } - JClassSymbol enclosing = getEnclosingClass(); - if (enclosing == null) { - canoName = names.packageName + '.' + getSimpleName(); - names.canonicalName = canoName; - return canoName; - } - String outerName = enclosing.getCanonicalName(); - if (outerName == null) { - return null; - } - canoName = outerName + '.' + getSimpleName(); + canoName = computeCanonicalName(); names.canonicalName = canoName; - return canoName; } return canoName; } + private @Nullable String computeCanonicalName() { + parseLock.ensureParsed(); + if (names.canonicalName != null) { + return names.canonicalName; + } + JClassSymbol enclosing = getEnclosingClass(); + if (enclosing == null) { + return names.packageName + '.' + getSimpleName(); + } + String outerName = enclosing.getCanonicalName(); + if (outerName == null) { + return null; + } + return outerName + '.' + getSimpleName(); + } + @Override public @NonNull String getPackageName() { return getNames().packageName; @@ -593,5 +593,24 @@ final class ClassStub implements JClassSymbol, AsmStub { return getEnclosingClass(); } } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + EnclosingInfo that = (EnclosingInfo) o; + return Objects.equals(stub, that.stub) + && Objects.equals(methodName, that.methodName) + && Objects.equals(methodDescriptor, that.methodDescriptor); + } + + @Override + public int hashCode() { + return Objects.hash(stub, methodName, methodDescriptor); + } } } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt index ac0d363060..befc8ae424 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt @@ -53,6 +53,11 @@ class AsmLoaderTest : IntelliMarker, FunSpec({ } val ts = testTypeSystem + + /** + * Note: we don't share a single resolver between all tests because that + * could cause issues because of the order of classloading (the order of test execution). + */ fun symLoader() = AsmSymbolResolver(ts, contextClasspath) test("Generic class") { diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt index 1d76df1cd6..5bff9ca925 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt @@ -329,7 +329,7 @@ class HeaderScopesTest : ProcessorTestSpec({ ) } - parserTest("f:Import of an unconventional name with dollar") { + parserTest("Import of an unconventional name with dollar") { assertNoSemanticErrorsOrWarnings() From 99425d53ff275e9f3721cd43da77f2b93a8f56fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 6 Mar 2022 18:56:36 +0100 Subject: [PATCH 11/89] Fix OutOfMemory in tests This did not show up earlier because we used soft class references, which reduces the memory footprint of unused TypeSystems. However, they still remain in old gen and are a large memory hog. Since e97e2cd we don't use SoftReference anymore as parsing the same class several times may have unintended side-effects. This revealed the out of memory error. This will be fixed when we have proper language lifecycle and resources like the classloader can be reclaimed later. --- .../lang/java/internal/JavaAstProcessor.java | 5 ++++ .../pmd/testframework/RuleTst.java | 23 ++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java index 335d3c8a53..913f53b36e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java @@ -43,6 +43,11 @@ import net.sourceforge.pmd.lang.java.types.internal.infer.TypeInferenceLogger.Ve */ public final class JavaAstProcessor { + /** + * FIXME get rid of that, this prevents both ClassLoader and TypeSystem + * to be garbage-collected, which is an important memory leak. Will be + * fixed by https://github.com/pmd/pmd/issues/3782 (Language Lifecycle) + */ private static final Map TYPE_SYSTEMS = new IdentityHashMap<>(); private static final Level INFERENCE_LOG_LEVEL; diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java index e3a35697ac..d9ceed4b85 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java @@ -56,7 +56,12 @@ import net.sourceforge.pmd.util.datasource.DataSource; public abstract class RuleTst { private final DocumentBuilder documentBuilder; + /** Use a single classloader for all tests. */ + private final ClassLoader classpathClassLoader; + public RuleTst() { + classpathClassLoader = makeClassPathClassLoader(); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema; @@ -87,6 +92,19 @@ public abstract class RuleTst { } } + private ClassLoader makeClassPathClassLoader() { + final ClassLoader classpathClassLoader; + PMDConfiguration config = new PMDConfiguration(); + try { + config.prependClasspath("."); + } catch (IOException ignored) { + + } + classpathClassLoader = config.getClassLoader(); + return classpathClassLoader; + } + + protected void setUp() { // This method is intended to be overridden by subclasses. } @@ -263,7 +281,10 @@ public abstract class RuleTst { if (isUseAuxClasspath) { // configure the "auxclasspath" option for unit testing - configuration.prependClasspath("."); + // we share a single classloader so that pmd-java doesn't create + // a new TypeSystem for every test. This problem will go + // away when languages have a lifecycle. + configuration.setClassLoader(classpathClassLoader); } else { // simple class loader, that doesn't delegate to parent. // this allows us in the tests to simulate PMD run without From 45a85806b590ea29b08af70101b0ba67015e37b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Mar 2022 03:01:36 +0000 Subject: [PATCH 12/89] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- .github/workflows/git-repo-sync.yml | 2 +- .github/workflows/troubleshooting.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35ef711b07..dd481af5a0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: os: [ ubuntu-latest, windows-latest, macos-latest ] if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 2 - uses: actions/cache@v2 diff --git a/.github/workflows/git-repo-sync.yml b/.github/workflows/git-repo-sync.yml index fe8cf614f9..657e82e484 100644 --- a/.github/workflows/git-repo-sync.yml +++ b/.github/workflows/git-repo-sync.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest continue-on-error: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 100 - name: Setup Environment diff --git a/.github/workflows/troubleshooting.yml b/.github/workflows/troubleshooting.yml index d58e0f2aa1..4554ddedf7 100644 --- a/.github/workflows/troubleshooting.yml +++ b/.github/workflows/troubleshooting.yml @@ -12,7 +12,7 @@ jobs: os: [ ubuntu-latest ] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions/cache@v2 with: path: | From 26c4999b53b929911190e3103cde77ce750f10f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 6 Mar 2022 21:34:20 +0100 Subject: [PATCH 13/89] Fix NPE with missing simple name --- .../java/symbols/internal/asm/ClassStub.java | 14 +++++------ .../internal/asm/ClassStubBuilder.java | 7 ++++-- .../testdata/deep/OuterWithoutDollar.java | 13 ++++++++++ .../symbols/internal/asm/AsmLoaderTest.kt | 15 +++++++++++ .../table/internal/HeaderScopesTest.kt | 25 +++++++++++++++---- 5 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 pmd-java/src/test/java/javasymbols/testdata/deep/OuterWithoutDollar.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java index 05d78ffda4..e07d6582a3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java @@ -212,12 +212,14 @@ final class ClassStub implements JClassSymbol, AsmStub { } } - void setOuterClass(String outerName, @Nullable String methodName, @Nullable String methodDescriptor) { + void setOuterClass(ClassStub outer, @Nullable String methodName, @Nullable String methodDescriptor) { if (enclosingInfo == null) { - if (outerName == null) { + if (outer == null) { + assert methodName == null && methodDescriptor == null + : "Enclosing method requires enclosing class"; this.enclosingInfo = EnclosingInfo.NO_ENCLOSING; } else { - this.enclosingInfo = new EnclosingInfo(resolver.resolveFromInternalNameCannotFail(outerName), methodName, methodDescriptor); + this.enclosingInfo = new EnclosingInfo(outer, methodName, methodDescriptor); } } } @@ -231,9 +233,7 @@ final class ClassStub implements JClassSymbol, AsmStub { } void addMemberClass(ClassStub classStub) { - if (classStub.enclosingInfo == null) { - classStub.enclosingInfo = new EnclosingInfo(this, null, null); - } + classStub.setOuterClass(this, null, null); memberClasses.add(classStub); } @@ -417,7 +417,7 @@ final class ClassStub implements JClassSymbol, AsmStub { String mySimpleName = names.simpleName; if (mySimpleName == null) { parseLock.ensureParsed(); - return Objects.requireNonNull(names.simpleName); + return Objects.requireNonNull(names.simpleName, "Null simple name after parsing"); } return mySimpleName; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStubBuilder.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStubBuilder.java index 555fb1695d..5443da83ca 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStubBuilder.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStubBuilder.java @@ -42,7 +42,8 @@ class ClassStubBuilder extends ClassVisitor { public void visitOuterClass(String ownerInternalName, @Nullable String methodName, @Nullable String methodDescriptor) { isInnerNonStaticClass = true; // only for enclosing method - myStub.setOuterClass(ownerInternalName, methodName, methodDescriptor); + ClassStub outer = resolver.resolveFromInternalNameCannotFail(ownerInternalName); + myStub.setOuterClass(outer, methodName, methodDescriptor); } @Override @@ -70,14 +71,16 @@ class ClassStubBuilder extends ClassVisitor { public void visitInnerClass(String innerInternalName, @Nullable String outerName, @Nullable String innerSimpleName, int access) { if (myInternalName.equals(outerName) && innerSimpleName != null) { // not anonymous ClassStub member = resolver.resolveFromInternalNameCannotFail(innerInternalName, ClassStub.UNKNOWN_ARITY); + member.setSimpleName(innerSimpleName); member.setModifiers(access, false); myStub.addMemberClass(member); } else if (myInternalName.equals(innerInternalName) && outerName != null) { // then it's specifying the enclosing class // (myStub is the inner class) + ClassStub outer = resolver.resolveFromInternalNameCannotFail(outerName); myStub.setSimpleName(innerSimpleName); myStub.setModifiers(access, false); - myStub.setOuterClass(outerName, null, null); + myStub.setOuterClass(outer, null, null); isInnerNonStaticClass = (Opcodes.ACC_STATIC & access) == 0; } } diff --git a/pmd-java/src/test/java/javasymbols/testdata/deep/OuterWithoutDollar.java b/pmd-java/src/test/java/javasymbols/testdata/deep/OuterWithoutDollar.java new file mode 100644 index 0000000000..3b28ebb5ae --- /dev/null +++ b/pmd-java/src/test/java/javasymbols/testdata/deep/OuterWithoutDollar.java @@ -0,0 +1,13 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package javasymbols.testdata.deep; + +/** + * @author Clément Fournier + */ +public class OuterWithoutDollar { + + final class Inner {} +} diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt index befc8ae424..eb5b3f5af5 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmLoaderTest.kt @@ -17,6 +17,7 @@ import javasymbols.testdata.Enums import javasymbols.testdata.NestedClasses import javasymbols.testdata.Statics import javasymbols.testdata.deep.AClassWithLocals +import javasymbols.testdata.deep.OuterWithoutDollar import javasymbols.testdata.deep.`Another$ClassWith$Dollar` import javasymbols.testdata.impls.GenericClass import net.sourceforge.pmd.lang.ast.test.IntelliMarker @@ -123,6 +124,20 @@ class AsmLoaderTest : IntelliMarker, FunSpec({ inner.canonicalName shouldBe "javasymbols.testdata.deep.Another\$ClassWith\$Dollar.AnInner\$ClassWithDollar" } + test("Regular inner name not populated") { + // this test doesn't reproduce the broken behaviour, it looks like + // this is somewhat compiler-dependent what InnerClasses attribute + // are in the class file... + + val outerName = OuterWithoutDollar::class.java.name + + val outer = symLoader().resolveClassFromBinaryName(outerName)!! + val inner = outer.getDeclaredClass("Inner")!! + + inner.simpleName shouldBe "Inner" + inner.canonicalName shouldBe "$outerName.Inner" + } + test("Local classes") { val outerClass = AClassWithLocals::class.java diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt index 5bff9ca925..e580ec1ceb 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/table/internal/HeaderScopesTest.kt @@ -6,10 +6,7 @@ package net.sourceforge.pmd.lang.java.symbols.table.internal -import io.kotest.matchers.collections.shouldContainExactly -import io.kotest.matchers.collections.shouldHaveSize -import io.kotest.matchers.collections.haveSize -import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder +import io.kotest.matchers.collections.* import io.kotest.matchers.maps.shouldBeEmpty import io.kotest.matchers.maps.shouldContain import io.kotest.matchers.nulls.shouldNotBeNull @@ -18,6 +15,7 @@ import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe import javasymbols.testdata.StaticNameCollision import javasymbols.testdata.StaticsSuper +import javasymbols.testdata.deep.OuterWithoutDollar import net.sourceforge.pmd.lang.ast.test.shouldBe import net.sourceforge.pmd.lang.ast.test.shouldBeA import net.sourceforge.pmd.lang.java.ast.* @@ -347,13 +345,30 @@ class HeaderScopesTest : ProcessorTestSpec({ ) val moduleAccess = acu.descendants(ASTFieldAccess::class.java).first().shouldNotBeNull() - with (acu.typeDsl) { + with(acu.typeDsl) { moduleAccess shouldHaveType ts.OBJECT moduleAccess.qualifier.shouldBeA { it shouldHaveType ts.rawType(ts.getClassSymbol("javasymbols.testdata.deep.ClassWithDollar\$")) } } } + parserTest("Import static on demand with inner (non-static) class") { + + assertNoSemanticErrorsOrWarnings() + + val acu = parser.parse( + """ + package ${OuterWithoutDollar::class.java.`package`.name}; + import static ${OuterWithoutDollar::class.java.name}.*; + class Foo { + static {} + } + """ + ) + + val block = acu.descendants(ASTBlock::class.java).firstOrThrow() + block.symbolTable.types().resolve("Inner").shouldBeEmpty() + } }) From fcd54c7abe137aac0c4ddc0ddb7e48158372fe20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 8 Mar 2022 12:16:08 +0100 Subject: [PATCH 14/89] Cleanups --- .../internal/asm/AsmSymbolResolver.java | 22 ------------------- .../java/symbols/internal/asm/ClassStub.java | 6 ----- .../pmd/lang/java/types/TypeOps.java | 2 +- .../java/symbols/internal/asm/NamesTest.kt | 11 ---------- 4 files changed, 1 insertion(+), 40 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java index 976aae10e0..2f0b8d5ba8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java @@ -83,28 +83,6 @@ public class AsmSymbolResolver implements SymbolResolver { return binaryName.replace('.', '/'); } - /** - * Test whether an internal name has a canonical name. This means, - * every segment of the simple name (part after the last '/'), where - * segments are separated by '$', is a valid java identifier. We only - * check the first character as anon/local classes are identified with - * integers, which are not valid java identifier starts. - */ - static boolean hasCanonicalName(String internalName) { - int packageEnd = internalName.lastIndexOf('/'); - for (int i = packageEnd; i + 1 < internalName.length();) { - char firstChar = internalName.charAt(i + 1); - if (!Character.isJavaIdentifierStart(firstChar)) { - return false; - } - i = internalName.indexOf('$', i + 1); - if (i == -1) { - break; - } - } - return !internalName.isEmpty(); - } - @Nullable URL getUrlOfInternalName(String internalName) { return classLoader.findResource(internalName + ".class"); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java index e07d6582a3..2ccebeb1c6 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java @@ -44,7 +44,6 @@ final class ClassStub implements JClassSymbol, AsmStub { static final int UNKNOWN_ARITY = 0; private final AsmSymbolResolver resolver; - private final Loader loader; private final Names names; @@ -76,7 +75,6 @@ final class ClassStub implements JClassSymbol, AsmStub { this.resolver = resolver; this.names = new Names(internalName); - this.loader = loader; this.parseLock = new ParseLock() { // note to devs: to debug the parsing logic you might have @@ -132,10 +130,6 @@ final class ClassStub implements JClassSymbol, AsmStub { }; } - Loader getLoader() { - return loader; - } - @Override public AsmSymbolResolver getResolver() { return resolver; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeOps.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeOps.java index aa99014bec..49a2781ee0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeOps.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeOps.java @@ -1147,7 +1147,7 @@ public final class TypeOps { // /** - * Returns true if m1 is return-type substitutable with m2. . The notion of return-type-substitutability + * Returns true if m1 is return-type substitutable with m2. The notion of return-type-substitutability * supports covariant returns, that is, the specialization of the return type to a subtype. * * https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.4.5 diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt index 8b2c6f459e..77d0df6cf4 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/asm/NamesTest.kt @@ -30,17 +30,6 @@ class NamesTest : IntelliMarker, FunSpec({ names.packageName shouldBe "" } - test("Test cano name") { - AsmSymbolResolver.hasCanonicalName("Num") shouldBe true - AsmSymbolResolver.hasCanonicalName("") shouldBe false - AsmSymbolResolver.hasCanonicalName("a/b/C") shouldBe true - AsmSymbolResolver.hasCanonicalName("a/b/C\$D") shouldBe true - AsmSymbolResolver.hasCanonicalName("a/b/C\$1D") shouldBe false - AsmSymbolResolver.hasCanonicalName("a/b/C\$1D\$D") shouldBe false - AsmSymbolResolver.hasCanonicalName("a/b/C\$D\$1") shouldBe false - AsmSymbolResolver.hasCanonicalName("a/b/C\$D") shouldBe true - } - test("Test names with trailing dollar") { val names = ClassStub.Names("javasymbols/testdata/deep/ClassWithDollar\$") From d8c94019eecefb34c3af92e804905c5f2a3e0724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 8 Mar 2022 20:43:19 +0100 Subject: [PATCH 15/89] Address PR review --- docs/pages/pmd/userdocs/tools/java-api.md | 2 +- pmd-core/src/main/java/net/sourceforge/pmd/PmdAnalysis.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/pages/pmd/userdocs/tools/java-api.md b/docs/pages/pmd/userdocs/tools/java-api.md index b82cf62ced..d6e0f4c4e5 100644 --- a/docs/pages/pmd/userdocs/tools/java-api.md +++ b/docs/pages/pmd/userdocs/tools/java-api.md @@ -191,7 +191,7 @@ public class PmdExample2 { try (PmdAnalysis pmd = PmdAnalysis.create(configuration)) { // optional: add more rulesets - pmd.addRuleSet(RuleSetLoader.fromPmdConfig(configuration).loadFromResource("custom-ruleset.xml")); + pmd.addRuleSet(pmd.newRuleSetLoader().loadFromResource("custom-ruleset.xml")); // optional: add more files pmd.files().addFile(Paths.get("src", "main", "more-java", "ExtraSource.java")); // optional: add more renderers diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PmdAnalysis.java b/pmd-core/src/main/java/net/sourceforge/pmd/PmdAnalysis.java index 1b4b92a554..3a56f33055 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PmdAnalysis.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PmdAnalysis.java @@ -113,8 +113,7 @@ public final class PmdAnalysis implements AutoCloseable { FileCollectionUtil.collectFiles(config, pmd.files()); if (config.getReportFormat() != null) { - Renderer renderer = config.createRenderer(); - renderer.setReportFile(config.getReportFile()); + Renderer renderer = config.createRenderer(true); pmd.addRenderer(renderer); } From 9dae9d70db48bb6715324f3835539e5243193527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 25 May 2021 13:52:34 +0200 Subject: [PATCH 16/89] Update saxon to 10.7 --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 64f0f268ec..fd8c79f61a 100644 --- a/pom.xml +++ b/pom.xml @@ -99,6 +99,7 @@ 3.2.0 4.8 2.0.0-alpha6 + 10.7 UTF-8 UTF-8 @@ -693,7 +694,7 @@ net.sf.saxon Saxon-HE - 10.2 + ${saxon.version} net.java.dev.javacc From 5f3d289d81e25caed01bcd2ac54a9172d6918049 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 10:09:29 +0100 Subject: [PATCH 17/89] Update java-api sample --- docs/pages/pmd/userdocs/tools/java-api.md | 7 +++---- .../src/main/java/net/sourceforge/pmd/PmdAnalysis.java | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/pages/pmd/userdocs/tools/java-api.md b/docs/pages/pmd/userdocs/tools/java-api.md index d6e0f4c4e5..3bcf034b87 100644 --- a/docs/pages/pmd/userdocs/tools/java-api.md +++ b/docs/pages/pmd/userdocs/tools/java-api.md @@ -66,7 +66,7 @@ public class PmdExample { public static void main(String[] args) { PMDConfiguration configuration = new PMDConfiguration(); configuration.setInputPaths("/home/workspace/src/main/java/code"); - configuration.setRuleSets("rulesets/java/quickstart.xml"); + configuration.addRuleSet("rulesets/java/quickstart.xml"); configuration.setReportFormat("xml"); configuration.setReportFile("/home/workspace/pmd-report.xml"); @@ -85,7 +85,7 @@ You can also provide your own custom renderers. ```java PMDConfiguration configuration = new PMDConfiguration(); configuration.setMinimumPriority(RulePriority.MEDIUM); - configuration.setRuleSets("rulesets/java/quickstart.xml"); + configuration.addRuleSet("rulesets/java/quickstart.xml"); ``` 2. Then we configure, which paths to analyze: @@ -166,7 +166,6 @@ import java.nio.file.Paths; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.PmdAnalysis; import net.sourceforge.pmd.RulePriority; -import net.sourceforge.pmd.RuleSetLoader; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.renderers.XMLRenderer; @@ -176,7 +175,7 @@ public class PmdExample2 { public static void main(String[] args) throws IOException { PMDConfiguration configuration = new PMDConfiguration(); configuration.setMinimumPriority(RulePriority.MEDIUM); - configuration.setRuleSets("rulesets/java/quickstart.xml"); + configuration.addRuleSet("rulesets/java/quickstart.xml"); configuration.setInputPaths("/home/workspace/src/main/java/code"); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PmdAnalysis.java b/pmd-core/src/main/java/net/sourceforge/pmd/PmdAnalysis.java index 3a56f33055..abec9ff1b9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PmdAnalysis.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PmdAnalysis.java @@ -46,7 +46,7 @@ import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter; * config.setInputPaths("src/main/java"); * config.prependClasspath("target/classes"); * config.setMinimumPriority(RulePriority.HIGH); - * config.setRuleSets("rulesets/java/quickstart.xml"); + * config.addRuleSet("rulesets/java/quickstart.xml"); * config.setReportFormat("xml"); * config.setReportFile("target/pmd-report.xml"); * From 6264092a1f57eab5d5eced98c016d9909780f858 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 10:10:09 +0100 Subject: [PATCH 18/89] [doc] Update release notes (#3299, #3822) --- docs/pages/release_notes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index c5e1fe39d1..184a196688 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -53,6 +53,8 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is * apex-performance * [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() +* core + * [#3299](https://github.com/pmd/pmd/issues/3299): \[core] Deprecate system properties of PMDCommandLineInterface ### API Changes @@ -71,6 +73,9 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is {% jdoc core::PMDConfiguration#addRuleSet(java.lang.String) %}, and {% jdoc core::PMDConfiguration#getRuleSetPaths() %}. * Several members of {% jdoc test::cli.BaseCLITest %} have been deprecated with replacements. +* Several members of {% jdoc core::cli.PMDCommandLineInterface %} have been explicitly deprecated. + The whole class however was deprecated long ago already with 6.30.0. It is internal API and should + not be used. #### Experimental APIs From e27be9f0817b2496eafe5009487f35e65eefbd38 Mon Sep 17 00:00:00 2001 From: jeickhoff Date: Thu, 10 Mar 2022 10:13:04 +0100 Subject: [PATCH 19/89] Make TOC scrollable when too many subheadings --- docs/css/customstyles.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/css/customstyles.css b/docs/css/customstyles.css index 45885d182b..af50b5ecdb 100644 --- a/docs/css/customstyles.css +++ b/docs/css/customstyles.css @@ -29,6 +29,8 @@ body { margin-top: 60px; margin-left: -15px; margin-right: 15px; + height: 80%; + overflow: auto; } .container { margin-left: 15px; @@ -49,6 +51,8 @@ body { margin-top: 60px; margin-left: -15px; margin-right: 15px; + height: 80%; + overflow: auto; } .container { margin-left: 15px; From c421e7e646c1b5676a4e3fef8b9f0940b63fe732 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 10:58:16 +0100 Subject: [PATCH 20/89] Update gems Fixes https://github.com/pmd/pmd/security/dependabot/12 --- Gemfile.lock | 6 +++--- docs/Gemfile.lock | 27 ++++++++++++--------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 359c937c19..3c5a1abe22 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,7 +12,7 @@ GEM concurrent-ruby (1.1.9) cork (0.3.0) colored2 (~> 3.1) - danger (8.4.3) + danger (8.4.5) claide (~> 1.0) claide-plugins (>= 0.9.2) colored2 (~> 3.1) @@ -26,7 +26,7 @@ GEM octokit (~> 4.7) terminal-table (>= 1, < 4) differ (0.1.2) - et-orbi (1.2.6) + et-orbi (1.2.7) tzinfo faraday (1.10.0) faraday-em_http (~> 1.0) @@ -62,7 +62,7 @@ GEM rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) - liquid (5.1.0) + liquid (5.2.0) logger-colors (1.0.0) mini_portile2 (2.8.0) multipart-post (2.1.1) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 327bd7ca7d..48cf85a1d9 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.0.4.6) + activesupport (6.0.4.7) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -14,8 +14,7 @@ GEM execjs coffee-script-source (1.11.1) colorator (1.1.0) - commonmarker (0.17.13) - ruby-enum (~> 0.5) + commonmarker (0.23.4) concurrent-ruby (1.1.9) dnsruby (1.61.9) simpleidn (~> 0.1) @@ -52,12 +51,12 @@ GEM ffi (1.15.5) forwardable-extended (2.6.0) gemoji (3.0.1) - github-pages (223) + github-pages (225) github-pages-health-check (= 1.17.9) jekyll (= 3.9.0) jekyll-avatar (= 0.7.0) jekyll-coffeescript (= 1.1.1) - jekyll-commonmark-ghpages (= 0.1.6) + jekyll-commonmark-ghpages (= 0.2.0) jekyll-default-layout (= 0.1.4) jekyll-feed (= 0.15.1) jekyll-gist (= 1.5.0) @@ -71,7 +70,7 @@ GEM jekyll-relative-links (= 0.6.1) jekyll-remote-theme (= 0.4.3) jekyll-sass-converter (= 1.5.2) - jekyll-seo-tag (= 2.7.1) + jekyll-seo-tag (= 2.8.0) jekyll-sitemap (= 1.4.0) jekyll-swiss (= 1.0.0) jekyll-theme-architect (= 0.2.0) @@ -127,12 +126,12 @@ GEM jekyll-coffeescript (1.1.1) coffee-script (~> 2.2) coffee-script-source (~> 1.11.1) - jekyll-commonmark (1.3.1) - commonmarker (~> 0.14) - jekyll (>= 3.7, < 5.0) - jekyll-commonmark-ghpages (0.1.6) - commonmarker (~> 0.17.6) - jekyll-commonmark (~> 1.2) + jekyll-commonmark (1.4.0) + commonmarker (~> 0.22) + jekyll-commonmark-ghpages (0.2.0) + commonmarker (~> 0.23.4) + jekyll (~> 3.9.0) + jekyll-commonmark (~> 1.4.0) rouge (>= 2.0, < 4.0) jekyll-default-layout (0.1.4) jekyll (~> 3.0) @@ -164,7 +163,7 @@ GEM rubyzip (>= 1.3.0, < 3.0) jekyll-sass-converter (1.5.2) sass (~> 3.4) - jekyll-seo-tag (2.7.1) + jekyll-seo-tag (2.8.0) jekyll (>= 3.8, < 5.0) jekyll-sitemap (1.4.0) jekyll (>= 3.7, < 5.0) @@ -248,8 +247,6 @@ GEM ffi (~> 1.0) rexml (3.2.5) rouge (3.26.0) - ruby-enum (0.9.0) - i18n ruby2_keywords (0.0.5) rubyzip (2.3.2) safe_yaml (1.0.5) From b3ab5f0c403acd5036d015f20cf6dc93cb2cccd0 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 11:59:18 +0100 Subject: [PATCH 21/89] [java] Add Java 18 language version --- docs/_data/sidebars/pmd_sidebar.yml | 13 +++++- docs/pages/pmd/languages/java.md | 40 +++++++++++++++++++ docs/pages/pmd/userdocs/cli_reference.md | 3 +- docs/pages/pmd/userdocs/tools/ant.md | 4 +- .../pmd/lang/java/JavaLanguageModule.java | 4 +- .../pmd/lang/java/ast/KotlinTestingDsl.kt | 3 +- 6 files changed, 60 insertions(+), 7 deletions(-) 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 cf4d32d421..fcd51e57b2 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -343,9 +343,18 @@ entries: - title: JSP Support url: /pmd_languages_jsp.html output: web, pdf - - title: Java code metrics - url: /pmd_java_metrics_index.html + - title: null output: web, pdf + subfolders: + - title: Java Support + output: web, pdf + subfolderitems: + - title: Java Versions + url: /pmd_languages_java.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 diff --git a/docs/pages/pmd/languages/java.md b/docs/pages/pmd/languages/java.md new file mode 100644 index 0000000000..b76e01d9b7 --- /dev/null +++ b/docs/pages/pmd/languages/java.md @@ -0,0 +1,40 @@ +--- +title: Supported Java Versions +permalink: pmd_languages_java.html +--- + +## Overview of supported Java language versions + +Usually the latest non-preview Java Version is the default version. + +Java Version |Alias | Supported by PMD since | +-------------|------|------------------------| +18-preview | | 6.44.0 | +18 (default) | | 6.44.0 | +17-preview | | 6.37.0 | +17 | | 6.37.0 | +16-preview | | 6.32.0 | +16 | | 6.32.0 | +15 | | 6.27.0 | +14 | | 6.22.0 | +13 | | 6.18.0 | +12 | | 6.13.0 | +11 | | 6.6.0 | +10 | 1.10 | 6.4.0 | +9 | 1.9 | 6.0.0 | +8 | 1.8 | 5.1.0 | +7 | 1.7 | 5.0.0 | +6 | 1.6 | 3.9 | +5 | 1.5 | 3.0 | +1.4 | | 1.2.2 | +1.3 | | 1.0.0 | + +## Using Java preview features + +In order to analyze a project with PMD that uses preview language features, you'll need to enable +it via the environment variable `PMD_JAVA_OPTS` and select the new language version, e.g. `17-preview`: + + export PMD_JAVA_OPTS=--enable-preview + ./run.sh pmd -language java -version 17-preview ... + +Note: we only support preview language features for the latest two java versions. diff --git a/docs/pages/pmd/userdocs/cli_reference.md b/docs/pages/pmd/userdocs/cli_reference.md index 9ada368c91..0a27287864 100644 --- a/docs/pages/pmd/userdocs/cli_reference.md +++ b/docs/pages/pmd/userdocs/cli_reference.md @@ -198,8 +198,7 @@ Example: * [apex](pmd_rules_apex.html) (Salesforce Apex) * [java](pmd_rules_java.html) - * Supported Versions: 1.3, 1.4, 1.5, 5, 1.6, 6, 1.7, 7, 1.8, 8, 9, 1.9, 10, 1.10, 11, 12, - 13, 14, 15, 16, 16-preview, 17 (default), 17-preview + * [Supported Versions](pmd_languages_java.html) * [ecmascript](pmd_rules_ecmascript.html) (JavaScript) * [jsp](pmd_rules_jsp.html) * [modelica](pmd_rules_modelica.html) diff --git a/docs/pages/pmd/userdocs/tools/ant.md b/docs/pages/pmd/userdocs/tools/ant.md index 638805f356..b523329aff 100644 --- a/docs/pages/pmd/userdocs/tools/ant.md +++ b/docs/pages/pmd/userdocs/tools/ant.md @@ -236,8 +236,10 @@ nested element. Possible values are: - + + + diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java index ab9e22f796..b421acf80d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java @@ -31,8 +31,10 @@ public class JavaLanguageModule extends BaseLanguageModule { addVersion("15", new JavaLanguageHandler(15)); addVersion("16", new JavaLanguageHandler(16)); addVersion("16-preview", new JavaLanguageHandler(16, true)); - addDefaultVersion("17", new JavaLanguageHandler(17)); // 17 is the default + addVersion("17", new JavaLanguageHandler(17)); addVersion("17-preview", new JavaLanguageHandler(17, true)); + addDefaultVersion("18", new JavaLanguageHandler(18)); // 18 is the default + addVersion("18-preview", new JavaLanguageHandler(18, true)); } } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt index ce4e63419b..207d229c4c 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt @@ -23,7 +23,8 @@ enum class JavaVersion : Comparable { J14, J15, J16, J16__PREVIEW, - J17, J17__PREVIEW; + J17, J17__PREVIEW, + J18, J18__PREVIEW; /** Name suitable for use with e.g. [JavaParsingHelper.parse] */ val pmdName: String = name.removePrefix("J").replaceFirst("__", "-").replace('_', '.').toLowerCase() From 1e042ce4d05eb5d3b0c58e1412f8fef203d1a868 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 12:22:24 +0100 Subject: [PATCH 22/89] [java] Fix unit tests for new version 18 --- pmd-java/etc/grammar/Java.jjt | 10 +++++----- .../pmd/lang/java/ast/Java17PreviewTreeDumpTest.java | 6 +++--- .../sourceforge/pmd/lang/java/ast/ASTPatternTest.kt | 8 +++++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index ed32a5bae5..6bd184c7d4 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -529,30 +529,30 @@ public class JavaParser { } private boolean isJEP406Supported() { - return jdkVersion == 17 && preview; + return (jdkVersion == 17 || jdkVersion == 18) && preview; } private void checkForPatternMatchingInSwitch() { if (!isJEP406Supported()) { - throwParseException("Pattern Matching in Switch is only supported with JDK 17 Preview."); + throwParseException("Pattern Matching in Switch is only supported with JDK 17 Preview or JDK 18 Preview."); } } private void checkForNullCaseLabel() { if (!isJEP406Supported()) { - throwParseException("Null case labels in switch are only supported with JDK 17 Preview."); + throwParseException("Null case labels in switch are only supported with JDK 17 Preview or JDK 18 Preview."); } } private void checkForDefaultCaseLabel() { if (!isJEP406Supported()) { - throwParseException("Default case labels in switch are only supported with JDK 17 Preview."); + throwParseException("Default case labels in switch are only supported with JDK 17 Preview or JDK 18 Preview."); } } private void checkForGuardedPatterns() { if (!isJEP406Supported()) { - throwParseException("Guarded patterns are only supported with JDK 17 Preview."); + throwParseException("Guarded patterns are only supported with JDK 17 Preview or JDK 18 Preview."); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17PreviewTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17PreviewTreeDumpTest.java index ce7d7d779b..4f8d583872 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17PreviewTreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17PreviewTreeDumpTest.java @@ -38,7 +38,7 @@ public class Java17PreviewTreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 17 Preview.")); + thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 17 Preview or JDK 18 Preview.")); } @Test @@ -65,7 +65,7 @@ public class Java17PreviewTreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Null case labels in switch are only supported with JDK 17 Preview.")); + thrown.getMessage().contains("Null case labels in switch are only supported with JDK 17 Preview or JDK 18 Preview.")); } @Test @@ -82,7 +82,7 @@ public class Java17PreviewTreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Guarded patterns are only supported with JDK 17 Preview.")); + thrown.getMessage().contains("Guarded patterns are only supported with JDK 17 Preview or JDK 18 Preview.")); } @Test diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt index 4d01bc1f4a..6558e336a4 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt @@ -12,8 +12,10 @@ import java.io.IOException class ASTPatternTest : ParserTestSpec({ - parserTest("Test patterns only available on JDK16 and JDK16 (preview) and JDK17 and JDK 17 (preview)", - javaVersions = JavaVersion.values().asList().minus(J16).minus(J16__PREVIEW).minus(J17).minus(J17__PREVIEW)) { + parserTest("Test patterns only available on JDK16 or higher (including preview)", + javaVersions = JavaVersion.values().asList().minus(J16).minus(J16__PREVIEW) + .minus(J17).minus(J17__PREVIEW) + .minus(J18).minus(J18__PREVIEW)) { expectParseException("Pattern Matching for instanceof is only supported with JDK >= 16") { parseAstExpression("obj instanceof Class c") @@ -21,7 +23,7 @@ class ASTPatternTest : ParserTestSpec({ } - parserTest("Test simple patterns", javaVersions = listOf(J16, J17)) { + parserTest("Test simple patterns", javaVersions = listOf(J16, J17, J18)) { importedTypes += IOException::class.java From de21986ac3f953a1a46f4da36e5d48bec54bbd4e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 14:56:27 +0100 Subject: [PATCH 23/89] [java] Add Java 18 Preview Tree Dump Test --- .../java/ast/Java18PreviewTreeDumpTest.java | 102 +++ .../java18p/DealingWithNull.java | 90 +++ .../java18p/DealingWithNull.txt | 637 ++++++++++++++++++ .../java18p/EnhancedTypeCheckingSwitch.java | 29 + .../java18p/EnhancedTypeCheckingSwitch.txt | 199 ++++++ .../java18p/ExhaustiveSwitch.java | 87 +++ .../java18p/ExhaustiveSwitch.txt | 634 +++++++++++++++++ .../GuardedAndParenthesizedPatterns.java | 60 ++ .../GuardedAndParenthesizedPatterns.txt | 590 ++++++++++++++++ .../java18p/PatternsInSwitchLabels.java | 22 + .../java18p/PatternsInSwitchLabels.txt | 150 +++++ .../java18p/RefiningPatternsInSwitch.java | 71 ++ .../java18p/RefiningPatternsInSwitch.txt | 456 +++++++++++++ .../ScopeOfPatternVariableDeclarations.java | 48 ++ .../ScopeOfPatternVariableDeclarations.txt | 241 +++++++ 15 files changed, 3416 insertions(+) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java18PreviewTreeDumpTest.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.txt diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java18PreviewTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java18PreviewTreeDumpTest.java new file mode 100644 index 0000000000..19ff4e4cd9 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java18PreviewTreeDumpTest.java @@ -0,0 +1,102 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.function.ThrowingRunnable; + +import net.sourceforge.pmd.lang.ast.ParseException; +import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper; +import net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest; +import net.sourceforge.pmd.lang.ast.test.RelevantAttributePrinter; +import net.sourceforge.pmd.lang.java.JavaParsingHelper; + +public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest { + private final JavaParsingHelper java18p = + JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("18-preview") + .withResourceContext(Java18PreviewTreeDumpTest.class, "jdkversiontests/java18p/"); + private final JavaParsingHelper java18 = java18p.withDefaultVersion("18"); + + public Java18PreviewTreeDumpTest() { + super(new RelevantAttributePrinter(), ".java"); + } + + @Override + public BaseParsingHelper getParser() { + return java18p; + } + + @Test + public void dealingWithNullBeforeJava18Preview() { + ParseException thrown = Assert.assertThrows(ParseException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + java18.parseResource("DealingWithNull.java"); + } + }); + Assert.assertTrue("Unexpected message: " + thrown.getMessage(), + thrown.getMessage().contains("Null case labels in switch are only supported with JDK 17 Preview or JDK 18 Preview.")); + } + + @Test + public void dealingWithNull() { + doTest("DealingWithNull"); + } + + @Test + public void enhancedTypeCheckingSwitch() { + doTest("EnhancedTypeCheckingSwitch"); + } + + @Test + public void exhaustiveSwitch() { + doTest("ExhaustiveSwitch"); + } + + @Test + public void guardedAndParenthesizedPatternsBeforeJava18Preview() { + ParseException thrown = Assert.assertThrows(ParseException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + java18.parseResource("GuardedAndParenthesizedPatterns.java"); + } + }); + Assert.assertTrue("Unexpected message: " + thrown.getMessage(), + thrown.getMessage().contains("Guarded patterns are only supported with JDK 17 Preview or JDK 18 Preview.")); + } + + @Test + public void guardedAndParenthesizedPatterns() { + doTest("GuardedAndParenthesizedPatterns"); + } + + @Test + public void patternsInSwitchLabelsBeforeJava18Preview() { + ParseException thrown = Assert.assertThrows(ParseException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + java18.parseResource("PatternsInSwitchLabels.java"); + } + }); + Assert.assertTrue("Unexpected message: " + thrown.getMessage(), + thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 17 Preview or JDK 18 Preview.")); + } + + @Test + public void patternsInSwitchLabels() { + doTest("PatternsInSwitchLabels"); + } + + @Test + public void refiningPatternsInSwitch() { + doTest("RefiningPatternsInSwitch"); + } + + @Test + public void scopeOfPatternVariableDeclarations() { + doTest("ScopeOfPatternVariableDeclarations"); + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.java new file mode 100644 index 0000000000..fcb7d01c83 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.java @@ -0,0 +1,90 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * @see JEP 420: Pattern Matching for switch (Second Preview) + */ +public class DealingWithNull { + + static void testFooBar(String s) { + switch (s) { + case null -> System.out.println("Oops"); + case "Foo", "Bar" -> System.out.println("Great"); + default -> System.out.println("Ok"); + } + } + + static void testStringOrNull(Object o) { + switch (o) { + case null, String s -> System.out.println("String: " + s); + case default -> System.out.print("default case"); + } + } + + static void test(Object o) { + switch (o) { + case null -> System.out.println("null!"); + case String s -> System.out.println("String"); + default -> System.out.println("Something else"); + } + } + + + static void test2(Object o) { + switch (o) { + case null -> throw new NullPointerException(); + case String s -> System.out.println("String: "+s); + case Integer i -> System.out.println("Integer"); + default -> System.out.println("default"); + } + } + + + static void test3(Object o) { + switch(o) { + case null: case String s: + System.out.println("String, including null"); + break; + default: + System.out.println("default case"); + break; + } + + switch(o) { + case null, String s -> System.out.println("String, including null"); + default -> System.out.println("default case"); + } + + switch(o) { + case null: default: + System.out.println("The rest (including null)"); + } + + switch(o) { + case null, default -> + System.out.println("The rest (including null)"); + } + } + + public static void main(String[] args) { + test("test"); + test2(2); + try { + test2(null); + } catch (NullPointerException e) { + System.out.println(e); + } + test3(3); + test3("test"); + test3(null); + + testFooBar(null); + testFooBar("Foo"); + testFooBar("Bar"); + testFooBar("baz"); + + testStringOrNull(null); + testStringOrNull("some string"); + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.txt new file mode 100644 index 0000000000..72878864b5 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.txt @@ -0,0 +1,637 @@ ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] + +- TypeDeclaration[] + +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "DealingWithNull", @Default = false, @Final = false, @Image = "DealingWithNull", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "DealingWithNull", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testFooBar", @Modifiers = 16, @Name = "testFooBar", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "testFooBar", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "s"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- NullLiteral[] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Oops"", @FloatLiteral = false, @Image = ""Oops"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Oops"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Foo"", @FloatLiteral = false, @Image = ""Foo"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Foo"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Bar"", @FloatLiteral = false, @Image = ""Bar"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Bar"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Great"", @FloatLiteral = false, @Image = ""Great"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Great"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Ok"", @FloatLiteral = false, @Image = ""Ok"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Ok"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testStringOrNull", @Modifiers = 16, @Name = "testStringOrNull", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "testStringOrNull", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | | +- NullLiteral[] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- AdditiveExpression[@Image = "+", @Operator = "+"] + | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String: "", @FloatLiteral = false, @Image = ""String: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "s"] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.print"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test", @Modifiers = 16, @Name = "test", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "test", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- NullLiteral[] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""null!"", @FloatLiteral = false, @Image = ""null!"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""null!"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String"", @FloatLiteral = false, @Image = ""String"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Something else"", @FloatLiteral = false, @Image = ""Something else"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Something else"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test2", @Modifiers = 16, @Name = "test2", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "test2", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabeledThrowStatement[] + | | +- SwitchLabel[@Default = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- NullLiteral[] + | | +- ThrowStatement[@FirstClassOrInterfaceTypeImage = "NullPointerException"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- AllocationExpression[@AnonymousClass = false] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "NullPointerException", @ReferenceToClassSameCompilationUnit = false] + | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- AdditiveExpression[@Image = "+", @Operator = "+"] + | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String: "", @FloatLiteral = false, @Image = ""String: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "s"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Integer"", @FloatLiteral = false, @Image = ""Integer"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Integer"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default"", @FloatLiteral = false, @Image = ""default"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test3", @Modifiers = 16, @Name = "test3", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "test3", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "o"] + | | +- SwitchLabel[@Default = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- NullLiteral[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- StatementExpression[] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String, including null"", @FloatLiteral = false, @Image = ""String, including null"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String, including null"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- BreakStatement[] + | | +- SwitchLabel[@Default = true] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- StatementExpression[] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- BreakStatement[] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "o"] + | | +- SwitchLabeledExpression[] + | | | +- SwitchLabel[@Default = false] + | | | | +- Expression[@StandAlonePrimitive = false] + | | | | | +- PrimaryExpression[] + | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | | | +- NullLiteral[] + | | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String, including null"", @FloatLiteral = false, @Image = ""String, including null"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String, including null"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = true] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "o"] + | | +- SwitchLabel[@Default = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- NullLiteral[] + | | +- SwitchLabel[@Default = true] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""The rest (including null)"", @FloatLiteral = false, @Image = ""The rest (including null)"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""The rest (including null)"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- NullLiteral[] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""The rest (including null)"", @FloatLiteral = false, @Image = ""The rest (including null)"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""The rest (including null)"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] + +- ResultType[@Void = true, @returnsArray = false] + +- MethodDeclarator[@Image = "main", @ParameterCount = 1] + | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] + | | +- ReferenceType[@Array = true, @ArrayDepth = 1] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] + +- Block[@containsComment = false] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""test"", @FloatLiteral = false, @Image = ""test"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""test"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test2"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "2", @FloatLiteral = false, @Image = "2", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "2", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 2, @ValueAsLong = 2] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- TryStatement[@Finally = false, @TryWithResources = false] + | +- Block[@containsComment = false] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "test2"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- NullLiteral[] + | +- CatchStatement[@ExceptionName = "e", @MulticatchStatement = false] + | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "NullPointerException"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "NullPointerException", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = true, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "e", @LambdaParameter = false, @LocalVariable = false, @Name = "e", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "e"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "e"] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test3"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "3", @FloatLiteral = false, @Image = "3", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "3", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 3, @ValueAsLong = 3] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test3"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""test"", @FloatLiteral = false, @Image = ""test"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""test"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test3"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- NullLiteral[] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testFooBar"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- NullLiteral[] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testFooBar"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Foo"", @FloatLiteral = false, @Image = ""Foo"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Foo"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testFooBar"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Bar"", @FloatLiteral = false, @Image = ""Bar"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Bar"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testFooBar"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""baz"", @FloatLiteral = false, @Image = ""baz"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""baz"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testStringOrNull"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- NullLiteral[] + +- BlockStatement[@Allocation = false] + +- Statement[] + +- StatementExpression[] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "testStringOrNull"] + +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + +- Arguments[@ArgumentCount = 1, @Size = 1] + +- ArgumentList[@Size = 1] + +- Expression[@StandAlonePrimitive = false] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""some string"", @FloatLiteral = false, @Image = ""some string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""some string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.java new file mode 100644 index 0000000000..96118f9bb7 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.java @@ -0,0 +1,29 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * @see JEP 420: Pattern Matching for switch (Second Preview) + */ +public class EnhancedTypeCheckingSwitch { + + + static void typeTester(Object o) { + switch (o) { + case null -> System.out.println("null"); + case String s -> System.out.println("String"); + case Color c -> System.out.println("Color with " + c.values().length + " values"); + case Point p -> System.out.println("Record class: " + p.toString()); + case int[] ia -> System.out.println("Array of ints of length" + ia.length); + default -> System.out.println("Something else"); + } + } + + public static void main(String[] args) { + Object o = "test"; + typeTester(o); + } +} + +record Point(int i, int j) {} +enum Color { RED, GREEN, BLUE; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.txt new file mode 100644 index 0000000000..d5ea56fdf2 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.txt @@ -0,0 +1,199 @@ ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] + +- TypeDeclaration[] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "EnhancedTypeCheckingSwitch", @Default = false, @Final = false, @Image = "EnhancedTypeCheckingSwitch", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "EnhancedTypeCheckingSwitch", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "typeTester", @Modifiers = 16, @Name = "typeTester", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | | +- ResultType[@Void = true, @returnsArray = false] + | | +- MethodDeclarator[@Image = "typeTester", @ParameterCount = 1] + | | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | | +- Block[@containsComment = false] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "o"] + | | +- SwitchLabeledExpression[] + | | | +- SwitchLabel[@Default = false] + | | | | +- Expression[@StandAlonePrimitive = false] + | | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | | +- NullLiteral[] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""null"", @FloatLiteral = false, @Image = ""null"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""null"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- SwitchLabeledExpression[] + | | | +- SwitchLabel[@Default = false] + | | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String"", @FloatLiteral = false, @Image = ""String"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- SwitchLabeledExpression[] + | | | +- SwitchLabel[@Default = false] + | | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Color"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Color", @ReferenceToClassSameCompilationUnit = true] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- AdditiveExpression[@Image = "+", @Operator = "+"] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Color with "", @FloatLiteral = false, @Image = ""Color with "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Color with "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "c.values"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | | +- PrimarySuffix[@ArgumentCount = -1, @Arguments = false, @ArrayDereference = false, @Image = "length"] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "" values"", @FloatLiteral = false, @Image = "" values"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "" values"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- SwitchLabeledExpression[] + | | | +- SwitchLabel[@Default = false] + | | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Point"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Point", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "p", @LambdaParameter = false, @LocalVariable = false, @Name = "p", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "p"] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- AdditiveExpression[@Image = "+", @Operator = "+"] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Record class: "", @FloatLiteral = false, @Image = ""Record class: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Record class: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "p.toString"] + | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | +- SwitchLabeledExpression[] + | | | +- SwitchLabel[@Default = false] + | | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "int"] + | | | | | +- ReferenceType[@Array = true, @ArrayDepth = 1] + | | | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "ia", @LambdaParameter = false, @LocalVariable = false, @Name = "ia", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "ia"] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- AdditiveExpression[@Image = "+", @Operator = "+"] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Array of ints of length"", @FloatLiteral = false, @Image = ""Array of ints of length"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Array of ints of length"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "ia.length"] + | | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = true] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Something else"", @FloatLiteral = false, @Image = ""Something else"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Something else"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "main", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] + | | | +- ReferenceType[@Array = true, @ArrayDepth = 1] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "o", @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclarator[@Initializer = true, @Name = "o"] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "o", @LambdaParameter = false, @LocalVariable = true, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | | +- VariableInitializer[] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""test"", @FloatLiteral = false, @Image = ""test"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""test"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "typeTester"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "o"] + +- TypeDeclaration[] + | +- RecordDeclaration[@Abstract = false, @BinaryName = "Point", @Default = false, @Final = true, @Image = "Point", @Local = false, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "Point", @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyFinal = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false] + | +- RecordComponentList[@Size = 2] + | | +- RecordComponent[@Varargs = false] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] + | | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = true, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | | +- RecordComponent[@Varargs = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] + | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = true, @ForeachVariable = false, @FormalParameter = false, @Image = "j", @LambdaParameter = false, @LocalVariable = false, @Name = "j", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "j"] + | +- RecordBody[] + +- TypeDeclaration[] + +- EnumDeclaration[@Abstract = false, @BinaryName = "Color", @Default = false, @Final = false, @Image = "Color", @Local = false, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "Color", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.ENUM, @Volatile = false] + +- EnumBody[] + +- EnumConstant[@AnonymousClass = false, @Image = "RED"] + +- EnumConstant[@AnonymousClass = false, @Image = "GREEN"] + +- EnumConstant[@AnonymousClass = false, @Image = "BLUE"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.java new file mode 100644 index 0000000000..d2e35ec75a --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.java @@ -0,0 +1,87 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * @see JEP 420: Pattern Matching for switch (Second Preview) + */ +public class ExhaustiveSwitch { + + static int coverage(Object o) { + return switch (o) { + case String s -> s.length(); + case Integer i -> i; + default -> 0; + }; + } + + static void coverageStatement(Object o) { + switch (o) { + case String s: + System.out.println(s); + break; + case Integer i: + System.out.println("Integer"); + break; + default: // Now exhaustive! + break; + } + } + + sealed interface S permits A, B, C {} + final static class A implements S {} + final static class B implements S {} + record C(int i) implements S {} // Implicitly final + + static int testSealedExhaustive(S s) { + return switch (s) { + case A a -> 1; + case B b -> 2; + case C c -> 3; + }; + } + + static void switchStatementExhaustive(S s) { + switch (s) { + case A a : + System.out.println("A"); + break; + case C c : + System.out.println("C"); + break; + default: + System.out.println("default case, should be B"); + break; + }; + } + sealed interface I permits E, F {} + final static class E implements I {} + final static class F implements I {} + + static int testGenericSealedExhaustive(I i) { + return switch (i) { + // Exhaustive as no E case possible! + case F bi -> 42; + }; + } + + public static void main(String[] args) { + System.out.println(coverage("a string")); + System.out.println(coverage(42)); + System.out.println(coverage(new Object())); + + coverageStatement("a string"); + coverageStatement(21); + coverageStatement(new Object()); + + System.out.println("A:" + testSealedExhaustive(new A())); + System.out.println("B:" + testSealedExhaustive(new B())); + System.out.println("C:" + testSealedExhaustive(new C(1))); + + switchStatementExhaustive(new A()); + switchStatementExhaustive(new B()); + switchStatementExhaustive(new C(2)); + + System.out.println("F:" + testGenericSealedExhaustive(new F())); + } +} \ No newline at end of file diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.txt new file mode 100644 index 0000000000..ce57bb07ea --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.txt @@ -0,0 +1,634 @@ ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] + +- TypeDeclaration[] + +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch", @Default = false, @Final = false, @Image = "ExhaustiveSwitch", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "ExhaustiveSwitch", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "coverage", @Modifiers = 16, @Name = "coverage", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = false, @Volatile = false] + | +- ResultType[@Void = false, @returnsArray = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] + | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | +- MethodDeclarator[@Image = "coverage", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- ReturnStatement[] + | +- Expression[@StandAlonePrimitive = false] + | +- SwitchExpression[] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "s.length"] + | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "i"] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "0", @FloatLiteral = false, @Image = "0", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "0", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "coverageStatement", @Modifiers = 16, @Name = "coverageStatement", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "coverageStatement", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabel[@Default = false] + | | +- TypePattern[@ParenthesisDepth = 0] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "s"] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- BreakStatement[] + | +- SwitchLabel[@Default = false] + | | +- TypePattern[@ParenthesisDepth = 0] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Integer"", @FloatLiteral = false, @Image = ""Integer"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Integer"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- BreakStatement[] + | +- SwitchLabel[@Default = true] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- BreakStatement[] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.INTERFACE] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$S", @Default = false, @Final = false, @Image = "S", @Interface = true, @Local = false, @Modifiers = 16384, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = true, @SimpleName = "S", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.INTERFACE, @Volatile = false] + | +- PermitsList[] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "B", @ReferenceToClassSameCompilationUnit = true] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$A", @Default = false, @Final = true, @Image = "A", @Interface = false, @Local = false, @Modifiers = 48, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "A", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + | +- ImplementsList[] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$B", @Default = false, @Final = true, @Image = "B", @Interface = false, @Local = false, @Modifiers = 48, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "B", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + | +- ImplementsList[] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.RECORD] + | +- RecordDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$C", @Default = false, @Final = true, @Image = "C", @Local = false, @Modifiers = 0, @Native = false, @Nested = true, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "C", @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyFinal = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false] + | +- RecordComponentList[@Size = 1] + | | +- RecordComponent[@Varargs = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] + | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = true, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | +- ImplementsList[] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] + | +- RecordBody[] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testSealedExhaustive", @Modifiers = 16, @Name = "testSealedExhaustive", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = false, @Volatile = false] + | +- ResultType[@Void = false, @returnsArray = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] + | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | +- MethodDeclarator[@Image = "testSealedExhaustive", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "S"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- ReturnStatement[] + | +- Expression[@StandAlonePrimitive = false] + | +- SwitchExpression[] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "s"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "A"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "a", @LambdaParameter = false, @LocalVariable = false, @Name = "a", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "a"] + | | +- Expression[@StandAlonePrimitive = true] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "B"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "B", @ReferenceToClassSameCompilationUnit = true] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "b", @LambdaParameter = false, @LocalVariable = false, @Name = "b", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "b"] + | | +- Expression[@StandAlonePrimitive = true] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "2", @FloatLiteral = false, @Image = "2", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "2", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 2, @ValueAsLong = 2] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = false] + | | +- TypePattern[@ParenthesisDepth = 0] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "C"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "3", @FloatLiteral = false, @Image = "3", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "3", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 3, @ValueAsLong = 3] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "switchStatementExhaustive", @Modifiers = 16, @Name = "switchStatementExhaustive", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "switchStatementExhaustive", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "S"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "s"] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "A"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "a", @LambdaParameter = false, @LocalVariable = false, @Name = "a", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "a"] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- StatementExpression[] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A"", @FloatLiteral = false, @Image = ""A"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = true, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- BreakStatement[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "C"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- StatementExpression[] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""C"", @FloatLiteral = false, @Image = ""C"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = true, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""C"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- BreakStatement[] + | | +- SwitchLabel[@Default = true] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- StatementExpression[] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case, should be B"", @FloatLiteral = false, @Image = ""default case, should be B"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case, should be B"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- BreakStatement[] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- EmptyStatement[] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.INTERFACE] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$I", @Default = false, @Final = false, @Image = "I", @Interface = true, @Local = false, @Modifiers = 16384, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = true, @SimpleName = "I", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.INTERFACE, @Volatile = false] + | +- TypeParameters[] + | | +- TypeParameter[@Image = "T", @Name = "T", @ParameterName = "T", @TypeBound = false] + | +- PermitsList[] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "E", @ReferenceToClassSameCompilationUnit = true] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "F", @ReferenceToClassSameCompilationUnit = true] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$E", @Default = false, @Final = true, @Image = "E", @Interface = false, @Local = false, @Modifiers = 48, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "E", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + | +- TypeParameters[] + | | +- TypeParameter[@Image = "X", @Name = "X", @ParameterName = "X", @TypeBound = false] + | +- ImplementsList[] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "I", @ReferenceToClassSameCompilationUnit = true] + | | +- TypeArguments[@Diamond = false] + | | +- TypeArgument[@Wildcard = false] + | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$F", @Default = false, @Final = true, @Image = "F", @Interface = false, @Local = false, @Modifiers = 48, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "F", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + | +- TypeParameters[] + | | +- TypeParameter[@Image = "Y", @Name = "Y", @ParameterName = "Y", @TypeBound = false] + | +- ImplementsList[] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "I", @ReferenceToClassSameCompilationUnit = true] + | | +- TypeArguments[@Diamond = false] + | | +- TypeArgument[@Wildcard = false] + | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Y", @ReferenceToClassSameCompilationUnit = false] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testGenericSealedExhaustive", @Modifiers = 16, @Name = "testGenericSealedExhaustive", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = false, @Volatile = false] + | +- ResultType[@Void = false, @returnsArray = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] + | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | +- MethodDeclarator[@Image = "testGenericSealedExhaustive", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "I"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "I", @ReferenceToClassSameCompilationUnit = true] + | | | +- TypeArguments[@Diamond = false] + | | | +- TypeArgument[@Wildcard = false] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- ReturnStatement[] + | +- Expression[@StandAlonePrimitive = false] + | +- SwitchExpression[] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "i"] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = false] + | | +- TypePattern[@ParenthesisDepth = 0] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "F"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "F", @ReferenceToClassSameCompilationUnit = true] + | | | +- TypeArguments[@Diamond = false] + | | | +- TypeArgument[@Wildcard = false] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "bi", @LambdaParameter = false, @LocalVariable = false, @Name = "bi", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "bi"] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "42", @FloatLiteral = false, @Image = "42", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "42", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 42, @ValueAsLong = 42] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] + +- ResultType[@Void = true, @returnsArray = false] + +- MethodDeclarator[@Image = "main", @ParameterCount = 1] + | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] + | | +- ReferenceType[@Array = true, @ArrayDepth = 1] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] + +- Block[@containsComment = false] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "coverage"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""a string"", @FloatLiteral = false, @Image = ""a string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""a string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "coverage"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "42", @FloatLiteral = false, @Image = "42", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "42", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 42, @ValueAsLong = 42] + +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "coverage"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "coverageStatement"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""a string"", @FloatLiteral = false, @Image = ""a string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""a string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "coverageStatement"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "21", @FloatLiteral = false, @Image = "21", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "21", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 21, @ValueAsLong = 21] + +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "coverageStatement"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- AdditiveExpression[@Image = "+", @Operator = "+"] + | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A:"", @FloatLiteral = false, @Image = ""A:"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A:"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testSealedExhaustive"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- AdditiveExpression[@Image = "+", @Operator = "+"] + | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""B:"", @FloatLiteral = false, @Image = ""B:"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""B:"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testSealedExhaustive"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "B", @ReferenceToClassSameCompilationUnit = true] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- AdditiveExpression[@Image = "+", @Operator = "+"] + | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""C:"", @FloatLiteral = false, @Image = ""C:"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""C:"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testSealedExhaustive"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "switchStatementExhaustive"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "switchStatementExhaustive"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "B", @ReferenceToClassSameCompilationUnit = true] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "switchStatementExhaustive"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "2", @FloatLiteral = false, @Image = "2", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "2", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 2, @ValueAsLong = 2] + +- BlockStatement[@Allocation = true] + +- Statement[] + +- StatementExpression[] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "System.out.println"] + +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + +- Arguments[@ArgumentCount = 1, @Size = 1] + +- ArgumentList[@Size = 1] + +- Expression[@StandAlonePrimitive = false] + +- AdditiveExpression[@Image = "+", @Operator = "+"] + +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""F:"", @FloatLiteral = false, @Image = ""F:"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""F:"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "testGenericSealedExhaustive"] + +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + +- Arguments[@ArgumentCount = 1, @Size = 1] + +- ArgumentList[@Size = 1] + +- Expression[@StandAlonePrimitive = false] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + +- AllocationExpression[@AnonymousClass = false] + +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "F", @ReferenceToClassSameCompilationUnit = true] + | +- TypeArguments[@Diamond = false] + | +- TypeArgument[@Wildcard = false] + | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + +- Arguments[@ArgumentCount = 0, @Size = 0] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.java new file mode 100644 index 0000000000..1a4663701f --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.java @@ -0,0 +1,60 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * @see JEP 420: Pattern Matching for switch (Second Preview) + */ +public class GuardedAndParenthesizedPatterns { + + + static void test(Object o) { + switch (o) { + case String s && (s.length() == 1) -> System.out.println("single char string"); + case String s -> System.out.println("string"); + case (Integer i && i.intValue() == 1) -> System.out.println("integer 1"); + case (((Long l && l.longValue() == 1L))) -> System.out.println("long 1 with parens"); + case (((Double d))) -> System.out.println("double with parens"); + default -> System.out.println("default case"); + } + } + + static void testWithNull(Object o) { + switch (o) { + case String s && (s.length() == 1) -> System.out.println("single char string"); + case String s -> System.out.println("string"); + case (Integer i && i.intValue() == 1) -> System.out.println("integer 1"); + case (((Long l && l.longValue() == 1L))) -> System.out.println("long 1 with parens"); + case (((Double d))) -> System.out.println("double with parens"); + case null -> System.out.println("null!"); + default -> System.out.println("default case"); + } + } + + + static void instanceOfPattern(Object o) { + if (o instanceof String s && s.length() > 2) { + System.out.println("A string containing at least two characters"); + } + if (o != null && (o instanceof String s && s.length() > 3)) { + System.out.println("A string containing at least three characters"); + } + if (o instanceof (String s && s.length() > 4)) { + System.out.println("A string containing at least four characters"); + } + } + + public static void main(String[] args) { + test("a"); + test("fooo"); + test(1); + test(1L); + instanceOfPattern("abcde"); + try { + test(null); // throws NPE + } catch (NullPointerException e) { + e.printStackTrace(); + } + testWithNull(null); + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.txt new file mode 100644 index 0000000000..c9c3d0a1c5 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.txt @@ -0,0 +1,590 @@ ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] + +- TypeDeclaration[] + +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "GuardedAndParenthesizedPatterns", @Default = false, @Final = false, @Image = "GuardedAndParenthesizedPatterns", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "GuardedAndParenthesizedPatterns", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test", @Modifiers = 16, @Name = "test", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "test", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- GuardedPattern[@ParenthesisDepth = 0] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- EqualityExpression[@Image = "==", @Operator = "=="] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "s.length"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""single char string"", @FloatLiteral = false, @Image = ""single char string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""single char string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""string"", @FloatLiteral = false, @Image = ""string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- GuardedPattern[@ParenthesisDepth = 1] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | | | +- EqualityExpression[@Image = "==", @Operator = "=="] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "i.intValue"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""integer 1"", @FloatLiteral = false, @Image = ""integer 1"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""integer 1"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- GuardedPattern[@ParenthesisDepth = 3] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Long"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Long", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "l", @LambdaParameter = false, @LocalVariable = false, @Name = "l", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "l"] + | | | +- EqualityExpression[@Image = "==", @Operator = "=="] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "l.longValue"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1L", @FloatLiteral = false, @Image = "1L", @IntLiteral = false, @LongLiteral = true, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1L", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""long 1 with parens"", @FloatLiteral = false, @Image = ""long 1 with parens"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""long 1 with parens"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 3] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Double"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Double", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "d", @LambdaParameter = false, @LocalVariable = false, @Name = "d", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "d"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""double with parens"", @FloatLiteral = false, @Image = ""double with parens"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""double with parens"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testWithNull", @Modifiers = 16, @Name = "testWithNull", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "testWithNull", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- GuardedPattern[@ParenthesisDepth = 0] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- EqualityExpression[@Image = "==", @Operator = "=="] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "s.length"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""single char string"", @FloatLiteral = false, @Image = ""single char string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""single char string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""string"", @FloatLiteral = false, @Image = ""string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- GuardedPattern[@ParenthesisDepth = 1] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | | | +- EqualityExpression[@Image = "==", @Operator = "=="] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "i.intValue"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""integer 1"", @FloatLiteral = false, @Image = ""integer 1"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""integer 1"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- GuardedPattern[@ParenthesisDepth = 3] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Long"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Long", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "l", @LambdaParameter = false, @LocalVariable = false, @Name = "l", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "l"] + | | | +- EqualityExpression[@Image = "==", @Operator = "=="] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "l.longValue"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1L", @FloatLiteral = false, @Image = "1L", @IntLiteral = false, @LongLiteral = true, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1L", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""long 1 with parens"", @FloatLiteral = false, @Image = ""long 1 with parens"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""long 1 with parens"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 3] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Double"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Double", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "d", @LambdaParameter = false, @LocalVariable = false, @Name = "d", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "d"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""double with parens"", @FloatLiteral = false, @Image = ""double with parens"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""double with parens"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | +- NullLiteral[] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""null!"", @FloatLiteral = false, @Image = ""null!"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""null!"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "instanceOfPattern", @Modifiers = 16, @Name = "instanceOfPattern", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "instanceOfPattern", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- IfStatement[@Else = false] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- ConditionalAndExpression[] + | | | +- InstanceOfExpression[] + | | | | +- PrimaryExpression[] + | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "o"] + | | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | | +- RelationalExpression[@Image = ">"] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "s.length"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "2", @FloatLiteral = false, @Image = "2", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "2", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 2, @ValueAsLong = 2] + | | +- Statement[] + | | +- Block[@containsComment = false] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A string containing at least two characters"", @FloatLiteral = false, @Image = ""A string containing at least two characters"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A string containing at least two characters"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- IfStatement[@Else = false] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- ConditionalAndExpression[] + | | | +- EqualityExpression[@Image = "!=", @Operator = "!="] + | | | | +- PrimaryExpression[] + | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "o"] + | | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | | | +- NullLiteral[] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- ConditionalAndExpression[] + | | | +- InstanceOfExpression[] + | | | | +- PrimaryExpression[] + | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "o"] + | | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | | +- RelationalExpression[@Image = ">"] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "s.length"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "3", @FloatLiteral = false, @Image = "3", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "3", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 3, @ValueAsLong = 3] + | | +- Statement[] + | | +- Block[@containsComment = false] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A string containing at least three characters"", @FloatLiteral = false, @Image = ""A string containing at least three characters"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A string containing at least three characters"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- IfStatement[@Else = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- InstanceOfExpression[] + | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "o"] + | | +- GuardedPattern[@ParenthesisDepth = 1] + | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | +- RelationalExpression[@Image = ">"] + | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "s.length"] + | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "4", @FloatLiteral = false, @Image = "4", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "4", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 4, @ValueAsLong = 4] + | +- Statement[] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A string containing at least four characters"", @FloatLiteral = false, @Image = ""A string containing at least four characters"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A string containing at least four characters"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] + +- ResultType[@Void = true, @returnsArray = false] + +- MethodDeclarator[@Image = "main", @ParameterCount = 1] + | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] + | | +- ReferenceType[@Array = true, @ArrayDepth = 1] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] + +- Block[@containsComment = false] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""a"", @FloatLiteral = false, @Image = ""a"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = true, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""a"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""fooo"", @FloatLiteral = false, @Image = ""fooo"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""fooo"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1L", @FloatLiteral = false, @Image = "1L", @IntLiteral = false, @LongLiteral = true, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1L", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "instanceOfPattern"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""abcde"", @FloatLiteral = false, @Image = ""abcde"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""abcde"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- TryStatement[@Finally = false, @TryWithResources = false] + | +- Block[@containsComment = true] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "test"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- NullLiteral[] + | +- CatchStatement[@ExceptionName = "e", @MulticatchStatement = false] + | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "NullPointerException"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "NullPointerException", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = true, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "e", @LambdaParameter = false, @LocalVariable = false, @Name = "e", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "e"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "e.printStackTrace"] + | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- BlockStatement[@Allocation = false] + +- Statement[] + +- StatementExpression[] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "testWithNull"] + +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + +- Arguments[@ArgumentCount = 1, @Size = 1] + +- ArgumentList[@Size = 1] + +- Expression[@StandAlonePrimitive = false] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- NullLiteral[] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.java new file mode 100644 index 0000000000..70c4401a17 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.java @@ -0,0 +1,22 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * @see JEP 420: Pattern Matching for switch (Second Preview) + */ +public class PatternsInSwitchLabels { + + + public static void main(String[] args) { + Object o = 123L; + String formatted = switch (o) { + case Integer i -> String.format("int %d", i); + case Long l -> String.format("long %d", l); + case Double d -> String.format("double %f", d); + case String s -> String.format("String %s", s); + default -> o.toString(); + }; + System.out.println(formatted); + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.txt new file mode 100644 index 0000000000..c13492cb44 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.txt @@ -0,0 +1,150 @@ ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] + +- TypeDeclaration[] + +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "PatternsInSwitchLabels", @Default = false, @Final = false, @Image = "PatternsInSwitchLabels", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "PatternsInSwitchLabels", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] + +- ResultType[@Void = true, @returnsArray = false] + +- MethodDeclarator[@Image = "main", @ParameterCount = 1] + | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] + | | +- ReferenceType[@Array = true, @ArrayDepth = 1] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] + +- Block[@containsComment = false] + +- BlockStatement[@Allocation = false] + | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "o", @Volatile = false] + | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | +- VariableDeclarator[@Initializer = true, @Name = "o"] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "o", @LambdaParameter = false, @LocalVariable = true, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- VariableInitializer[] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "123L", @FloatLiteral = false, @Image = "123L", @IntLiteral = false, @LongLiteral = true, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "123L", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 123, @ValueAsLong = 123] + +- BlockStatement[@Allocation = false] + | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "formatted", @Volatile = false] + | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | +- VariableDeclarator[@Initializer = true, @Name = "formatted"] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "formatted", @LambdaParameter = false, @LocalVariable = true, @Name = "formatted", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "formatted"] + | +- VariableInitializer[] + | +- Expression[@StandAlonePrimitive = false] + | +- SwitchExpression[] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "String.format"] + | | +- PrimarySuffix[@ArgumentCount = 2, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 2, @Size = 2] + | | +- ArgumentList[@Size = 2] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""int %d"", @FloatLiteral = false, @Image = ""int %d"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""int %d"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "i"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Long"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Long", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "l", @LambdaParameter = false, @LocalVariable = false, @Name = "l", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "l"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "String.format"] + | | +- PrimarySuffix[@ArgumentCount = 2, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 2, @Size = 2] + | | +- ArgumentList[@Size = 2] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""long %d"", @FloatLiteral = false, @Image = ""long %d"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""long %d"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "l"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Double"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Double", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "d", @LambdaParameter = false, @LocalVariable = false, @Name = "d", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "d"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "String.format"] + | | +- PrimarySuffix[@ArgumentCount = 2, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 2, @Size = 2] + | | +- ArgumentList[@Size = 2] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""double %f"", @FloatLiteral = false, @Image = ""double %f"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""double %f"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "d"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "String.format"] + | | +- PrimarySuffix[@ArgumentCount = 2, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 2, @Size = 2] + | | +- ArgumentList[@Size = 2] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String %s"", @FloatLiteral = false, @Image = ""String %s"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String %s"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "s"] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o.toString"] + | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- BlockStatement[@Allocation = false] + +- Statement[] + +- StatementExpression[] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "System.out.println"] + +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + +- Arguments[@ArgumentCount = 1, @Size = 1] + +- ArgumentList[@Size = 1] + +- Expression[@StandAlonePrimitive = false] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + +- Name[@Image = "formatted"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.java new file mode 100644 index 0000000000..79fea58634 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.java @@ -0,0 +1,71 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * @see JEP 420: Pattern Matching for switch (Second Preview) + */ +public class RefiningPatternsInSwitch { + + static class Shape {} + static class Rectangle extends Shape {} + static class Triangle extends Shape { + private int area; + Triangle(int area) { + this.area = area; + } + int calculateArea() { return area; } + } + + static void testTriangle(Shape s) { + switch (s) { + case null: + break; + case Triangle t: + if (t.calculateArea() > 100) { + System.out.println("Large triangle"); + break; + } + default: + System.out.println("A shape, possibly a small triangle"); + } + } + + static void testTriangleRefined(Shape s) { + switch (s) { + case Triangle t && (t.calculateArea() > 100) -> + System.out.println("Large triangle"); + default -> + System.out.println("A shape, possibly a small triangle"); + } + } + + static void testTriangleRefined2(Shape s) { + switch (s) { + case Triangle t && (t.calculateArea() > 100) -> + System.out.println("Large triangle"); + case Triangle t -> + System.out.println("Small triangle"); + default -> + System.out.println("Non-triangle"); + } + } + + public static void main(String[] args) { + Triangle large = new Triangle(200); + Triangle small = new Triangle(10); + Rectangle rect = new Rectangle(); + + testTriangle(large); + testTriangle(small); + testTriangle(rect); + + testTriangleRefined(large); + testTriangleRefined(small); + testTriangleRefined(rect); + + testTriangleRefined2(large); + testTriangleRefined2(small); + testTriangleRefined2(rect); + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.txt new file mode 100644 index 0000000000..87d4845579 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.txt @@ -0,0 +1,456 @@ ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] + +- TypeDeclaration[] + +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "RefiningPatternsInSwitch", @Default = false, @Final = false, @Image = "RefiningPatternsInSwitch", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "RefiningPatternsInSwitch", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "RefiningPatternsInSwitch$Shape", @Default = false, @Final = false, @Image = "Shape", @Interface = false, @Local = false, @Modifiers = 16, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "Shape", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "RefiningPatternsInSwitch$Rectangle", @Default = false, @Final = false, @Image = "Rectangle", @Interface = false, @Local = false, @Modifiers = 16, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "Rectangle", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + | +- ExtendsList[] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] + | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "RefiningPatternsInSwitch$Triangle", @Default = false, @Final = false, @Image = "Triangle", @Interface = false, @Local = false, @Modifiers = 16, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "Triangle", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + | +- ExtendsList[] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] + | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.FIELD] + | | +- FieldDeclaration[@Abstract = false, @AnnotationMember = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @InterfaceMember = false, @Modifiers = 4, @Native = false, @PackagePrivate = false, @Private = true, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyFinal = false, @SyntacticallyPublic = false, @SyntacticallyStatic = false, @Transient = false, @VariableName = "area", @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] + | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | | +- VariableDeclarator[@Initializer = false, @Name = "area"] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = true, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "area", @LambdaParameter = false, @LocalVariable = false, @Name = "area", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "area"] + | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CONSTRUCTOR] + | | +- ConstructorDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @Image = "Triangle", @Kind = MethodLikeKind.CONSTRUCTOR, @Modifiers = 0, @Native = false, @PackagePrivate = true, @ParameterCount = 1, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @Volatile = false, @containsComment = false] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] + | | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "area", @LambdaParameter = false, @LocalVariable = false, @Name = "area", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "area"] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = true] + | | | +- PrimarySuffix[@ArgumentCount = -1, @Arguments = false, @ArrayDereference = false, @Image = "area"] + | | +- AssignmentOperator[@Compound = false, @Image = "="] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "area"] + | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 0, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "calculateArea", @Modifiers = 0, @Name = "calculateArea", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = false, @Volatile = false] + | +- ResultType[@Void = false, @returnsArray = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] + | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] + | +- MethodDeclarator[@Image = "calculateArea", @ParameterCount = 0] + | | +- FormalParameters[@ParameterCount = 0, @Size = 0] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- ReturnStatement[] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "area"] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testTriangle", @Modifiers = 16, @Name = "testTriangle", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "testTriangle", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Shape"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "s"] + | +- SwitchLabel[@Default = false] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- NullLiteral[] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- BreakStatement[] + | +- SwitchLabel[@Default = false] + | | +- TypePattern[@ParenthesisDepth = 0] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "t", @LambdaParameter = false, @LocalVariable = false, @Name = "t", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "t"] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- IfStatement[@Else = false] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- RelationalExpression[@Image = ">"] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "t.calculateArea"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "100", @FloatLiteral = false, @Image = "100", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "100", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 100, @ValueAsLong = 100] + | | +- Statement[] + | | +- Block[@containsComment = false] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- StatementExpression[] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Large triangle"", @FloatLiteral = false, @Image = ""Large triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Large triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- BreakStatement[] + | +- SwitchLabel[@Default = true] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A shape, possibly a small triangle"", @FloatLiteral = false, @Image = ""A shape, possibly a small triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A shape, possibly a small triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testTriangleRefined", @Modifiers = 16, @Name = "testTriangleRefined", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "testTriangleRefined", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Shape"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "s"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- GuardedPattern[@ParenthesisDepth = 0] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "t", @LambdaParameter = false, @LocalVariable = false, @Name = "t", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "t"] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- RelationalExpression[@Image = ">"] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "t.calculateArea"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "100", @FloatLiteral = false, @Image = "100", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "100", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 100, @ValueAsLong = 100] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Large triangle"", @FloatLiteral = false, @Image = ""Large triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Large triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A shape, possibly a small triangle"", @FloatLiteral = false, @Image = ""A shape, possibly a small triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A shape, possibly a small triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testTriangleRefined2", @Modifiers = 16, @Name = "testTriangleRefined2", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "testTriangleRefined2", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Shape"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "s"] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- GuardedPattern[@ParenthesisDepth = 0] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] + | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] + | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "t", @LambdaParameter = false, @LocalVariable = false, @Name = "t", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "t"] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- RelationalExpression[@Image = ">"] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "t.calculateArea"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "100", @FloatLiteral = false, @Image = "100", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "100", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 100, @ValueAsLong = 100] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Large triangle"", @FloatLiteral = false, @Image = ""Large triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Large triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "t", @LambdaParameter = false, @LocalVariable = false, @Name = "t", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "t"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Small triangle"", @FloatLiteral = false, @Image = ""Small triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Small triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledExpression[] + | +- SwitchLabel[@Default = true] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Non-triangle"", @FloatLiteral = false, @Image = ""Non-triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Non-triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] + +- ResultType[@Void = true, @returnsArray = false] + +- MethodDeclarator[@Image = "main", @ParameterCount = 1] + | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] + | | +- ReferenceType[@Array = true, @ArrayDepth = 1] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] + +- Block[@containsComment = false] + +- BlockStatement[@Allocation = true] + | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "large", @Volatile = false] + | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] + | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] + | +- VariableDeclarator[@Initializer = true, @Name = "large"] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "large", @LambdaParameter = false, @LocalVariable = true, @Name = "large", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "large"] + | +- VariableInitializer[] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "200", @FloatLiteral = false, @Image = "200", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "200", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 200, @ValueAsLong = 200] + +- BlockStatement[@Allocation = true] + | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "small", @Volatile = false] + | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] + | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] + | +- VariableDeclarator[@Initializer = true, @Name = "small"] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "small", @LambdaParameter = false, @LocalVariable = true, @Name = "small", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "small"] + | +- VariableInitializer[] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "10", @FloatLiteral = false, @Image = "10", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "10", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 10, @ValueAsLong = 10] + +- BlockStatement[@Allocation = true] + | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "rect", @Volatile = false] + | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Rectangle"] + | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Rectangle", @ReferenceToClassSameCompilationUnit = true] + | +- VariableDeclarator[@Initializer = true, @Name = "rect"] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "rect", @LambdaParameter = false, @LocalVariable = true, @Name = "rect", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "rect"] + | +- VariableInitializer[] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- AllocationExpression[@AnonymousClass = false] + | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Rectangle", @ReferenceToClassSameCompilationUnit = true] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testTriangle"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "large"] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testTriangle"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "small"] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testTriangle"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "rect"] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testTriangleRefined"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "large"] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testTriangleRefined"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "small"] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testTriangleRefined"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "rect"] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testTriangleRefined2"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "large"] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "testTriangleRefined2"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "small"] + +- BlockStatement[@Allocation = false] + +- Statement[] + +- StatementExpression[] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "testTriangleRefined2"] + +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + +- Arguments[@ArgumentCount = 1, @Size = 1] + +- ArgumentList[@Size = 1] + +- Expression[@StandAlonePrimitive = false] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + +- Name[@Image = "rect"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.java new file mode 100644 index 0000000000..06c77ea661 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.java @@ -0,0 +1,48 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +/** + * @see JEP 420: Pattern Matching for switch (Second Preview) + */ +public class ScopeOfPatternVariableDeclarations { + + + static void test(Object o) { + switch (o) { + case Character c -> { + if (c.charValue() == 7) { + System.out.println("Ding!"); + } + System.out.println("Character"); + } + case Integer i -> + throw new IllegalStateException("Invalid Integer argument of value " + i.intValue()); + default -> { + break; + } + } + } + + + static void test2(Object o) { + switch (o) { + case Character c: + if (c.charValue() == 7) { + System.out.print("Ding "); + } + if (c.charValue() == 9) { + System.out.print("Tab "); + } + System.out.println("character"); + default: + System.out.println(); + } + } + + + public static void main(String[] args) { + test('A'); + test2('\t'); + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.txt new file mode 100644 index 0000000000..1a11900d39 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.txt @@ -0,0 +1,241 @@ ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] + +- TypeDeclaration[] + +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ScopeOfPatternVariableDeclarations", @Default = false, @Final = false, @Image = "ScopeOfPatternVariableDeclarations", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "ScopeOfPatternVariableDeclarations", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] + +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test", @Modifiers = 16, @Name = "test", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "test", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = true] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabeledBlock[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Character"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Character", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] + | | +- Block[@containsComment = false] + | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- IfStatement[@Else = false] + | | | +- Expression[@StandAlonePrimitive = false] + | | | | +- EqualityExpression[@Image = "==", @Operator = "=="] + | | | | +- PrimaryExpression[] + | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | | +- Name[@Image = "c.charValue"] + | | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "7", @FloatLiteral = false, @Image = "7", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "7", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 7, @ValueAsLong = 7] + | | | +- Statement[] + | | | +- Block[@containsComment = false] + | | | +- BlockStatement[@Allocation = false] + | | | +- Statement[] + | | | +- StatementExpression[] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | +- Name[@Image = "System.out.println"] + | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | | +- ArgumentList[@Size = 1] + | | | +- Expression[@StandAlonePrimitive = false] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Ding!"", @FloatLiteral = false, @Image = ""Ding!"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Ding!"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Character"", @FloatLiteral = false, @Image = ""Character"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Character"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabeledThrowStatement[] + | | +- SwitchLabel[@Default = false] + | | | +- TypePattern[@ParenthesisDepth = 0] + | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] + | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] + | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] + | | +- ThrowStatement[@FirstClassOrInterfaceTypeImage = "IllegalStateException"] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- AllocationExpression[@AnonymousClass = false] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "IllegalStateException", @ReferenceToClassSameCompilationUnit = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- AdditiveExpression[@Image = "+", @Operator = "+"] + | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Invalid Integer argument of value "", @FloatLiteral = false, @Image = ""Invalid Integer argument of value "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Invalid Integer argument of value "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "i.intValue"] + | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | +- SwitchLabeledBlock[] + | +- SwitchLabel[@Default = true] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- BreakStatement[] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test2", @Modifiers = 16, @Name = "test2", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] + | +- ResultType[@Void = true, @returnsArray = false] + | +- MethodDeclarator[@Image = "test2", @ParameterCount = 1] + | | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] + | +- Block[@containsComment = false] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] + | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "o"] + | +- SwitchLabel[@Default = false] + | | +- TypePattern[@ParenthesisDepth = 0] + | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Character"] + | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Character", @ReferenceToClassSameCompilationUnit = false] + | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- IfStatement[@Else = false] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- EqualityExpression[@Image = "==", @Operator = "=="] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "c.charValue"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "7", @FloatLiteral = false, @Image = "7", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "7", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 7, @ValueAsLong = 7] + | | +- Statement[] + | | +- Block[@containsComment = false] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.print"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Ding "", @FloatLiteral = false, @Image = ""Ding "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Ding "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- IfStatement[@Else = false] + | | +- Expression[@StandAlonePrimitive = false] + | | | +- EqualityExpression[@Image = "==", @Operator = "=="] + | | | +- PrimaryExpression[] + | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | | | +- Name[@Image = "c.charValue"] + | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] + | | | +- PrimaryExpression[] + | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "9", @FloatLiteral = false, @Image = "9", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "9", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 9, @ValueAsLong = 9] + | | +- Statement[] + | | +- Block[@containsComment = false] + | | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.print"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Tab "", @FloatLiteral = false, @Image = ""Tab "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Tab "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- BlockStatement[@Allocation = false] + | | +- Statement[] + | | +- StatementExpression[] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | | +- Name[@Image = "System.out.println"] + | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | | +- Arguments[@ArgumentCount = 1, @Size = 1] + | | +- ArgumentList[@Size = 1] + | | +- Expression[@StandAlonePrimitive = false] + | | +- PrimaryExpression[] + | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""character"", @FloatLiteral = false, @Image = ""character"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""character"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- SwitchLabel[@Default = true] + | +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "System.out.println"] + | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] + +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] + +- ResultType[@Void = true, @returnsArray = false] + +- MethodDeclarator[@Image = "main", @ParameterCount = 1] + | +- FormalParameters[@ParameterCount = 1, @Size = 1] + | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] + | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] + | | +- ReferenceType[@Array = true, @ArrayDepth = 1] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] + +- Block[@containsComment = false] + +- BlockStatement[@Allocation = false] + | +- Statement[] + | +- StatementExpression[] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | | +- Name[@Image = "test"] + | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 1, @Size = 1] + | +- ArgumentList[@Size = 1] + | +- Expression[@StandAlonePrimitive = true] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = true, @DoubleLiteral = false, @EscapedStringLiteral = "'A'", @FloatLiteral = false, @Image = "'A'", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "'A'", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + +- BlockStatement[@Allocation = false] + +- Statement[] + +- StatementExpression[] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "test2"] + +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] + +- Arguments[@ArgumentCount = 1, @Size = 1] + +- ArgumentList[@Size = 1] + +- Expression[@StandAlonePrimitive = true] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + +- Literal[@CharLiteral = true, @DoubleLiteral = false, @EscapedStringLiteral = "' '", @FloatLiteral = false, @Image = "' '", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "' '", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] From 07549b1283165009d1c592ce8e3e3db28996bf37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 26 Feb 2022 22:50:56 +0100 Subject: [PATCH 24/89] Remove old symbol table --- .../pmd/lang/java/ast/ASTCompilationUnit.java | 9 - .../lang/java/ast/ASTFieldDeclaration.java | 4 +- .../pmd/lang/java/ast/ASTPrimitiveType.java | 13 - .../java/ast/ASTVariableDeclaratorId.java | 37 +- .../pmd/lang/java/ast/AbstractJavaNode.java | 19 +- .../pmd/lang/java/ast/InternalApiBridge.java | 48 -- .../pmd/lang/java/ast/JavaNode.java | 3 +- .../lang/java/ast/internal/ImportWrapper.java | 148 ----- .../java/symboltable/AbstractJavaScope.java | 53 -- .../symboltable/ClassNameDeclaration.java | 52 -- .../pmd/lang/java/symboltable/ClassScope.java | 615 ------------------ .../DeclarationFinderFunction.java | 51 -- .../java/symboltable/JavaNameOccurrence.java | 232 ------- .../pmd/lang/java/symboltable/LocalScope.java | 71 -- .../symboltable/MethodNameDeclaration.java | 121 ---- .../lang/java/symboltable/MethodScope.java | 84 --- .../pmd/lang/java/symboltable/NameFinder.java | 98 --- .../java/symboltable/OccurrenceFinder.java | 96 --- .../ScopeAndDeclarationFinder.java | 298 --------- .../pmd/lang/java/symboltable/Search.java | 71 -- .../SimpleTypedNameDeclaration.java | 194 ------ .../java/symboltable/SourceFileScope.java | 167 ----- .../lang/java/symboltable/SymbolFacade.java | 23 - .../pmd/lang/java/symboltable/TypeSet.java | 564 ---------------- .../symboltable/TypedNameDeclaration.java | 20 - .../symboltable/VariableNameDeclaration.java | 143 ---- .../lang/java/symboltable/package-info.java | 8 - .../lang/java/ast/AllJavaAstTreeDumpTest.java | 1 + .../pmd/lang/java/ast/Java14Test.java | 190 ------ .../pmd/lang/java/ast/Java14TreeDumpTest.java | 70 ++ .../pmd/lang/java/ast/Java16TreeDumpTest.java | 16 +- .../pmd/lang/java/ast/ParserCornersTest.java | 70 +- .../lang/java/symboltable/AcceptanceTest.java | 191 ------ .../lang/java/symboltable/ClassScopeTest.java | 381 ----------- .../java/symboltable/GlobalScopeTest.java | 45 -- .../symboltable/ImageFinderFunctionTest.java | 50 -- .../lang/java/symboltable/LocalScopeTest.java | 101 --- .../MethodNameDeclarationTest.java | 39 -- .../java/symboltable/MethodScopeTest.java | 56 -- .../java/symboltable/NameOccurrencesTest.java | 132 ---- .../ScopeAndDeclarationFinderTest.java | 94 --- .../symboltable/ScopeCreationVisitorTest.java | 35 - .../SimpleTypedNameDeclarationTest.java | 88 --- .../java/symboltable/SourceFileScopeTest.java | 62 -- .../lang/java/symboltable/TypeSetTest.java | 204 ------ .../VariableNameDeclarationTest.java | 180 ----- .../java/symboltable/testdata/InnerClass.java | 26 - .../pmd/lang/java/types/AstTestUtil.kt | 30 + .../lang/java/types/TypeTestMockingUtil.kt | 20 - .../java/ast/MethodReferenceConfused.java | 15 +- 50 files changed, 158 insertions(+), 5180 deletions(-) delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/ImportWrapper.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassNameDeclaration.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/DeclarationFinderFunction.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/JavaNameOccurrence.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/LocalScope.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/MethodNameDeclaration.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/MethodScope.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/NameFinder.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/OccurrenceFinder.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinder.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/Search.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SimpleTypedNameDeclaration.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SourceFileScope.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SymbolFacade.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypeSet.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypedNameDeclaration.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/VariableNameDeclaration.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/package-info.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14Test.java create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14TreeDumpTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/AcceptanceTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ClassScopeTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/GlobalScopeTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ImageFinderFunctionTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/LocalScopeTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/MethodNameDeclarationTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/MethodScopeTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/NameOccurrencesTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinderTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeCreationVisitorTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/SimpleTypedNameDeclarationTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/SourceFileScopeTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/TypeSetTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/VariableNameDeclarationTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/testdata/InnerClass.java create mode 100644 pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/AstTestUtil.kt diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTCompilationUnit.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTCompilationUnit.java index 15e057330a..c50bb27f76 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTCompilationUnit.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTCompilationUnit.java @@ -9,13 +9,11 @@ import java.util.List; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.AstInfo; import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.ast.RootNode; import net.sourceforge.pmd.lang.ast.impl.GenericNode; import net.sourceforge.pmd.lang.java.symbols.table.JSymbolTable; -import net.sourceforge.pmd.lang.java.typeresolution.ClassTypeResolver; import net.sourceforge.pmd.lang.java.types.TypeSystem; import net.sourceforge.pmd.lang.java.types.ast.LazyTypeResolver; @@ -90,13 +88,6 @@ public final class ASTCompilationUnit extends AbstractJavaTypeNode implements Ja return children(ASTAnyTypeDeclaration.class); } - - @InternalApi - @Deprecated - public ClassTypeResolver getClassTypeResolver() { - return new ClassTypeResolver(); - } - @Override public @NonNull JSymbolTable getSymbolTable() { assert symbolTable != null : "Symbol table wasn't set"; 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 9c164b2242..877b5f7000 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 @@ -14,8 +14,8 @@ import net.sourceforge.pmd.lang.rule.xpath.DeprecatedAttribute; * Represents a field declaration in the body of a type declaration. * *

This declaration may define several variables, possibly of different - * types (see {@link ASTVariableDeclaratorId#getType()}). The nodes - * corresponding to the declared variables are accessible through {@link #iterator()}. + * types. The nodes corresponding to the declared variables are accessible + * through {@link #iterator()}. * *

  *
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPrimitiveType.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPrimitiveType.java
index e2f5b1eeb7..47dcf4a460 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPrimitiveType.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPrimitiveType.java
@@ -6,8 +6,6 @@ package net.sourceforge.pmd.lang.java.ast;
 
 import org.checkerframework.checker.nullness.qual.NonNull;
 
-import net.sourceforge.pmd.annotation.InternalApi;
-import net.sourceforge.pmd.lang.java.symboltable.ClassScope;
 import net.sourceforge.pmd.lang.java.types.JPrimitiveType;
 import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind;
 
@@ -25,17 +23,6 @@ public final class ASTPrimitiveType extends AbstractJavaTypeNode implements ASTT
 
     private PrimitiveTypeKind kind;
 
-    /**
-     * @deprecated Made public for one shady usage in {@link ClassScope}
-     */
-    @Deprecated
-    @InternalApi
-    public ASTPrimitiveType(PrimitiveTypeKind type) {
-        super(JavaParserImplTreeConstants.JJTPRIMITIVETYPE);
-        setKind(type);
-    }
-
-
     ASTPrimitiveType(int id) {
         super(id);
     }
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 5a25cbe9da..2864573ea8 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
@@ -11,13 +11,10 @@ import java.util.List;
 import org.checkerframework.checker.nullness.qual.NonNull;
 import org.checkerframework.checker.nullness.qual.Nullable;
 
-import net.sourceforge.pmd.annotation.InternalApi;
 import net.sourceforge.pmd.lang.ast.Node;
 import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr;
 import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol;
-import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
 import net.sourceforge.pmd.lang.rule.xpath.DeprecatedAttribute;
-import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
 
 // @formatter:off
 /**
@@ -33,13 +30,9 @@ import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
  *    
  • Resource declarations occurring in try-with-resources statements. * * - *

    Since this node conventionally represents the declared variable in PMD, our symbol table - * populates it with a {@link VariableNameDeclaration}, and its usages can be accessed through - * the method {@link #getUsages()}. - * - *

    Type resolution assigns the type of the variable to this node. See {@link #getType()}'s - * documentation for the contract of this method. - * + *

    Since this node conventionally represents the declared variable in PMD, + * it owns a {@link JVariableSymbol} and can provide access to + * {@linkplain #getLocalUsages() variable usages}. * *

      *
    @@ -51,8 +44,6 @@ import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
     // @formatter:on
     public final class ASTVariableDeclaratorId extends AbstractTypedSymbolDeclarator implements AccessNode, SymbolDeclaratorNode, FinalizableNode {
     
    -    private VariableNameDeclaration nameDeclaration;
    -
         private List usages = Collections.emptyList();
     
         ASTVariableDeclaratorId(int id) {
    @@ -64,28 +55,6 @@ public final class ASTVariableDeclaratorId extends AbstractTypedSymbolDeclarator
             return visitor.visit(this, data);
         }
     
    -    /**
    -     * Note: this might be null in certain cases.
    -     */
    -    public VariableNameDeclaration getNameDeclaration() {
    -        return nameDeclaration;
    -    }
    -
    -    @InternalApi
    -    @Deprecated
    -    public void setNameDeclaration(VariableNameDeclaration decl) {
    -        nameDeclaration = decl;
    -    }
    -
    -    /**
    -     * @deprecated transitional, use {@link #getLocalUsages()}
    -     */
    -    @Deprecated
    -    public List getUsages() {
    -        return getScope().getDeclarations(VariableNameDeclaration.class)
    -                         .getOrDefault(nameDeclaration, Collections.emptyList());
    -    }
    -
         /**
          * Returns an unmodifiable list of the usages of this variable that
          * are made in this file. Note that for a record component, this returns
    diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java
    index d4b60ac96f..523cf73f03 100644
    --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java
    +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java
    @@ -12,11 +12,9 @@ import net.sourceforge.pmd.lang.ast.impl.javacc.AbstractJjtreeNode;
     import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken;
     import net.sourceforge.pmd.lang.java.symbols.table.JSymbolTable;
     import net.sourceforge.pmd.lang.java.types.TypeSystem;
    -import net.sourceforge.pmd.lang.symboltable.Scope;
     
     abstract class AbstractJavaNode extends AbstractJjtreeNode implements JavaNode {
     
    -    private Scope scope;
         protected JSymbolTable symbolTable;
         private ASTCompilationUnit root;
     
    @@ -97,8 +95,7 @@ abstract class AbstractJavaNode extends AbstractJjtreeNode= 0; i--) {
    -            ASTFormalParameter formalParameter = new ASTFormalParameter(0);
    -            formalParameters.addChild(formalParameter, i);
    -
    -            ASTVariableDeclaratorId variableDeclaratorId = new ASTVariableDeclaratorId(0);
    -            variableDeclaratorId.setImage("arg" + i);
    -            formalParameter.addChild(variableDeclaratorId, 1);
    -
    -            PrimitiveTypeKind primitive = PrimitiveTypeKind.fromName(parameterTypes[i]);
    -            // TODO : this could actually be a primitive array...
    -            AbstractJavaNode type = primitive != null
    -                           ? new ASTPrimitiveType(primitive)
    -                           : new ASTClassOrInterfaceType(parameterTypes[i]);
    -
    -            formalParameter.addChild(type, 0);
    -        }
    -
    -        return methodDeclaration;
    -    }
    -
         public static JavaccTokenDocument javaTokenDoc(String fullText) {
             return new JavaTokenDocument(fullText);
         }
    @@ -216,10 +172,6 @@ public final class InternalApiBridge {
             ((AbstractJavaNode) node).setSymbolTable(table);
         }
     
    -    public static void setScope(JavaNode node, Scope scope) {
    -        ((AbstractJavaNode) node).setScope(scope);
    -    }
    -
         public static void setQname(ASTAnyTypeDeclaration declaration, String binaryName, @Nullable String canon) {
             ((AbstractAnyTypeDeclaration) declaration).setBinaryName(binaryName, canon);
         }
    diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaNode.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaNode.java
    index d91a102706..0b09974992 100644
    --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaNode.java
    +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaNode.java
    @@ -12,13 +12,12 @@ import net.sourceforge.pmd.lang.ast.AstVisitor;
     import net.sourceforge.pmd.lang.ast.impl.javacc.JjtreeNode;
     import net.sourceforge.pmd.lang.java.symbols.table.JSymbolTable;
     import net.sourceforge.pmd.lang.java.types.TypeSystem;
    -import net.sourceforge.pmd.lang.symboltable.ScopedNode;
     
     
     /**
      * Root interface for all Nodes of the Java AST.
      */
    -public interface JavaNode extends JjtreeNode, ScopedNode {
    +public interface JavaNode extends JjtreeNode {
     
         /**
          * Calls back the visitor's visit method corresponding to the runtime type of this Node.
    diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/ImportWrapper.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/ImportWrapper.java
    deleted file mode 100644
    index a3b15bd4fe..0000000000
    --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/ImportWrapper.java
    +++ /dev/null
    @@ -1,148 +0,0 @@
    -/*
    - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    - */
    -
    -
    -package net.sourceforge.pmd.lang.java.ast.internal;
    -
    -import java.lang.reflect.Field;
    -import java.lang.reflect.Method;
    -import java.lang.reflect.Modifier;
    -import java.util.Collections;
    -import java.util.HashSet;
    -import java.util.Objects;
    -import java.util.Set;
    -
    -import org.slf4j.Logger;
    -import org.slf4j.LoggerFactory;
    -
    -import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
    -
    -/**
    - * Helper class to analyze {@link ASTImportDeclaration}s.
    - */
    -public final class ImportWrapper {
    -    private static final Logger LOG = LoggerFactory.getLogger(ImportWrapper.class);
    -
    -    private final ASTImportDeclaration node;
    -    private final String name;
    -    private final String fullname;
    -    private final Set allStaticDemands;
    -
    -    public ImportWrapper(ASTImportDeclaration node) {
    -        this.node = node;
    -        this.fullname = node.getImportedName();
    -        this.name = node.getImportedSimpleName();
    -        this.allStaticDemands = collectStaticFieldsAndMethods(node);
    -    }
    -
    -    /**
    -     * @param node
    -     */
    -    private Set collectStaticFieldsAndMethods(ASTImportDeclaration node) {
    -        if (!isStaticOnDemand() || node == null) {
    -            return Collections.emptySet();
    -        }
    -
    -        // This was edited during the grammar updating process, because
    -        // ImportDeclaration is not a TypeNode anymore, and there is no Name anymore.
    -        // If tests are failing, refer to the history of this file to get the
    -        // previously working version.
    -        Class type = null;
    -        if (node != null) {
    -            type = node.getRoot().getClassTypeResolver().loadClassOrNull(node.getImportedName());
    -        }
    -
    -        if (type == null) {
    -            return Collections.emptySet();
    -        }
    -
    -        try {
    -            Set names = new HashSet<>();
    -            while (type != null) {
    -                // consider static fields, public and non-public
    -                for (Field f : type.getDeclaredFields()) {
    -                    if (Modifier.isStatic(f.getModifiers())) {
    -                        names.add(f.getName());
    -                    }
    -                }
    -                // and methods, too
    -                for (Method m : type.getDeclaredMethods()) {
    -                    if (Modifier.isStatic(m.getModifiers())) {
    -                        names.add(m.getName());
    -                    }
    -                }
    -
    -                // consider statics of super classes as well
    -                type = type.getSuperclass();
    -            }
    -            return names;
    -        } catch (LinkageError e) {
    -            // This is an incomplete classpath, report the missing class
    -            LOG.debug("Possible incomplete auxclasspath: Error while processing imports", e);
    -            return Collections.emptySet();
    -        }
    -    }
    -
    -
    -
    -    public boolean matches(String fullName, String name) {
    -        if (isStaticOnDemand()) {
    -            if (allStaticDemands.contains(fullName)) {
    -                return true;
    -            }
    -        }
    -        if (this.name == null && name == null) {
    -            return fullName.equals(fullname);
    -        }
    -        return name.equals(this.name);
    -    }
    -
    -    @Override
    -    public boolean equals(Object o) {
    -        if (this == o) {
    -            return true;
    -        }
    -        if (o == null || getClass() != o.getClass()) {
    -            return false;
    -        }
    -        ImportWrapper that = (ImportWrapper) o;
    -        return Objects.equals(node.isStatic(), that.node.isStatic())
    -            && Objects.equals(isOnDemand(), that.isOnDemand())
    -            && Objects.equals(node.getImportedName(), that.node.getImportedName());
    -    }
    -
    -    @Override
    -    public int hashCode() {
    -        return Objects.hash(node.isStatic(), node.isImportOnDemand(), node.getImportedName());
    -    }
    -
    -    public String getName() {
    -        return name;
    -    }
    -
    -    public String getPackageName() {
    -        return node.getPackageName();
    -    }
    -
    -    public String getFullName() {
    -        return fullname;
    -    }
    -
    -    public ASTImportDeclaration getNode() {
    -        return node;
    -    }
    -
    -    public boolean isStaticOnDemand() {
    -        return node.isStatic() && node.isImportOnDemand();
    -    }
    -
    -    @Override
    -    public String toString() {
    -        return "Import[name=" + name + ",fullname=" + fullname + ",static*=" + isStaticOnDemand() + ']';
    -    }
    -
    -    public boolean isOnDemand() {
    -        return node.isImportOnDemand();
    -    }
    -}
    diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java
    deleted file mode 100644
    index a189768370..0000000000
    --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.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.symboltable;
    -
    -import java.util.Set;
    -
    -import net.sourceforge.pmd.annotation.InternalApi;
    -import net.sourceforge.pmd.lang.symboltable.AbstractScope;
    -import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
    -import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
    -
    -/**
    - * Provides the basic java scope implementation.
    - *
    - * @see JLS 6.3
    - */
    -@Deprecated
    -@InternalApi
    -public abstract class AbstractJavaScope extends AbstractScope {
    -
    -    @Override
    -    public void addDeclaration(NameDeclaration declaration) {
    -        checkForDuplicatedNameDeclaration(declaration);
    -        super.addDeclaration(declaration);
    -    }
    -
    -    protected void checkForDuplicatedNameDeclaration(NameDeclaration declaration) {
    -        if (declaration instanceof VariableNameDeclaration && getDeclarations().keySet().contains(declaration)) {
    -            // don't throw anymore
    -            // Scopes will be removed before 7.0, and this sometimes triggers for no reason
    -            // because Scopes were not ported to the newer grammar
    -            // throw new RuntimeException(declaration + " is already in the symbol table");
    -        }
    -    }
    -
    -    @Override
    -    public boolean contains(NameOccurrence occurrence) {
    -        return !findVariableHere((JavaNameOccurrence) occurrence).isEmpty();
    -    }
    -
    -    protected abstract Set findVariableHere(JavaNameOccurrence occurrence);
    -
    -    protected  String glomNames(Set s) {
    -        StringBuilder result = new StringBuilder();
    -        for (T t : s) {
    -            result.append(t.toString());
    -            result.append(',');
    -        }
    -        return result.length() == 0 ? "" : result.toString().substring(0, result.length() - 1);
    -    }
    -}
    diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassNameDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassNameDeclaration.java
    deleted file mode 100644
    index f4909fa755..0000000000
    --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassNameDeclaration.java
    +++ /dev/null
    @@ -1,52 +0,0 @@
    -/**
    - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    - */
    -
    -package net.sourceforge.pmd.lang.java.symboltable;
    -
    -import net.sourceforge.pmd.lang.ast.Node;
    -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
    -import net.sourceforge.pmd.lang.java.ast.JavaNode;
    -import net.sourceforge.pmd.lang.java.ast.TypeNode;
    -import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil;
    -import net.sourceforge.pmd.lang.symboltable.AbstractNameDeclaration;
    -
    -public class ClassNameDeclaration extends AbstractNameDeclaration implements TypedNameDeclaration {
    -
    -    public ClassNameDeclaration(JavaNode node) {
    -        super(node);
    -    }
    -
    -    @Override
    -    public String toString() {
    -        if (node instanceof ASTAnyTypeDeclaration) {
    -            return PrettyPrintingUtil.getPrintableNodeKind((ASTAnyTypeDeclaration) node) + node.getImage();
    -        }
    -        return "anonymous";
    -    }
    -
    -    public Node getAccessNodeParent() {
    -        return node;
    -    }
    -
    -    @Override
    -    public String getTypeImage() {
    -        return getTypeNode().getImage();
    -    }
    -
    -    @Override
    -    public Class getType() {
    -        if (node instanceof ASTAnyTypeDeclaration) {
    -            return ((ASTAnyTypeDeclaration) node).getType();
    -        }
    -        return null;
    -    }
    -
    -    /**
    -     * Null for anonymous classes.
    -     */
    -    @Override
    -    public TypeNode getTypeNode() {
    -        return node instanceof TypeNode ? (TypeNode) node : null;
    -    }
    -}
    diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java
    deleted file mode 100644
    index be83d084e2..0000000000
    --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java
    +++ /dev/null
    @@ -1,615 +0,0 @@
    -/**
    - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    - */
    -
    -package net.sourceforge.pmd.lang.java.symboltable;
    -
    -import static net.sourceforge.pmd.lang.java.ast.InternalApiBridge.createBuiltInMethodDeclaration;
    -
    -import java.util.ArrayList;
    -import java.util.Collections;
    -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.ast.Node;
    -import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
    -import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
    -import net.sourceforge.pmd.lang.java.ast.ASTBodyDeclaration;
    -import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral;
    -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
    -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
    -import net.sourceforge.pmd.lang.java.ast.ASTExtendsList;
    -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
    -import net.sourceforge.pmd.lang.java.ast.ASTImplementsList;
    -import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
    -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
    -import net.sourceforge.pmd.lang.java.ast.ASTName;
    -import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
    -import net.sourceforge.pmd.lang.java.ast.ASTTypeParameter;
    -import net.sourceforge.pmd.lang.java.ast.ASTTypeParameters;
    -import net.sourceforge.pmd.lang.java.ast.InternalApiBridge;
    -import net.sourceforge.pmd.lang.symboltable.Applier;
    -import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction;
    -import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
    -import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
    -import net.sourceforge.pmd.lang.symboltable.Scope;
    -
    -/**
    - * This scope represents one Java class. It can have variable declarations,
    - * method declarations and inner class declarations.
    - */
    -public class ClassScope extends AbstractJavaScope {
    -
    -    // FIXME - this breaks given sufficiently nested code
    -    private static ThreadLocal anonymousInnerClassCounter = new ThreadLocal() {
    -        @Override
    -        protected Integer initialValue() {
    -            return Integer.valueOf(1);
    -        }
    -    };
    -
    -    private final String className;
    -
    -    private boolean isEnum;
    -
    -    /**
    -     * The current class scope declaration. Technically it belongs to out parent scope,
    -     * but knowing it we can better resolve this, super and direct class references such as Foo.X
    -     */
    -    private final ClassNameDeclaration classDeclaration;
    -
    -    public ClassScope(final String className, final ClassNameDeclaration classNameDeclaration) {
    -        this.className = Objects.requireNonNull(className);
    -        anonymousInnerClassCounter.set(Integer.valueOf(1));
    -        this.classDeclaration = classNameDeclaration;
    -    }
    -
    -    /**
    -     * This is only for anonymous inner classes.
    -     *
    -     * 

    FIXME - should have name like Foo$1, not Anonymous$1 to get this working - * right, the parent scope needs to be passed in when instantiating a - * ClassScope

    - * - * @param classNameDeclaration The declaration of this class, as known to the parent scope. - */ - public ClassScope(final ClassNameDeclaration classNameDeclaration) { - // this.className = getParent().getEnclosingClassScope().getClassName() - // + "$" + String.valueOf(anonymousInnerClassCounter); - int v = anonymousInnerClassCounter.get(); - this.className = "Anonymous$" + v; - anonymousInnerClassCounter.set(v + 1); - classDeclaration = classNameDeclaration; - } - - public ClassNameDeclaration getClassDeclaration() { - return classDeclaration; - } - - public void setIsEnum(boolean isEnum) { - this.isEnum = isEnum; - } - - public Map> getClassDeclarations() { - return getDeclarations(ClassNameDeclaration.class); - } - - public Map> getMethodDeclarations() { - return getDeclarations(MethodNameDeclaration.class); - } - - public Map> getVariableDeclarations() { - return getDeclarations(VariableNameDeclaration.class); - } - - @Override - public Set addNameOccurrence(NameOccurrence occurrence) { - JavaNameOccurrence javaOccurrence = (JavaNameOccurrence) occurrence; - Set declarations = findVariableHere(javaOccurrence); - if (!declarations.isEmpty() - && (javaOccurrence.isMethodOrConstructorInvocation() || javaOccurrence.isMethodReference())) { - for (NameDeclaration decl : declarations) { - List nameOccurrences = getMethodDeclarations().get(decl); - if (nameOccurrences == null) { - // TODO may be a class name: Foo.this.super(); - - // search inner classes - for (ClassNameDeclaration innerClass : getClassDeclarations().keySet()) { - Scope innerClassScope = innerClass.getScope(); - if (innerClassScope.contains(javaOccurrence)) { - innerClassScope.addNameOccurrence(javaOccurrence); - } - } - } else { - nameOccurrences.add(javaOccurrence); - Node n = javaOccurrence.getLocation(); - if (n instanceof ASTName) { - ((ASTName) n).setNameDeclaration(decl); - } // TODO what to do with PrimarySuffix case? - } - } - } else if (!declarations.isEmpty() && !javaOccurrence.isThisOrSuper()) { - for (NameDeclaration decl : declarations) { - List nameOccurrences = getVariableDeclarations().get(decl); - if (nameOccurrences == null) { - // TODO may be a class name - - // search inner classes - for (ClassNameDeclaration innerClass : getClassDeclarations().keySet()) { - Scope innerClassScope = innerClass.getScope(); - if (innerClassScope.contains(javaOccurrence)) { - innerClassScope.addNameOccurrence(javaOccurrence); - } - } - } else { - nameOccurrences.add(javaOccurrence); - Node n = javaOccurrence.getLocation(); - if (n instanceof ASTName) { - ((ASTName) n).setNameDeclaration(decl); - } // TODO what to do with PrimarySuffix case? - } - } - } - return declarations; - } - - public String getClassName() { - return this.className; - } - - @Override - protected Set findVariableHere(JavaNameOccurrence occurrence) { - if (occurrence.isThisOrSuper() || className.equals(occurrence.getImage())) { - // Reference to ourselves! - return Collections.singleton(classDeclaration); - } - - Map> methodDeclarations = getMethodDeclarations(); - Set result = new HashSet<>(); - if (occurrence.isMethodOrConstructorInvocation()) { - final boolean hasAuxclasspath = getEnclosingScope(SourceFileScope.class).hasAuxclasspath(); - matchMethodDeclaration(occurrence, methodDeclarations.keySet(), hasAuxclasspath, result); - - if (isEnum && "valueOf".equals(occurrence.getImage())) { - ASTMethodDeclaration declarator = createBuiltInMethodDeclaration("valueOf", "String"); - InternalApiBridge.setScope(declarator, this); - result.add(new MethodNameDeclaration(declarator)); - } - - if (result.isEmpty()) { - for (ClassNameDeclaration innerClass : getClassDeclarations().keySet()) { - matchMethodDeclaration(occurrence, innerClass.getScope().getDeclarations(MethodNameDeclaration.class).keySet(), hasAuxclasspath, result); - } - } - return result; - } - if (occurrence.isMethodReference()) { - for (MethodNameDeclaration mnd : methodDeclarations.keySet()) { - if (mnd.getImage().equals(occurrence.getImage())) { - result.add(mnd); - } - } - return result; - } - - List images = new ArrayList<>(); - if (occurrence.getImage() != null) { - images.add(occurrence.getImage()); - if (occurrence.getImage().startsWith(className)) { - images.add(clipClassName(occurrence.getImage())); - } - } - - Map> variableDeclarations = getVariableDeclarations(); - ImageFinderFunction finder = new ImageFinderFunction(images); - Applier.apply(finder, variableDeclarations.keySet().iterator()); - if (finder.getDecl() != null) { - result.add(finder.getDecl()); - } - - // search references to inner classes - Map> classDeclarations = getClassDeclarations(); - if (result.isEmpty() && !classDeclarations.isEmpty()) { - Applier.apply(finder, classDeclarations.keySet().iterator()); - if (finder.getDecl() != null) { - result.add(finder.getDecl()); - } - for (ClassNameDeclaration innerClass : getClassDeclarations().keySet()) { - Applier.apply(finder, innerClass.getScope().getDeclarations(VariableNameDeclaration.class).keySet().iterator()); - if (finder.getDecl() != null) { - result.add(finder.getDecl()); - } - } - } - return result; - } - - private void matchMethodDeclaration(JavaNameOccurrence occurrence, - Set methodDeclarations, final boolean hasAuxclasspath, - Set result) { - for (MethodNameDeclaration mnd : methodDeclarations) { - if (mnd.getImage().equals(occurrence.getImage())) { - List parameterTypes = determineParameterTypes(mnd); - List argumentTypes = determineArgumentTypes(occurrence, parameterTypes); - - if (!mnd.isVarargs() && occurrence.getArgumentCount() == mnd.getParameterCount() - && (!hasAuxclasspath || parameterTypes.equals(argumentTypes))) { - result.add(mnd); - } else if (mnd.isVarargs()) { - int varArgIndex = parameterTypes.size() - 1; - TypedNameDeclaration varArgType = parameterTypes.get(varArgIndex); - - // first parameter is varArg, calling method might have - // 0 or more arguments - // or the calling method has enough arguments to fill in - // the parameters before the vararg - if ((varArgIndex == 0 || argumentTypes.size() >= varArgIndex) - && (!hasAuxclasspath || parameterTypes - .subList(0, varArgIndex).equals(argumentTypes.subList(0, varArgIndex)))) { - - if (!hasAuxclasspath) { - result.add(mnd); - continue; - } - - boolean sameType = true; - for (int i = varArgIndex; i < argumentTypes.size(); i++) { - if (!varArgType.equals(argumentTypes.get(i))) { - sameType = false; - break; - } - } - if (sameType) { - result.add(mnd); - } - } - } - } - } - } - - /** - * Provide a list of types of the parameters of the given method - * declaration. The types are simple type images. - * - * @param mnd - * the method declaration. - * @return List of types - */ - private List determineParameterTypes(MethodNameDeclaration mnd) { - List parameters = mnd.getDeclarator() - .getFormalParameters() - .findChildrenOfType(ASTFormalParameter.class); - if (parameters.isEmpty()) { - return Collections.emptyList(); - } - - List parameterTypes = new ArrayList<>(parameters.size()); - SourceFileScope fileScope = getEnclosingScope(SourceFileScope.class); - Map qualifiedTypeNames = fileScope.getQualifiedTypeNames(); - - for (ASTFormalParameter p : parameters) { - - String typeImage = p.getTypeNode().getTypeImage(); - // typeImage might be qualified/unqualified. If it refers to a type, - // defined in the same toplevel class, - // we should normalize the name here. - // It might also refer to a type, that is imported. - typeImage = qualifyTypeName(typeImage); - Node declaringNode = qualifiedTypeNames.get(typeImage); - Class resolvedType = fileScope.resolveType(typeImage); - if (resolvedType == null) { - resolvedType = resolveGenericType(p, typeImage); - } - parameterTypes.add(new SimpleTypedNameDeclaration(typeImage, resolvedType, determineSuper(declaringNode))); - } - return parameterTypes; - } - - private String qualifyTypeName(String typeImage) { - if (typeImage == null) { - return null; - } - - final SourceFileScope fileScope = getEnclosingScope(SourceFileScope.class); - - // Is it an inner class being accessed? - String qualified = findQualifiedName(typeImage, fileScope.getQualifiedTypeNames().keySet()); - if (qualified != null) { - return qualified; - } - - // Is it an explicit import? - qualified = findQualifiedName(typeImage, fileScope.getExplicitImports()); - if (qualified != null) { - return qualified; - } - - // Is it an inner class of an explicit import? - int dotIndex = typeImage.indexOf('.'); - if (dotIndex != -1) { - qualified = findQualifiedName(typeImage.substring(0, dotIndex), fileScope.getExplicitImports()); - if (qualified != null) { - return qualified.concat(typeImage.substring(dotIndex)); - } - } - - return typeImage; - } - - private String findQualifiedName(String typeImage, Set candidates) { - int nameLength = typeImage.length(); - for (String qualified : candidates) { - int fullLength = qualified.length(); - if (qualified.endsWith(typeImage) - && (fullLength == nameLength || qualified.charAt(fullLength - nameLength - 1) == '.')) { - return qualified; - } - } - - return null; - } - - /** - * Provide a list of types of the arguments of the given method call. The - * types are simple type images. If the argument type cannot be determined - * (e.g. because it is itself the result of a method call), the parameter - * type is used - so it is assumed, it is of the correct type. This might - * cause confusion when methods are overloaded. - * - * @param occurrence - * the method call - * @param parameterTypes - * the parameter types of the called method - * @return the list of argument types - */ - private List determineArgumentTypes(JavaNameOccurrence occurrence, - List parameterTypes) { - ASTArgumentList arguments = null; - Node nextSibling; - if (occurrence.getLocation() instanceof ASTPrimarySuffix) { - nextSibling = getNextSibling(occurrence.getLocation()); - } else { - nextSibling = getNextSibling(occurrence.getLocation().getParent()); - } - - if (nextSibling != null) { - arguments = nextSibling.getFirstDescendantOfType(ASTArgumentList.class); - } - - if (arguments == null) { - return Collections.emptyList(); - } - - List argumentTypes = new ArrayList<>(arguments.getNumChildren()); - Map qualifiedTypeNames = getEnclosingScope(SourceFileScope.class).getQualifiedTypeNames(); - - for (int i = 0; i < arguments.getNumChildren(); i++) { - Node argument = arguments.getChild(i); - Node child = null; - boolean isMethodCall = false; - if (argument.getNumChildren() > 0 && argument.getChild(0).getNumChildren() > 0 - && argument.getChild(0).getChild(0).getNumChildren() > 0) { - child = argument.getChild(0).getChild(0).getChild(0); - isMethodCall = argument.getChild(0).getNumChildren() > 1; - } - TypedNameDeclaration type = null; - if (!isMethodCall) { - if (child instanceof ASTName) { - ASTName name = (ASTName) child; - Scope s = name.getScope(); - final JavaNameOccurrence nameOccurrence = new JavaNameOccurrence(name, name.getImage()); - while (s != null) { - if (s.contains(nameOccurrence)) { - break; - } - s = s.getParent(); - } - if (s != null) { - Map> vars = s - .getDeclarations(VariableNameDeclaration.class); - for (VariableNameDeclaration d : vars.keySet()) { - // in case of simple lambda expression, the type - // might be unknown - if (d.getImage().equals(name.getImage()) && d.getTypeImage() != null) { - String typeName = d.getTypeImage(); - typeName = qualifyTypeName(typeName); - Node declaringNode = qualifiedTypeNames.get(typeName); - type = new SimpleTypedNameDeclaration(typeName, - this.getEnclosingScope(SourceFileScope.class).resolveType(typeName), - determineSuper(declaringNode)); - break; - } - } - } - } else if (child instanceof ASTLiteral) { - ASTLiteral literal = (ASTLiteral) child; - if (literal.isCharLiteral()) { - type = new SimpleTypedNameDeclaration("char", literal.getType()); - } else if (literal.isStringLiteral()) { - type = new SimpleTypedNameDeclaration("String", literal.getType()); - } else if (literal.isFloatLiteral()) { - type = new SimpleTypedNameDeclaration("float", literal.getType()); - } else if (literal.isDoubleLiteral()) { - type = new SimpleTypedNameDeclaration("double", literal.getType()); - } else if (literal.isIntLiteral()) { - type = new SimpleTypedNameDeclaration("int", literal.getType()); - } else if (literal.isLongLiteral()) { - type = new SimpleTypedNameDeclaration("long", literal.getType()); - } else if (literal.getNumChildren() == 1 - && literal.getChild(0) instanceof ASTBooleanLiteral) { - type = new SimpleTypedNameDeclaration("boolean", Boolean.TYPE); - } - } else if (child instanceof ASTAllocationExpression - && child.getChild(0) instanceof ASTClassOrInterfaceType) { - ASTClassOrInterfaceType classInterface = (ASTClassOrInterfaceType) child.getChild(0); - type = convertToSimpleType(classInterface); - } - } - if ((type == null || "lombok.val".equals(type.getTypeImage())) && !parameterTypes.isEmpty()) { - // replace the unknown type with the correct parameter type - // of the method. unknown type could be a "var" (local variable type inference) - // or a lombok.val type. - // in case the argument is itself a method call, we can't - // determine the result type of the called - // method. Therefore the parameter type is used. - // This might cause confusion, if method overloading is - // used. - - // the method might be vararg, so, there might be more - // arguments than parameterTypes - if (parameterTypes.size() > i) { - type = parameterTypes.get(i); - } else { - // last parameter is the vararg type - type = parameterTypes.get(parameterTypes.size() - 1); - } - } - if (type != null && type.getType() == null) { - Class typeBound = resolveGenericType(argument, type.getTypeImage()); - if (typeBound != null) { - type = new SimpleTypedNameDeclaration(type.getTypeImage(), typeBound); - } - } - argumentTypes.add(type); - } - return argumentTypes; - } - - private SimpleTypedNameDeclaration determineSuper(Node declaringNode) { - SimpleTypedNameDeclaration result = null; - if (declaringNode instanceof ASTClassOrInterfaceDeclaration) { - ASTClassOrInterfaceDeclaration classDeclaration = (ASTClassOrInterfaceDeclaration) declaringNode; - ASTImplementsList implementsList = classDeclaration.getFirstChildOfType(ASTImplementsList.class); - if (implementsList != null) { - List types = implementsList.findChildrenOfType(ASTClassOrInterfaceType.class); - SimpleTypedNameDeclaration type = convertToSimpleType(types); - result = type; - } - ASTExtendsList extendsList = classDeclaration.getFirstChildOfType(ASTExtendsList.class); - if (extendsList != null) { - List types = extendsList.findChildrenOfType(ASTClassOrInterfaceType.class); - SimpleTypedNameDeclaration type = convertToSimpleType(types); - if (result == null) { - result = type; - } else { - result.addNext(type); - } - } - } - return result; - } - - private SimpleTypedNameDeclaration convertToSimpleType(List types) { - SimpleTypedNameDeclaration result = null; - for (ASTClassOrInterfaceType t : types) { - SimpleTypedNameDeclaration type = convertToSimpleType(t); - if (result == null) { - result = type; - } else { - result.addNext(type); - } - } - return result; - } - - private SimpleTypedNameDeclaration convertToSimpleType(ASTClassOrInterfaceType t) { - String typeImage = t.getImage(); - typeImage = qualifyTypeName(typeImage); - Node declaringNode = getEnclosingScope(SourceFileScope.class).getQualifiedTypeNames().get(typeImage); - return new SimpleTypedNameDeclaration(typeImage, - this.getEnclosingScope(SourceFileScope.class).resolveType(typeImage), determineSuper(declaringNode)); - } - - public Class resolveType(final String name) { - return this.getEnclosingScope(SourceFileScope.class).resolveType(qualifyTypeName(name)); - } - - /** - * Tries to resolve a given typeImage as a generic Type. If the Generic Type - * is found, any defined ClassOrInterfaceType below this type declaration is - * used (this is typically a type bound, e.g. {@code }. - * - * @param argument - * the node, from where to start searching. - * @param typeImage - * the type as string - * @return the resolved class or null if nothing was found. - */ - private Class resolveGenericType(Node argument, String typeImage) { - List types = new ArrayList<>(); - // first search only within the same method - ASTBodyDeclaration firstParentOfType = argument.getFirstParentOfType(ASTBodyDeclaration.class); - if (firstParentOfType != null) { - types.addAll(firstParentOfType.findDescendantsOfType(ASTTypeParameter.class)); - } - - // then search class level types, from inner-most to outer-most - List enclosingClasses = argument - .getParentsOfType(ASTClassOrInterfaceDeclaration.class); - for (ASTClassOrInterfaceDeclaration enclosing : enclosingClasses) { - ASTTypeParameters classLevelTypeParameters = enclosing.getFirstChildOfType(ASTTypeParameters.class); - if (classLevelTypeParameters != null) { - types.addAll(classLevelTypeParameters.findDescendantsOfType(ASTTypeParameter.class)); - } - } - return resolveGenericType(typeImage, types); - } - - private Class resolveGenericType(String typeImage, List types) { - for (ASTTypeParameter type : types) { - if (typeImage.equals(type.getImage())) { - ASTClassOrInterfaceType bound = type.getFirstDescendantOfType(ASTClassOrInterfaceType.class); - if (bound != null) { - if (bound.getType() != null) { - return bound.getType(); - } else { - return this.getEnclosingScope(SourceFileScope.class).resolveType(bound.getImage()); - } - } else { - // type parameter found, but no binding. - return Object.class; - } - } - } - return null; - } - - private Node getNextSibling(Node current) { - if (current.getParent().getNumChildren() > current.getIndexInParent() + 1) { - return current.getParent().getChild(current.getIndexInParent() + 1); - } - return null; - } - - @Override - public String toString() { - StringBuilder res = new StringBuilder("ClassScope (").append(className).append("): "); - Map> classDeclarations = getClassDeclarations(); - if (classDeclarations.isEmpty()) { - res.append("Inner Classes ").append(glomNames(classDeclarations.keySet())).append("; "); - } - Map> methodDeclarations = getMethodDeclarations(); - if (!methodDeclarations.isEmpty()) { - for (Map.Entry> entry : methodDeclarations.entrySet()) { - res.append(entry.getKey().toString()); - int usages = entry.getValue().size(); - res.append("(begins at line ").append(entry.getKey().getNode().getBeginLine()).append(", ").append(usages) - .append(" usages)"); - res.append(", "); - } - } - Map> variableDeclarations = getVariableDeclarations(); - if (!variableDeclarations.isEmpty()) { - res.append("Variables ").append(glomNames(variableDeclarations.keySet())); - } - return res.toString(); - } - - private String clipClassName(String s) { - return s.substring(s.indexOf('.') + 1); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/DeclarationFinderFunction.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/DeclarationFinderFunction.java deleted file mode 100644 index 7239c5b450..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/DeclarationFinderFunction.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.function.Predicate; - -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.java.ast.ASTMethodReference; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -@Deprecated -@InternalApi -public class DeclarationFinderFunction implements Predicate { - - private NameOccurrence occurrence; - private NameDeclaration decl; - - public DeclarationFinderFunction(NameOccurrence occurrence) { - this.occurrence = occurrence; - } - - @Override - public boolean test(NameDeclaration nameDeclaration) { - // do not match method references - if (occurrence.getLocation() instanceof ASTMethodReference) { - return false; - } - - if (isDeclaredBefore(nameDeclaration) && isSameName(nameDeclaration)) { - decl = nameDeclaration; - return false; - } - return true; - } - - private boolean isDeclaredBefore(NameDeclaration nameDeclaration) { - return nameDeclaration.getNode() == null || occurrence.getLocation() == null - || nameDeclaration.getNode().getBeginLine() <= occurrence.getLocation().getBeginLine(); - } - - private boolean isSameName(NameDeclaration nameDeclaration) { - return occurrence.getImage().equals(nameDeclaration.getName()); - } - - public NameDeclaration getDecl() { - return this.decl; - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/JavaNameOccurrence.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/JavaNameOccurrence.java deleted file mode 100644 index e4688e7748..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/JavaNameOccurrence.java +++ /dev/null @@ -1,232 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator; -import net.sourceforge.pmd.lang.java.ast.ASTExpression; -import net.sourceforge.pmd.lang.java.ast.ASTMethodReference; -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.ASTResource; -import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; -import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; -import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -public class JavaNameOccurrence implements NameOccurrence { - - private JavaNode location; - private String image; - private NameOccurrence qualifiedName; - - private boolean isMethodOrConstructorInvocation; - private int argumentCount; - - private static final String THIS = "this"; - private static final String SUPER = "super"; - - private static final String THIS_DOT = "this."; - private static final String SUPER_DOT = "super."; - - public JavaNameOccurrence(JavaNode location, String image) { - this.location = location; - this.image = image; - } - - public void setIsMethodOrConstructorInvocation() { - isMethodOrConstructorInvocation = true; - } - - public void setArgumentCount(int count) { - argumentCount = count; - } - - public int getArgumentCount() { - return argumentCount; - } - - public boolean isMethodOrConstructorInvocation() { - return isMethodOrConstructorInvocation; - } - - public boolean isMethodReference() { - return location instanceof ASTMethodReference; - } - - public void setNameWhichThisQualifies(NameOccurrence qualifiedName) { - this.qualifiedName = qualifiedName; - } - - public NameOccurrence getNameForWhichThisIsAQualifier() { - return qualifiedName; - } - - public boolean isPartOfQualifiedName() { - return qualifiedName != null; - } - - @Override - public JavaNode getLocation() { - return location; - } - - public boolean isOnRightHandSide() { - Node node = location.getParent().getParent().getParent(); - return node instanceof ASTExpression && node.getNumChildren() == 3; - } - - public boolean isOnLeftHandSide() { - // I detest this method with every atom of my being - Node primaryExpression; - if (location.getParent() instanceof ASTPrimaryExpression) { - primaryExpression = location.getParent().getParent(); - } else if (location.getParent().getParent() instanceof ASTPrimaryExpression) { - primaryExpression = location.getParent().getParent().getParent(); - } else if (location.getParent() instanceof ASTResource) { - return false; - } else { - throw new RuntimeException( - "Found a NameOccurrence (" + location + ") that didn't have an ASTPrimary Expression" - + " as parent or grandparent nor is a concise resource. Parent = " - + location.getParent() + " and grandparent = " + location.getParent().getParent() - + " (location line " + location.getBeginLine() + " col " + location.getBeginColumn() + ")"); - } - - return isStandAlonePostfix(primaryExpression) - || primaryExpression.getNumChildren() > 1 - && primaryExpression.getChild(1) instanceof ASTAssignmentOperator - && !isPartOfQualifiedName() /* and is not an array type */ - && !isCompoundAssignment(primaryExpression); - } - - private boolean isCompoundAssignment(Node primaryExpression) { - return ((ASTAssignmentOperator) primaryExpression.getChild(1)).isCompound(); - } - - private boolean isStandAlonePostfix(Node primaryExpression) { - if (!(primaryExpression instanceof ASTUnaryExpression)) { - return false; - } - - ASTUnaryExpression unaryExpr = (ASTUnaryExpression) primaryExpression; - - if (unaryExpr.getOperator().isPure() - || unaryExpr.getOperator().isPrefix() - || !(primaryExpression.getParent() instanceof ASTStatementExpression)) { - return false; - } - - ASTPrimaryPrefix pf = (ASTPrimaryPrefix) ((ASTPrimaryExpression) primaryExpression.getChild(0)) - .getChild(0); - - return pf.usesThisModifier() || thirdChildHasDottedName(primaryExpression); - } - - private boolean thirdChildHasDottedName(Node primaryExpression) { - Node thirdChild = primaryExpression.getChild(0).getChild(0).getChild(0); - return thirdChild instanceof ASTName && ((ASTName) thirdChild).getImage().indexOf('.') == -1; - } - - /** - * Assert it the occurrence is a self assignment such as: - * i += 3; - * - * @return true, if the occurrence is self-assignment, false, otherwise. - */ - @SuppressWarnings("PMD.AvoidBranchingStatementAsLastInLoop") - public boolean isSelfAssignment() { - Node l = location; - while (true) { - Node p = l.getParent(); - Node gp = p.getParent(); - Node node = gp.getParent(); - if (node instanceof ASTUnaryExpression && !((ASTUnaryExpression) node).getOperator().isPure()) { - return true; - } - - if (hasAssignmentOperator(gp)) { - return isCompoundAssignment(gp); - } - - if (hasAssignmentOperator(node)) { - return isCompoundAssignment(node); - } - - // deal with extra parenthesis: "(i)++" - if (p instanceof ASTPrimaryPrefix && p.getNumChildren() == 1 && gp instanceof ASTPrimaryExpression - && gp.getNumChildren() == 1 && node instanceof ASTExpression && node.getNumChildren() == 1 - && node.getParent() instanceof ASTPrimaryPrefix - && node.getParent().getNumChildren() == 1) { - l = node; - continue; - } - - // catch this.i++ or ++this.i - return node instanceof ASTUnaryExpression && !((ASTUnaryExpression) node).getOperator().isPure(); - } - } - - private boolean hasAssignmentOperator(Node node) { - if (node instanceof ASTStatementExpression || node instanceof ASTExpression) { - if (node.getNumChildren() >= 2 && node.getChild(1) instanceof ASTAssignmentOperator) { - return true; - } - } - return false; - } - - /** - * Simply return true is the image is equal to keyword 'this' or 'super'. - * - * @return return true if image equal to 'this' or 'super'. - */ - public boolean isThisOrSuper() { - return THIS.equals(image) || SUPER.equals(image); - } - - /** - * Simply return if the image start with keyword 'this' or 'super'. - * - * @return true, if keyword is used, false otherwise. - */ - public boolean useThisOrSuper() { - Node node = location.getParent(); - if (node instanceof ASTPrimaryExpression) { - ASTPrimaryExpression primaryExpression = (ASTPrimaryExpression) node; - ASTPrimaryPrefix prefix = (ASTPrimaryPrefix) primaryExpression.getChild(0); - if (prefix != null) { - return prefix.usesSuperModifier() || prefix.usesThisModifier(); - } - } - return image.startsWith(THIS_DOT) || image.startsWith(SUPER_DOT); - } - - @Override - public boolean equals(Object o) { - if (o instanceof JavaNameOccurrence) { - JavaNameOccurrence n = (JavaNameOccurrence) o; - return n.getImage().equals(getImage()); - } - return false; - } - - @Override - public int hashCode() { - return getImage().hashCode(); - } - - @Override - public String getImage() { - return image; - } - - @Override - public String toString() { - return getImage() + ":" + location.getBeginLine() + ":" + location.getClass() - + (this.isMethodOrConstructorInvocation() ? "(method call)" : ""); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/LocalScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/LocalScope.java deleted file mode 100644 index 47a855ff28..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/LocalScope.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.symboltable.Applier; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -/** - * A LocalScope can have variable declarations and class declarations within it. - */ -public class LocalScope extends AbstractJavaScope { - - public Map> getVariableDeclarations() { - return getDeclarations(VariableNameDeclaration.class); - } - - @Override - public Set addNameOccurrence(NameOccurrence occurrence) { - JavaNameOccurrence javaOccurrence = (JavaNameOccurrence) occurrence; - Set declarations = findVariableHere(javaOccurrence); - if (!declarations.isEmpty() && !javaOccurrence.isThisOrSuper()) { - for (NameDeclaration decl : declarations) { - List nameOccurrences = getVariableDeclarations().get(decl); - nameOccurrences.add(javaOccurrence); - Node n = javaOccurrence.getLocation(); - if (n instanceof ASTName) { - ((ASTName) n).setNameDeclaration(decl); - } // TODO what to do with PrimarySuffix case? - } - } - return declarations; - } - - @Override - public void addDeclaration(NameDeclaration nameDecl) { - if (!(nameDecl instanceof VariableNameDeclaration || nameDecl instanceof ClassNameDeclaration)) { - throw new IllegalArgumentException( - "A LocalScope can contain only VariableNameDeclarations or ClassNameDeclarations. " - + "Tried to add " + nameDecl.getClass() + "(" + nameDecl + ")"); - } - super.addDeclaration(nameDecl); - } - - @Override - public Set findVariableHere(JavaNameOccurrence occurrence) { - if (occurrence.isThisOrSuper() || occurrence.isMethodOrConstructorInvocation()) { - return Collections.emptySet(); - } - DeclarationFinderFunction finder = new DeclarationFinderFunction(occurrence); - Applier.apply(finder, getVariableDeclarations().keySet().iterator()); - if (finder.getDecl() != null) { - return Collections.singleton(finder.getDecl()); - } - return Collections.emptySet(); - } - - @Override - public String toString() { - return "LocalScope:" + glomNames(getVariableDeclarations().keySet()); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/MethodNameDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/MethodNameDeclaration.java deleted file mode 100644 index 65c3c54d7f..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/MethodNameDeclaration.java +++ /dev/null @@ -1,121 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.List; -import java.util.Objects; - -import net.sourceforge.pmd.internal.util.IteratorUtil; -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTType; -import net.sourceforge.pmd.lang.symboltable.AbstractNameDeclaration; - -public class MethodNameDeclaration extends AbstractNameDeclaration { - - public MethodNameDeclaration(ASTMethodDeclaration node) { - super(node); - } - - public int getParameterCount() { - return getDeclarator().getArity(); - } - - public boolean isVarargs() { - return getDeclarator().isVarargs(); - } - - public String getParameterDisplaySignature() { - StringBuilder sb = new StringBuilder("("); - // TODO - this can be written with Streams and Collectors::joining - for (ASTFormalParameter p : getDeclarator().getFormalParameters()) { - sb.append(p.getTypeNode().getTypeImage()); - if (p.isVarargs()) { - sb.append("..."); - } - sb.append(','); - } - if (sb.charAt(sb.length() - 1) == ',') { - sb.deleteCharAt(sb.length() - 1); - } - sb.append(')'); - return sb.toString(); - } - - public ASTMethodDeclaration getDeclarator() { - return (ASTMethodDeclaration) node; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof MethodNameDeclaration)) { - return false; - } - - MethodNameDeclaration other = (MethodNameDeclaration) o; - - // compare name - if (!other.getName().equals(getName())) { - return false; - } - - // compare parameter count - this catches the case where there are no - // params, too - if (other.getParameterCount() != this.getParameterCount()) { - return false; - } - - // compare parameter types - - List myParams = IteratorUtil.toList(getDeclarator().getFormalParameters().iterator()); - List otherParams = IteratorUtil.toList(other.getDeclarator().getFormalParameters().iterator()); - - for (int i = 0; i < myParams.size(); i++) { - ASTFormalParameter myParam = myParams.get(i); - ASTFormalParameter otherParam = otherParams.get(i); - - // Compare vararg - if (myParam.isVarargs() != otherParam.isVarargs()) { - return false; - } - - ASTType myTypeNode = myParam.getTypeNode(); - ASTType otherTypeNode = otherParam.getTypeNode(); - - // compare primitive vs reference type - if (myTypeNode.getClass() != otherTypeNode.getClass()) { - return false; - } - - // fallback on simple comparison of type images - // this can be fooled by one method using "String" - // and the other method using "java.lang.String" - // once we get real types in here that should get fixed - if (!Objects.equals(myTypeNode.getTypeImage(), otherTypeNode.getTypeImage())) { - return false; - } - } - return true; - } - - @Override - public int hashCode() { - ASTMethodDeclaration declaration = getDeclarator(); - int hash = declaration.getName().hashCode() * 31 + declaration.getArity(); - - for (ASTFormalParameter myParam : declaration.getFormalParameters()) { - String myTypeImg = myParam.getTypeNode().getTypeImage(); - hash = hash * 31 + myTypeImg.hashCode(); - } - - return hash; - } - - @Override - public String toString() { - return "Method " + node.getImage() + ", line " + node.getBeginLine() + ", params = " - + getDeclarator().getArity(); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/MethodScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/MethodScope.java deleted file mode 100644 index 946b32dc44..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/MethodScope.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.symboltable.Applier; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -/** - * A Method Scope can have variable declarations and class declarations within - * it. - */ -public class MethodScope extends AbstractJavaScope { - - private Node node; - - public MethodScope(Node node) { - this.node = node; - } - - public Map> getVariableDeclarations() { - return getDeclarations(VariableNameDeclaration.class); - } - - @Override - public Set addNameOccurrence(NameOccurrence occurrence) { - JavaNameOccurrence javaOccurrence = (JavaNameOccurrence) occurrence; - Set declarations = findVariableHere(javaOccurrence); - if (!declarations.isEmpty() && !javaOccurrence.isThisOrSuper()) { - for (NameDeclaration decl : declarations) { - getVariableDeclarations().get(decl).add(javaOccurrence); - Node n = javaOccurrence.getLocation(); - if (n instanceof ASTName) { - ((ASTName) n).setNameDeclaration(decl); - } // TODO what to do with PrimarySuffix case? - } - } - return declarations; - } - - @Override - public void addDeclaration(NameDeclaration variableDecl) { - if (!(variableDecl instanceof VariableNameDeclaration || variableDecl instanceof ClassNameDeclaration)) { - throw new IllegalArgumentException( - "A MethodScope can contain only VariableNameDeclarations or ClassNameDeclarations"); - } - super.addDeclaration(variableDecl); - } - - @Override - public Set findVariableHere(JavaNameOccurrence occurrence) { - if (occurrence.isThisOrSuper() || occurrence.isMethodOrConstructorInvocation()) { - return Collections.emptySet(); - } - DeclarationFinderFunction finder = new DeclarationFinderFunction(occurrence); - Applier.apply(finder, getVariableDeclarations().keySet().iterator()); - if (finder.getDecl() != null) { - return Collections.singleton(finder.getDecl()); - } - return Collections.emptySet(); - } - - public String getName() { - if (node instanceof ASTConstructorDeclaration) { - return this.getEnclosingScope(ClassScope.class).getClassName(); - } - return node.getChild(1).getImage(); - } - - @Override - public String toString() { - return "MethodScope:" + glomNames(getVariableDeclarations().keySet()); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/NameFinder.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/NameFinder.java deleted file mode 100644 index c58d6689c5..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/NameFinder.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.java.ast.ASTArguments; -import net.sourceforge.pmd.lang.java.ast.ASTMemberSelector; -import net.sourceforge.pmd.lang.java.ast.ASTMethodReference; -import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; -import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; -import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -@Deprecated -@InternalApi -@SuppressWarnings("PMD") -public class NameFinder { - - private List names = new ArrayList<>(); - - public NameFinder(ASTPrimaryExpression node) { - - // ASTPrimaryPrefix prefix = (ASTPrimaryPrefix) node.getChild(0); - // if (prefix.usesSuperModifier()) { - // add(new JavaNameOccurrence(prefix, "super")); - // } else if (prefix.usesThisModifier()) { - // add(new JavaNameOccurrence(prefix, "this")); - // } - // for (int i = 0; i < node.getNumChildren(); i++) { - // checkForNameChild((JavaNode) node.getChild(i)); - // } - } - - public List getNames() { - return names; - } - - private void checkForNameChild(JavaNode node) { - if (node.getImage() != null) { - add(new JavaNameOccurrence(node, node.getImage())); - } - if (node.getNumChildren() > 0 && node.getChild(0) instanceof ASTName) { - ASTName grandchild = (ASTName) node.getChild(0); - for (StringTokenizer st = new StringTokenizer(grandchild.getImage(), "."); st.hasMoreTokens();) { - add(new JavaNameOccurrence(grandchild, st.nextToken())); - } - } - if (node.getNumChildren() > 1 && node.getChild(1) instanceof ASTMethodReference) { - ASTMethodReference methodRef = (ASTMethodReference) node.getChild(1); - add(new JavaNameOccurrence(methodRef, methodRef.getImage())); - } - if (node instanceof ASTPrimarySuffix) { - ASTPrimarySuffix suffix = (ASTPrimarySuffix) node; - if (suffix.isArguments()) { - if (!names.isEmpty()) { - JavaNameOccurrence occurrence = names.get(names.size() - 1); - occurrence.setIsMethodOrConstructorInvocation(); - ASTArguments args = (ASTArguments) ((ASTPrimarySuffix) node).getChild(0); - occurrence.setArgumentCount(args.size()); - } - } else if (suffix.getNumChildren() == 1 && suffix.getChild(0) instanceof ASTMemberSelector) { - ASTMemberSelector member = (ASTMemberSelector) suffix.getChild(0); - if (member.getNumChildren() == 1 && member.getChild(0) instanceof ASTMethodReference) { - ASTMethodReference methodRef = (ASTMethodReference) member.getChild(0); - add(new JavaNameOccurrence(methodRef, methodRef.getImage())); - } else { - add(new JavaNameOccurrence(member, member.getImage())); - } - } - } - } - - private void add(JavaNameOccurrence name) { - names.add(name); - if (names.size() > 1) { - JavaNameOccurrence qualifiedName = names.get(names.size() - 2); - qualifiedName.setNameWhichThisQualifies(name); - } - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - for (NameOccurrence occ : names) { - result.append(occ); - result.append(PMD.EOL); - } - return result.toString(); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/OccurrenceFinder.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/OccurrenceFinder.java deleted file mode 100644 index 72964c04f7..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/OccurrenceFinder.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.symboltable; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.Scope; - -@Deprecated -@InternalApi -public class OccurrenceFinder extends JavaParserVisitorAdapter { - - // Maybe do some sort of State pattern thingy for when NameDeclaration - // is empty/not empty? - private final Set declarations = new HashSet<>(); - - private final Set additionalDeclarations = new HashSet<>(); - - @Override - public Object visit(ASTPrimaryExpression node, Object data) { - NameFinder nameFinder = new NameFinder(node); - - declarations.clear(); - additionalDeclarations.clear(); - - List names = nameFinder.getNames(); - for (JavaNameOccurrence occ : names) { - Search search = new Search(occ); - if (declarations.isEmpty()) { - // doing the first name lookup - search.execute(); - declarations.addAll(search.getResult()); - if (declarations.isEmpty()) { - // we can't find it, so just give up - // when we decide to do full symbol resolution - // force this to either find a symbol or throw a - // SymbolNotFoundException - break; - } - } else { - for (NameDeclaration decl : declarations) { - // now we've got a scope we're starting with, so work from - // there - Scope startingScope = decl.getScope(); - // in case the previous found declaration is a class - // reference - // for a class inside the same source file - // we need to search this class - // e.g. the list of name occurrence could come from - // outerClassRef.member. See also bug #1302 - if (decl instanceof VariableNameDeclaration) { - String typeImage = ((VariableNameDeclaration) decl).getTypeImage(); - ClassNameDeclaration clazzDeclaration = startingScope.getEnclosingScope(SourceFileScope.class) - .findClassNameDeclaration(typeImage); - if (clazzDeclaration != null) { - startingScope = clazzDeclaration.getScope(); - } - } - search.execute(startingScope); - Set result = search.getResult(); - additionalDeclarations.addAll(result); - if (result.isEmpty()) { - // nothing found - // This seems to be a lack of type resolution here. - // Theoretically we have the previous declaration node - // and - // know from there the Type of - // the variable. The current occurrence (occ) should - // then be - // found in the declaration of - // this type. The type however may or may not be known - // to - // PMD (see aux classpath). - - // we can't find it, so just give up - // when we decide to do full symbol resolution - // force this to either find a symbol or throw a - // SymbolNotFoundException - break; - } - } - declarations.addAll(additionalDeclarations); - } - } - return super.visit(node, data); - } - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinder.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinder.java deleted file mode 100644 index 3da063cf3c..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinder.java +++ /dev/null @@ -1,298 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.ArrayDeque; -import java.util.Deque; - -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTAnonymousClassDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTBlock; -import net.sourceforge.pmd.lang.java.ast.ASTCatchClause; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTForStatement; -import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTPackageDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTRecordDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; -import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.java.ast.InternalApiBridge; -import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; -import net.sourceforge.pmd.lang.symboltable.Scope; - -/** - * Visitor for scope creation. Visits all nodes of an AST and creates scope - * objects for nodes representing syntactic entities which may contain - * declarations. For example, a block may contain variable definitions (which - * are declarations) and therefore needs a scope object where these declarations - * can be associated, whereas an expression can't contain declarations and - * therefore doesn't need a scope object. With the exception of global scopes, - * each scope object is linked to its parent scope, which is the scope object of - * the next embedding syntactic entity that has a scope. - */ -@Deprecated -@InternalApi -public class ScopeAndDeclarationFinder extends JavaParserVisitorAdapter { - - private ClassLoader classLoader; - - /** - * A stack of scopes reflecting the scope hierarchy when a node is visited. - * This is used to set the parents of the created scopes correctly. - */ - private Deque scopes = new ArrayDeque<>(); - - /** - * Creates a new {@link ScopeAndDeclarationFinder} using the current class - * loader. - */ - public ScopeAndDeclarationFinder() { - this(ScopeAndDeclarationFinder.class.getClassLoader()); - } - - /** - * Creates a new {@link ScopeAndDeclarationFinder}. - * - * @param classLoader - * the class loader to use to resolve types, see - * {@link SourceFileScope} and {@link TypeSet} - */ - public ScopeAndDeclarationFinder(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - /** - * Sets the scope of a node and adjusts the scope stack accordingly. The - * scope on top of the stack is set as the parent of the given scope, which - * is then also stored on the scope stack. - * - * @param newScope - * the scope for the node. - * @param node - * the AST node for which the scope is to be set. - * @throws java.util.EmptyStackException - * if the scope stack is empty. - */ - private void addScope(Scope newScope, JavaNode node) { - newScope.setParent(scopes.peek()); - scopes.push(newScope); - InternalApiBridge.setScope(node, newScope); - } - - /** - * Creates a new local scope for an AST node. The scope on top of the stack - * is set as the parent of the new scope, which is then also stored on the - * scope stack. - * - * @param node - * the AST node for which the scope has to be created. - * @throws java.util.EmptyStackException - * if the scope stack is empty. - */ - private void createLocalScope(JavaNode node) { - addScope(new LocalScope(), node); - } - - /** - * Creates a new method scope for an AST node. The scope on top of the stack - * is set as the parent of the new scope, which is then also stored on the - * scope stack. - * - * @param node - * the AST node for which the scope has to be created. - * @throws java.util.EmptyStackException - * if the scope stack is empty. - */ - private void createMethodScope(JavaNode node) { - addScope(new MethodScope(node), node); - } - - /** - * Creates a new class scope for an AST node. The scope on top of the stack - * is set as the parent of the new scope, which is then also stored on the - * scope stack. - * - * @param node - * the AST node for which the scope has to be created. - * @throws java.util.EmptyStackException - * if the scope stack is empty. - */ - private void createClassScope(JavaNode node) { - Scope s = ((JavaNode) node.getParent()).getScope(); - ClassNameDeclaration classNameDeclaration = new ClassNameDeclaration(node); - s.addDeclaration(classNameDeclaration); - - if (node instanceof ASTAnonymousClassDeclaration) { - addScope(new ClassScope(classNameDeclaration), node); - } else { - addScope(new ClassScope(node.getImage(), classNameDeclaration), node); - } - } - - /** - * Creates a new global scope for an AST node. The new scope is stored on - * the scope stack. - * - * @param node - * the AST node for which the scope has to be created. - */ - private void createSourceFileScope(ASTCompilationUnit node) { - // When we do full symbol resolution, we'll need to add a truly - // top-level GlobalScope. - SourceFileScope scope; - ASTPackageDeclaration n = node.getPackageDeclaration(); - if (n != null) { - scope = new SourceFileScope(classLoader, n.getName()); - } else { - scope = new SourceFileScope(classLoader); - } - scope.configureImports(node.findChildrenOfType(ASTImportDeclaration.class)); - - scopes.push(scope); - InternalApiBridge.setScope(node, scope); - } - - @Override - public Object visit(ASTCompilationUnit node, Object data) { - createSourceFileScope(node); - cont(node); - return data; - } - - @Override - public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { - createClassScope(node); - cont(node); - return data; - } - - @Override - public Object visit(ASTEnumDeclaration node, Object data) { - createClassScope(node); - ((ClassScope) node.getScope()).setIsEnum(true); - cont(node); - return data; - } - - @Override - public Object visit(ASTAnnotationTypeDeclaration node, Object data) { - createClassScope(node); - cont(node); - return data; - } - - @Override - public Object visit(ASTRecordDeclaration node, Object data) { - createClassScope(node); - cont(node); - return data; - } - - @Override - public Object visit(ASTAnonymousClassDeclaration node, Object data) { - createClassScope(node); - cont(node); - return data; - } - - @Override - public Object visit(ASTBlock node, Object data) { - // top-level blocks for methods should have the same scope as parameters, just skip them - // same applies to catch statements defining exceptions + the catch block, and for-blocks - if (node.getParent() instanceof ASTMethodDeclaration - || node.getParent() instanceof ASTConstructorDeclaration - || node.getParent() instanceof ASTLambdaExpression - || node.getParent() instanceof ASTCatchClause - || node.getParent() instanceof ASTForStatement) { - super.visit(node, null); - } else { - createLocalScope(node); - cont(node); - } - return data; - } - - @Override - public Object visit(ASTCatchClause node, Object data) { - createLocalScope(node); - cont(node); - return data; - } - - @Override - public Object visit(ASTConstructorDeclaration node, Object data) { - createMethodScope(node); - cont(node); - return data; - } - - @Override - public Object visit(ASTMethodDeclaration node, Object data) { - createMethodScope(node); - node.getScope().getEnclosingScope(ClassScope.class).addDeclaration(new MethodNameDeclaration(node)); - cont(node); - return data; - } - - @Override - public Object visit(ASTLambdaExpression node, Object data) { - createLocalScope(node); - cont(node); - return data; - } - - @Override - public Object visit(ASTTryStatement node, Object data) { - createLocalScope(node); - cont(node); - return data; - } - - // TODO - what about while loops and do loops? - @Override - public Object visit(ASTForStatement node, Object data) { - createLocalScope(node); - cont(node); - return data; - } - - @Override - public Object visit(ASTVariableDeclaratorId node, Object data) { - if (node.isPatternBinding()) { - // Don't consider type test patterns here. It could bind to a name - // that is already in the scope (e.g. field names). - // type tests patterns are tricky to implement - // and given it's a preview feature, and the sym table will be replaced - // for 7.0, it's not useful to support them. - // See https://cr.openjdk.java.net/~briangoetz/amber/pattern-semantics.html#scoping-of-pattern-variables - return super.visit(node, data); - } - - VariableNameDeclaration decl = new VariableNameDeclaration(node); - node.getScope().addDeclaration(decl); - node.setNameDeclaration(decl); - return super.visit(node, data); - } - - @Override - public Object visit(ASTSwitchStatement node, Object data) { - createLocalScope(node); - cont(node); - return data; - } - - private void cont(JavaNode node) { - super.visitJavaNode(node, null); - scopes.pop(); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/Search.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/Search.java deleted file mode 100644 index 34a644682f..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/Search.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; -import net.sourceforge.pmd.lang.symboltable.Scope; - -@Deprecated -@InternalApi -public class Search { - private static final boolean TRACE = false; - - private NameOccurrence occ; - private Set declarations = new HashSet<>(); - - public Search(JavaNameOccurrence occ) { - if (TRACE) { - System.out.println( - "new search for " + (occ.isMethodOrConstructorInvocation() ? "method" : "variable") + " " + occ); - } - this.occ = occ; - } - - public void execute() { - Set found = searchUpward(occ, occ.getLocation().getScope()); - if (TRACE) { - System.out.println("found " + found); - } - declarations.addAll(found); - } - - public void execute(Scope startingScope) { - Set found = searchUpward(occ, startingScope); - if (TRACE) { - System.out.println("found " + found); - } - declarations.addAll(found); - } - - public Set getResult() { - return declarations; - } - - private Set searchUpward(NameOccurrence nameOccurrence, Scope scope) { - if (TRACE) { - System.out.println(" checking scope " + scope + " for name occurrence " + nameOccurrence); - } - final boolean isInScope = scope.contains(nameOccurrence); - if (!isInScope && scope.getParent() != null) { - if (TRACE) { - System.out.println(" moving up from " + scope + " to " + scope.getParent()); - } - return searchUpward(nameOccurrence, scope.getParent()); - } - if (isInScope) { - if (TRACE) { - System.out.println(" found it!"); - } - return scope.addNameOccurrence(nameOccurrence); - } - return Collections.emptySet(); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SimpleTypedNameDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SimpleTypedNameDeclaration.java deleted file mode 100644 index 58bf7b95d8..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SimpleTypedNameDeclaration.java +++ /dev/null @@ -1,194 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; - -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.java.ast.TypeNode; - -/** - * Just stores a type image and a actual type. And makes it easy to compare - * these. - */ -@Deprecated -@InternalApi -public class SimpleTypedNameDeclaration implements TypedNameDeclaration { - - private final String typeImage; - private final Class type; - private SimpleTypedNameDeclaration next; - - private static Set primitiveTypes = new HashSet<>(); - - static { - primitiveTypes.add("float"); - primitiveTypes.add("double"); - primitiveTypes.add("int"); - primitiveTypes.add("integer"); - primitiveTypes.add("long"); - primitiveTypes.add("byte"); - primitiveTypes.add("short"); - primitiveTypes.add("boolean"); - primitiveTypes.add("char"); - primitiveTypes.add("character"); - } - - /** - * Creates a new {@link SimpleTypedNameDeclaration} with the given type - * - * @param typeImage - * the type image - * @param type - * the actual type - */ - public SimpleTypedNameDeclaration(String typeImage, Class type) { - this.typeImage = typeImage; - this.type = type; - } - - public SimpleTypedNameDeclaration(String typeImage, Class type, SimpleTypedNameDeclaration next) { - this.typeImage = typeImage; - this.type = type; - this.next = next; - } - - public void addNext(SimpleTypedNameDeclaration next) { - if (next == null) { - return; - } - - if (this.next == null) { - this.next = next; - } else { - this.next.addNext(next); - } - } - - @Override - public TypeNode getTypeNode() { - return null; - } - - @Override - public String getTypeImage() { - return typeImage; - } - - @Override - public Class getType() { - return type; - } - - @Override - public String toString() { - String nextString = next != null ? "(next: " + next + ")" : ""; - return "SimpleType:" + type + "/" + typeImage + nextString; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((typeImage == null) ? 0 : typeImage.hashCode()); - return result; - } - - /** - * {@inheritDoc} - *

    - * Additionally - two {@link SimpleTypedNameDeclaration} are equal, if they - * contain types, that can be cast into each other. - *

    - */ - @Override - public boolean equals(Object obj) { - return internalEquals(obj) || internalEqualsNext(obj); - } - - private boolean internalEqualsNext(Object obj) { - if (next != null) { - return next.equals(obj); - } - if (obj instanceof SimpleTypedNameDeclaration) { - SimpleTypedNameDeclaration otherNext = ((SimpleTypedNameDeclaration) obj).next; - if (otherNext != null) { - return otherNext.equals(this); - } - } - return false; - } - - @SuppressWarnings("PMD.CompareObjectsWithEquals") - private boolean internalEquals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - SimpleTypedNameDeclaration other = (SimpleTypedNameDeclaration) obj; - if (type == null) { - if (other.type == Object.class) { - return true; - } - if (other.type != null) { - return false; - } - } - if (type != null && (type.equals(other.type) || type == Object.class)) { - return true; - } - - // if the type is given, only compare the type and don't care about the - // type image - if (type != null && other.type != null - && (type.isAssignableFrom(other.type) || other.type.isAssignableFrom(type))) { - return true; - } - - if (typeImage == null) { - if (other.typeImage != null) { - return false; - } - } else if (!typeImage.equals(other.typeImage)) { - // consider auto-boxing - if (other.typeImage != null) { - String lcType = typeImage.toLowerCase(Locale.ROOT); - String otherLcType = other.typeImage.toLowerCase(Locale.ROOT); - if (primitiveTypes.contains(lcType) && primitiveTypes.contains(otherLcType)) { - if (lcType.equals(otherLcType)) { - return true; - } else if (("char".equals(lcType) || "character".equals(lcType)) - && ("char".equals(otherLcType) || "character".equals(otherLcType))) { - return true; - } else if (("int".equals(lcType) || "integer".equals(lcType)) - && ("int".equals(otherLcType) || "integer".equals(otherLcType) - || "short".equals(otherLcType) || "char".equals(otherLcType) - || "character".equals(otherLcType) || "byte".equals(otherLcType))) { - return true; - } else if ("double".equals(lcType) && ("float".equals(otherLcType) || "int".equals(otherLcType) - || "integer".equals(otherLcType) || "long".equals(otherLcType))) { - return true; - } else if ("float".equals(lcType) && ("int".equals(otherLcType) || "integer".equals(otherLcType) - || "long".equals(otherLcType))) { - return true; - } else if ("long".equals(lcType) && ("int".equals(otherLcType) || "integer".equals(otherLcType) - || "char".equals(otherLcType) || "character".equals(otherLcType))) { - return true; - } - } - } - return false; - } - return true; - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SourceFileScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SourceFileScope.java deleted file mode 100644 index 877231c3de..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SourceFileScope.java +++ /dev/null @@ -1,167 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; -import net.sourceforge.pmd.lang.symboltable.Applier; -import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; -import net.sourceforge.pmd.lang.symboltable.Scope; - -/** - * This scope is the outer most scope of a Java file. A Source File can contain - * one ore more classes. - */ -public class SourceFileScope extends AbstractJavaScope { - - private final String packageImage; - private final TypeSet types; - private Map qualifiedTypeNames; - - public SourceFileScope(final ClassLoader classLoader) { - this(classLoader, ""); - } - - public SourceFileScope(final ClassLoader classLoader, final String packageImage) { - this.types = new TypeSet(classLoader); - this.packageImage = packageImage; - types.setASTCompilationUnitPackage(packageImage); - } - - /** - * Configures the type resolution for the symbol table. - * - * @param imports - * the import declarations - */ - public void configureImports(final List imports) { - for (ASTImportDeclaration i : imports) { - if (i.isImportOnDemand()) { - types.addImport(i.getImportedName() + ".*"); - } else { - types.addImport(i.getImportedName()); - } - } - } - - public Set getExplicitImports() { - return types.getExplicitImports(); - } - - /** - * Whether an auxclasspath has been configured or not. This can be used to - * enable/disable more detailed symbol table analysis and type resolution - * can be used - or to fall back to more simple implementation. - * - * @return true if the auxclasspath is configured and types can - * be resolved reliably. - * @see #resolveType(String) - */ - public boolean hasAuxclasspath() { - return types.hasAuxclasspath(); - } - - /** - * Tries to resolve a class by name. - * - * @param name - * the name of the class - * @return the class or null if no class could be found - */ - public Class resolveType(String name) { - return types.findClass(name); - } - - public String getPackageName() { - return packageImage; - } - - /** - * - * - * @throws IllegalArgumentException - * if declaration is not a {@link ClassNameDeclaration} - */ - @Override - public void addDeclaration(NameDeclaration declaration) { - if (!(declaration instanceof ClassNameDeclaration)) { - throw new IllegalArgumentException("A SourceFileScope can only contain classes."); - } - super.addDeclaration(declaration); - } - - /** - * Convenience method that casts the declarations to - * {@link ClassNameDeclaration}s. - * - * @see #getDeclarations() - * @return all class name declarations - */ - public Map> getClassDeclarations() { - return getDeclarations(ClassNameDeclaration.class); - } - - @Override - public String toString() { - return "SourceFileScope: " + glomNames(getClassDeclarations().keySet()); - } - - public ClassNameDeclaration findClassNameDeclaration(String name) { - ImageFinderFunction finder = new ImageFinderFunction(name); - Applier.apply(finder, getClassDeclarations().keySet().iterator()); - return (ClassNameDeclaration) finder.getDecl(); - } - - @Override - protected Set findVariableHere(JavaNameOccurrence occ) { - ImageFinderFunction finder = new ImageFinderFunction(occ.getImage()); - Applier.apply(finder, getDeclarations().keySet().iterator()); - if (finder.getDecl() != null) { - return Collections.singleton(finder.getDecl()); - } - return Collections.emptySet(); - } - - /** - * Returns a set of all types defined within this source file. This includes - * all top-level types and nested types. - * - * @return set of all types in this source file. - */ - public Map getQualifiedTypeNames() { - if (qualifiedTypeNames != null) { - return qualifiedTypeNames; - } - - qualifiedTypeNames = getSubTypes(null, this); - return qualifiedTypeNames; - } - - private Map getSubTypes(String qualifyingName, Scope subType) { - Set classDeclarations = subType.getDeclarations(ClassNameDeclaration.class).keySet(); - if (classDeclarations.isEmpty()) { - return Collections.emptyMap(); - } - - Map types = new HashMap<>((int) (classDeclarations.size() / 0.75f) + 1); - for (ClassNameDeclaration c : classDeclarations) { - String typeName = c.getName(); - if (qualifyingName != null) { - typeName = qualifyingName + "." + typeName; - } - types.put(typeName, c.getNode()); - types.putAll(getSubTypes(typeName, c.getScope())); - } - return types; - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SymbolFacade.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SymbolFacade.java deleted file mode 100644 index 4192845643..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/SymbolFacade.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; - -@Deprecated -@InternalApi -public class SymbolFacade { - public void initializeWith(ASTCompilationUnit node) { - initializeWith(SymbolFacade.class.getClassLoader(), node); - } - - public void initializeWith(ClassLoader classLoader, ASTCompilationUnit node) { - ScopeAndDeclarationFinder sc = new ScopeAndDeclarationFinder(classLoader); - node.jjtAccept(sc, null); - OccurrenceFinder of = new OccurrenceFinder(); - node.jjtAccept(of, null); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypeSet.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypeSet.java deleted file mode 100644 index f128299a41..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypeSet.java +++ /dev/null @@ -1,564 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.java.typeresolution.PMDASMClassLoader; -import net.sourceforge.pmd.util.ClasspathClassLoader; - -/** - * Keeps track of the types encountered in a ASTCompilationUnit - */ -@Deprecated -@InternalApi -public class TypeSet { - - private final PMDASMClassLoader pmdClassLoader; - private boolean hasAuxclasspath; - private String pkg; - private Set imports = new HashSet<>(); - private List resolvers = new ArrayList<>(); - - /** - * The {@link TypeSet} provides type resolution for the symbol facade. - */ - public TypeSet() { - this(TypeSet.class.getClassLoader()); - } - - /** - * The {@link TypeSet} provides type resolution for the symbol facade. - * - * @param classLoader - * the class loader to use to search classes (could be an - * auxiliary class path) - */ - public TypeSet(ClassLoader classLoader) { - ClassLoader cl = classLoader; - if (cl == null) { - cl = TypeSet.class.getClassLoader(); - } - hasAuxclasspath = cl instanceof ClasspathClassLoader; - pmdClassLoader = PMDASMClassLoader.getInstance(cl); - } - - /** - * Whether the classloader is using the auxclasspath or not. - * - * @return true if the classloader is using the auxclasspath - * feature - */ - public boolean hasAuxclasspath() { - return hasAuxclasspath; - } - - /** - * A resolver that can resolve a class by name. The name can be a simple - * name or a fully qualified name. - */ - // TODO should Resolver provide a canResolve() and a resolve()? Requiring 2 - // calls seems clunky... but so does this throwing an exception for flow - // control... - public interface Resolver { - /** - * Resolve the class by the given name - * - * @param name - * the name of the class, might be fully classified or not. - * @return the class - * @throws ClassNotFoundException - * if the class couldn't be found - */ - Class resolve(String name) throws ClassNotFoundException; - - /** - * Checks if the given class could be resolved by this resolver. Notice, - * that a resolver's ability to resolve a class does not imply that the - * class will actually be found and resolved. - * - * @param name - * the name of the class, might be fully classified or not. - * @return whether the class can be resolved - */ - boolean couldResolve(String name); - } - - /** - * Base Resolver class that support a {@link PMDASMClassLoader} class - * loader. - */ - public abstract static class AbstractResolver implements Resolver { - /** the class loader. */ - protected final PMDASMClassLoader pmdClassLoader; - private final Map classNames; - - /** - * Creates a new AbstractResolver that uses the given class loader. - * - * @param pmdClassLoader - * the class loader to use - */ - public AbstractResolver(final PMDASMClassLoader pmdClassLoader) { - this.pmdClassLoader = pmdClassLoader; - classNames = new HashMap<>(); - } - - /** - * Resolves the given class name with the given FQCN, considering it may - * be an inner class. - * - * @param name - * The name of the class to load. - * @param fqName - * The proposed FQCN for the class. - * @return The matched class or null if not found. - */ - protected Class resolveMaybeInner(final String name, final String fqName) { - // Do we know the actual class name? - final String className = classNames.get(name); - if (className != null) { - try { - return pmdClassLoader.loadClass(className); - } catch (final ClassNotFoundException e) { - // Ignored, can never actually happen, since we loaded the class at least once before... - throw new RuntimeException(e); // in case it happens anyway - } - } - - if (fqName != null) { - final StringBuilder sb = new StringBuilder(fqName); - String actualClassName = fqName; - // We have a FQCN, but it may be an inner class, so we have to - // brute force our way... - do { - if (pmdClassLoader.couldResolve(actualClassName)) { - try { - final Class c = pmdClassLoader.loadClass(actualClassName); - // Update the mapping - classNames.put(name, actualClassName); - return c; - } catch (final ClassNotFoundException ignored) { - // Ignored, we'll try again with a different class name, assuming inner classes - } - } - - // Check if the last segment is an inner class - final int lastDot = actualClassName.lastIndexOf('.'); - if (lastDot == -1) { - break; - } - - sb.setCharAt(lastDot, '$'); - actualClassName = sb.toString(); - } while (true); - } - - return null; - } - - @Override - public boolean couldResolve(final String name) { - /* - * Resolvers based on this one, will attempt to load the class from - * the class loader, so ask him - */ - return classNames.containsKey(name) || pmdClassLoader.couldResolve(name); - } - } - - /** - * Resolver that tries to resolve the given simple class name with the - * explicit import statements. - */ - public static class ExplicitImportResolver extends AbstractResolver { - private Map importStmts; - - /** - * Creates a new {@link ExplicitImportResolver}. - * - * @param pmdClassLoader - * the class loader to use. - * @param importStmts - * the import statements - */ - public ExplicitImportResolver(PMDASMClassLoader pmdClassLoader, Set importStmts) { - super(pmdClassLoader); - - // unfold imports, to store both FQ and unqualified names mapped to - // the FQ name - this.importStmts = new HashMap<>(); - for (final String stmt : importStmts) { - if (stmt.endsWith("*")) { - continue; - } - - this.importStmts.put(stmt, stmt); - final int lastDotIdx = stmt.lastIndexOf('.'); - if (lastDotIdx != -1) { - this.importStmts.put(stmt.substring(lastDotIdx + 1), stmt); - } - } - } - - @Override - public Class resolve(final String name) throws ClassNotFoundException { - final Class c = resolveMaybeInner(name, importStmts.get(name)); - - if (c == null) { - throw new ClassNotFoundException("Type " + name + " not found"); - } - - return c; - } - - @Override - public boolean couldResolve(final String name) { - return importStmts.containsKey(name); - } - } - - /** - * Resolver that uses the current package to resolve a simple class name. - */ - public static class CurrentPackageResolver extends AbstractResolver { - private final String pkg; - - /** - * Creates a new {@link CurrentPackageResolver} - * - * @param pmdClassLoader - * the class loader to use - * @param pkg - * the package name - */ - public CurrentPackageResolver(PMDASMClassLoader pmdClassLoader, String pkg) { - super(pmdClassLoader); - if (pkg == null || pkg.length() == 0) { - this.pkg = null; - } else { - this.pkg = pkg + "."; - } - } - - @Override - public Class resolve(String name) throws ClassNotFoundException { - if (name == null) { - throw new ClassNotFoundException(); - } - - return pmdClassLoader.loadClass(qualifyName(name)); - } - - @Override - public boolean couldResolve(String name) { - return pmdClassLoader.couldResolve(qualifyName(name)); - } - - private String qualifyName(final String name) { - final String qualifiedName = name.replace('.', '$'); - if (pkg == null) { - return qualifiedName; - } - - /* - * String.concat is bad in general, but for simple 2 string concatenation, it's the fastest - * See http://www.rationaljava.com/2015/02/the-optimum-method-to-concatenate.html - */ - return pkg.concat(qualifiedName); - } - } - - /** - * Resolver that resolves simple class names from the implicit import of - * java.lang.*. - */ - // TODO cite the JLS section on implicit imports - public static class ImplicitImportResolver extends AbstractResolver { - /* - * They aren't so many to bother about memory, but are used all the - * time, so we worry about performance. On average, you can expect this - * cache to have ~90% hit ratio unless abusing star imports (import on - * demand) - */ - private static final ConcurrentMap> CLASS_CACHE = new ConcurrentHashMap<>(); - - /** - * Creates a {@link ImplicitImportResolver} - * - * @param pmdClassLoader - * the class loader - */ - public ImplicitImportResolver(PMDASMClassLoader pmdClassLoader) { - super(pmdClassLoader); - } - - @Override - public Class resolve(String name) throws ClassNotFoundException { - if (name == null) { - throw new ClassNotFoundException(); - } - - Class clazz = CLASS_CACHE.get(name); - if (clazz != null) { - return clazz; - } - - /* - * String.concat is bad in general, but for simple 2 string concatenation, it's the fastest - * See http://www.rationaljava.com/2015/02/the-optimum-method-to-concatenate.html - */ - clazz = pmdClassLoader.loadClass("java.lang.".concat(name.replace('.', '$'))); - CLASS_CACHE.putIfAbsent(name, clazz); - - return clazz; - } - - @Override - public boolean couldResolve(String name) { - /* - * String.concat is bad in general, but for simple 2 string concatenation, it's the fastest - * See http://www.rationaljava.com/2015/02/the-optimum-method-to-concatenate.html - */ - return pmdClassLoader.couldResolve("java.lang.".concat(name.replace('.', '$'))); - } - } - - /** - * Resolver that uses the "on demand" import statements. - */ - public static class ImportOnDemandResolver extends AbstractResolver { - private Set importStmts; - - /** - * Creates a {@link ImportOnDemandResolver} - * - * @param pmdClassLoader - * the class loader to use - * @param importStmts - * the import statements - */ - public ImportOnDemandResolver(PMDASMClassLoader pmdClassLoader, Set importStmts) { - super(pmdClassLoader); - this.importStmts = new HashSet<>(); - for (final String stmt : importStmts) { - if (stmt.endsWith("*")) { - this.importStmts.add(stmt); - } - } - } - - @Override - public Class resolve(String name) throws ClassNotFoundException { - if (name == null) { - throw new ClassNotFoundException(); - } - - name = name.replace('.', '$'); - for (String importStmt : importStmts) { - final String fqClassName = new StringBuilder(importStmt.length() + name.length()).append(importStmt) - .replace(importStmt.length() - 1, importStmt.length(), name).toString(); - if (pmdClassLoader.couldResolve(fqClassName)) { - try { - return pmdClassLoader.loadClass(fqClassName); - } catch (ClassNotFoundException ignored) { - // ignored, we'll throw a custom exception later - } - } - } - - throw new ClassNotFoundException("Type " + name + " not found"); - } - - @Override - public boolean couldResolve(String name) { - name = name.replace('.', '$'); - for (String importStmt : importStmts) { - final String fqClassName = new StringBuilder(importStmt.length() + name.length()).append(importStmt) - .replace(importStmt.length() - 1, importStmt.length(), name).toString(); - // can any class be resolved / was never attempted? - if (pmdClassLoader.couldResolve(fqClassName)) { - return true; - } - } - - return false; - } - } - - /** - * Resolver that resolves primitive types such as int or double. - */ - public static class PrimitiveTypeResolver implements Resolver { - private static final Map> PRIMITIVE_TYPES; - - static { - final Map> types = new HashMap<>(); - types.put("int", int.class); - types.put("float", float.class); - types.put("double", double.class); - types.put("long", long.class); - types.put("boolean", boolean.class); - types.put("byte", byte.class); - - @SuppressWarnings("PMD.AvoidUsingShortType") // scoping the suppression just for the following statement - Class shortType = short.class; - types.put("short", shortType); - - types.put("char", char.class); - PRIMITIVE_TYPES = Collections.unmodifiableMap(types); - } - - @Override - public Class resolve(String name) throws ClassNotFoundException { - if (!PRIMITIVE_TYPES.containsKey(name)) { - throw new ClassNotFoundException(name); - } - return PRIMITIVE_TYPES.get(name); - } - - @Override - public boolean couldResolve(String name) { - return PRIMITIVE_TYPES.containsKey(name); - } - } - - /** - * Resolver that resolves the "void" type. - */ - public static class VoidResolver implements Resolver { - @Override - public Class resolve(String name) throws ClassNotFoundException { - if ("void".equals(name)) { - return void.class; - } - throw new ClassNotFoundException(name); - } - - @Override - public boolean couldResolve(String name) { - return "void".equals(name); - } - } - - /** - * Resolver that simply loads the class by name. This only works if the - * class name is given as a fully qualified name. - */ - public static class FullyQualifiedNameResolver extends AbstractResolver { - /** - * Creates a {@link FullyQualifiedNameResolver} - * - * @param pmdClassLoader - * the class loader to use - */ - public FullyQualifiedNameResolver(PMDASMClassLoader pmdClassLoader) { - super(pmdClassLoader); - } - - @Override - public Class resolve(String name) throws ClassNotFoundException { - if (name == null) { - throw new ClassNotFoundException(); - } - - final Class c = resolveMaybeInner(name, name); - - if (c == null) { - throw new ClassNotFoundException("Type " + name + " not found"); - } - - return c; - } - - @Override - public boolean couldResolve(String name) { - /* - * We can always try! - * If a file used an explicit import on A.Inner, the class loader will register - * A.Inner can't be resolved even if A$Inner can. - * If a second file used A.Inner without an explicit import, we would end here, - * super.couldResolve("A.Inner") will return false, but we CAN resolve it as A$Inner. - */ - return true; - } - } - - public void setASTCompilationUnitPackage(String pkg) { - this.pkg = pkg; - } - - public String getASTCompilationUnitPackage() { - return pkg; - } - - /** - * Adds a import to the list of imports - * - * @param importString - * the import to add - */ - public void addImport(String importString) { - imports.add(importString); - } - - public int getImportsCount() { - return imports.size(); - } - - public Set getExplicitImports() { - return imports; - } - - /** - * Resolves a class by its name using all known resolvers. - * - * @param name - * the name of the class, can be a simple name or a fully - * qualified name. - * @return the class or null if none found - */ - public Class findClass(String name) { - // we don't build the resolvers until now since we first want to get all - // the imports - if (resolvers.isEmpty()) { - buildResolvers(); - } - - for (final Resolver resolver : resolvers) { - if (resolver.couldResolve(name)) { - try { - return resolver.resolve(name); - } catch (ClassNotFoundException ignored) { - // ignored, maybe another resolver will find the class - } catch (LinkageError le) { - // we found the class, but there is a problem with it (see https://github.com/pmd/pmd/issues/328) - return null; - } - } - } - - return null; - } - - private void buildResolvers() { - resolvers.add(new PrimitiveTypeResolver()); - resolvers.add(new VoidResolver()); - resolvers.add(new ExplicitImportResolver(pmdClassLoader, imports)); - resolvers.add(new CurrentPackageResolver(pmdClassLoader, pkg)); - resolvers.add(new ImplicitImportResolver(pmdClassLoader)); - resolvers.add(new ImportOnDemandResolver(pmdClassLoader, imports)); - resolvers.add(new FullyQualifiedNameResolver(pmdClassLoader)); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypedNameDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypedNameDeclaration.java deleted file mode 100644 index c06d8e9e55..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/TypedNameDeclaration.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.symboltable; - -import net.sourceforge.pmd.lang.java.ast.TypeNode; - -public interface TypedNameDeclaration { - - String getTypeImage(); - - Class getType(); - - /** - * Nullable - */ - TypeNode getTypeNode(); - -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/VariableNameDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/VariableNameDeclaration.java deleted file mode 100644 index 5c0e88c526..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/VariableNameDeclaration.java +++ /dev/null @@ -1,143 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import net.sourceforge.pmd.lang.java.ast.ASTCatchParameter; -import net.sourceforge.pmd.lang.java.ast.ASTEnumConstant; -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; -import net.sourceforge.pmd.lang.java.ast.ASTLambdaParameter; -import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType; -import net.sourceforge.pmd.lang.java.ast.ASTRecordComponent; -import net.sourceforge.pmd.lang.java.ast.ASTReferenceType; -import net.sourceforge.pmd.lang.java.ast.ASTType; -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.java.ast.AccessNode; -import net.sourceforge.pmd.lang.java.ast.TypeNode; -import net.sourceforge.pmd.lang.symboltable.AbstractNameDeclaration; -import net.sourceforge.pmd.lang.symboltable.Scope; - -public class VariableNameDeclaration extends AbstractNameDeclaration implements TypedNameDeclaration { - - public VariableNameDeclaration(ASTVariableDeclaratorId node) { - super(node); - } - - @Override - public Scope getScope() { - return node.getScope().getEnclosingScope(ClassScope.class); - } - - public boolean isArray() { - return getDeclaratorId().hasArrayType(); - } - - @Deprecated - public int getArrayDepth() { - return getExplicitTypeNode().getArrayDepth(); - } - - public boolean isVarargs() { - ASTFormalParameter parameter = node.getFirstParentOfType(ASTFormalParameter.class); - return parameter != null && parameter.isVarargs(); - } - - public boolean isExceptionBlockParameter() { - return getDeclaratorId().isExceptionBlockParameter(); - } - - /** - * @deprecated use {@link #isTypeInferred()} - */ - @Deprecated - public boolean isLambdaTypelessParameter() { - return isTypeInferred(); - } - - public boolean isTypeInferred() { - return getDeclaratorId().isTypeInferred(); - } - - public boolean isPrimitiveType() { - return getExplicitTypeNode() instanceof ASTPrimitiveType; - } - - @Override - public String getTypeImage() { - ASTType typeNode = getExplicitTypeNode(); - if (typeNode != null) { - return typeNode.getTypeImage(); - } - return null; - } - - /** - * Note that an array of primitive types (int[]) is a reference type. - */ - public boolean isReferenceType() { - return getTypeNode() instanceof ASTReferenceType; - } - - public boolean isRecordComponent() { - return node.getParent() instanceof ASTRecordComponent; - } - - public AccessNode getAccessNodeParent() { - if (node.getParent() instanceof ASTFormalParameter) { - return (ASTFormalParameter) node.getParent(); - } else if (node.getParent() instanceof ASTLambdaParameter) { - return (ASTLambdaParameter) node.getParent(); - } else if (node.getParent() instanceof ASTEnumConstant) { - return (ASTEnumConstant) node.getParent(); - } else if (node.getParent() instanceof ASTCatchParameter) { - return (AccessNode) node.getParent(); - } else if (node.getParent() instanceof ASTRecordComponent) { - return null; - } - return (AccessNode) node.getParent().getParent(); - } - - public ASTVariableDeclaratorId getDeclaratorId() { - return (ASTVariableDeclaratorId) node; - } - - @Override - public TypeNode getTypeNode() { - return getDeclaratorId(); - } - - private ASTType getExplicitTypeNode() { - return getDeclaratorId().getTypeNode(); - } - - @Override - public Class getType() { - TypeNode typeNode = getExplicitTypeNode(); - if (typeNode != null) { - return typeNode.getType(); - } - // if there is no type node, then return the type of the declarator id. - // this might be a inferred type - return getDeclaratorId().getType(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof VariableNameDeclaration)) { - return false; - } - VariableNameDeclaration n = (VariableNameDeclaration) o; - return n.node.getImage().equals(node.getImage()); - } - - @Override - public int hashCode() { - return node.getImage().hashCode(); - } - - @Override - public String toString() { - return "Variable: image = '" + node.getImage() + "', line = " + node.getBeginLine(); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/package-info.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/package-info.java deleted file mode 100644 index de9b19d83d..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -/** - * This entire package is deprecated. - */ -package net.sourceforge.pmd.lang.java.symboltable; diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/AllJavaAstTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/AllJavaAstTreeDumpTest.java index 0e0207ce48..75a2ce437e 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/AllJavaAstTreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/AllJavaAstTreeDumpTest.java @@ -11,6 +11,7 @@ import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({ ParserCornersTest.class, + Java14TreeDumpTest.class, Java15TreeDumpTest.class, Java16PreviewTreeDumpTest.class, Java16TreeDumpTest.class, diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14Test.java deleted file mode 100644 index 836f0de1e3..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14Test.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - - -package net.sourceforge.pmd.lang.java.ast; - -import static org.hamcrest.Matchers.instanceOf; - -import java.util.ArrayList; -import java.util.List; - -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.lang.ast.ParseException; -import net.sourceforge.pmd.lang.java.JavaParsingHelper; - -/** - * Tests new java14 standard features. - */ -@Ignore("Needs to be fixed for new AST structure. All of this is already much better tested in Kotlin, I don't want to port these tests...") -public class Java14Test { - private final JavaParsingHelper java14 = - JavaParsingHelper.DEFAULT.withDefaultVersion("14") - .withResourceContext(Java14Test.class, "jdkversiontests/java14/"); - - private final JavaParsingHelper java13 = java14.withDefaultVersion("13"); - - /** - * Tests switch expressions with yield. - */ - @Test - public void switchExpressions() { - parseAndCheckSwitchExpression(java14); - } - - /** - * In java13, switch expressions are only available with preview. - */ - @Test(expected = ParseException.class) - public void switchExpressions13ShouldFail() { - parseAndCheckSwitchExpression(java13); - } - - private void parseAndCheckSwitchExpression(JavaParsingHelper parser) { - ASTCompilationUnit compilationUnit = parser.parseResource("SwitchExpressions.java"); - List switchStatements = compilationUnit.findDescendantsOfType(ASTSwitchStatement.class); - Assert.assertEquals(2, switchStatements.size()); - - Assert.assertTrue(switchStatements.get(0).getChild(0) instanceof ASTExpression); - Assert.assertTrue(switchStatements.get(0).getChild(1) instanceof ASTSwitchArrowBranch); - Assert.assertTrue(switchStatements.get(0).getChild(1).getChild(0) instanceof ASTSwitchLabel); - Assert.assertEquals(3, switchStatements.get(0).getChild(1).getChild(0).getNumChildren()); - Assert.assertTrue(switchStatements.get(0).getChild(2).getChild(0) instanceof ASTSwitchLabel); - Assert.assertFalse(((ASTSwitchLabel) switchStatements.get(0).getChild(2).getChild(0)).isDefault()); - Assert.assertEquals(1, switchStatements.get(0).getChild(2).getChild(0).getNumChildren()); - - Assert.assertTrue(switchStatements.get(1).getChild(3) instanceof ASTSwitchArrowBranch); - Assert.assertTrue(switchStatements.get(1).getChild(3).getChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(((ASTSwitchLabel) switchStatements.get(1).getChild(3).getChild(0)).isDefault()); - - List switchExpressions = compilationUnit.findDescendantsOfType(ASTSwitchExpression.class); - Assert.assertEquals(4, switchExpressions.size()); - - Assert.assertEquals(Integer.TYPE, switchExpressions.get(0).getType()); - Assert.assertEquals(4, switchExpressions.get(0).findChildrenOfType(ASTSwitchArrowBranch.class).size()); - Assert.assertEquals(Integer.TYPE, switchExpressions.get(0).getFirstChildOfType(ASTSwitchArrowBranch.class) - .getFirstChildOfType(ASTExpression.class).getType()); - - Assert.assertTrue(switchExpressions.get(1).getChild(3) instanceof ASTSwitchArrowBranch); - - Assert.assertEquals(Integer.TYPE, switchExpressions.get(2).getType()); - List yields = switchExpressions.get(2).findDescendantsOfType(ASTYieldStatement.class); - Assert.assertEquals(4, yields.size()); - Assert.assertEquals("SwitchExpressions.BAZ", yields.get(2).getImage()); - - Assert.assertEquals(String.class, switchExpressions.get(3).getType()); - } - - @Test - public void checkYieldConditionalBehaviour() { - checkYieldStatements(java14); - } - - private void checkYieldStatements(JavaParsingHelper parser) { - ASTCompilationUnit compilationUnit = parser.parseResource("YieldStatements.java"); - List blockStmts = compilationUnit.findDescendantsOfType(ASTBlockStatement.class); - List stmts = new ArrayList<>(); - // fetch the interesting node, on the java-grammar branch this is not needed - for (int i = 0; i < blockStmts.size(); i++) { - JavaNode child = blockStmts.get(i).getChild(0); - - if (child instanceof ASTStatement) { - stmts.add(child.getChild(0)); - } else { - stmts.add(child); - } - } - - Assert.assertEquals(18, stmts.size()); - - int i = 0; - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTLocalVariableDeclaration.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTYieldStatement.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTYieldStatement.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTYieldStatement.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTIfStatement.class)); - - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTYieldStatement.class)); - - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTYieldStatement.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTStatementExpression.class)); - MatcherAssert.assertThat(stmts.get(i++), instanceOf(ASTYieldStatement.class)); - - Assert.assertEquals(i, stmts.size()); - } - - @Test - public void multipleCaseLabels() { - multipleCaseLabels(java14); - } - - private void multipleCaseLabels(JavaParsingHelper parser) { - ASTCompilationUnit compilationUnit = parser.parseResource("MultipleCaseLabels.java"); - ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class); - Assert.assertTrue(switchStatement.getChild(0) instanceof ASTExpression); - Assert.assertTrue(switchStatement.getChild(1) instanceof ASTSwitchLabel); - ASTSwitchLabel switchLabel = switchStatement.getFirstChildOfType(ASTSwitchLabel.class); - Assert.assertEquals(3, switchLabel.findChildrenOfType(ASTExpression.class).size()); - } - - @Test - public void switchRules() { - switchRules(java14); - } - - private void switchRules(JavaParsingHelper parser) { - ASTCompilationUnit compilationUnit = parser.parseResource("SwitchRules.java"); - ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class); - Assert.assertTrue(switchStatement.getChild(0) instanceof ASTExpression); - Assert.assertTrue(switchStatement.getChild(1) instanceof ASTSwitchArrowBranch); - ASTSwitchArrowBranch switchLabeledExpression = (ASTSwitchArrowBranch) switchStatement.getChild(1); - Assert.assertEquals(2, switchLabeledExpression.getNumChildren()); - Assert.assertTrue(switchLabeledExpression.getChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(switchLabeledExpression.getChild(1) instanceof ASTExpression); - - ASTSwitchArrowBranch switchLabeledBlock = (ASTSwitchArrowBranch) switchStatement.getChild(4); - Assert.assertEquals(2, switchLabeledBlock.getNumChildren()); - Assert.assertTrue(switchLabeledBlock.getChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(switchLabeledBlock.getChild(1) instanceof ASTBlock); - - ASTSwitchArrowBranch switchLabeledThrowStatement = (ASTSwitchArrowBranch) switchStatement.getChild(5); - Assert.assertEquals(2, switchLabeledThrowStatement.getNumChildren()); - Assert.assertTrue(switchLabeledThrowStatement.getChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(switchLabeledThrowStatement.getChild(1) instanceof ASTThrowStatement); - } - - @Test - public void simpleSwitchExpressions() { - simpleSwitchExpressions(java14); - } - - private void simpleSwitchExpressions(JavaParsingHelper parser) { - ASTCompilationUnit compilationUnit = parser.parseResource("SimpleSwitchExpressions.java"); - ASTSwitchExpression switchExpression = compilationUnit.getFirstDescendantOfType(ASTSwitchExpression.class); - Assert.assertEquals(6, switchExpression.getNumChildren()); - Assert.assertTrue(switchExpression.getChild(0) instanceof ASTExpression); - Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchArrowBranch.class).size()); - - ASTLocalVariableDeclaration localVar = compilationUnit.findDescendantsOfType(ASTLocalVariableDeclaration.class).get(1); - ASTVariableDeclarator localVarDecl = localVar.getFirstChildOfType(ASTVariableDeclarator.class); - Assert.assertEquals(Integer.TYPE, localVarDecl.getType()); - Assert.assertEquals(Integer.TYPE, switchExpression.getType()); - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14TreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14TreeDumpTest.java new file mode 100644 index 0000000000..8f7fa253d8 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14TreeDumpTest.java @@ -0,0 +1,70 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + + +package net.sourceforge.pmd.lang.java.ast; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.junit.Test; + +import net.sourceforge.pmd.lang.ast.ParseException; +import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper; +import net.sourceforge.pmd.lang.java.BaseJavaTreeDumpTest; +import net.sourceforge.pmd.lang.java.JavaParsingHelper; + +/** + * Tests new java14 standard features. + */ +public class Java14TreeDumpTest extends BaseJavaTreeDumpTest { + + private final JavaParsingHelper java14 = + JavaParsingHelper.DEFAULT.withDefaultVersion("14") + .withResourceContext(Java14TreeDumpTest.class, "jdkversiontests/java14/"); + + private final JavaParsingHelper java13 = java14.withDefaultVersion("13"); + + @Override + public @NonNull BaseParsingHelper getParser() { + return java14; + } + + /** + * Tests switch expressions with yield. + */ + @Test + public void switchExpressions() { + doTest("SwitchExpressions"); + } + + /** + * In java13, switch expressions are only available with preview. + */ + @Test + public void switchExpressions13ShouldFail() { + assertThrows(ParseException.class, () -> java13.parseResource("SwitchExpressions.java")); + } + + @Test + public void checkYieldConditionalBehaviour() { + doTest("YieldStatements"); + } + + @Test + public void multipleCaseLabels() { + doTest("MultipleCaseLabels"); + } + + @Test + public void switchRules() { + doTest("SwitchRules"); + } + + @Test + public void simpleSwitchExpressions() { + doTest("SimpleSwitchExpressions"); + } + +} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java index 7c852d2a53..7614137726 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java @@ -9,12 +9,14 @@ import java.util.List; import org.junit.Assert; import org.junit.Test; +import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.ast.ParseException; import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper; import net.sourceforge.pmd.lang.java.BaseJavaTreeDumpTest; import net.sourceforge.pmd.lang.java.JavaParsingHelper; import net.sourceforge.pmd.lang.java.symbols.JElementSymbol; import net.sourceforge.pmd.lang.java.types.JPrimitiveType; +import net.sourceforge.pmd.lang.java.types.TypeTestUtil; public class Java16TreeDumpTest extends BaseJavaTreeDumpTest { private final JavaParsingHelper java16 = @@ -34,14 +36,12 @@ public class Java16TreeDumpTest extends BaseJavaTreeDumpTest { doTest("PatternMatchingInstanceof"); // extended tests for type resolution etc. - ASTCompilationUnit compilationUnit = java16.parseResource("PatternMatchingInstanceof.java"); - List instanceOfExpressions = compilationUnit.findDescendantsOfType(ASTInstanceOfExpression.class); - for (ASTInstanceOfExpression expr : instanceOfExpressions) { - ASTVariableDeclaratorId variable = expr.getChild(1).getFirstChildOfType(ASTVariableDeclaratorId.class); - Assert.assertEquals(String.class, variable.getType()); - // Note: these variables are not part of the symbol table - // See ScopeAndDeclarationFinder#visit(ASTVariableDeclaratorId, Object) - Assert.assertNull(variable.getNameDeclaration()); + ASTCompilationUnit ast = java16.parseResource("PatternMatchingInstanceof.java"); + NodeStream patterns = + ast.descendants(ASTTypePattern.class) + .filter(it -> BinaryOp.isInfixExprWithOperator(it, BinaryOp.INSTANCEOF)); + for (ASTTypePattern expr : patterns) { + Assert.assertTrue(TypeTestUtil.isA(String.class, expr.getVarId())); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java index 3a6161dbc8..1c28c9c3f1 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java @@ -4,12 +4,13 @@ package net.sourceforge.pmd.lang.java.ast; -import java.util.List; -import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.collection.IsEmptyCollection.empty; import org.checkerframework.checker.nullness.qual.NonNull; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -19,8 +20,8 @@ import net.sourceforge.pmd.lang.ast.TokenMgrError; import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper; import net.sourceforge.pmd.lang.java.BaseJavaTreeDumpTest; import net.sourceforge.pmd.lang.java.JavaParsingHelper; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; +import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; +import net.sourceforge.pmd.lang.java.types.AstTestUtil; public class ParserCornersTest extends BaseJavaTreeDumpTest { private final JavaParsingHelper java = JavaParsingHelper.DEFAULT.withResourceContext(getClass()); @@ -89,12 +90,17 @@ public class ParserCornersTest extends BaseJavaTreeDumpTest { @Test public final void testGetFirstASTNameImageNull() { - java4.parse(ABSTRACT_METHOD_LEVEL_CLASS_DECL); + java4.parse("public class Test {\n" + + " void bar() {\n" + + " abstract class X { public abstract void f(); }\n" + + " class Y extends X { public void f() { new Y().f(); } }\n" + + " }\n" + + "}"); } @Test public final void testCastLookaheadProblem() { - java4.parse(CAST_LOOKAHEAD_PROBLEM); + java4.parse("public class BadClass {\n public Class foo() {\n return (byte[].class);\n }\n}"); } @Test @@ -130,8 +136,13 @@ public class ParserCornersTest extends BaseJavaTreeDumpTest { */ @Test public void testGenericsProblem() { - java5.parse(GENERICS_PROBLEM); - java7.parse(GENERICS_PROBLEM); + String code = "public class Test {\n" + + " public void test() {\n" + + " String o = super. doStuff(\"\");\n" + + " }\n" + + "}"; + java5.parse(code); + java7.parse(code); } @Test @@ -228,7 +239,7 @@ public class ParserCornersTest extends BaseJavaTreeDumpTest { // https://github.com/pmd/pmd/issues/1484 String code = "public class Test {\n" + " public static void main(String[] args) {\n" + " System.out.println(\"X\" + (args) + \"Y\");\n" + " }\n" + "}"; - Assert.assertEquals(0, java8.parse(code).findDescendantsOfType(ASTCastExpression.class).size()); + Assert.assertEquals(0, java8.parse(code).descendants(ASTCastExpression.class).count()); } @@ -253,24 +264,15 @@ public class ParserCornersTest extends BaseJavaTreeDumpTest { } @Test - @Ignore("this test depends on usage resolution") public void testMethodReferenceConfused() { - ASTCompilationUnit compilationUnit = java.parseResource("MethodReferenceConfused.java", "10"); - Assert.assertNotNull(compilationUnit); - ASTBlock firstBlock = compilationUnit.getFirstDescendantOfType(ASTBlock.class); - Map> declarations = firstBlock.getScope().getDeclarations(); - boolean foundVariable = false; - for (Map.Entry> declaration : declarations.entrySet()) { - String varName = declaration.getKey().getImage(); - if ("someVarNameSameAsMethodReference".equals(varName)) { - foundVariable = true; - Assert.assertTrue("no usages expected", declaration.getValue().isEmpty()); - } else if ("someObject".equals(varName)) { - Assert.assertEquals("1 usage expected", 1, declaration.getValue().size()); - Assert.assertEquals(6, declaration.getValue().get(0).getLocation().getBeginLine()); - } - } - Assert.assertTrue("Test setup wrong - variable 'someVarNameSameAsMethodReference' not found anymore!", foundVariable); + ASTCompilationUnit ast = java.parseResource("MethodReferenceConfused.java", "10"); + ASTVariableDeclaratorId someVarNameSameAsMethodReference = AstTestUtil.varId(ast, "someVarNameSameAsMethodReference"); + ASTVariableDeclaratorId someObject = AstTestUtil.varId(ast, "someObject"); + + assertThat(someVarNameSameAsMethodReference.getLocalUsages(), empty()); + assertThat(someObject.getLocalUsages(), hasSize(1)); + ASTNamedReferenceExpr usage = someObject.getLocalUsages().get(0); + assertThat(usage.getParent(), instanceOf(ASTCastExpression.class)); } @Test @@ -289,20 +291,6 @@ public class ParserCornersTest extends BaseJavaTreeDumpTest { } - private static final String GENERICS_PROBLEM = - "public class Test {\n public void test() {\n String o = super. doStuff(\"\");\n }\n}"; - - private static final String ABSTRACT_METHOD_LEVEL_CLASS_DECL = - "public class Test {\n" - + " void bar() {\n" - + " abstract class X { public abstract void f(); }\n" - + " class Y extends X { public void f() { new Y().f(); } }\n" - + " }\n" - + "}"; - - private static final String CAST_LOOKAHEAD_PROBLEM = - "public class BadClass {\n public Class foo() {\n return (byte[].class);\n }\n}"; - @Test public void testGithubBug3101UnresolvedTypeParams() { java.parseResource("GitHubBug3101.java"); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/AcceptanceTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/AcceptanceTest.java deleted file mode 100644 index acc562f48a..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/AcceptanceTest.java +++ /dev/null @@ -1,191 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.List; -import java.util.Map; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTBlock; -import net.sourceforge.pmd.lang.java.ast.ASTCatchClause; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression; -import net.sourceforge.pmd.lang.java.ast.ASTInitializer; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; -import net.sourceforge.pmd.lang.symboltable.Scope; - -@Ignore -public class AcceptanceTest extends BaseParserTest { - - @Test - public void testClashingSymbols() { - parseCode(TEST1); - } - - @Test - public void testInitializer() { - ASTCompilationUnit acu = parseCode(TEST_INITIALIZERS); - ASTInitializer a = acu.findDescendantsOfType(ASTInitializer.class).get(0); - assertFalse(a.isStatic()); - a = acu.findDescendantsOfType(ASTInitializer.class).get(1); - assertTrue(a.isStatic()); - } - - @Test - public void testCatchBlocks() { - ASTCompilationUnit acu = parseCode(TEST_CATCH_BLOCKS); - ASTCatchClause c = acu.findDescendantsOfType(ASTCatchClause.class).get(0); - ASTBlock a = c.findDescendantsOfType(ASTBlock.class).get(0); - Scope s = a.getScope(); - Map> vars = s.getDeclarations(); - assertEquals(1, vars.size()); - NameDeclaration v = vars.keySet().iterator().next(); - assertEquals("e", v.getImage()); - assertEquals(1, (vars.get(v)).size()); - } - - @Test - public void testEq() { - ASTCompilationUnit acu = parseCode(TEST_EQ); - ASTEqualityExpression e = acu.findDescendantsOfType(ASTEqualityExpression.class).get(0); - ASTMethodDeclaration method = e.getFirstParentOfType(ASTMethodDeclaration.class); - Scope s = method.getScope(); - Map> m = s.getDeclarations(); - assertEquals(2, m.size()); - for (Map.Entry> entry : m.entrySet()) { - NameDeclaration vnd = entry.getKey(); - List usages = entry.getValue(); - - if (vnd.getImage().equals("a") || vnd.getImage().equals("b")) { - assertEquals(1, usages.size()); - assertEquals(3, usages.get(0).getLocation().getBeginLine()); - } else { - fail("Unknown variable " + vnd); - } - } - } - - @Test - public void testFieldFinder() { - ASTCompilationUnit acu = parseCode(TEST_FIELD); - // System.out.println(TEST_FIELD); - - ASTVariableDeclaratorId declaration = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(1); - assertEquals(3, declaration.getBeginLine()); - assertEquals("bbbbbbbbbb", declaration.getImage()); - assertEquals(1, declaration.getUsages().size()); - NameOccurrence no = declaration.getUsages().get(0); - Node location = no.getLocation(); - assertEquals(6, location.getBeginLine()); - // System.out.println("variable " + declaration.getImage() + " is used - // here: " + location.getImage()); - } - - @Test - public void testDemo() { - ASTCompilationUnit acu = parseCode(TEST_DEMO); - // System.out.println(TEST_DEMO); - ASTMethodDeclaration node = acu.findDescendantsOfType(ASTMethodDeclaration.class).get(0); - Scope s = node.getScope(); - Map> m = s.getDeclarations(); - for (Map.Entry> entry : m.entrySet()) { - assertEquals("buz", entry.getKey().getImage()); - assertEquals("ArrayList", ((TypedNameDeclaration) entry.getKey()).getTypeImage()); - List u = entry.getValue(); - assertEquals(1, u.size()); - NameOccurrence o = u.get(0); - int beginLine = o.getLocation().getBeginLine(); - assertEquals(3, beginLine); - - // System.out.println("Variable: " + d.getImage()); - // System.out.println("Type: " + d.getTypeImage()); - // System.out.println("Usages: " + u.size()); - // System.out.println("Used in line " + beginLine); - } - } - - @Test - public void testEnum() { - ASTCompilationUnit acu = parseCode(NameOccurrencesTest.TEST_ENUM); - - ASTVariableDeclaratorId vdi = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0); - List usages = vdi.getUsages(); - assertEquals(2, usages.size()); - assertEquals(5, usages.get(0).getLocation().getBeginLine()); - assertEquals(9, usages.get(1).getLocation().getBeginLine()); - } - - @Test - public void testInnerOuterClass() { - ASTCompilationUnit acu = parseCode(TEST_INNER_CLASS); - ASTVariableDeclaratorId vdi = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(1) // get inner class - .getFirstDescendantOfType(ASTVariableDeclaratorId.class); // get first declaration - List usages = vdi.getUsages(); - assertEquals(2, usages.size()); - assertEquals(5, usages.get(0).getLocation().getBeginLine()); - assertEquals(10, usages.get(1).getLocation().getBeginLine()); - } - - /** - * Unit test for bug #1490 - * - * @see #1490 [java] PMD - * Error while processing - NullPointerException - */ - @Test - public void testNullPointerEnumValueOfOverloaded() { - ASTCompilationUnit acu = parseCode("public enum EsmDcVoltageSensor {\n" + " A;\n" + " void bar(int... args) {\n" - + " int idx;\n" + " int startIdx;\n" - + " String name = EsmDcVoltageSensor.valueOf((byte) (idx - startIdx)).getName();\n" + " }\n" - // that's the overloaded method - + " public EsmDCVoltageSensor valueOf(byte b) {\n" - + " }\n" + "}\n"); - } - - private static final String TEST_DEMO = "public class Foo {" + PMD.EOL + " void bar(ArrayList buz) { " + PMD.EOL - + " buz.add(\"foo\");" + PMD.EOL + " } " + PMD.EOL + "}" + PMD.EOL; - - private static final String TEST_EQ = "public class Foo {" + PMD.EOL + " boolean foo(String a, String b) { " - + PMD.EOL + " return a == b; " + PMD.EOL + " } " + PMD.EOL + "}" + PMD.EOL; - - private static final String TEST1 = "import java.io.*;" + PMD.EOL + "public class Foo {" + PMD.EOL - + " void buz( ) {" + PMD.EOL + " Object o = new Serializable() { int x; };" + PMD.EOL - + " Object o1 = new Serializable() { int x; };" + PMD.EOL + " }" + PMD.EOL + "}" + PMD.EOL; - - private static final String TEST_INITIALIZERS = "public class Foo {" + PMD.EOL + " {} " + PMD.EOL + " static {} " - + PMD.EOL + "}" + PMD.EOL; - - private static final String TEST_CATCH_BLOCKS = "public class Foo {" + PMD.EOL + " void foo() { " + PMD.EOL - + " try { " + PMD.EOL + " } catch (Exception e) { " + PMD.EOL + " e.printStackTrace(); " + PMD.EOL - + " } " + PMD.EOL + " } " + PMD.EOL + "}" + PMD.EOL; - - private static final String TEST_FIELD = "public class MyClass {" + PMD.EOL + " private int aaaaaaaaaa; " + PMD.EOL - + " boolean bbbbbbbbbb = MyClass.ASCENDING; " + PMD.EOL + " private int zzzzzzzzzz;" + PMD.EOL - + " private void doIt() {" + PMD.EOL + " if (bbbbbbbbbb) {" + PMD.EOL + " }" + PMD.EOL + " }" + PMD.EOL - + "}" + PMD.EOL; - - public static final String TEST_INNER_CLASS = "public class Outer {" + PMD.EOL + " private static class Inner {" - + PMD.EOL + " private int i;" + PMD.EOL + " private Inner(int i) {" + PMD.EOL + " this.i = i;" - + PMD.EOL + " }" + PMD.EOL + " }" + PMD.EOL + " public int modify(int i) {" + PMD.EOL - + " Inner in = new Inner(i);" + PMD.EOL + " return in.i;" + PMD.EOL + " }" + PMD.EOL + "}" + PMD.EOL; - - public static junit.framework.Test suite() { - return new junit.framework.JUnit4TestAdapter(AcceptanceTest.class); - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ClassScopeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ClassScopeTest.java deleted file mode 100644 index 6351fe0c35..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ClassScopeTest.java +++ /dev/null @@ -1,381 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -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.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.java.ast.InternalApiBridge; -import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.symboltable.testdata.InnerClass; -import net.sourceforge.pmd.lang.java.symboltable.testdata.InnerClass.TheInnerClass; -import net.sourceforge.pmd.lang.java.symboltable.testdata.InnerClass.TheInnerClass.EnumTest; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -@Ignore -public class ClassScopeTest extends BaseParserTest { - - @Test - public void testEnumsClassScope() { - java5.parse(ENUM_SCOPE); - } - - @Test - public void testEnumTypeParameter() { - java5.parse(ENUM_TYPE_PARAMETER); - } - - @Test - public void testVarArgsEmpty() { - java5.parse("public class Foo {\n" + " public void bar1(String s, Integer... i) {}\n" - + " public void bar1() {}\n" + " public void c() {\n" + " bar1();\n" + " }\n" + "}\n"); - } - - // FIXME - these will break when this goes from Anonymous$1 to Foo$1 - @Test - public void testAnonymousInnerClassName() { - ClassNameDeclaration classDeclaration = new ClassNameDeclaration(null); - ClassScope s = new ClassScope("Foo", classDeclaration); - s = new ClassScope(classDeclaration); - assertEquals("Anonymous$1", s.getClassName()); - s = new ClassScope(classDeclaration); - assertEquals("Anonymous$2", s.getClassName()); - } - - @Test - public void testContains() { - ClassNameDeclaration classDeclaration = new ClassNameDeclaration(null); - ClassScope s = new ClassScope("Foo", classDeclaration); - ASTVariableDeclaratorId node = InternalApiBridge.newVarId("bar"); - s.addDeclaration(new VariableNameDeclaration(node)); - assertTrue(s.getDeclarations().keySet().iterator().hasNext()); - } - - @Test - public void testCantContainsSuperToString() { - ASTCompilationUnit cu = java.parse("class Foo { public String toString() { return super.toString(); } }"); - ClassNameDeclaration classDeclaration = new ClassNameDeclaration(cu.getFirstDescendantOfType(ASTClassOrInterfaceDeclaration.class)); - ClassScope s = new ClassScope("Foo", classDeclaration); - JavaNode node = cu.getFirstDescendantOfType(ASTPrimaryExpression.class); // "super.toString();" - assertFalse(s.contains(new JavaNameOccurrence(node, "super.toString"))); - } - - @Test - public void testContainsStaticVariablePrefixedWithClassName() { - ASTCompilationUnit cu = java.parse("class Foo { static int X; public int bar() { return Foo.X; } }"); - - ClassNameDeclaration classDeclaration = new ClassNameDeclaration(cu.getFirstDescendantOfType(ASTClassOrInterfaceDeclaration.class)); - ClassScope s = new ClassScope("Foo", classDeclaration); - ASTVariableDeclaratorId node = cu.getFirstDescendantOfType(ASTVariableDeclaratorId.class); - s.addDeclaration(new VariableNameDeclaration(node)); - - JavaNode node2 = cu.getFirstDescendantOfType(ASTName.class); - assertTrue(s.contains(new JavaNameOccurrence(node2, node2.getImage()))); - } - - @Test - public void testClassName() { - ASTCompilationUnit acu = parseCode(CLASS_NAME); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - assertEquals("Foo", n.getScope().getEnclosingScope(ClassScope.class).getClassName()); - } - - @Test - public void testMethodDeclarationRecorded() { - ASTCompilationUnit acu = parseCode(METHOD_DECLARATIONS_RECORDED); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - ClassScope s = (ClassScope) n.getScope(); - Map> m = s.getDeclarations(); - assertEquals(1, m.size()); - MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next(); - assertEquals("bar", mnd.getImage()); - ASTMethodDeclaration node = (ASTMethodDeclaration) mnd.getNode().getParent(); - assertTrue(node.isPrivate()); - } - - @Test - public void testTwoMethodsSameNameDiffArgs() { - // TODO this won't work with String and java.lang.String - ASTCompilationUnit acu = parseCode(METHODS_WITH_DIFF_ARG); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - assertEquals(2, m.size()); - Iterator i = m.keySet().iterator(); - MethodNameDeclaration mnd = (MethodNameDeclaration) i.next(); - assertEquals("bar", mnd.getImage()); - assertEquals("bar", ((MethodNameDeclaration) i.next()).getImage()); - } - - @Test - public final void testOneParam() { - ASTCompilationUnit acu = parseCode(ONE_PARAM); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next(); - assertEquals("(String)", mnd.getParameterDisplaySignature()); - } - - @Test - public final void testTwoParams() { - ASTCompilationUnit acu = parseCode(TWO_PARAMS); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next(); - assertEquals("(String,int)", mnd.getParameterDisplaySignature()); - } - - @Test - public final void testNoParams() { - ASTCompilationUnit acu = parseCode(NO_PARAMS); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next(); - assertEquals("()", mnd.getParameterDisplaySignature()); - } - - @Test - public final void testOneParamVararg() { - ASTCompilationUnit acu = java5.parse(ONE_PARAM_VARARG); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next(); - assertEquals("(String...)", mnd.getParameterDisplaySignature()); - } - - @Test - public final void testTwoParamsVararg() { - ASTCompilationUnit acu = java5.parse(TWO_PARAMS_VARARG); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next(); - assertEquals("(String,String...)", mnd.getParameterDisplaySignature()); - } - - @Test - public void testNestedClassesOfImportResolution() { - ASTCompilationUnit acu = parseCode(NESTED_CLASSES_OF_IMPORT); - final ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - final ClassScope c = (ClassScope) n.getScope(); - assertEquals(EnumTest.class, c.resolveType("TheInnerClass.EnumTest")); - } - - @Test - public void testNestedClassesResolution() { - final ASTClassOrInterfaceDeclaration n = java.parseClass(InnerClass.class) - .findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - final ClassScope c = (ClassScope) n.getScope(); - assertEquals(InnerClass.class, c.resolveType("InnerClass")); - assertEquals(TheInnerClass.class, c.resolveType("InnerClass.TheInnerClass")); - assertEquals(TheInnerClass.class, c.resolveType("TheInnerClass")); // Within this scope, we can access it directly - } - - @Test - public void testImportNestedClassesResolution() { - ASTCompilationUnit acu = parseCode(IMPORT_NESTED_CLASSES); - final ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - final ClassScope c = (ClassScope) n.getScope(); - assertEquals(EnumTest.class, c.resolveType("EnumTest")); - } - - @Test - public final void testNestedClassDeclFound() { - ASTCompilationUnit acu = parseCode(NESTED_CLASS_FOUND); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - ClassScope c = (ClassScope) n.getScope(); - Map> m = c.getDeclarations(); - ClassNameDeclaration cnd = (ClassNameDeclaration) m.keySet().iterator().next(); - assertEquals("Buz", cnd.getImage()); - } - - @Test - public final void testbuz() { - parseCode(METH); - // SymbolTableViewer st = new SymbolTableViewer(); - // acu.jjtAccept(st, null); - } - - @Test - public void testMethodUsageSeen() { - ASTCompilationUnit acu = parseCode(METHOD_USAGE_SEEN); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - Iterator>> i = m.entrySet().iterator(); - MethodNameDeclaration mnd; - Map.Entry> entry; - - do { - entry = i.next(); - mnd = (MethodNameDeclaration) entry.getKey(); - } while (!mnd.getImage().equals("bar")); - - List usages = entry.getValue(); - assertEquals(1, usages.size()); - assertEquals("bar", ((JavaNameOccurrence) usages.get(0)).getImage()); - } - - @Test - public void testMethodUsageSeenWithThis() { - ASTCompilationUnit acu = parseCode(METHOD_USAGE_SEEN_WITH_THIS); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - Iterator>> i = m.entrySet().iterator(); - MethodNameDeclaration mnd; - Map.Entry> entry; - - do { - entry = i.next(); - mnd = (MethodNameDeclaration) entry.getKey(); - } while (!mnd.getImage().equals("bar")); - - List usages = entry.getValue(); - assertEquals(1, usages.size()); - assertEquals("bar", ((JavaNameOccurrence) usages.get(0)).getImage()); - } - - @Test - public void testMethodUsageSeen2() { - ASTCompilationUnit acu = parseCode(METHOD_USAGE_SEEN2); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - - assertEquals(2, m.size()); - - for (Map.Entry> entry : m.entrySet()) { - assertEquals("baz", entry.getKey().getImage()); - if (entry.getKey().getNode().getBeginLine() == 2) { - // this is the public method declaration - it is not used - // anywhere - assertEquals(0, entry.getValue().size()); - } else if (entry.getKey().getNode().getBeginLine() == 5) { - // this is the private (overloaded) method - assertEquals(1, entry.getValue().size()); - // it's used once in line 3 - assertEquals(3, entry.getValue().get(0).getLocation().getBeginLine()); - } else { - fail("unexpected name declaration"); - } - } - } - - /** - * Test case for bug report #2410201 - */ - @Test - public void testNestedClassFieldAndParameter() { - ASTCompilationUnit acu = parseCode(NESTED_CLASS_FIELD_AND_PARAM); - ASTMethodDeclaration node = acu.getFirstDescendantOfType(ASTMethodDeclaration.class); - Map> vd = node.getScope().getDeclarations(VariableNameDeclaration.class); - assertEquals(2, vd.size()); - - int paramCount = 0; - for (Map.Entry> entry : vd.entrySet()) { - if (entry.getKey().getDeclaratorId().isFormalParameter()) { - assertEquals("field", entry.getKey().getImage()); - - List occurrences = entry.getValue(); - assertEquals(2, occurrences.size()); - NameOccurrence no1 = occurrences.get(0); - assertEquals(8, no1.getLocation().getBeginLine()); - NameOccurrence no2 = occurrences.get(1); - assertEquals(9, no2.getLocation().getBeginLine()); - paramCount++; - } - } - - assertEquals(1, paramCount); - } - - @Test - public void testNullType() { - ASTCompilationUnit acu = parseCode(TEST_NULL_TYPE); - } - - private static final String NESTED_CLASS_FIELD_AND_PARAM = "public class Foo {" + PMD.EOL + " class Test {" - + PMD.EOL + " public String field;" + PMD.EOL + " public Test t;" + PMD.EOL + " }" + PMD.EOL - + " public void foo(String field) {" + PMD.EOL + " Test t = new Test();" + PMD.EOL + " t.field = field;" - + PMD.EOL + " t.t.field = field;" + PMD.EOL + " }" + PMD.EOL + "}"; - - private static final String METHOD_USAGE_SEEN2 = "public class Foo {" + PMD.EOL + " public void baz() {" + PMD.EOL - + " baz(x, y);" + PMD.EOL + " }" + PMD.EOL + " private void baz(int x, int y) {}" + PMD.EOL + "}"; - - private static final String METHOD_USAGE_SEEN = "public class Foo {" + PMD.EOL + " private void bar() {}" + PMD.EOL - + " public void buz() {" + PMD.EOL + " bar();" + PMD.EOL + " }" + PMD.EOL + "}"; - - private static final String METHOD_USAGE_SEEN_WITH_THIS = "public class Foo {" + PMD.EOL + " private void bar() {}" - + PMD.EOL + " public void buz() {" + PMD.EOL + " this.bar();" + PMD.EOL + " }" + PMD.EOL + "}"; - - private static final String METH = "public class Test {" + PMD.EOL + " static { " + PMD.EOL + " int y; " - + PMD.EOL + " } " + PMD.EOL + " void bar(int x) {} " + PMD.EOL + " void baz(int x) {} " + PMD.EOL + "}"; - - private static final String NESTED_CLASS_FOUND = "public class Test {" + PMD.EOL + " private class Buz {} " - + PMD.EOL + "}"; - - private static final String ONE_PARAM = "public class Test {" + PMD.EOL + " void bar(String x) {" + PMD.EOL + " }" - + PMD.EOL + "}"; - - private static final String TWO_PARAMS = "public class Test {" + PMD.EOL + " void bar(String x, int y) {" + PMD.EOL - + " }" + PMD.EOL + "}"; - - private static final String NO_PARAMS = "public class Test {" + PMD.EOL + " void bar() {" + PMD.EOL + " }" - + PMD.EOL + "}"; - - private static final String ONE_PARAM_VARARG = "public class Test {" + PMD.EOL + " void bar(String... s) {" - + PMD.EOL + " }" + PMD.EOL + "}"; - - private static final String TWO_PARAMS_VARARG = "public class Test {" + PMD.EOL - + " void bar(String s1, String... s2) {" + PMD.EOL + " }" + PMD.EOL + "}"; - - private static final String CLASS_NAME = "public class Foo {}"; - - private static final String METHOD_DECLARATIONS_RECORDED = "public class Foo {" + PMD.EOL + " private void bar() {}" - + PMD.EOL + "}"; - - private static final String METHODS_WITH_DIFF_ARG = "public class Foo {" + PMD.EOL - + " private void bar(String x) {}" + PMD.EOL + " private void bar() {}" + PMD.EOL + "}"; - - private static final String ENUM_SCOPE = "public enum Foo {" + PMD.EOL + " HEAP(\"foo\");" + PMD.EOL - + " private final String fuz;" + PMD.EOL + " public String getFuz() {" + PMD.EOL + " return fuz;" + PMD.EOL - + " }" + PMD.EOL + "}"; - - public static final String TEST_NULL_TYPE = "public abstract class NullTypeTest {" + PMD.EOL - + " protected Comparator nodesComparator = (o1, o2) -> StringHelper.saveCompare(getFilterableString(o1), getFilterableString(o2));" - + PMD.EOL + " public abstract String getFilterableString(TreeNode node);" + PMD.EOL + "}"; - - private static final String ENUM_TYPE_PARAMETER = "public enum Foo {" + PMD.EOL - + " BAR(isCustomer(BazEnum.FOO_BAR));" + PMD.EOL + " Foo(boolean isCustomer) { }" + PMD.EOL - + " private static boolean isCustomer(BazEnum baz) {" + PMD.EOL + " return false;" + PMD.EOL + " }" - + PMD.EOL + "}"; - - private static final String IMPORT_NESTED_CLASSES = - "import net.sourceforge.pmd.lang.java.symboltable.testdata.InnerClass.TheInnerClass.EnumTest;" + PMD.EOL - + "public class Foo {" + PMD.EOL - + " public EnumTest e;" + PMD.EOL - + "}" + PMD.EOL; - - private static final String NESTED_CLASSES_OF_IMPORT = - "import net.sourceforge.pmd.lang.java.symboltable.testdata.InnerClass.TheInnerClass;" + PMD.EOL - + "public class Foo {" + PMD.EOL - + " public TheInnerClass.EnumTest e;" + PMD.EOL - + "}" + PMD.EOL; -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/GlobalScopeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/GlobalScopeTest.java deleted file mode 100644 index f80b59cdec..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/GlobalScopeTest.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.symboltable; - -import static org.junit.Assert.assertEquals; - -import java.util.List; -import java.util.Map; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; -import net.sourceforge.pmd.lang.symboltable.Scope; - -@Ignore -public class GlobalScopeTest extends BaseParserTest { - - @Test - public void testClassDeclAppears() { - ASTCompilationUnit acu = parseCode(TEST1); - Scope scope = acu.getScope(); - Map> m = scope.getDeclarations(); - ClassNameDeclaration classNameDeclaration = (ClassNameDeclaration) m.keySet().iterator().next(); - assertEquals(classNameDeclaration.getImage(), "Foo"); - } - - @Test - public void testEnums() { - java5.parse(TEST2); - } - - private static final String TEST1 = "public class Foo {}" + PMD.EOL; - - private static final String TEST2 = "public enum Bar {" + PMD.EOL + " FOO1 { " + PMD.EOL - + " private static final String FIELD_NAME = \"\";" + PMD.EOL + " }," + PMD.EOL + " FOO2 { " - + PMD.EOL + " private static final String FIELD_NAME = \"\";" + PMD.EOL + " }" + PMD.EOL + "}" - + PMD.EOL; -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ImageFinderFunctionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ImageFinderFunctionTest.java deleted file mode 100644 index 7d413586ce..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ImageFinderFunctionTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.java.ast.InternalApiBridge; -import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; - -@Ignore -public class ImageFinderFunctionTest { - - @Test - public void testSingleImage() { - ImageFinderFunction f = new ImageFinderFunction("foo"); - // These tests were completely broken, they built a PrimaryPrefix - // that is a child of a Name (not the reverse) - // This is an example of why tests should never build nodes manually - ASTVariableDeclaratorId node = InternalApiBridge.newVarId("foo"); - NameDeclaration decl = new VariableNameDeclaration(node); - f.test(decl); - assertEquals(decl, f.getDecl()); - } - - @Test - public void testSeveralImages() { - List imgs = new ArrayList<>(); - imgs.add("Foo.foo"); - imgs.add("foo"); - ImageFinderFunction f = new ImageFinderFunction(imgs); - ASTVariableDeclaratorId node = InternalApiBridge.newVarId("foo"); - NameDeclaration decl = new VariableNameDeclaration(node); - f.test(decl); - assertEquals(decl, f.getDecl()); - } - - public static junit.framework.Test suite() { - return new junit.framework.JUnit4TestAdapter(ImageFinderFunctionTest.class); - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/LocalScopeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/LocalScopeTest.java deleted file mode 100644 index 83630f99bc..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/LocalScopeTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import static org.junit.Assert.assertEquals; - -import java.util.List; -import java.util.Map; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; -import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -@Ignore -public class LocalScopeTest extends BaseParserTest { - - @Test - public void testLocalVariableDeclarationFound() { - ASTCompilationUnit acu = parseCode(TEST1); - List nodes = acu.findDescendantsOfType(ASTVariableDeclaratorId.class); - ASTVariableDeclaratorId node = nodes.get(0); - Map> vars = node.getScope().getDeclarations(); - assertEquals(1, vars.size()); - NameDeclaration decl = vars.keySet().iterator().next(); - assertEquals("b", decl.getImage()); - } - - @Test - public void testQualifiedNameOccurrence() { - ASTCompilationUnit acu = parseCode(TEST2); - List nodes = acu.findDescendantsOfType(ASTVariableDeclaratorId.class); - ASTVariableDeclaratorId node = nodes.get(0); - Map> vars = node.getScope().getDeclarations(); - NameDeclaration decl = vars.keySet().iterator().next(); - JavaNameOccurrence occ = (JavaNameOccurrence) vars.get(decl).get(0); - assertEquals("b", occ.getImage()); - } - - @Test - public void testPostfixUsageIsRecorded() { - ASTCompilationUnit acu = parseCode(TEST3); - List nodes = acu.findDescendantsOfType(ASTVariableDeclaratorId.class); - ASTVariableDeclaratorId node = nodes.get(0); - Map> vars = node.getScope().getDeclarations(); - NameDeclaration decl = vars.keySet().iterator().next(); - List usages = vars.get(decl); - JavaNameOccurrence occ = (JavaNameOccurrence) usages.get(0); - assertEquals(4, occ.getLocation().getBeginLine()); - } - - @Test - public void testLocalVariableTypesAreRecorded() { - ASTCompilationUnit acu = parseCode(TEST1); - List nodes = acu.findDescendantsOfType(ASTVariableDeclaratorId.class); - Map> vars = nodes.get(0).getScope().getDeclarations(); - VariableNameDeclaration decl = (VariableNameDeclaration) vars.keySet().iterator().next(); - assertEquals("Bar", decl.getTypeImage()); - } - - @Test - public void testMethodArgumentTypesAreRecorded() { - ASTCompilationUnit acu = parseCode(TEST5); - List nodes = acu.findDescendantsOfType(ASTFormalParameter.class); - Map> vars = nodes.get(0).getScope().getDeclarations(); - VariableNameDeclaration decl = (VariableNameDeclaration) vars.keySet().iterator().next(); - assertEquals("String", decl.getTypeImage()); - } - - @Test - public void testgetEnclosingMethodScope() { - ASTCompilationUnit acu = parseCode(TEST4); - ASTLocalVariableDeclaration node = acu.findDescendantsOfType(ASTLocalVariableDeclaration.class).get(0); - LocalScope scope = (LocalScope) node.getScope(); - MethodScope ms = scope.getEnclosingScope(MethodScope.class); - assertEquals(2, ms.getDeclarations().size()); - } - - public static final String TEST1 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL - + " Bar b = new Bar();" + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST2 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL - + " Bar b = new Bar();" + PMD.EOL + " b.buz = 2;" + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST3 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " int x = 2;" - + PMD.EOL + " x++;" + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST4 = "public class Foo {" + PMD.EOL + " void foo(String x, String z) { { int x; } }" - + PMD.EOL + "}"; - - public static final String TEST5 = "public class Foo {" + PMD.EOL + " void foo(String x);" + PMD.EOL + "}"; -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/MethodNameDeclarationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/MethodNameDeclarationTest.java deleted file mode 100644 index 828a5f972f..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/MethodNameDeclarationTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import static org.junit.Assert.assertEquals; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -@Ignore -public class MethodNameDeclarationTest extends BaseParserTest { - - @Test - public void testEquality() { - // Verify proper number of nodes are not equal - ASTCompilationUnit acu = java5.parse(SIMILAR); - ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0); - Map> m = ((ClassScope) n.getScope()).getDeclarations(); - Set methodNameDeclarations = m.keySet(); - assertEquals("Wrong number of method name declarations", methodNameDeclarations.size(), 3); - } - - private static final String SIMILAR = "public class Foo {" + PMD.EOL + " public void bar() {" + PMD.EOL - + " bar(x, y);" + PMD.EOL + " }" + PMD.EOL + " private void bar(int x, int y) {}" + PMD.EOL - + " private void bar(int x, int... y) {}" + PMD.EOL + "}"; -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/MethodScopeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/MethodScopeTest.java deleted file mode 100644 index 0ca2f77957..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/MethodScopeTest.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.java.symboltable; - -import static org.junit.Assert.assertEquals; - -import java.util.List; -import java.util.Map; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -@Ignore -public class MethodScopeTest extends BaseParserTest { - - @Test - public void testMethodParameterOccurrenceRecorded() { - ASTCompilationUnit acu = parseCode(TEST1); - Map> m = acu.findDescendantsOfType(ASTMethodDeclaration.class).get(0) - .getScope().getDeclarations(); - NameDeclaration vnd = m.keySet().iterator().next(); - assertEquals("bar", vnd.getImage()); - List occs = m.get(vnd); - NameOccurrence occ = occs.get(0); - assertEquals(3, occ.getLocation().getBeginLine()); - } - - @Test - public void testMethodName() { - ASTCompilationUnit acu = parseCode(TEST1); - ASTMethodDeclaration meth = acu.findDescendantsOfType(ASTMethodDeclaration.class).get(0); - MethodScope ms = (MethodScope) meth.getScope(); - assertEquals(ms.getName(), "foo"); - } - - @Test - public void testGenerics() { - parseCode(TEST_GENERICS); - } - - public static final String TEST1 = "public class Foo {" + PMD.EOL + " void foo(int bar) {" + PMD.EOL + " bar = 2;" - + PMD.EOL + " }" + PMD.EOL + "}"; - - private static final String TEST_GENERICS = "public class Tree {" + PMD.EOL + " private List subForest;" - + PMD.EOL + " public Tree fmap(final F f) { return Tree.foo(); }" + PMD.EOL - + " public List subForest() { return null; }" + PMD.EOL + "}" + PMD.EOL; -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/NameOccurrencesTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/NameOccurrencesTest.java deleted file mode 100644 index 01d0a58caa..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/NameOccurrencesTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.List; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; - -@Ignore -public class NameOccurrencesTest extends BaseParserTest { - - @Test - public void testSuper() { - ASTCompilationUnit acu = parseCode(TEST1); - List nodes = acu.findDescendantsOfType(ASTPrimaryExpression.class); - NameFinder occs = new NameFinder(nodes.get(0)); - assertEquals("super", occs.getNames().get(0).getImage()); - } - - @Test - public void testThis() { - ASTCompilationUnit acu = parseCode(TEST2); - List nodes = acu.findDescendantsOfType(ASTPrimaryExpression.class); - NameFinder occs = new NameFinder(nodes.get(0)); - assertEquals("this", occs.getNames().get(0).getImage()); - assertEquals("x", occs.getNames().get(1).getImage()); - } - - @Test - public void testNameLinkage() { - ASTCompilationUnit acu = parseCode(TEST2); - List nodes = acu.findDescendantsOfType(ASTPrimaryExpression.class); - NameFinder occs = new NameFinder(nodes.get(0)); - JavaNameOccurrence thisNameOccurrence = occs.getNames().get(0); - assertEquals(thisNameOccurrence.getNameForWhichThisIsAQualifier(), occs.getNames().get(1)); - } - - @Test - public void testSimpleVariableOccurrence() { - ASTCompilationUnit acu = parseCode(TEST3); - List nodes = acu.findDescendantsOfType(ASTPrimaryExpression.class); - NameFinder occs = new NameFinder(nodes.get(0)); - assertEquals("x", occs.getNames().get(0).getImage()); - assertFalse(occs.getNames().get(0).isThisOrSuper()); - assertFalse(occs.getNames().get(0).isMethodOrConstructorInvocation()); - assertTrue(occs.getNames().get(0).isOnLeftHandSide()); - } - - @Test - public void testQualifiedOccurrence() { - ASTCompilationUnit acu = parseCode(TEST4); - List nodes = acu.findDescendantsOfType(ASTPrimaryExpression.class); - NameFinder occs = new NameFinder(nodes.get(0)); - assertEquals("b", occs.getNames().get(0).getImage()); - assertEquals("x", occs.getNames().get(1).getImage()); - } - - @Test - public void testIsSelfAssignment() { - ASTCompilationUnit acu = parseCode(TEST5); - List nodes = acu.findDescendantsOfType(ASTPrimaryExpression.class); - NameFinder occs = new NameFinder(nodes.get(2)); - assertTrue(occs.getNames().get(0).isSelfAssignment()); - - acu = parseCode(TEST6); - nodes = acu.findDescendantsOfType(ASTPrimaryExpression.class); - occs = new NameFinder(nodes.get(2)); - assertTrue(occs.getNames().get(0).isSelfAssignment()); - } - - @Test - public void testEnumStaticUsage() { - ASTCompilationUnit acu = parseCode(TEST_ENUM); - List nodes = acu.findDescendantsOfType(ASTPrimaryExpression.class); - - NameFinder occs = new NameFinder(nodes.get(4)); - List names = occs.getNames(); - assertEquals(3, names.size()); - assertEquals("myEnum", names.get(0).getImage()); - assertFalse(names.get(0).isMethodOrConstructorInvocation()); - assertEquals("desc", names.get(1).getImage()); - assertFalse(names.get(1).isMethodOrConstructorInvocation()); - assertEquals("equals", names.get(2).getImage()); - assertTrue(names.get(2).isMethodOrConstructorInvocation()); - } - - public static final String TEST1 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " super.x = 2;" - + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST2 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " this.x = 2;" - + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST3 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " x = 2;" + PMD.EOL - + " }" + PMD.EOL + "}"; - - public static final String TEST4 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " b.x = 2;" - + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST5 = "public class Foo{" + PMD.EOL + " private int counter;" + PMD.EOL - + " private Foo(){" + PMD.EOL + " counter = 0;" + PMD.EOL + " }" + PMD.EOL - + " private int foo(){" + PMD.EOL + " if (++counter < 3) {" + PMD.EOL + " return 0;" - + PMD.EOL + " }" + PMD.EOL + " return 1;" + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST6 = "public class Foo{" + PMD.EOL + " private int counter;" + PMD.EOL - + " private Foo(){" + PMD.EOL + " counter = 0;" + PMD.EOL + " }" + PMD.EOL - + " private int foo(){" + PMD.EOL + " if (++this.counter < 3) {" + PMD.EOL - + " return 0;" + PMD.EOL + " }" + PMD.EOL + " return 1;" + PMD.EOL + " }" - + PMD.EOL + "}"; - - public static final String TEST_ENUM = "public enum MyEnum {" + PMD.EOL + " A(\"a\");" + PMD.EOL - + " private final String desc;" + PMD.EOL + " private MyEnum(String desc) {" + PMD.EOL - + " this.desc = desc;" + PMD.EOL + " }" + PMD.EOL + " public static MyEnum byDesc(String desc) {" - + PMD.EOL + " for (MyEnum myEnum : value()) {" + PMD.EOL - + " if (myEnum.desc.equals(desc)) return myEnum;" + PMD.EOL + " }" + PMD.EOL + " return null;" - + PMD.EOL + " }" + PMD.EOL + " }"; - - public static junit.framework.Test suite() { - return new junit.framework.JUnit4TestAdapter(NameOccurrencesTest.class); - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinderTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinderTest.java deleted file mode 100644 index 4bd3abb318..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinderTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.List; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; - -@Ignore -public class ScopeAndDeclarationFinderTest extends BaseParserTest { - - /** - * Unit test for https://sourceforge.net/p/pmd/bugs/1317/ - */ - @Test - public void testJava8LambdaScoping() { - String source = "public class MultipleLambdas {\n" - + " Observer a = (o, arg) -> System.out.println(\"a:\" + arg);\n" - + " Observer b = (o, arg) -> System.out.println(\"b:\" + arg);\n" + "}"; - List lambdas = java.parse(source, "1.8").findDescendantsOfType(ASTLambdaExpression.class); - - Assert.assertEquals(2, lambdas.size()); - LocalScope scope1 = (LocalScope) lambdas.get(0).getScope(); - LocalScope scope2 = (LocalScope) lambdas.get(1).getScope(); - Assert.assertNotSame(scope1, scope2); - - for (ASTLambdaExpression l : lambdas) { - LocalScope scope = (LocalScope) l.getScope(); - Assert.assertEquals(2, scope.getVariableDeclarations().size()); - Assert.assertTrue(scope.contains(new JavaNameOccurrence(null, "o"))); - Assert.assertTrue(scope.contains(new JavaNameOccurrence(null, "arg"))); - Set declarations = scope.findVariableHere(new JavaNameOccurrence(null, "arg")); - Assert.assertEquals(1, declarations.size()); - NameDeclaration decl = declarations.iterator().next(); - Assert.assertEquals(1, scope.getVariableDeclarations().get(decl).size()); - } - } - - @Test - public void testAnnonInnerClassScoping() { - String source = "public class Foo {" + PMD.EOL - + " public static final Creator CREATOR = new Creator() {" + PMD.EOL - + " @Override public Foo createFromParcel(Parcel source) {" + PMD.EOL - + " return new Foo();" + PMD.EOL - + " }" + PMD.EOL - + " @Override public Foo[] newArray(int size) {" + PMD.EOL - + " return new Foo[size];" + PMD.EOL - + " }" + PMD.EOL - + " };" + PMD.EOL - + "}" + PMD.EOL; - ASTCompilationUnit acu = java.parse(source, "1.6"); - - ClassScope cs = (ClassScope) acu.getFirstDescendantOfType(ASTClassOrInterfaceDeclaration.class).getScope(); - Assert.assertEquals(1, cs.getClassDeclarations().size()); // There should be 1 anonymous class - - List methods = acu.getFirstDescendantOfType(ASTClassOrInterfaceBody.class) // outer class - .getFirstDescendantOfType(ASTClassOrInterfaceBody.class) // inner class - .findDescendantsOfType(ASTMethodDeclarator.class, true); // inner class methods - Assert.assertEquals(2, methods.size()); - ClassScope scope1 = methods.get(0).getScope().getEnclosingScope(ClassScope.class); - ClassScope scope2 = methods.get(1).getScope().getEnclosingScope(ClassScope.class); - Assert.assertSame(scope1, scope2); - } - - - - @Test - public void testSuperCtor() { - // #3698 -- test that parsing does not throw (this executes the symbol pass) - ASTCompilationUnit acu = parseCode("class Foo { Object rs; class Inner { \n" - + " Inner(Object phase) {\n" - + " (rs.deferredAttr).super(AttrMode.SPECULATIVE, msym, phase);\n" - + " } } }"); - ASTClassOrInterfaceDeclaration inner = acu.getFirstDescendantOfType(ASTClassOrInterfaceDeclaration.class) - .getFirstDescendantOfType(ASTClassOrInterfaceDeclaration.class); - Assert.assertEquals(5, inner.findDescendantsOfType(ASTPrimaryExpression.class).size()); - } - -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeCreationVisitorTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeCreationVisitorTest.java deleted file mode 100644 index d748cf2883..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeCreationVisitorTest.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.java.symboltable; - -import static org.junit.Assert.assertTrue; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTBlock; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; - -@Ignore -public class ScopeCreationVisitorTest extends BaseParserTest { - - @Test - public void testScopesAreCreated() { - ASTCompilationUnit acu = parseCode(TEST1); - ASTBlock n = acu.getFirstDescendantOfType(ASTIfStatement.class) - .getFirstDescendantOfType(ASTBlock.class); - assertTrue(n.getScope() instanceof LocalScope); - } - - private static final String TEST1 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " if (x>2) {}" - + PMD.EOL + " }" + PMD.EOL + "}" + PMD.EOL; - - public static junit.framework.Test suite() { - return new junit.framework.JUnit4TestAdapter(ScopeCreationVisitorTest.class); - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/SimpleTypedNameDeclarationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/SimpleTypedNameDeclarationTest.java deleted file mode 100644 index 8f75a3441a..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/SimpleTypedNameDeclarationTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import javax.swing.JComponent; -import javax.swing.JTextField; - -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -/** - * Unit test for {@link SimpleTypedNameDeclaration} - */ -@Ignore -public class SimpleTypedNameDeclarationTest { - - /** - * Tests the equal method. - */ - @Test - public void testEquals() { - Assert.assertEquals(byClass(SimpleTypedNameDeclaration.class), byClass(SimpleTypedNameDeclaration.class)); - Assert.assertEquals(byClass(List.class), byClass(ArrayList.class)); - Assert.assertEquals(byClass(ArrayList.class), byClass(List.class)); - Assert.assertEquals(byName("String"), byName("String")); - Assert.assertEquals(byClass(String.class), byName("String")); - Assert.assertEquals(byClass(JComponent.class), byClass(JTextField.class)); - - Assert.assertFalse(byClass(Map.class).equals(byClass(List.class))); - Assert.assertFalse(byName("A").equals(byName("B"))); - Assert.assertFalse(byClass(String.class).equals(byName("A"))); - - Assert.assertEquals(by(Double.TYPE, "double"), by(null, "double")); - Assert.assertEquals(by(Double.class, "Double"), by(null, "double")); - Assert.assertEquals(by(Character.class, "Character"), by(null, "char")); - Assert.assertEquals(by(Double.TYPE, "double"), by(null, "float")); - Assert.assertEquals(by(Double.TYPE, "double"), by(null, "int")); - Assert.assertEquals(by(Double.TYPE, "double"), by(Integer.class, "Integer")); - Assert.assertEquals(by(Double.TYPE, "double"), by(null, "long")); - Assert.assertEquals(by(Double.TYPE, "double"), by(Long.TYPE, "long")); - Assert.assertEquals(by(Double.TYPE, "double"), by(Long.class, "Long")); - Assert.assertEquals(by(Float.TYPE, "float"), by(null, "int")); - Assert.assertEquals(by(Float.TYPE, "float"), by(Integer.TYPE, "int")); - Assert.assertEquals(by(Float.TYPE, "float"), by(Integer.class, "Integer")); - Assert.assertEquals(by(Float.TYPE, "float"), by(null, "long")); - Assert.assertEquals(by(Float.TYPE, "float"), by(Long.TYPE, "long")); - Assert.assertEquals(by(Float.TYPE, "float"), by(Long.class, "Long")); - Assert.assertEquals(by(Integer.TYPE, "int"), by(null, "char")); - Assert.assertEquals(by(Integer.TYPE, "int"), by(Character.TYPE, "char")); - Assert.assertEquals(by(Integer.TYPE, "int"), by(Character.class, "Character")); - Assert.assertEquals(by(Long.TYPE, "long"), by(null, "int")); - Assert.assertEquals(by(Long.TYPE, "long"), by(Integer.TYPE, "int")); - Assert.assertEquals(by(Long.TYPE, "long"), by(Integer.class, "Integer")); - Assert.assertEquals(by(Long.TYPE, "long"), by(null, "char")); - Assert.assertEquals(by(Long.TYPE, "long"), by(Character.TYPE, "char")); - Assert.assertEquals(by(Long.TYPE, "long"), by(Character.class, "Character")); - - // should always equal to Object - Assert.assertEquals(by(Object.class, "Object"), by(null, "Something")); - - Assert.assertEquals(withNext(byName("Foo.I"), "Foo.B"), byName("Foo.I")); - Assert.assertEquals(byName("Foo.I"), withNext(byName("Foo.I"), "Foo.B")); - } - - private static SimpleTypedNameDeclaration byClass(Class c) { - return new SimpleTypedNameDeclaration(c.getSimpleName(), c); - } - - private static SimpleTypedNameDeclaration byName(String n) { - return new SimpleTypedNameDeclaration(n, null); - } - - private static SimpleTypedNameDeclaration by(Class c, String n) { - return new SimpleTypedNameDeclaration(n, c); - } - - private static SimpleTypedNameDeclaration withNext(SimpleTypedNameDeclaration next, String n) { - SimpleTypedNameDeclaration t = new SimpleTypedNameDeclaration(n, null); - t.addNext(next); - return t; - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/SourceFileScopeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/SourceFileScopeTest.java deleted file mode 100644 index befb8bb121..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/SourceFileScopeTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.NameOccurrence; - -@Ignore -public class SourceFileScopeTest extends BaseParserTest { - - @Test - public void testClassDeclAppears() { - ASTCompilationUnit acu = parseCode(TEST1); - Map> m = acu.getScope().getDeclarations(); - ClassNameDeclaration classNameDeclaration = (ClassNameDeclaration) m.keySet().iterator().next(); - assertEquals(classNameDeclaration.getImage(), "Foo"); - } - - @Test - public void testPackageIsEmptyString() { - ASTCompilationUnit acu = parseCode(TEST1); - assertEquals(acu.getScope().getEnclosingScope(SourceFileScope.class).getPackageName(), ""); - } - - @Test - public void testPackageNameFound() { - ASTCompilationUnit acu = parseCode(TEST2); - assertEquals(acu.getScope().getEnclosingScope(SourceFileScope.class).getPackageName(), "foo.bar"); - } - - @Test - public void testNestedClasses() { - ASTCompilationUnit acu = parseCode(TEST3); - Map> m = acu.getScope().getDeclarations(); - Iterator iterator = m.keySet().iterator(); - ClassNameDeclaration classNameDeclaration = (ClassNameDeclaration) iterator.next(); - assertEquals(classNameDeclaration.getImage(), "Foo"); - assertFalse(iterator.hasNext()); - } - - private static final String TEST1 = "public class Foo {}" + PMD.EOL; - - private static final String TEST2 = "package foo.bar;" + PMD.EOL + "public class Foo {" + PMD.EOL + "}" + PMD.EOL; - - private static final String TEST3 = "public class Foo {" + PMD.EOL + " public class Bar {" + PMD.EOL + " }" - + PMD.EOL + "}" + PMD.EOL; -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/TypeSetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/TypeSetTest.java deleted file mode 100644 index 595c11c84f..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/TypeSetTest.java +++ /dev/null @@ -1,204 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import static org.junit.Assert.assertEquals; - -import java.io.File; -import java.util.HashSet; -import java.util.Set; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.typeresolution.PMDASMClassLoader; - -@Ignore -public class TypeSetTest { - private PMDASMClassLoader pmdClassLoader = PMDASMClassLoader.getInstance(TypeSetTest.class.getClassLoader()); - - @Test - public void testASTCompilationUnitPackage() { - TypeSet t = new TypeSet(); - t.setASTCompilationUnitPackage("java.lang."); - assertEquals("java.lang.", t.getASTCompilationUnitPackage()); - } - - @Test - public void testAddImport() { - TypeSet t = new TypeSet(); - t.addImport("java.io.File"); - assertEquals(1, t.getImportsCount()); - } - - @Test - public void testFindClassImplicitImport() throws ClassNotFoundException { - TypeSet t = new TypeSet(); - Class clazz = t.findClass("String"); - assertEquals(String.class, clazz); - } - - @Test - public void testFindClassSamePackage() throws ClassNotFoundException { - TypeSet t = new TypeSet(); - t.setASTCompilationUnitPackage("net.sourceforge.pmd"); - Class clazz = t.findClass("PMD"); - assertEquals(PMD.class, clazz); - } - - @Test - public void testFindClassExplicitImport() throws ClassNotFoundException { - TypeSet t = new TypeSet(); - t.addImport("java.io.File"); - Class clazz = t.findClass("File"); - assertEquals(File.class, clazz); - } - - @Test - public void testFindClassImportOnDemand() throws ClassNotFoundException { - TypeSet t = new TypeSet(); - t.addImport("java.io.*"); - Class clazz = t.findClass("File"); - assertEquals(File.class, clazz); - } - - @Test - public void testFindClassPrimitive() throws ClassNotFoundException { - TypeSet t = new TypeSet(); - assertEquals(int.class, t.findClass("int")); - } - - @Test - public void testFindClassVoid() throws ClassNotFoundException { - TypeSet t = new TypeSet(); - assertEquals(void.class, t.findClass("void")); - } - - @Test - public void testFindFullyQualified() throws ClassNotFoundException { - TypeSet t = new TypeSet(); - assertEquals(String.class, t.findClass("java.lang.String")); - assertEquals(Set.class, t.findClass("java.util.Set")); - } - - // inner class tests - @Test - public void testPrimitiveTypeResolver() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.PrimitiveTypeResolver(); - assertEquals(int.class, r.resolve("int")); - assertEquals(byte.class, r.resolve("byte")); - assertEquals(long.class, r.resolve("long")); - } - - @Test(expected = ClassNotFoundException.class) - public void testPrimitiveTypeResolverWithNull() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.PrimitiveTypeResolver(); - r.resolve(null); - } - - @Test - public void testVoidTypeResolver() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.VoidResolver(); - assertEquals(void.class, r.resolve("void")); - } - - @Test(expected = ClassNotFoundException.class) - public void testVoidTypeResolverWithNull() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.VoidResolver(); - r.resolve(null); - } - - @Test - public void testExplicitImportResolver() throws ClassNotFoundException { - Set imports = new HashSet<>(); - imports.add("java.io.File"); - TypeSet.Resolver r = new TypeSet.ExplicitImportResolver(pmdClassLoader, imports); - assertEquals(File.class, r.resolve("File")); - } - - @Test(expected = ClassNotFoundException.class) - public void testExplicitImportResolverWithNull() throws ClassNotFoundException { - Set imports = new HashSet<>(); - imports.add("java.io.File"); - TypeSet.Resolver r = new TypeSet.ExplicitImportResolver(pmdClassLoader, imports); - r.resolve(null); - } - - @Test(expected = ClassNotFoundException.class) - public void testExplicitImportResolverWithNullAndEmptyImports() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.ExplicitImportResolver(pmdClassLoader, new HashSet()); - r.resolve(null); - } - - @Test - public void testImplicitImportResolverPass() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.ImplicitImportResolver(pmdClassLoader); - assertEquals(String.class, r.resolve("String")); - } - - @Test(expected = ClassNotFoundException.class) - public void testImplicitImportResolverPassFail() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.ImplicitImportResolver(pmdClassLoader); - r.resolve("PMD"); - } - - @Test(expected = ClassNotFoundException.class) - public void testImplicitImportResolverWithNull() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.ImplicitImportResolver(pmdClassLoader); - r.resolve(null); - } - - @Test - public void testCurrentPackageResolverPass() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.CurrentPackageResolver(pmdClassLoader, "net.sourceforge.pmd"); - assertEquals(PMD.class, r.resolve("PMD")); - } - - @Test(expected = ClassNotFoundException.class) - public void testCurrentPackageResolverWithNull() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.CurrentPackageResolver(pmdClassLoader, "net.sourceforge.pmd"); - r.resolve(null); - } - - @Test - public void testImportOnDemandResolverPass() throws ClassNotFoundException { - TypeSet.Resolver r = getResolver(); - assertEquals(Set.class, r.resolve("Set")); - assertEquals(File.class, r.resolve("File")); - } - - @Test(expected = ClassNotFoundException.class) - public void testImportOnDemandResolverWithNull() throws ClassNotFoundException { - TypeSet.Resolver r = getResolver(); - r.resolve(null); - } - - @Test(expected = ClassNotFoundException.class) - public void importOnDemandResolverFail1() throws ClassNotFoundException { - TypeSet.Resolver r = getResolver(); - r.resolve("foo"); - } - - @Test(expected = ClassNotFoundException.class) - public void importOnDemandResolverFail2() throws ClassNotFoundException { - TypeSet.Resolver r = getResolver(); - r.resolve("String"); - } - - private TypeSet.Resolver getResolver() { - Set imports = new HashSet<>(); - imports.add("java.io.*"); - imports.add("java.util.*"); - TypeSet.Resolver r = new TypeSet.ImportOnDemandResolver(pmdClassLoader, imports); - return r; - } - - @Test(expected = ClassNotFoundException.class) - public void testFullyQualifiedNameResolverWithNull() throws ClassNotFoundException { - TypeSet.Resolver r = new TypeSet.FullyQualifiedNameResolver(pmdClassLoader); - r.resolve(null); - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/VariableNameDeclarationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/VariableNameDeclarationTest.java deleted file mode 100644 index b682ba0add..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/VariableNameDeclarationTest.java +++ /dev/null @@ -1,180 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.symboltable; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.junit.Ignore; -import org.junit.Test; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.symboltable.NameDeclaration; -import net.sourceforge.pmd.lang.symboltable.Scope; - -@Ignore -public class VariableNameDeclarationTest extends BaseParserTest { - - @Test - public void testConstructor() { - ASTCompilationUnit acu = parseCode(TEST1); - List nodes = acu.findDescendantsOfType(ASTVariableDeclaratorId.class); - Scope s = nodes.get(0).getScope(); - NameDeclaration decl = s.getDeclarations().keySet().iterator().next(); - assertEquals("bar", decl.getImage()); - assertEquals(3, decl.getNode().getBeginLine()); - } - - @Test - public void testExceptionBlkParam() { - ASTCompilationUnit acu = java.parse(EXCEPTION_PARAMETER); - ASTVariableDeclaratorId id = acu.getFirstDescendantOfType(ASTVariableDeclaratorId.class); - assertTrue(new VariableNameDeclaration(id).isExceptionBlockParameter()); - } - - @Test - public void testIsArray() { - ASTCompilationUnit acu = parseCode(TEST3); - VariableNameDeclaration decl = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0).getScope() - .getDeclarations(VariableNameDeclaration.class).keySet().iterator().next(); - assertTrue(decl.isArray()); - } - - @Test - public void testPrimitiveType() { - ASTCompilationUnit acu = parseCode(TEST1); - VariableNameDeclaration decl = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0).getScope() - .getDeclarations(VariableNameDeclaration.class).keySet().iterator().next(); - assertTrue(decl.isPrimitiveType()); - } - - @Test - public void testArrayIsReferenceType() { - ASTCompilationUnit acu = parseCode(TEST3); - VariableNameDeclaration decl = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0).getScope() - .getDeclarations(VariableNameDeclaration.class).keySet().iterator().next(); - assertTrue(decl.isReferenceType()); - } - - @Test - public void testPrimitiveTypeImage() { - ASTCompilationUnit acu = parseCode(TEST3); - NameDeclaration decl = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0).getScope() - .getDeclarations().keySet().iterator().next(); - assertEquals("int", ((TypedNameDeclaration) decl).getTypeImage()); - } - - @Test - public void testRefTypeImage() { - ASTCompilationUnit acu = parseCode(TEST4); - NameDeclaration decl = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0).getScope() - .getDeclarations().keySet().iterator().next(); - assertEquals("String", ((TypedNameDeclaration) decl).getTypeImage()); - } - - @Test - public void testParamTypeImage() { - ASTCompilationUnit acu = parseCode(TEST5); - NameDeclaration decl = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0).getScope() - .getDeclarations().keySet().iterator().next(); - assertEquals("String", ((TypedNameDeclaration) decl).getTypeImage()); - } - - @Test - public void testVarKeywordTypeImage() { - ASTCompilationUnit acu = parseCode(TEST6); - NameDeclaration decl = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0).getScope() - .getDeclarations().keySet().iterator().next(); - assertEquals("java.util.ArrayList", ((TypedNameDeclaration) decl).getType().getName()); - // since the type is inferred, there is no type image - assertEquals(null, ((TypedNameDeclaration) decl).getTypeImage()); - } - - @Test - public void testVarKeywordWithPrimitiveTypeImage() { - ASTCompilationUnit acu = parseCode(TEST7); - NameDeclaration decl = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0).getScope() - .getDeclarations().keySet().iterator().next(); - assertEquals("long", ((TypedNameDeclaration) decl).getType().getName()); - // since the type is inferred, there is no type image - assertEquals(null, ((TypedNameDeclaration) decl).getTypeImage()); - } - - @Test - public void testVarKeywordWithIndirectReference() { - ASTCompilationUnit acu = parseCode(TEST8); - Iterator nameDeclarationIterator = acu.findDescendantsOfType(ASTVariableDeclaratorId.class).get(0).getScope() - .getDeclarations().keySet().iterator(); - nameDeclarationIterator.next(); // first variable 'bar' - NameDeclaration decl = nameDeclarationIterator.next(); // second variable 'foo' - assertEquals("java.lang.String", ((TypedNameDeclaration) decl).getType().getName()); - // since the type is inferred, there is no type image - assertEquals(null, ((TypedNameDeclaration) decl).getTypeImage()); - } - - @Test - public void testLamdaParameterTypeImage() { - ASTCompilationUnit acu = parseCode(TEST9); - List variableDeclaratorIds = acu.findDescendantsOfType( - ASTVariableDeclaratorId.class, - true - ); - - List nameDeclarations = new ArrayList<>(); - for (ASTVariableDeclaratorId variableDeclaratorId : variableDeclaratorIds) { - nameDeclarations.add(variableDeclaratorId.getNameDeclaration()); - } - - assertEquals("Map", nameDeclarations.get(0).getTypeImage()); // variable 'bar' - assertEquals(null, nameDeclarations.get(1).getTypeImage()); // variable 'key' - assertEquals(null, nameDeclarations.get(2).getTypeImage()); // variable 'value' - - // variable 'foo' - assertEquals("foo", nameDeclarations.get(3).getName()); - assertEquals("long", nameDeclarations.get(3).getType().getName()); - // since the type is inferred, there is no type image - assertEquals(null, nameDeclarations.get(3).getTypeImage()); - } - - private static final String EXCEPTION_PARAMETER = "public class Test { { try {} catch(Exception ie) {} } }"; - - public static final String TEST1 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " int bar = 42;" - + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST2 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL - + " try {} catch(Exception e) {}" + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST3 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " int[] x;" - + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST4 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " String x;" - + PMD.EOL + " }" + PMD.EOL + "}"; - public static final String TEST5 = "public class Foo {" + PMD.EOL + " void foo(String x) {}" + PMD.EOL + "}"; - - public static final String TEST6 = "import java.util.ArrayList; public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL - + " var bar = new ArrayList(\"param\");" + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST7 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " var bar = 42L;" - + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST8 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL - + " var bar = \"test\";" + PMD.EOL + " var foo = bar;" + PMD.EOL + " }" + PMD.EOL + "}"; - - public static final String TEST9 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL - + " Map bar = new HashMap<>();" + PMD.EOL + " bar.forEach((key, value) -> {" + PMD.EOL - + " if (value instanceof String) {" + PMD.EOL + " var foo = 42L;" + PMD.EOL - + " System.out.println(value);" + PMD.EOL + " }" + PMD.EOL + " });" + PMD.EOL + " }" + PMD.EOL + "}"; - - public static junit.framework.Test suite() { - return new junit.framework.JUnit4TestAdapter(VariableNameDeclarationTest.class); - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/testdata/InnerClass.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/testdata/InnerClass.java deleted file mode 100644 index 1c981bf0b4..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/testdata/InnerClass.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.symboltable.testdata; - -public class InnerClass { - public static class TheInnerClass { - public enum EnumTest { - THREE, FOUR; - } - } - - enum EnumTest { - ONE, TWO; - } - - public void foo(TheInnerClass arg) { - } - - public void bar(InnerClass.TheInnerClass arg) { - } - - public void baz(EnumTest e) { - } -} diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/AstTestUtil.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/AstTestUtil.kt new file mode 100644 index 0000000000..37119fe5cb --- /dev/null +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/AstTestUtil.kt @@ -0,0 +1,30 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +@file:JvmName("AstTestUtil") + +package net.sourceforge.pmd.lang.java.types + +import net.sourceforge.pmd.lang.ast.NodeStream +import net.sourceforge.pmd.lang.ast.NodeStream.DescendantNodeStream +import net.sourceforge.pmd.lang.java.ast.* + + +fun JavaNode.methodDeclarations(): DescendantNodeStream = descendants(ASTMethodDeclaration::class.java).crossFindBoundaries() +fun JavaNode.typeDeclarations(): DescendantNodeStream = descendants(ASTAnyTypeDeclaration::class.java).crossFindBoundaries() +fun JavaNode.ctorDeclarations(): DescendantNodeStream = descendants(ASTConstructorDeclaration::class.java).crossFindBoundaries() + +fun JavaNode.firstTypeSignature(): JClassType = typeDeclarations().firstOrThrow().typeMirror +fun JavaNode.declaredTypeSignatures(): List = typeDeclarations().toList { it.typeMirror } +fun JavaNode.declaredMethodSignatures(): List = methodDeclarations().toList { it.genericSignature } + +fun JavaNode.methodCalls(): DescendantNodeStream = descendants(ASTMethodCall::class.java) +fun JavaNode.firstMethodCall() = methodCalls().crossFindBoundaries().firstOrThrow() + +fun JavaNode.ctorCalls(): DescendantNodeStream = descendants(ASTConstructorCall::class.java) +fun JavaNode.firstCtorCall() = ctorCalls().crossFindBoundaries().firstOrThrow() + +fun JavaNode.typeVariables(): MutableList = descendants(ASTTypeParameter::class.java).crossFindBoundaries().toList { it.typeMirror } +fun JavaNode.varAccesses(name: String): NodeStream = descendants(ASTVariableAccess::class.java).filter { it.name == name } +fun JavaNode.varId(name: String) = descendants(ASTVariableDeclaratorId::class.java).filter { it.name == name }.firstOrThrow() +fun JavaNode.typeVar(name: String) = descendants(ASTTypeParameter::class.java).filter { it.name == name }.firstOrThrow().typeMirror diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeTestMockingUtil.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeTestMockingUtil.kt index b55b19faaf..509994b855 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeTestMockingUtil.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeTestMockingUtil.kt @@ -77,23 +77,3 @@ data class TypeInferenceSpy(private val spy: TypeInferenceLogger, val ts: TypeSy verify(spy, times(1)).ambiguityError(any(), any(), any()) } } - - -fun JavaNode.methodDeclarations(): DescendantNodeStream = descendants(ASTMethodDeclaration::class.java).crossFindBoundaries() -fun JavaNode.typeDeclarations(): DescendantNodeStream = descendants(ASTAnyTypeDeclaration::class.java).crossFindBoundaries() -fun JavaNode.ctorDeclarations(): DescendantNodeStream = descendants(ASTConstructorDeclaration::class.java).crossFindBoundaries() - -fun JavaNode.firstTypeSignature(): JClassType = typeDeclarations().firstOrThrow().typeMirror -fun JavaNode.declaredTypeSignatures(): List = typeDeclarations().toList { it.typeMirror } -fun JavaNode.declaredMethodSignatures(): List = methodDeclarations().toList { it.genericSignature } - -fun JavaNode.methodCalls(): DescendantNodeStream = descendants(ASTMethodCall::class.java) -fun JavaNode.firstMethodCall() = methodCalls().crossFindBoundaries().firstOrThrow() - -fun JavaNode.ctorCalls(): DescendantNodeStream = descendants(ASTConstructorCall::class.java) -fun JavaNode.firstCtorCall() = ctorCalls().crossFindBoundaries().firstOrThrow() - -fun JavaNode.typeVariables(): MutableList = descendants(ASTTypeParameter::class.java).crossFindBoundaries().toList { it.typeMirror } -fun JavaNode.varAccesses(name: String): NodeStream = descendants(ASTVariableAccess::class.java).filter { it.name == name } -fun JavaNode.varId(name: String) = descendants(ASTVariableDeclaratorId::class.java).filter { it.name == name }.firstOrThrow() -fun JavaNode.typeVar(name: String) = descendants(ASTTypeParameter::class.java).filter { it.name == name }.firstOrThrow().typeMirror diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/MethodReferenceConfused.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/MethodReferenceConfused.java index c0124489c1..88ca15a7c3 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/MethodReferenceConfused.java +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/MethodReferenceConfused.java @@ -1,8 +1,17 @@ +import java.security.AccessController; +import java.security.PrivilegedAction; + public class MethodReferenceConfused { + public void wrongVariableAccessor() { - Object someVarNameSameAsMethodReference = null; + Object method = null; Object someObject = null; - String result = AccessController.doPrivileged((PrivilegedAction) - ((SomeCast) someObject)::someVarNameSameAsMethodReference); + String result = AccessController.doPrivileged( + (PrivilegedAction) ((I) someObject)::method); + } + + interface I { + + String method(); } } From b769594fc76bbbb26530928721d827e60e4e0756 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 15:25:53 +0100 Subject: [PATCH 25/89] [java] Update UnnecessaryImportRule for @link in @snippet javadoc --- .../rule/codestyle/UnnecessaryImportRule.java | 24 ++++++++++++------- .../rule/codestyle/xml/UnnecessaryImport.xml | 23 ++++++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryImportRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryImportRule.java index c1a4318fa3..3359462489 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryImportRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryImportRule.java @@ -46,19 +46,23 @@ public class UnnecessaryImportRule extends AbstractJavaRule { /* * Patterns to match the following constructs: * - * @see package.class#member(param, param) label {@linkplain - * package.class#member(param, param) label} {@link - * package.class#member(param, param) label} {@link package.class#field} + * @see package.class#member(param, param) label + * {@linkplain package.class#member(param, param) label} + * {@link package.class#member(param, param) label} + * {@link package.class#field} * {@value package.class#field} * * @throws package.class label * @exception package.class label */ - private static final Pattern SEE_PATTERN = Pattern - .compile("@see\\s+((?:\\p{Alpha}\\w*\\.)*(?:\\p{Alpha}\\w*))?(?:#\\w*(?:\\(([.\\w\\s,\\[\\]]*)\\))?)?"); - private static final Pattern LINK_PATTERNS = Pattern - .compile("\\{@link(?:plain)?\\s+((?:\\p{Alpha}\\w*\\.)*(?:\\p{Alpha}\\w*))?(?:#\\w*(?:\\(([.\\w\\s,\\[\\]]*)\\))?)?[\\s\\}]"); + /* package.class#member(param, param) */ + private static final String TYPE_PART_GROUP = "((?:\\p{Alpha}\\w*\\.)*(?:\\p{Alpha}\\w*))?(?:#\\w*(?:\\(([.\\w\\s,\\[\\]]*)\\))?)?"; + + private static final Pattern SEE_PATTERN = Pattern.compile("@see\\s+" + TYPE_PART_GROUP); + + + private static final Pattern LINK_PATTERNS = Pattern.compile("\\{@link(?:plain)?\\s+" + TYPE_PART_GROUP + "[\\s\\}]"); private static final Pattern VALUE_PATTERN = Pattern.compile("\\{@value\\s+(\\p{Alpha}\\w*)[\\s#\\}]"); @@ -66,7 +70,11 @@ public class UnnecessaryImportRule extends AbstractJavaRule { private static final Pattern EXCEPTION_PATTERN = Pattern.compile("@exception\\s+(\\p{Alpha}\\w*)"); - private static final Pattern[] PATTERNS = { SEE_PATTERN, LINK_PATTERNS, VALUE_PATTERN, THROWS_PATTERN, EXCEPTION_PATTERN }; + /* // @link substring="a" target="package.class#member(param, param)" */ + private static final Pattern LINK_IN_SNIPPET = Pattern + .compile("//\\s*@link\\s+(?:.*?)?target=[\"']?" + TYPE_PART_GROUP + "[\"']?"); + + private static final Pattern[] PATTERNS = { SEE_PATTERN, LINK_PATTERNS, VALUE_PATTERN, THROWS_PATTERN, EXCEPTION_PATTERN, LINK_IN_SNIPPET }; /** * The deprecated rule {@link UnusedImportsRule} extends this class diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryImport.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryImport.xml index ecb60fe3c6..c1c8fb2e30 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryImport.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryImport.xml @@ -912,6 +912,29 @@ public class U { private void g() { String k = C.V; } +} + ]]> + + + + Necessary imports for @snippet tags introduced with JEP 413 in Java 18 + 0 + Other example: + * {@snippet : + * Sample.add(this); // @link target="ArrayList#add(Object)" + * } + */ +public class Sample { + // ... } ]]> From 937eb90a705bf7a2e009c4a61ef229e2709e98fa Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 15:33:22 +0100 Subject: [PATCH 26/89] [java] Remove support for Java 16 Preview --- docs/pages/pmd/languages/java.md | 5 +- docs/pages/pmd/userdocs/tools/ant.md | 1 - pmd-java/etc/grammar/Java.jjt | 17 +++--- .../pmd/lang/java/JavaLanguageModule.java | 1 - .../pmd/lang/java/JavaLanguageModuleTest.java | 6 +-- .../lang/java/ast/AllJavaAstTreeDumpTest.java | 4 +- .../java/ast/Java16PreviewTreeDumpTest.java | 54 ------------------- .../pmd/lang/java/ast/Java16TreeDumpTest.java | 2 - .../pmd/lang/java/ast/Java17TreeDumpTest.java | 4 +- .../pmd/lang/java/ast/ASTPatternTest.kt | 2 +- .../pmd/lang/java/ast/KotlinTestingDsl.kt | 2 +- .../java16p/expression/ConstantExpr.java | 9 ---- .../java16p/expression/Expr.java | 10 ---- .../java16p/expression/Expr.txt | 11 ---- .../java16p/expression/NegExpr.java | 9 ---- .../java16p/expression/PlusExpr.java | 9 ---- .../java16p/expression/TimesExpr.java | 9 ---- .../java16p/geometry/Circle.java | 9 ---- .../java16p/geometry/FilledRectangle.java | 10 ---- .../java16p/geometry/Rectangle.java | 11 ---- .../java16p/geometry/Shape.java | 11 ---- .../java16p/geometry/Shape.txt | 10 ---- .../java16p/geometry/Square.java | 10 ---- .../java16p/geometry/Square.txt | 8 --- .../geometry/TransparentRectangle.java | 10 ---- 25 files changed, 22 insertions(+), 212 deletions(-) delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16PreviewTreeDumpTest.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/ConstantExpr.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/Expr.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/Expr.txt delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/NegExpr.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/PlusExpr.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/TimesExpr.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Circle.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/FilledRectangle.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Rectangle.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Shape.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Shape.txt delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Square.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Square.txt delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/TransparentRectangle.java diff --git a/docs/pages/pmd/languages/java.md b/docs/pages/pmd/languages/java.md index b76e01d9b7..73029ef0a0 100644 --- a/docs/pages/pmd/languages/java.md +++ b/docs/pages/pmd/languages/java.md @@ -13,7 +13,6 @@ Java Version |Alias | Supported by PMD since | 18 (default) | | 6.44.0 | 17-preview | | 6.37.0 | 17 | | 6.37.0 | -16-preview | | 6.32.0 | 16 | | 6.32.0 | 15 | | 6.27.0 | 14 | | 6.22.0 | @@ -32,9 +31,9 @@ Java Version |Alias | Supported by PMD since | ## Using Java preview features In order to analyze a project with PMD that uses preview language features, you'll need to enable -it via the environment variable `PMD_JAVA_OPTS` and select the new language version, e.g. `17-preview`: +it via the environment variable `PMD_JAVA_OPTS` and select the new language version, e.g. `18-preview`: export PMD_JAVA_OPTS=--enable-preview - ./run.sh pmd -language java -version 17-preview ... + ./run.sh pmd -language java -version 18-preview ... Note: we only support preview language features for the latest two java versions. diff --git a/docs/pages/pmd/userdocs/tools/ant.md b/docs/pages/pmd/userdocs/tools/ant.md index b523329aff..eb7eae4367 100644 --- a/docs/pages/pmd/userdocs/tools/ant.md +++ b/docs/pages/pmd/userdocs/tools/ant.md @@ -235,7 +235,6 @@ nested element. Possible values are: - diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 6bd184c7d4..e9eaacf5e5 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -1,4 +1,9 @@ /** + * Support "JEP 420: Pattern Matching for switch (Second Preview)" for Java 18 Preview + * There were no grammar changes between 18-preview and 17-preview + * Remove support for Java 16 preview language features + * Andreas Dangel 03/2022 + *==================================================================== * Promote "JEP 409: Sealed Classes" as permanent language feature with Java 17. * Support "JEP 406: Pattern Matching for switch (Preview)" for Java 17 Preview. * Remove support for Java 15 preview language features @@ -445,11 +450,11 @@ public class JavaParser { if (jdkVersion >= 16 && "record".equals(image)) { throwParseException("With JDK >= 16, 'record' is a contextual keyword and cannot be used for type declarations!"); } - if ((jdkVersion == 16 && preview || jdkVersion >= 17) && "sealed".equals(image)) { - throwParseException("With JDK 16 Preview and JDK >= 17, 'sealed' is a contextual keyword and cannot be used for type declarations!"); + if (jdkVersion >= 17 && "sealed".equals(image)) { + throwParseException("With JDK >= 17, 'sealed' is a contextual keyword and cannot be used for type declarations!"); } - if ((jdkVersion == 16 && preview || jdkVersion >= 17) && "permits".equals(image)) { - throwParseException("With JDK 16 Preview and JDK >= 17, 'permits' is a contextual keyword and cannot be used for type declarations!"); + if (jdkVersion >= 17 && "permits".equals(image)) { + throwParseException("With JDK >= 17, 'permits' is a contextual keyword and cannot be used for type declarations!"); } } private void checkForMultipleCaseLabels() { @@ -519,12 +524,12 @@ public class JavaParser { } private boolean isSealedClassSupported() { - return jdkVersion == 16 && preview || jdkVersion >= 17; + return jdkVersion >= 17; } private void checkForSealedClassUsage() { if (!isSealedClassSupported()) { - throwParseException("Sealed Classes are only supported with JDK 16 Preview and JDK >= 17."); + throwParseException("Sealed Classes are only supported with JDK >= 17."); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java index b421acf80d..bba3743fa8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java @@ -30,7 +30,6 @@ public class JavaLanguageModule extends BaseLanguageModule { addVersion("14", new JavaLanguageHandler(14)); addVersion("15", new JavaLanguageHandler(15)); addVersion("16", new JavaLanguageHandler(16)); - addVersion("16-preview", new JavaLanguageHandler(16, true)); addVersion("17", new JavaLanguageHandler(17)); addVersion("17-preview", new JavaLanguageHandler(17, true)); addDefaultVersion("18", new JavaLanguageHandler(18)); // 18 is the default diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/JavaLanguageModuleTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/JavaLanguageModuleTest.java index 12bb3b0b5c..3dcafd789f 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/JavaLanguageModuleTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/JavaLanguageModuleTest.java @@ -26,10 +26,10 @@ public class JavaLanguageModuleTest { @Test public void previewVersionShouldBeGreaterThanNonPreview() { - LanguageVersion java16 = javaLanguage.getVersion("16"); - LanguageVersion java16p = javaLanguage.getVersion("16-preview"); + LanguageVersion java18 = javaLanguage.getVersion("18"); + LanguageVersion java18p = javaLanguage.getVersion("18-preview"); - Assert.assertTrue("java16-preview should be greater than java16", java16p.compareTo(java16) > 0); + Assert.assertTrue("java18-preview should be greater than java18", java18p.compareTo(java18) > 0); } @Test diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/AllJavaAstTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/AllJavaAstTreeDumpTest.java index 0e0207ce48..9ba724d357 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/AllJavaAstTreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/AllJavaAstTreeDumpTest.java @@ -12,10 +12,10 @@ import org.junit.runners.Suite.SuiteClasses; @SuiteClasses({ ParserCornersTest.class, Java15TreeDumpTest.class, - Java16PreviewTreeDumpTest.class, Java16TreeDumpTest.class, Java17PreviewTreeDumpTest.class, - Java17TreeDumpTest.class + Java17TreeDumpTest.class, + Java18PreviewTreeDumpTest.class }) public class AllJavaAstTreeDumpTest { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16PreviewTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16PreviewTreeDumpTest.java deleted file mode 100644 index 0ee445909c..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16PreviewTreeDumpTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.ast; - -import org.junit.Test; - -import net.sourceforge.pmd.lang.ast.ParseException; -import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper; -import net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest; -import net.sourceforge.pmd.lang.ast.test.RelevantAttributePrinter; -import net.sourceforge.pmd.lang.java.JavaParsingHelper; - -public class Java16PreviewTreeDumpTest extends BaseTreeDumpTest { - private final JavaParsingHelper java16p = - JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("16-preview") - .withResourceContext(Java16PreviewTreeDumpTest.class, "jdkversiontests/java16p/"); - private final JavaParsingHelper java16 = java16p.withDefaultVersion("16"); - - public Java16PreviewTreeDumpTest() { - super(new RelevantAttributePrinter(), ".java"); - } - - @Override - public BaseParsingHelper getParser() { - return java16p; - } - - @Test(expected = ParseException.class) - public void sealedClassBeforeJava16Preview() { - java16.parseResource("geometry/Shape.java"); - } - - @Test - public void sealedClass() { - doTest("geometry/Shape"); - } - - @Test - public void nonSealedClass() { - doTest("geometry/Square"); - } - - @Test(expected = ParseException.class) - public void sealedInterfaceBeforeJava15Preview() { - java16.parseResource("expression/Expr.java"); - } - - @Test - public void sealedInterface() { - doTest("expression/Expr"); - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java index a6b9cbe848..487d5aeceb 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java @@ -19,7 +19,6 @@ public class Java16TreeDumpTest extends BaseTreeDumpTest { private final JavaParsingHelper java16 = JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("16") .withResourceContext(Java16TreeDumpTest.class, "jdkversiontests/java16/"); - private final JavaParsingHelper java16p = java16.withDefaultVersion("16-preview"); private final JavaParsingHelper java15 = java16.withDefaultVersion("15"); public Java16TreeDumpTest() { @@ -116,6 +115,5 @@ public class Java16TreeDumpTest extends BaseTreeDumpTest { @Test public void sealedAndNonSealedIdentifiers() { doTest("NonSealedIdentifier"); - java16p.parseResource("NonSealedIdentifier.java"); // make sure we can parse it with preview as well } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java index 6dd38772ac..2a03fdedf1 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java @@ -39,7 +39,7 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Sealed Classes are only supported with JDK 16 Preview and JDK >= 17.")); + thrown.getMessage().contains("Sealed Classes are only supported with JDK >= 17.")); } @Test @@ -63,7 +63,7 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Sealed Classes are only supported with JDK 16 Preview and JDK >= 17.")); + thrown.getMessage().contains("Sealed Classes are only supported with JDK >= 17.")); } @Test diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt index 6558e336a4..a5a1cfed5c 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt @@ -13,7 +13,7 @@ import java.io.IOException class ASTPatternTest : ParserTestSpec({ parserTest("Test patterns only available on JDK16 or higher (including preview)", - javaVersions = JavaVersion.values().asList().minus(J16).minus(J16__PREVIEW) + javaVersions = JavaVersion.values().asList().minus(J16) .minus(J17).minus(J17__PREVIEW) .minus(J18).minus(J18__PREVIEW)) { diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt index 207d229c4c..e429a3b12e 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt @@ -22,7 +22,7 @@ enum class JavaVersion : Comparable { J13, J14, J15, - J16, J16__PREVIEW, + J16, J17, J17__PREVIEW, J18, J18__PREVIEW; diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/ConstantExpr.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/ConstantExpr.java deleted file mode 100644 index a4265b4c3b..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/ConstantExpr.java +++ /dev/null @@ -1,9 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.expression; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public final class ConstantExpr implements Expr { } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/Expr.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/Expr.java deleted file mode 100644 index 8b7055e9f9..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/Expr.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.expression; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public sealed interface Expr - permits ConstantExpr, PlusExpr, TimesExpr, NegExpr { } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/Expr.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/Expr.txt deleted file mode 100644 index 12d87ee160..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/Expr.txt +++ /dev/null @@ -1,11 +0,0 @@ -+- CompilationUnit[@PackageName = "com.example.expression", @declarationsAreInDefaultPackage = false] - +- PackageDeclaration[@Name = "com.example.expression", @PackageNameImage = "com.example.expression"] - | +- Name[@Image = "com.example.expression"] - +- TypeDeclaration[] - +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "com.example.expression.Expr", @Default = false, @Final = false, @Image = "Expr", @Interface = true, @Local = false, @Modifiers = 16385, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = true, @SimpleName = "Expr", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.INTERFACE, @Volatile = false] - +- PermitsList[] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "ConstantExpr", @ReferenceToClassSameCompilationUnit = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "PlusExpr", @ReferenceToClassSameCompilationUnit = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "TimesExpr", @ReferenceToClassSameCompilationUnit = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "NegExpr", @ReferenceToClassSameCompilationUnit = false] - +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/NegExpr.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/NegExpr.java deleted file mode 100644 index 727c84a2d6..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/NegExpr.java +++ /dev/null @@ -1,9 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.expression; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public final class NegExpr implements Expr { } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/PlusExpr.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/PlusExpr.java deleted file mode 100644 index 17f8f3a5a2..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/PlusExpr.java +++ /dev/null @@ -1,9 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.expression; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public final class PlusExpr implements Expr { } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/TimesExpr.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/TimesExpr.java deleted file mode 100644 index 13ca04ebc7..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/expression/TimesExpr.java +++ /dev/null @@ -1,9 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.expression; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public final class TimesExpr implements Expr { } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Circle.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Circle.java deleted file mode 100644 index 5d3c50900c..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Circle.java +++ /dev/null @@ -1,9 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.geometry; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public final class Circle extends Shape { } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/FilledRectangle.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/FilledRectangle.java deleted file mode 100644 index 6b6ec1ccec..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/FilledRectangle.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.geometry; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public final class FilledRectangle extends Rectangle { } - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Rectangle.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Rectangle.java deleted file mode 100644 index ec502a8cf3..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Rectangle.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.geometry; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public sealed class Rectangle extends Shape - permits TransparentRectangle, FilledRectangle { } - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Shape.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Shape.java deleted file mode 100644 index 7d74060afc..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Shape.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.geometry; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public sealed class Shape - permits Circle, Rectangle, Square { } - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Shape.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Shape.txt deleted file mode 100644 index 2a2f3f01fc..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Shape.txt +++ /dev/null @@ -1,10 +0,0 @@ -+- CompilationUnit[@PackageName = "com.example.geometry", @declarationsAreInDefaultPackage = false] - +- PackageDeclaration[@Name = "com.example.geometry", @PackageNameImage = "com.example.geometry"] - | +- Name[@Image = "com.example.geometry"] - +- TypeDeclaration[] - +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "com.example.geometry.Shape", @Default = false, @Final = false, @Image = "Shape", @Interface = false, @Local = false, @Modifiers = 16385, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = true, @SimpleName = "Shape", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - +- PermitsList[] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Circle", @ReferenceToClassSameCompilationUnit = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Rectangle", @ReferenceToClassSameCompilationUnit = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Square", @ReferenceToClassSameCompilationUnit = false] - +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Square.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Square.java deleted file mode 100644 index ff8d2fdeaf..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Square.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.geometry; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public non-sealed class Square extends Shape { } - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Square.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Square.txt deleted file mode 100644 index 94cd4275e2..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/Square.txt +++ /dev/null @@ -1,8 +0,0 @@ -+- CompilationUnit[@PackageName = "com.example.geometry", @declarationsAreInDefaultPackage = false] - +- PackageDeclaration[@Name = "com.example.geometry", @PackageNameImage = "com.example.geometry"] - | +- Name[@Image = "com.example.geometry"] - +- TypeDeclaration[] - +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "com.example.geometry.Square", @Default = false, @Final = false, @Image = "Square", @Interface = false, @Local = false, @Modifiers = 32769, @Native = false, @Nested = false, @NonSealed = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "Square", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - +- ExtendsList[] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = false] - +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/TransparentRectangle.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/TransparentRectangle.java deleted file mode 100644 index 5f515ef038..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16p/geometry/TransparentRectangle.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package com.example.geometry; - -/** - * @see JEP 397: Sealed Classes (Second Preview) - */ -public final class TransparentRectangle extends Rectangle { } - From 690e5a66e347ef93576d316b1ae3a53cb078fedf Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 15:48:36 +0100 Subject: [PATCH 27/89] [doc] Update release notes (#3809) --- docs/pages/release_notes.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 184a196688..9a9c49b755 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -14,6 +14,19 @@ This is a {{ site.pmd.release_type }} release. ### New and noteworthy +#### Java 18 Support + +This release of PMD brings support for Java 18. There are no new standard language features. + +PMD also supports [JEP 420: Pattern Matching for switch (Second Preview)](https://openjdk.java.net/jeps/420) as a +preview language feature. In order to analyze a project with PMD that uses these language features, +you'll need to enable it via the environment variable `PMD_JAVA_OPTS` and select the new language +version `18-preview`: + + export PMD_JAVA_OPTS=--enable-preview + ./run.sh pmd -language java -version 18-preview ... + +Note: Support for Java 16 preview language features have been removed. The version "16-preview" is no longer available. #### New programmatic API @@ -55,6 +68,8 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is * [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() * core * [#3299](https://github.com/pmd/pmd/issues/3299): \[core] Deprecate system properties of PMDCommandLineInterface +* java + * [#3809](https://github.com/pmd/pmd/issues/3809): \[java] Support JDK 18 ### API Changes From c50f4f2903b40bf6f7a900084084cf6c8eb39570 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 16:25:10 +0100 Subject: [PATCH 28/89] [java] Fix unit tests after merge --- .../java/ast/Java17PreviewTreeDumpTest.java | 6 +- .../pmd/lang/java/ast/Java17TreeDumpTest.java | 4 +- .../java/ast/Java18PreviewTreeDumpTest.java | 8 +- .../java18p/DealingWithNull.txt | 972 ++++++---------- .../java18p/EnhancedTypeCheckingSwitch.txt | 346 +++--- .../java18p/ExhaustiveSwitch.txt | 1009 ++++++----------- .../GuardedAndParenthesizedPatterns.txt | 938 ++++++--------- .../java18p/PatternsInSwitchLabels.txt | 243 ++-- .../java18p/RefiningPatternsInSwitch.txt | 707 ++++-------- .../ScopeOfPatternVariableDeclarations.txt | 386 +++---- 10 files changed, 1703 insertions(+), 2916 deletions(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17PreviewTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17PreviewTreeDumpTest.java index ff1364b97c..86d198fc52 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17PreviewTreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17PreviewTreeDumpTest.java @@ -41,7 +41,7 @@ public class Java17PreviewTreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Pattern matching for switch is a preview feature of JDK 17 or JDK 18, you should select your language version accordingly")); + thrown.getMessage().contains("Pattern matching for switch is a preview feature of JDK 17, you should select your language version accordingly")); } @Test @@ -68,7 +68,7 @@ public class Java17PreviewTreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Null case labels is a preview feature of JDK 17 or JDK 18, you should select your language version accordingly")); + thrown.getMessage().contains("Null case labels is a preview feature of JDK 17, you should select your language version accordingly")); } @Test @@ -84,7 +84,7 @@ public class Java17PreviewTreeDumpTest extends BaseTreeDumpTest { java17.parseResource("GuardedAndParenthesizedPatterns.java"); } }); - assertThat(thrown.getMessage(), containsString("Pattern matching for switch is a preview feature of JDK 17 or JDK 18, you should select your language version accordingly")); + assertThat(thrown.getMessage(), containsString("Pattern matching for switch is a preview feature of JDK 17, you should select your language version accordingly")); } @Test diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java index 56a1fbdf0d..19356ba1fa 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java @@ -39,7 +39,7 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Sealed classes is a feature of JDK >= 17, you should select your language version accordingly")); + thrown.getMessage().contains("Sealed classes is a preview feature of JDK 16, you should select your language version accordingly")); } @Test @@ -69,7 +69,7 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Sealed classes is a feature of JDK >= 17, you should select your language version accordingly")); + thrown.getMessage().contains("Sealed classes is a preview feature of JDK 16, you should select your language version accordingly")); } @Test diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java18PreviewTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java18PreviewTreeDumpTest.java index bc8ae8cb14..66449c6159 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java18PreviewTreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java18PreviewTreeDumpTest.java @@ -20,7 +20,7 @@ import net.sourceforge.pmd.lang.java.JavaParsingHelper; public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest { private final JavaParsingHelper java18p = JavaParsingHelper.DEFAULT.withDefaultVersion("18-preview") - .withResourceContext(Java18PreviewTreeDumpTest.class, "jdkversiontests/java17p/"); + .withResourceContext(Java18PreviewTreeDumpTest.class, "jdkversiontests/java18p/"); private final JavaParsingHelper java18 = java18p.withDefaultVersion("18"); public Java18PreviewTreeDumpTest() { @@ -41,7 +41,7 @@ public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Null case labels is a preview feature of JDK 17 or JDK 18, you should select your language version accordingly")); + thrown.getMessage().contains("Null case labels is a preview feature of JDK 18, you should select your language version accordingly")); } @Test @@ -67,7 +67,7 @@ public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest { java18.parseResource("GuardedAndParenthesizedPatterns.java"); } }); - assertThat(thrown.getMessage(), containsString("Pattern matching for switch is a preview feature of JDK 17 or JDK 18, you should select your language version accordingly")); + assertThat(thrown.getMessage(), containsString("Pattern matching for switch is a preview feature of JDK 18, you should select your language version accordingly")); } @Test @@ -84,7 +84,7 @@ public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Pattern matching for switch is a preview feature of JDK 17 or JDK 18, you should select your language version accordingly")); + thrown.getMessage().contains("Pattern matching for switch is a preview feature of JDK 18, you should select your language version accordingly")); } @Test diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.txt index 72878864b5..d2506f01c6 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/DealingWithNull.txt @@ -1,637 +1,335 @@ -+- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] - +- TypeDeclaration[] - +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "DealingWithNull", @Default = false, @Final = false, @Image = "DealingWithNull", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "DealingWithNull", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testFooBar", @Modifiers = 16, @Name = "testFooBar", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "testFooBar", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "s"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- NullLiteral[] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Oops"", @FloatLiteral = false, @Image = ""Oops"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Oops"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Foo"", @FloatLiteral = false, @Image = ""Foo"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Foo"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Bar"", @FloatLiteral = false, @Image = ""Bar"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Bar"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Great"", @FloatLiteral = false, @Image = ""Great"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Great"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Ok"", @FloatLiteral = false, @Image = ""Ok"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Ok"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testStringOrNull", @Modifiers = 16, @Name = "testStringOrNull", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "testStringOrNull", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | | +- NullLiteral[] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- AdditiveExpression[@Image = "+", @Operator = "+"] - | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String: "", @FloatLiteral = false, @Image = ""String: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "s"] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.print"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test", @Modifiers = 16, @Name = "test", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "test", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- NullLiteral[] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""null!"", @FloatLiteral = false, @Image = ""null!"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""null!"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String"", @FloatLiteral = false, @Image = ""String"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Something else"", @FloatLiteral = false, @Image = ""Something else"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Something else"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test2", @Modifiers = 16, @Name = "test2", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "test2", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabeledThrowStatement[] - | | +- SwitchLabel[@Default = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- NullLiteral[] - | | +- ThrowStatement[@FirstClassOrInterfaceTypeImage = "NullPointerException"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- AllocationExpression[@AnonymousClass = false] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "NullPointerException", @ReferenceToClassSameCompilationUnit = false] - | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- AdditiveExpression[@Image = "+", @Operator = "+"] - | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String: "", @FloatLiteral = false, @Image = ""String: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "s"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Integer"", @FloatLiteral = false, @Image = ""Integer"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Integer"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default"", @FloatLiteral = false, @Image = ""default"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test3", @Modifiers = 16, @Name = "test3", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "test3", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "o"] - | | +- SwitchLabel[@Default = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- NullLiteral[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- StatementExpression[] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String, including null"", @FloatLiteral = false, @Image = ""String, including null"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String, including null"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- BreakStatement[] - | | +- SwitchLabel[@Default = true] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- StatementExpression[] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- BreakStatement[] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "o"] - | | +- SwitchLabeledExpression[] - | | | +- SwitchLabel[@Default = false] - | | | | +- Expression[@StandAlonePrimitive = false] - | | | | | +- PrimaryExpression[] - | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | | | +- NullLiteral[] - | | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String, including null"", @FloatLiteral = false, @Image = ""String, including null"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String, including null"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = true] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "o"] - | | +- SwitchLabel[@Default = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- NullLiteral[] - | | +- SwitchLabel[@Default = true] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""The rest (including null)"", @FloatLiteral = false, @Image = ""The rest (including null)"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""The rest (including null)"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- NullLiteral[] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""The rest (including null)"", @FloatLiteral = false, @Image = ""The rest (including null)"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""The rest (including null)"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] - +- ResultType[@Void = true, @returnsArray = false] - +- MethodDeclarator[@Image = "main", @ParameterCount = 1] - | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] - | | +- ReferenceType[@Array = true, @ArrayDepth = 1] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] - +- Block[@containsComment = false] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""test"", @FloatLiteral = false, @Image = ""test"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""test"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test2"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "2", @FloatLiteral = false, @Image = "2", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "2", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 2, @ValueAsLong = 2] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- TryStatement[@Finally = false, @TryWithResources = false] - | +- Block[@containsComment = false] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "test2"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- NullLiteral[] - | +- CatchStatement[@ExceptionName = "e", @MulticatchStatement = false] - | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "NullPointerException"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "NullPointerException", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = true, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "e", @LambdaParameter = false, @LocalVariable = false, @Name = "e", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "e"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "e"] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test3"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "3", @FloatLiteral = false, @Image = "3", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "3", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 3, @ValueAsLong = 3] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test3"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""test"", @FloatLiteral = false, @Image = ""test"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""test"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test3"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- NullLiteral[] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testFooBar"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- NullLiteral[] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testFooBar"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Foo"", @FloatLiteral = false, @Image = ""Foo"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Foo"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testFooBar"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Bar"", @FloatLiteral = false, @Image = ""Bar"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Bar"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testFooBar"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""baz"", @FloatLiteral = false, @Image = ""baz"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""baz"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testStringOrNull"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- NullLiteral[] - +- BlockStatement[@Allocation = false] - +- Statement[] - +- StatementExpression[] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "testStringOrNull"] - +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - +- Arguments[@ArgumentCount = 1, @Size = 1] - +- ArgumentList[@Size = 1] - +- Expression[@StandAlonePrimitive = false] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""some string"", @FloatLiteral = false, @Image = ""some string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""some string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = "true"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "DealingWithNull", @CanonicalName = "DealingWithNull", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Image = "DealingWithNull", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "DealingWithNull", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "public", @Volatile = "false"] + +- ModifierList[] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "6"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "testFooBar", @MainMethod = "false", @MethodName = "testFooBar", @Name = "testFooBar", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "String", @TypeImage = "String"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @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 = "s", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Oops", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Oops\"", @IntLiteral = "false", @Length = "4", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Foo", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Foo\"", @IntLiteral = "false", @Length = "3", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Bar", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Bar\"", @IntLiteral = "false", @Length = "3", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Great", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Great\"", @IntLiteral = "false", @Length = "5", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Ok", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Ok\"", @IntLiteral = "false", @Length = "2", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "testStringOrNull", @MainMethod = "false", @MethodName = "testStringOrNull", @Name = "testStringOrNull", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "String: ", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"String: \"", @IntLiteral = "false", @Length = "8", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "print", @MethodName = "print", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "default case", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"default case\"", @IntLiteral = "false", @Length = "12", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "test", @MainMethod = "false", @MethodName = "test", @Name = "test", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "null!", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"null!\"", @IntLiteral = "false", @Length = "5", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "String", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"String\"", @IntLiteral = "false", @Length = "6", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Something else", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Something else\"", @IntLiteral = "false", @Length = "14", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "test2", @MainMethod = "false", @MethodName = "test2", @Name = "test2", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | +- ThrowStatement[] + | | +- 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 = "NullPointerException", @TypeImage = "NullPointerException"] + | | +- ArgumentList[@Empty = "true", @Size = "0"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "String: ", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"String: \"", @IntLiteral = "false", @Length = "8", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Integer", @TypeImage = "Integer"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @Visibility = "local", @Volatile = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Integer", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Integer\"", @IntLiteral = "false", @Length = "7", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "default", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"default\"", @IntLiteral = "false", @Length = "7", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "test3", @MainMethod = "false", @MethodName = "test3", @Name = "test3", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "4", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "true"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchFallthroughBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | +- SwitchFallthroughBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | | +- ExpressionStatement[] + | | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "String, including null", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"String, including null\"", @IntLiteral = "false", @Length = "22", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | | +- BreakStatement[@Label = null] + | | +- SwitchFallthroughBranch[@Default = "true"] + | | +- SwitchLabel[@Default = "true"] + | | +- ExpressionStatement[] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "default case", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"default case\"", @IntLiteral = "false", @Length = "12", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- BreakStatement[@Label = null] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "String, including null", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"String, including null\"", @IntLiteral = "false", @Length = "22", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- SwitchArrowBranch[@Default = "true"] + | | +- SwitchLabel[@Default = "true"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "default case", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"default case\"", @IntLiteral = "false", @Length = "12", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "true"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchFallthroughBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | +- SwitchFallthroughBranch[@Default = "true"] + | | +- SwitchLabel[@Default = "true"] + | | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "The rest (including null)", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"The rest (including null)\"", @IntLiteral = "false", @Length = "25", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "The rest (including null)", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"The rest (including null)\"", @IntLiteral = "false", @Length = "25", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Final = "false", @Image = "main", @MainMethod = "true", @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[] + +- VoidType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "void"] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- 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[] + | +- ArrayType[@ArrayDepth = "1", @ArrayType = "true", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "String[]"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] + | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | +- ArrayTypeDim[@Varargs = "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[@Empty = "false", @Size = "12", @containsComment = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test", @MethodName = "test", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "test", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"test\"", @IntLiteral = "false", @Length = "4", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test2", @MethodName = "test2", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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"] + +- TryStatement[@TryWithResources = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test2", @MethodName = "test2", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | +- CatchClause[] + | +- CatchParameter[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Multicatch = "false", @Name = "e", @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 = "NullPointerException", @TypeImage = "NullPointerException"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "true", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "e", @LambdaParameter = "false", @LocalVariable = "false", @Name = "e", @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 = "false", @VariableName = "e", @Visibility = "package", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "e", @Name = "e", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test3", @MethodName = "test3", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test3", @MethodName = "test3", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "test", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"test\"", @IntLiteral = "false", @Length = "4", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test3", @MethodName = "test3", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testFooBar", @MethodName = "testFooBar", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testFooBar", @MethodName = "testFooBar", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Foo", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Foo\"", @IntLiteral = "false", @Length = "3", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testFooBar", @MethodName = "testFooBar", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Bar", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Bar\"", @IntLiteral = "false", @Length = "3", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testFooBar", @MethodName = "testFooBar", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "baz", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"baz\"", @IntLiteral = "false", @Length = "3", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testStringOrNull", @MethodName = "testStringOrNull", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + +- ExpressionStatement[] + +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testStringOrNull", @MethodName = "testStringOrNull", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ArgumentList[@Empty = "false", @Size = "1"] + +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "some string", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"some string\"", @IntLiteral = "false", @Length = "11", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.txt index d5ea56fdf2..0cf85c5739 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/EnhancedTypeCheckingSwitch.txt @@ -1,199 +1,147 @@ -+- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] - +- TypeDeclaration[] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "EnhancedTypeCheckingSwitch", @Default = false, @Final = false, @Image = "EnhancedTypeCheckingSwitch", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "EnhancedTypeCheckingSwitch", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "typeTester", @Modifiers = 16, @Name = "typeTester", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | | +- ResultType[@Void = true, @returnsArray = false] - | | +- MethodDeclarator[@Image = "typeTester", @ParameterCount = 1] - | | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | | +- Block[@containsComment = false] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "o"] - | | +- SwitchLabeledExpression[] - | | | +- SwitchLabel[@Default = false] - | | | | +- Expression[@StandAlonePrimitive = false] - | | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | | +- NullLiteral[] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""null"", @FloatLiteral = false, @Image = ""null"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""null"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- SwitchLabeledExpression[] - | | | +- SwitchLabel[@Default = false] - | | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String"", @FloatLiteral = false, @Image = ""String"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- SwitchLabeledExpression[] - | | | +- SwitchLabel[@Default = false] - | | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Color"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Color", @ReferenceToClassSameCompilationUnit = true] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- AdditiveExpression[@Image = "+", @Operator = "+"] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Color with "", @FloatLiteral = false, @Image = ""Color with "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Color with "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "c.values"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | | +- PrimarySuffix[@ArgumentCount = -1, @Arguments = false, @ArrayDereference = false, @Image = "length"] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "" values"", @FloatLiteral = false, @Image = "" values"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "" values"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- SwitchLabeledExpression[] - | | | +- SwitchLabel[@Default = false] - | | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Point"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Point", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "p", @LambdaParameter = false, @LocalVariable = false, @Name = "p", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "p"] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- AdditiveExpression[@Image = "+", @Operator = "+"] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Record class: "", @FloatLiteral = false, @Image = ""Record class: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Record class: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "p.toString"] - | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | +- SwitchLabeledExpression[] - | | | +- SwitchLabel[@Default = false] - | | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "int"] - | | | | | +- ReferenceType[@Array = true, @ArrayDepth = 1] - | | | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "ia", @LambdaParameter = false, @LocalVariable = false, @Name = "ia", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "ia"] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- AdditiveExpression[@Image = "+", @Operator = "+"] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Array of ints of length"", @FloatLiteral = false, @Image = ""Array of ints of length"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Array of ints of length"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "ia.length"] - | | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = true] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Something else"", @FloatLiteral = false, @Image = ""Something else"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Something else"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "main", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] - | | | +- ReferenceType[@Array = true, @ArrayDepth = 1] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "o", @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclarator[@Initializer = true, @Name = "o"] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "o", @LambdaParameter = false, @LocalVariable = true, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | | +- VariableInitializer[] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""test"", @FloatLiteral = false, @Image = ""test"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""test"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "typeTester"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "o"] - +- TypeDeclaration[] - | +- RecordDeclaration[@Abstract = false, @BinaryName = "Point", @Default = false, @Final = true, @Image = "Point", @Local = false, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "Point", @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyFinal = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false] - | +- RecordComponentList[@Size = 2] - | | +- RecordComponent[@Varargs = false] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] - | | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = true, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | | +- RecordComponent[@Varargs = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] - | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = true, @ForeachVariable = false, @FormalParameter = false, @Image = "j", @LambdaParameter = false, @LocalVariable = false, @Name = "j", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "j"] - | +- RecordBody[] - +- TypeDeclaration[] - +- EnumDeclaration[@Abstract = false, @BinaryName = "Color", @Default = false, @Final = false, @Image = "Color", @Local = false, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "Color", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.ENUM, @Volatile = false] - +- EnumBody[] - +- EnumConstant[@AnonymousClass = false, @Image = "RED"] - +- EnumConstant[@AnonymousClass = false, @Image = "GREEN"] - +- EnumConstant[@AnonymousClass = false, @Image = "BLUE"] ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = "true"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "EnhancedTypeCheckingSwitch", @CanonicalName = "EnhancedTypeCheckingSwitch", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Image = "EnhancedTypeCheckingSwitch", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "EnhancedTypeCheckingSwitch", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "public", @Volatile = "false"] + | +- ModifierList[] + | +- ClassOrInterfaceBody[@Empty = "false", @Size = "2"] + | +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "typeTester", @MainMethod = "false", @MethodName = "typeTester", @Name = "typeTester", @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"] + | | +- FormalParameters[@Empty = "false", @Size = "1"] + | | | +- 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 = "Object", @TypeImage = "Object"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "null", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"null\"", @IntLiteral = "false", @Length = "4", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "String", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"String\"", @IntLiteral = "false", @Length = "6", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Color", @TypeImage = "Color"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "c", @LambdaParameter = "false", @LocalVariable = "false", @Name = "c", @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 = "c", @Visibility = "local", @Volatile = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Color with ", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Color with \"", @IntLiteral = "false", @Length = "11", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "length", @Name = "length", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "values", @MethodName = "values", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "c", @Name = "c", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = " values", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\" values\"", @IntLiteral = "false", @Length = "7", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Point", @TypeImage = "Point"] + | | | | +- 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 = "false", @Name = "p", @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 = "p", @Visibility = "local", @Volatile = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Record class: ", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Record class: \"", @IntLiteral = "false", @Length = "14", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "toString", @MethodName = "toString", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "p", @Name = "p", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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[] + | | | | +- ArrayType[@ArrayDepth = "1", @ArrayType = "true", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "int[]"] + | | | | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] + | | | | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | | | | +- ArrayTypeDim[@Varargs = "false"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "true", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "ia", @LambdaParameter = "false", @LocalVariable = "false", @Name = "ia", @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 = "ia", @Visibility = "local", @Volatile = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Array of ints of length", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Array of ints of length\"", @IntLiteral = "false", @Length = "23", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "length", @Name = "length", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "ia", @Name = "ia", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchArrowBranch[@Default = "true"] + | | +- SwitchLabel[@Default = "true"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Something else", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Something else\"", @IntLiteral = "false", @Length = "14", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Final = "false", @Image = "main", @MainMethod = "true", @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[] + | +- VoidType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "void"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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[] + | | +- ArrayType[@ArrayDepth = "1", @ArrayType = "true", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "String[]"] + | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] + | | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | | +- ArrayTypeDim[@Varargs = "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[@Empty = "false", @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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclarator[@Initializer = "true", @Name = "o"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "o", @LambdaParameter = "false", @LocalVariable = "true", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "test", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"test\"", @IntLiteral = "false", @Length = "4", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "typeTester", @MethodName = "typeTester", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "Point", @CanonicalName = "Point", @EffectiveVisibility = "package", @Enum = "false", @Final = "true", @Image = "Point", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "true", @RegularClass = "false", @RegularInterface = "false", @SimpleName = "Point", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- RecordComponentList[@Empty = "false", @Size = "2", @Varargs = "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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "j", @LambdaParameter = "false", @LocalVariable = "false", @Name = "j", @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 = "j", @Visibility = "private", @Volatile = "false"] + | +- RecordBody[@Empty = "true", @Size = "0"] + +- EnumDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "Color", @CanonicalName = "Color", @EffectiveVisibility = "package", @Enum = "true", @Final = "true", @Image = "Color", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "false", @RegularInterface = "false", @SimpleName = "Color", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "package", @Volatile = "false"] + +- ModifierList[] + +- EnumBody[@Empty = "false", @SeparatorSemi = "true", @Size = "3", @TrailingComma = "false"] + +- EnumConstant[@Abstract = "false", @AnonymousClass = "false", @EffectiveVisibility = "package", @Final = "true", @Image = "RED", @MethodName = "new", @Name = "RED", @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 = "package", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "RED", @LambdaParameter = "false", @LocalVariable = "false", @Name = "RED", @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 = "RED", @Visibility = "public", @Volatile = "false"] + +- EnumConstant[@Abstract = "false", @AnonymousClass = "false", @EffectiveVisibility = "package", @Final = "true", @Image = "GREEN", @MethodName = "new", @Name = "GREEN", @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 = "package", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "GREEN", @LambdaParameter = "false", @LocalVariable = "false", @Name = "GREEN", @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 = "GREEN", @Visibility = "public", @Volatile = "false"] + +- EnumConstant[@Abstract = "false", @AnonymousClass = "false", @EffectiveVisibility = "package", @Final = "true", @Image = "BLUE", @MethodName = "new", @Name = "BLUE", @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 = "package", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "BLUE", @LambdaParameter = "false", @LocalVariable = "false", @Name = "BLUE", @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 = "BLUE", @Visibility = "public", @Volatile = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.txt index ce57bb07ea..bf53de045f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ExhaustiveSwitch.txt @@ -1,634 +1,375 @@ -+- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] - +- TypeDeclaration[] - +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch", @Default = false, @Final = false, @Image = "ExhaustiveSwitch", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "ExhaustiveSwitch", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "coverage", @Modifiers = 16, @Name = "coverage", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = false, @Volatile = false] - | +- ResultType[@Void = false, @returnsArray = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] - | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | +- MethodDeclarator[@Image = "coverage", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- ReturnStatement[] - | +- Expression[@StandAlonePrimitive = false] - | +- SwitchExpression[] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "s.length"] - | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "i"] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "0", @FloatLiteral = false, @Image = "0", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "0", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "coverageStatement", @Modifiers = 16, @Name = "coverageStatement", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "coverageStatement", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabel[@Default = false] - | | +- TypePattern[@ParenthesisDepth = 0] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "s"] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- BreakStatement[] - | +- SwitchLabel[@Default = false] - | | +- TypePattern[@ParenthesisDepth = 0] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Integer"", @FloatLiteral = false, @Image = ""Integer"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Integer"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- BreakStatement[] - | +- SwitchLabel[@Default = true] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- BreakStatement[] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.INTERFACE] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$S", @Default = false, @Final = false, @Image = "S", @Interface = true, @Local = false, @Modifiers = 16384, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = true, @SimpleName = "S", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.INTERFACE, @Volatile = false] - | +- PermitsList[] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "B", @ReferenceToClassSameCompilationUnit = true] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$A", @Default = false, @Final = true, @Image = "A", @Interface = false, @Local = false, @Modifiers = 48, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "A", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - | +- ImplementsList[] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$B", @Default = false, @Final = true, @Image = "B", @Interface = false, @Local = false, @Modifiers = 48, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "B", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - | +- ImplementsList[] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.RECORD] - | +- RecordDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$C", @Default = false, @Final = true, @Image = "C", @Local = false, @Modifiers = 0, @Native = false, @Nested = true, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "C", @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyFinal = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false] - | +- RecordComponentList[@Size = 1] - | | +- RecordComponent[@Varargs = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] - | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = true, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | +- ImplementsList[] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] - | +- RecordBody[] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testSealedExhaustive", @Modifiers = 16, @Name = "testSealedExhaustive", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = false, @Volatile = false] - | +- ResultType[@Void = false, @returnsArray = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] - | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | +- MethodDeclarator[@Image = "testSealedExhaustive", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "S"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- ReturnStatement[] - | +- Expression[@StandAlonePrimitive = false] - | +- SwitchExpression[] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "s"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "A"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "a", @LambdaParameter = false, @LocalVariable = false, @Name = "a", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "a"] - | | +- Expression[@StandAlonePrimitive = true] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "B"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "B", @ReferenceToClassSameCompilationUnit = true] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "b", @LambdaParameter = false, @LocalVariable = false, @Name = "b", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "b"] - | | +- Expression[@StandAlonePrimitive = true] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "2", @FloatLiteral = false, @Image = "2", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "2", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 2, @ValueAsLong = 2] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = false] - | | +- TypePattern[@ParenthesisDepth = 0] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "C"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "3", @FloatLiteral = false, @Image = "3", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "3", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 3, @ValueAsLong = 3] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "switchStatementExhaustive", @Modifiers = 16, @Name = "switchStatementExhaustive", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "switchStatementExhaustive", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "S"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "S", @ReferenceToClassSameCompilationUnit = true] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "s"] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "A"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "a", @LambdaParameter = false, @LocalVariable = false, @Name = "a", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "a"] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- StatementExpression[] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A"", @FloatLiteral = false, @Image = ""A"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = true, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- BreakStatement[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "C"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- StatementExpression[] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""C"", @FloatLiteral = false, @Image = ""C"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = true, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""C"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- BreakStatement[] - | | +- SwitchLabel[@Default = true] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- StatementExpression[] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case, should be B"", @FloatLiteral = false, @Image = ""default case, should be B"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case, should be B"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- BreakStatement[] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- EmptyStatement[] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.INTERFACE] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$I", @Default = false, @Final = false, @Image = "I", @Interface = true, @Local = false, @Modifiers = 16384, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = true, @SimpleName = "I", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.INTERFACE, @Volatile = false] - | +- TypeParameters[] - | | +- TypeParameter[@Image = "T", @Name = "T", @ParameterName = "T", @TypeBound = false] - | +- PermitsList[] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "E", @ReferenceToClassSameCompilationUnit = true] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "F", @ReferenceToClassSameCompilationUnit = true] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$E", @Default = false, @Final = true, @Image = "E", @Interface = false, @Local = false, @Modifiers = 48, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "E", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - | +- TypeParameters[] - | | +- TypeParameter[@Image = "X", @Name = "X", @ParameterName = "X", @TypeBound = false] - | +- ImplementsList[] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "I", @ReferenceToClassSameCompilationUnit = true] - | | +- TypeArguments[@Diamond = false] - | | +- TypeArgument[@Wildcard = false] - | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ExhaustiveSwitch$F", @Default = false, @Final = true, @Image = "F", @Interface = false, @Local = false, @Modifiers = 48, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "F", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - | +- TypeParameters[] - | | +- TypeParameter[@Image = "Y", @Name = "Y", @ParameterName = "Y", @TypeBound = false] - | +- ImplementsList[] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "I", @ReferenceToClassSameCompilationUnit = true] - | | +- TypeArguments[@Diamond = false] - | | +- TypeArgument[@Wildcard = false] - | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Y", @ReferenceToClassSameCompilationUnit = false] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testGenericSealedExhaustive", @Modifiers = 16, @Name = "testGenericSealedExhaustive", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = false, @Volatile = false] - | +- ResultType[@Void = false, @returnsArray = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] - | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | +- MethodDeclarator[@Image = "testGenericSealedExhaustive", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "I"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "I", @ReferenceToClassSameCompilationUnit = true] - | | | +- TypeArguments[@Diamond = false] - | | | +- TypeArgument[@Wildcard = false] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- ReturnStatement[] - | +- Expression[@StandAlonePrimitive = false] - | +- SwitchExpression[] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "i"] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = false] - | | +- TypePattern[@ParenthesisDepth = 0] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "F"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "F", @ReferenceToClassSameCompilationUnit = true] - | | | +- TypeArguments[@Diamond = false] - | | | +- TypeArgument[@Wildcard = false] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "bi", @LambdaParameter = false, @LocalVariable = false, @Name = "bi", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "bi"] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "42", @FloatLiteral = false, @Image = "42", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "42", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 42, @ValueAsLong = 42] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] - +- ResultType[@Void = true, @returnsArray = false] - +- MethodDeclarator[@Image = "main", @ParameterCount = 1] - | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] - | | +- ReferenceType[@Array = true, @ArrayDepth = 1] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] - +- Block[@containsComment = false] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "coverage"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""a string"", @FloatLiteral = false, @Image = ""a string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""a string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "coverage"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "42", @FloatLiteral = false, @Image = "42", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "42", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 42, @ValueAsLong = 42] - +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "coverage"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "coverageStatement"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""a string"", @FloatLiteral = false, @Image = ""a string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""a string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "coverageStatement"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "21", @FloatLiteral = false, @Image = "21", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "21", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 21, @ValueAsLong = 21] - +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "coverageStatement"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- AdditiveExpression[@Image = "+", @Operator = "+"] - | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A:"", @FloatLiteral = false, @Image = ""A:"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A:"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testSealedExhaustive"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- AdditiveExpression[@Image = "+", @Operator = "+"] - | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""B:"", @FloatLiteral = false, @Image = ""B:"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""B:"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testSealedExhaustive"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "B", @ReferenceToClassSameCompilationUnit = true] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- AdditiveExpression[@Image = "+", @Operator = "+"] - | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""C:"", @FloatLiteral = false, @Image = ""C:"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""C:"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testSealedExhaustive"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "switchStatementExhaustive"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "A", @ReferenceToClassSameCompilationUnit = true] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "switchStatementExhaustive"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "B", @ReferenceToClassSameCompilationUnit = true] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "switchStatementExhaustive"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "C", @ReferenceToClassSameCompilationUnit = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "2", @FloatLiteral = false, @Image = "2", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "2", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 2, @ValueAsLong = 2] - +- BlockStatement[@Allocation = true] - +- Statement[] - +- StatementExpression[] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "System.out.println"] - +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - +- Arguments[@ArgumentCount = 1, @Size = 1] - +- ArgumentList[@Size = 1] - +- Expression[@StandAlonePrimitive = false] - +- AdditiveExpression[@Image = "+", @Operator = "+"] - +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""F:"", @FloatLiteral = false, @Image = ""F:"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""F:"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "testGenericSealedExhaustive"] - +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - +- Arguments[@ArgumentCount = 1, @Size = 1] - +- ArgumentList[@Size = 1] - +- Expression[@StandAlonePrimitive = false] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - +- AllocationExpression[@AnonymousClass = false] - +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "F", @ReferenceToClassSameCompilationUnit = true] - | +- TypeArguments[@Diamond = false] - | +- TypeArgument[@Wildcard = false] - | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - +- Arguments[@ArgumentCount = 0, @Size = 0] ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = "true"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "ExhaustiveSwitch", @CanonicalName = "ExhaustiveSwitch", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Image = "ExhaustiveSwitch", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "ExhaustiveSwitch", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "public", @Volatile = "false"] + +- ModifierList[] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "13"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "coverage", @MainMethod = "false", @MethodName = "coverage", @Name = "coverage", @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 = "false", @Volatile = "false"] + | +- ModifierList[] + | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- ReturnStatement[] + | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @Expression = "true", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | +- 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"] + | | +- ArgumentList[@Empty = "true", @Size = "0"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Integer", @TypeImage = "Integer"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @Visibility = "local", @Volatile = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "i", @Name = "i", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- 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"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "coverageStatement", @MainMethod = "false", @MethodName = "coverageStatement", @Name = "coverageStatement", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "true"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchFallthroughBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | +- ExpressionStatement[] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- BreakStatement[@Label = null] + | +- SwitchFallthroughBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Integer", @TypeImage = "Integer"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @Visibility = "local", @Volatile = "false"] + | | +- ExpressionStatement[] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Integer", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Integer\"", @IntLiteral = "false", @Length = "7", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- BreakStatement[@Label = null] + | +- SwitchFallthroughBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- BreakStatement[@Label = null] + +- ClassOrInterfaceDeclaration[@Abstract = "true", @Annotation = "false", @Anonymous = "false", @BinaryName = "ExhaustiveSwitch$S", @CanonicalName = "ExhaustiveSwitch.S", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Image = "S", @Interface = "true", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "false", @RegularInterface = "true", @SimpleName = "S", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- PermitsList[@Empty = "false", @Size = "3"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "A", @TypeImage = "A"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "B", @TypeImage = "B"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "C", @TypeImage = "C"] + | +- ClassOrInterfaceBody[@Empty = "true", @Size = "0"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "ExhaustiveSwitch$A", @CanonicalName = "ExhaustiveSwitch.A", @EffectiveVisibility = "package", @Enum = "false", @Final = "true", @Image = "A", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "A", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- ImplementsList[@Empty = "false", @Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "S", @TypeImage = "S"] + | +- ClassOrInterfaceBody[@Empty = "true", @Size = "0"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "ExhaustiveSwitch$B", @CanonicalName = "ExhaustiveSwitch.B", @EffectiveVisibility = "package", @Enum = "false", @Final = "true", @Image = "B", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "B", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- ImplementsList[@Empty = "false", @Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "S", @TypeImage = "S"] + | +- ClassOrInterfaceBody[@Empty = "true", @Size = "0"] + +- RecordDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "ExhaustiveSwitch$C", @CanonicalName = "ExhaustiveSwitch.C", @EffectiveVisibility = "package", @Enum = "false", @Final = "true", @Image = "C", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "true", @RegularClass = "false", @RegularInterface = "false", @SimpleName = "C", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- RecordComponentList[@Empty = "false", @Size = "1", @Varargs = "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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @Visibility = "private", @Volatile = "false"] + | +- ImplementsList[@Empty = "false", @Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "S", @TypeImage = "S"] + | +- RecordBody[@Empty = "true", @Size = "0"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "testSealedExhaustive", @MainMethod = "false", @MethodName = "testSealedExhaustive", @Name = "testSealedExhaustive", @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 = "false", @Volatile = "false"] + | +- ModifierList[] + | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "S", @TypeImage = "S"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @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 = "s", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- ReturnStatement[] + | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "false", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @Expression = "true", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "A", @TypeImage = "A"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @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 = "a", @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"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "B", @TypeImage = "B"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "b", @LambdaParameter = "false", @LocalVariable = "false", @Name = "b", @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 = "b", @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"] + | +- SwitchArrowBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "C", @TypeImage = "C"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "c", @LambdaParameter = "false", @LocalVariable = "false", @Name = "c", @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 = "c", @Visibility = "local", @Volatile = "false"] + | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "switchStatementExhaustive", @MainMethod = "false", @MethodName = "switchStatementExhaustive", @Name = "switchStatementExhaustive", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "S", @TypeImage = "S"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @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 = "s", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "2", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "true"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchFallthroughBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "A", @TypeImage = "A"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "a", @LambdaParameter = "false", @LocalVariable = "false", @Name = "a", @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 = "a", @Visibility = "local", @Volatile = "false"] + | | | +- ExpressionStatement[] + | | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "A", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"A\"", @IntLiteral = "false", @Length = "1", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | | +- BreakStatement[@Label = null] + | | +- SwitchFallthroughBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "C", @TypeImage = "C"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "c", @LambdaParameter = "false", @LocalVariable = "false", @Name = "c", @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 = "c", @Visibility = "local", @Volatile = "false"] + | | | +- ExpressionStatement[] + | | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "C", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"C\"", @IntLiteral = "false", @Length = "1", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | | +- BreakStatement[@Label = null] + | | +- SwitchFallthroughBranch[@Default = "true"] + | | +- SwitchLabel[@Default = "true"] + | | +- ExpressionStatement[] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "default case, should be B", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"default case, should be B\"", @IntLiteral = "false", @Length = "25", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- BreakStatement[@Label = null] + | +- EmptyStatement[] + +- ClassOrInterfaceDeclaration[@Abstract = "true", @Annotation = "false", @Anonymous = "false", @BinaryName = "ExhaustiveSwitch$I", @CanonicalName = "ExhaustiveSwitch.I", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Image = "I", @Interface = "true", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "false", @RegularInterface = "true", @SimpleName = "I", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- TypeParameters[@Empty = "false", @Size = "1"] + | | +- TypeParameter[@Image = "T", @Name = "T", @TypeBound = "false"] + | +- PermitsList[@Empty = "false", @Size = "2"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "E", @TypeImage = "E"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "F", @TypeImage = "F"] + | +- ClassOrInterfaceBody[@Empty = "true", @Size = "0"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "ExhaustiveSwitch$E", @CanonicalName = "ExhaustiveSwitch.E", @EffectiveVisibility = "package", @Enum = "false", @Final = "true", @Image = "E", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "E", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- TypeParameters[@Empty = "false", @Size = "1"] + | | +- TypeParameter[@Image = "X", @Name = "X", @TypeBound = "false"] + | +- ImplementsList[@Empty = "false", @Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "I", @TypeImage = "I"] + | | +- TypeArguments[@Diamond = "false", @Empty = "false", @Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] + | +- ClassOrInterfaceBody[@Empty = "true", @Size = "0"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "ExhaustiveSwitch$F", @CanonicalName = "ExhaustiveSwitch.F", @EffectiveVisibility = "package", @Enum = "false", @Final = "true", @Image = "F", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "F", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "true", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- TypeParameters[@Empty = "false", @Size = "1"] + | | +- TypeParameter[@Image = "Y", @Name = "Y", @TypeBound = "false"] + | +- ImplementsList[@Empty = "false", @Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "I", @TypeImage = "I"] + | | +- TypeArguments[@Diamond = "false", @Empty = "false", @Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Y", @TypeImage = "Y"] + | +- ClassOrInterfaceBody[@Empty = "true", @Size = "0"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "testGenericSealedExhaustive", @MainMethod = "false", @MethodName = "testGenericSealedExhaustive", @Name = "testGenericSealedExhaustive", @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 = "false", @Volatile = "false"] + | +- ModifierList[] + | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "I", @TypeImage = "I"] + | | | +- TypeArguments[@Diamond = "false", @Empty = "false", @Size = "1"] + | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Integer", @TypeImage = "Integer"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- ReturnStatement[] + | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "false", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @Expression = "true", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "i", @Name = "i", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "F", @TypeImage = "F"] + | | | +- TypeArguments[@Diamond = "false", @Empty = "false", @Size = "1"] + | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Integer", @TypeImage = "Integer"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "bi", @LambdaParameter = "false", @LocalVariable = "false", @Name = "bi", @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 = "bi", @Visibility = "local", @Volatile = "false"] + | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "42", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "42.0", @ValueAsFloat = "42.0", @ValueAsInt = "42", @ValueAsLong = "42"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Final = "false", @Image = "main", @MainMethod = "true", @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[] + +- VoidType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "void"] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- 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[] + | +- ArrayType[@ArrayDepth = "1", @ArrayType = "true", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "String[]"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] + | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | +- ArrayTypeDim[@Varargs = "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[@Empty = "false", @Size = "13", @containsComment = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "coverage", @MethodName = "coverage", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "a string", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"a string\"", @IntLiteral = "false", @Length = "8", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "coverage", @MethodName = "coverage", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "42", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "42.0", @ValueAsFloat = "42.0", @ValueAsInt = "42", @ValueAsLong = "42"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "coverage", @MethodName = "coverage", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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 = "Object", @TypeImage = "Object"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "coverageStatement", @MethodName = "coverageStatement", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "a string", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"a string\"", @IntLiteral = "false", @Length = "8", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "coverageStatement", @MethodName = "coverageStatement", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "21", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "21.0", @ValueAsFloat = "21.0", @ValueAsInt = "21", @ValueAsLong = "21"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "coverageStatement", @MethodName = "coverageStatement", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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 = "Object", @TypeImage = "Object"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "A:", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"A:\"", @IntLiteral = "false", @Length = "2", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testSealedExhaustive", @MethodName = "testSealedExhaustive", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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 = "A", @TypeImage = "A"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "B:", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"B:\"", @IntLiteral = "false", @Length = "2", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testSealedExhaustive", @MethodName = "testSealedExhaustive", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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 = "B", @TypeImage = "B"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "C:", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"C:\"", @IntLiteral = "false", @Length = "2", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testSealedExhaustive", @MethodName = "testSealedExhaustive", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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 = "C", @TypeImage = "C"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "switchStatementExhaustive", @MethodName = "switchStatementExhaustive", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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 = "A", @TypeImage = "A"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "switchStatementExhaustive", @MethodName = "switchStatementExhaustive", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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 = "B", @TypeImage = "B"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "switchStatementExhaustive", @MethodName = "switchStatementExhaustive", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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 = "C", @TypeImage = "C"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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[] + +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + +- ArgumentList[@Empty = "false", @Size = "1"] + +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "F:", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"F:\"", @IntLiteral = "false", @Length = "2", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testGenericSealedExhaustive", @MethodName = "testGenericSealedExhaustive", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ArgumentList[@Empty = "false", @Size = "1"] + +- 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 = "F", @TypeImage = "F"] + | +- TypeArguments[@Diamond = "false", @Empty = "false", @Size = "1"] + | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Integer", @TypeImage = "Integer"] + +- ArgumentList[@Empty = "true", @Size = "0"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.txt index c9c3d0a1c5..c78ad66ac2 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/GuardedAndParenthesizedPatterns.txt @@ -1,590 +1,348 @@ -+- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] - +- TypeDeclaration[] - +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "GuardedAndParenthesizedPatterns", @Default = false, @Final = false, @Image = "GuardedAndParenthesizedPatterns", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "GuardedAndParenthesizedPatterns", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test", @Modifiers = 16, @Name = "test", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "test", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- GuardedPattern[@ParenthesisDepth = 0] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- EqualityExpression[@Image = "==", @Operator = "=="] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "s.length"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""single char string"", @FloatLiteral = false, @Image = ""single char string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""single char string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""string"", @FloatLiteral = false, @Image = ""string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- GuardedPattern[@ParenthesisDepth = 1] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | | | +- EqualityExpression[@Image = "==", @Operator = "=="] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "i.intValue"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""integer 1"", @FloatLiteral = false, @Image = ""integer 1"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""integer 1"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- GuardedPattern[@ParenthesisDepth = 3] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Long"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Long", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "l", @LambdaParameter = false, @LocalVariable = false, @Name = "l", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "l"] - | | | +- EqualityExpression[@Image = "==", @Operator = "=="] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "l.longValue"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1L", @FloatLiteral = false, @Image = "1L", @IntLiteral = false, @LongLiteral = true, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1L", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""long 1 with parens"", @FloatLiteral = false, @Image = ""long 1 with parens"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""long 1 with parens"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 3] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Double"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Double", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "d", @LambdaParameter = false, @LocalVariable = false, @Name = "d", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "d"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""double with parens"", @FloatLiteral = false, @Image = ""double with parens"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""double with parens"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testWithNull", @Modifiers = 16, @Name = "testWithNull", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "testWithNull", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- GuardedPattern[@ParenthesisDepth = 0] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- EqualityExpression[@Image = "==", @Operator = "=="] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "s.length"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""single char string"", @FloatLiteral = false, @Image = ""single char string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""single char string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""string"", @FloatLiteral = false, @Image = ""string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- GuardedPattern[@ParenthesisDepth = 1] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | | | +- EqualityExpression[@Image = "==", @Operator = "=="] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "i.intValue"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""integer 1"", @FloatLiteral = false, @Image = ""integer 1"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""integer 1"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- GuardedPattern[@ParenthesisDepth = 3] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Long"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Long", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "l", @LambdaParameter = false, @LocalVariable = false, @Name = "l", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "l"] - | | | +- EqualityExpression[@Image = "==", @Operator = "=="] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "l.longValue"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1L", @FloatLiteral = false, @Image = "1L", @IntLiteral = false, @LongLiteral = true, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1L", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""long 1 with parens"", @FloatLiteral = false, @Image = ""long 1 with parens"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""long 1 with parens"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 3] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Double"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Double", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "d", @LambdaParameter = false, @LocalVariable = false, @Name = "d", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "d"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""double with parens"", @FloatLiteral = false, @Image = ""double with parens"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""double with parens"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | +- NullLiteral[] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""null!"", @FloatLiteral = false, @Image = ""null!"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""null!"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""default case"", @FloatLiteral = false, @Image = ""default case"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""default case"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "instanceOfPattern", @Modifiers = 16, @Name = "instanceOfPattern", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "instanceOfPattern", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- IfStatement[@Else = false] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- ConditionalAndExpression[] - | | | +- InstanceOfExpression[] - | | | | +- PrimaryExpression[] - | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "o"] - | | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | | +- RelationalExpression[@Image = ">"] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "s.length"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "2", @FloatLiteral = false, @Image = "2", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "2", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 2, @ValueAsLong = 2] - | | +- Statement[] - | | +- Block[@containsComment = false] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A string containing at least two characters"", @FloatLiteral = false, @Image = ""A string containing at least two characters"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A string containing at least two characters"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- IfStatement[@Else = false] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- ConditionalAndExpression[] - | | | +- EqualityExpression[@Image = "!=", @Operator = "!="] - | | | | +- PrimaryExpression[] - | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "o"] - | | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | | | +- NullLiteral[] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- ConditionalAndExpression[] - | | | +- InstanceOfExpression[] - | | | | +- PrimaryExpression[] - | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "o"] - | | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | | +- RelationalExpression[@Image = ">"] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "s.length"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "3", @FloatLiteral = false, @Image = "3", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "3", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 3, @ValueAsLong = 3] - | | +- Statement[] - | | +- Block[@containsComment = false] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A string containing at least three characters"", @FloatLiteral = false, @Image = ""A string containing at least three characters"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A string containing at least three characters"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- IfStatement[@Else = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- InstanceOfExpression[] - | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "o"] - | | +- GuardedPattern[@ParenthesisDepth = 1] - | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | +- RelationalExpression[@Image = ">"] - | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "s.length"] - | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "4", @FloatLiteral = false, @Image = "4", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "4", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 4, @ValueAsLong = 4] - | +- Statement[] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A string containing at least four characters"", @FloatLiteral = false, @Image = ""A string containing at least four characters"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A string containing at least four characters"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] - +- ResultType[@Void = true, @returnsArray = false] - +- MethodDeclarator[@Image = "main", @ParameterCount = 1] - | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] - | | +- ReferenceType[@Array = true, @ArrayDepth = 1] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] - +- Block[@containsComment = false] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""a"", @FloatLiteral = false, @Image = ""a"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = true, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""a"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""fooo"", @FloatLiteral = false, @Image = ""fooo"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""fooo"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1L", @FloatLiteral = false, @Image = "1L", @IntLiteral = false, @LongLiteral = true, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1L", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "instanceOfPattern"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""abcde"", @FloatLiteral = false, @Image = ""abcde"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""abcde"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- TryStatement[@Finally = false, @TryWithResources = false] - | +- Block[@containsComment = true] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "test"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- NullLiteral[] - | +- CatchStatement[@ExceptionName = "e", @MulticatchStatement = false] - | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "NullPointerException"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "NullPointerException", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = true, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "e", @LambdaParameter = false, @LocalVariable = false, @Name = "e", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "e"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "e.printStackTrace"] - | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- BlockStatement[@Allocation = false] - +- Statement[] - +- StatementExpression[] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "testWithNull"] - +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - +- Arguments[@ArgumentCount = 1, @Size = 1] - +- ArgumentList[@Size = 1] - +- Expression[@StandAlonePrimitive = false] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- NullLiteral[] ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = "true"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "GuardedAndParenthesizedPatterns", @CanonicalName = "GuardedAndParenthesizedPatterns", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Image = "GuardedAndParenthesizedPatterns", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "GuardedAndParenthesizedPatterns", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "public", @Volatile = "false"] + +- ModifierList[] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "4"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "test", @MainMethod = "false", @MethodName = "test", @Name = "test", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- GuardedPattern[@ParenthesisDepth = "0"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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 = "1", @Parenthesized = "true"] + | | | +- 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"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- 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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "single char string", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"single char string\"", @IntLiteral = "false", @Length = "18", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "string", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"string\"", @IntLiteral = "false", @Length = "6", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- GuardedPattern[@ParenthesisDepth = "1"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Integer", @TypeImage = "Integer"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @Visibility = "local", @Volatile = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "==", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "intValue", @MethodName = "intValue", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "i", @Name = "i", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- 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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "integer 1", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"integer 1\"", @IntLiteral = "false", @Length = "9", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- GuardedPattern[@ParenthesisDepth = "3"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Long", @TypeImage = "Long"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "l", @LambdaParameter = "false", @LocalVariable = "false", @Name = "l", @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 = "l", @Visibility = "local", @Volatile = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "==", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "longValue", @MethodName = "longValue", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "l", @Name = "l", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "1L", @IntLiteral = "false", @Integral = "true", @LongLiteral = "true", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "long 1 with parens", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"long 1 with parens\"", @IntLiteral = "false", @Length = "18", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "3", @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 = "Double", @TypeImage = "Double"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "d", @LambdaParameter = "false", @LocalVariable = "false", @Name = "d", @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 = "d", @Visibility = "local", @Volatile = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "double with parens", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"double with parens\"", @IntLiteral = "false", @Length = "18", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "default case", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"default case\"", @IntLiteral = "false", @Length = "12", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "testWithNull", @MainMethod = "false", @MethodName = "testWithNull", @Name = "testWithNull", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- GuardedPattern[@ParenthesisDepth = "0"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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 = "1", @Parenthesized = "true"] + | | | +- 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"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- 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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "single char string", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"single char string\"", @IntLiteral = "false", @Length = "18", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "string", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"string\"", @IntLiteral = "false", @Length = "6", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- GuardedPattern[@ParenthesisDepth = "1"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Integer", @TypeImage = "Integer"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @Visibility = "local", @Volatile = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "==", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "intValue", @MethodName = "intValue", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "i", @Name = "i", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- 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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "integer 1", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"integer 1\"", @IntLiteral = "false", @Length = "9", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- GuardedPattern[@ParenthesisDepth = "3"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Long", @TypeImage = "Long"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "l", @LambdaParameter = "false", @LocalVariable = "false", @Name = "l", @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 = "l", @Visibility = "local", @Volatile = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "==", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "longValue", @MethodName = "longValue", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "l", @Name = "l", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "1L", @IntLiteral = "false", @Integral = "true", @LongLiteral = "true", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "long 1 with parens", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"long 1 with parens\"", @IntLiteral = "false", @Length = "18", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "3", @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 = "Double", @TypeImage = "Double"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "d", @LambdaParameter = "false", @LocalVariable = "false", @Name = "d", @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 = "d", @Visibility = "local", @Volatile = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "double with parens", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"double with parens\"", @IntLiteral = "false", @Length = "18", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "null!", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"null!\"", @IntLiteral = "false", @Length = "5", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "default case", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"default case\"", @IntLiteral = "false", @Length = "12", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "instanceOfPattern", @MainMethod = "false", @MethodName = "instanceOfPattern", @Name = "instanceOfPattern", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "3", @containsComment = "false"] + | +- IfStatement[@Else = "false"] + | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "&&", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "instanceof", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- 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"] + | | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "A string containing at least two characters", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"A string containing at least two characters\"", @IntLiteral = "false", @Length = "43", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- IfStatement[@Else = "false"] + | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "&&", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "!=", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "&&", @ParenthesisDepth = "1", @Parenthesized = "true"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "instanceof", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] + | | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "A string containing at least three characters", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"A string containing at least three characters\"", @IntLiteral = "false", @Length = "45", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- IfStatement[@Else = "false"] + | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "instanceof", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- GuardedPattern[@ParenthesisDepth = "1"] + | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "4", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "4.0", @ValueAsFloat = "4.0", @ValueAsInt = "4", @ValueAsLong = "4"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "A string containing at least four characters", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"A string containing at least four characters\"", @IntLiteral = "false", @Length = "44", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Final = "false", @Image = "main", @MainMethod = "true", @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[] + +- VoidType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "void"] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- 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[] + | +- ArrayType[@ArrayDepth = "1", @ArrayType = "true", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "String[]"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] + | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | +- ArrayTypeDim[@Varargs = "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[@Empty = "false", @Size = "7", @containsComment = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test", @MethodName = "test", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "a", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"a\"", @IntLiteral = "false", @Length = "1", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test", @MethodName = "test", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "fooo", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"fooo\"", @IntLiteral = "false", @Length = "4", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test", @MethodName = "test", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- 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"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test", @MethodName = "test", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "1L", @IntLiteral = "false", @Integral = "true", @LongLiteral = "true", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "1.0", @ValueAsFloat = "1.0", @ValueAsInt = "1", @ValueAsLong = "1"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "instanceOfPattern", @MethodName = "instanceOfPattern", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "abcde", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"abcde\"", @IntLiteral = "false", @Length = "5", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- TryStatement[@TryWithResources = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "true"] + | | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test", @MethodName = "test", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | +- CatchClause[] + | +- CatchParameter[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Multicatch = "false", @Name = "e", @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 = "NullPointerException", @TypeImage = "NullPointerException"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "package", @EnumConstant = "false", @ExceptionBlockParameter = "true", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "e", @LambdaParameter = "false", @LocalVariable = "false", @Name = "e", @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 = "false", @VariableName = "e", @Visibility = "package", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "printStackTrace", @MethodName = "printStackTrace", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "e", @Name = "e", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- ExpressionStatement[] + +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testWithNull", @MethodName = "testWithNull", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ArgumentList[@Empty = "false", @Size = "1"] + +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.txt index c13492cb44..37f3dbb202 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/PatternsInSwitchLabels.txt @@ -1,150 +1,93 @@ -+- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] - +- TypeDeclaration[] - +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "PatternsInSwitchLabels", @Default = false, @Final = false, @Image = "PatternsInSwitchLabels", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "PatternsInSwitchLabels", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] - +- ResultType[@Void = true, @returnsArray = false] - +- MethodDeclarator[@Image = "main", @ParameterCount = 1] - | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] - | | +- ReferenceType[@Array = true, @ArrayDepth = 1] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] - +- Block[@containsComment = false] - +- BlockStatement[@Allocation = false] - | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "o", @Volatile = false] - | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | +- VariableDeclarator[@Initializer = true, @Name = "o"] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "o", @LambdaParameter = false, @LocalVariable = true, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- VariableInitializer[] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "123L", @FloatLiteral = false, @Image = "123L", @IntLiteral = false, @LongLiteral = true, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "123L", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 123, @ValueAsLong = 123] - +- BlockStatement[@Allocation = false] - | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "formatted", @Volatile = false] - | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | +- VariableDeclarator[@Initializer = true, @Name = "formatted"] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "formatted", @LambdaParameter = false, @LocalVariable = true, @Name = "formatted", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "formatted"] - | +- VariableInitializer[] - | +- Expression[@StandAlonePrimitive = false] - | +- SwitchExpression[] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "String.format"] - | | +- PrimarySuffix[@ArgumentCount = 2, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 2, @Size = 2] - | | +- ArgumentList[@Size = 2] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""int %d"", @FloatLiteral = false, @Image = ""int %d"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""int %d"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "i"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Long"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Long", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "l", @LambdaParameter = false, @LocalVariable = false, @Name = "l", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "l"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "String.format"] - | | +- PrimarySuffix[@ArgumentCount = 2, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 2, @Size = 2] - | | +- ArgumentList[@Size = 2] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""long %d"", @FloatLiteral = false, @Image = ""long %d"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""long %d"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "l"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Double"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Double", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "d", @LambdaParameter = false, @LocalVariable = false, @Name = "d", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "d"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "String.format"] - | | +- PrimarySuffix[@ArgumentCount = 2, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 2, @Size = 2] - | | +- ArgumentList[@Size = 2] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""double %f"", @FloatLiteral = false, @Image = ""double %f"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""double %f"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "d"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "String.format"] - | | +- PrimarySuffix[@ArgumentCount = 2, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 2, @Size = 2] - | | +- ArgumentList[@Size = 2] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""String %s"", @FloatLiteral = false, @Image = ""String %s"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""String %s"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "s"] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o.toString"] - | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- BlockStatement[@Allocation = false] - +- Statement[] - +- StatementExpression[] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "System.out.println"] - +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - +- Arguments[@ArgumentCount = 1, @Size = 1] - +- ArgumentList[@Size = 1] - +- Expression[@StandAlonePrimitive = false] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - +- Name[@Image = "formatted"] ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = "true"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "PatternsInSwitchLabels", @CanonicalName = "PatternsInSwitchLabels", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Image = "PatternsInSwitchLabels", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "PatternsInSwitchLabels", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "public", @Volatile = "false"] + +- ModifierList[] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "1"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Final = "false", @Image = "main", @MainMethod = "true", @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[] + +- VoidType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "void"] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- 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[] + | +- ArrayType[@ArrayDepth = "1", @ArrayType = "true", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "String[]"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] + | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | +- ArrayTypeDim[@Varargs = "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[@Empty = "false", @Size = "3", @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 = "Object", @TypeImage = "Object"] + | +- VariableDeclarator[@Initializer = "true", @Name = "o"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "o", @LambdaParameter = "false", @LocalVariable = "true", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "123L", @IntLiteral = "false", @Integral = "true", @LongLiteral = "true", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "123.0", @ValueAsFloat = "123.0", @ValueAsInt = "123", @ValueAsLong = "123"] + +- 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 = "String", @TypeImage = "String"] + | +- VariableDeclarator[@Initializer = "true", @Name = "formatted"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "formatted", @LambdaParameter = "false", @LocalVariable = "true", @Name = "formatted", @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 = "formatted", @Visibility = "local", @Volatile = "false"] + | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @Expression = "true", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Integer", @TypeImage = "Integer"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @Visibility = "local", @Volatile = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "format", @MethodName = "format", @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 = "String", @TypeImage = "String"] + | | +- ArgumentList[@Empty = "false", @Size = "2"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "int %d", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"int %d\"", @IntLiteral = "false", @Length = "6", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "i", @Name = "i", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Long", @TypeImage = "Long"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "l", @LambdaParameter = "false", @LocalVariable = "false", @Name = "l", @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 = "l", @Visibility = "local", @Volatile = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "format", @MethodName = "format", @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 = "String", @TypeImage = "String"] + | | +- ArgumentList[@Empty = "false", @Size = "2"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "long %d", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"long %d\"", @IntLiteral = "false", @Length = "7", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "l", @Name = "l", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Double", @TypeImage = "Double"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "d", @LambdaParameter = "false", @LocalVariable = "false", @Name = "d", @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 = "d", @Visibility = "local", @Volatile = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "format", @MethodName = "format", @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 = "String", @TypeImage = "String"] + | | +- ArgumentList[@Empty = "false", @Size = "2"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "double %f", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"double %f\"", @IntLiteral = "false", @Length = "9", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "d", @Name = "d", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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", @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"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "format", @MethodName = "format", @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 = "String", @TypeImage = "String"] + | | +- ArgumentList[@Empty = "false", @Size = "2"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "String %s", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"String %s\"", @IntLiteral = "false", @Length = "9", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "toString", @MethodName = "toString", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- ExpressionStatement[] + +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + +- ArgumentList[@Empty = "false", @Size = "1"] + +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "formatted", @Name = "formatted", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.txt index 87d4845579..df94e0ed14 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/RefiningPatternsInSwitch.txt @@ -1,456 +1,251 @@ -+- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] - +- TypeDeclaration[] - +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "RefiningPatternsInSwitch", @Default = false, @Final = false, @Image = "RefiningPatternsInSwitch", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "RefiningPatternsInSwitch", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "RefiningPatternsInSwitch$Shape", @Default = false, @Final = false, @Image = "Shape", @Interface = false, @Local = false, @Modifiers = 16, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "Shape", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "RefiningPatternsInSwitch$Rectangle", @Default = false, @Final = false, @Image = "Rectangle", @Interface = false, @Local = false, @Modifiers = 16, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "Rectangle", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - | +- ExtendsList[] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CLASS] - | +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "RefiningPatternsInSwitch$Triangle", @Default = false, @Final = false, @Image = "Triangle", @Interface = false, @Local = false, @Modifiers = 16, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Sealed = false, @SimpleName = "Triangle", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - | +- ExtendsList[] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] - | +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.FIELD] - | | +- FieldDeclaration[@Abstract = false, @AnnotationMember = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @InterfaceMember = false, @Modifiers = 4, @Native = false, @PackagePrivate = false, @Private = true, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyFinal = false, @SyntacticallyPublic = false, @SyntacticallyStatic = false, @Transient = false, @VariableName = "area", @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] - | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | | +- VariableDeclarator[@Initializer = false, @Name = "area"] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = true, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "area", @LambdaParameter = false, @LocalVariable = false, @Name = "area", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "area"] - | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.CONSTRUCTOR] - | | +- ConstructorDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @Image = "Triangle", @Kind = MethodLikeKind.CONSTRUCTOR, @Modifiers = 0, @Native = false, @PackagePrivate = true, @ParameterCount = 1, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @Volatile = false, @containsComment = false] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] - | | | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "area", @LambdaParameter = false, @LocalVariable = false, @Name = "area", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "area"] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = true] - | | | +- PrimarySuffix[@ArgumentCount = -1, @Arguments = false, @ArrayDereference = false, @Image = "area"] - | | +- AssignmentOperator[@Compound = false, @Image = "="] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "area"] - | +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 0, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "calculateArea", @Modifiers = 0, @Name = "calculateArea", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = false, @Volatile = false] - | +- ResultType[@Void = false, @returnsArray = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"] - | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"] - | +- MethodDeclarator[@Image = "calculateArea", @ParameterCount = 0] - | | +- FormalParameters[@ParameterCount = 0, @Size = 0] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- ReturnStatement[] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "area"] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testTriangle", @Modifiers = 16, @Name = "testTriangle", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "testTriangle", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Shape"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "s"] - | +- SwitchLabel[@Default = false] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- NullLiteral[] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- BreakStatement[] - | +- SwitchLabel[@Default = false] - | | +- TypePattern[@ParenthesisDepth = 0] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "t", @LambdaParameter = false, @LocalVariable = false, @Name = "t", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "t"] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- IfStatement[@Else = false] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- RelationalExpression[@Image = ">"] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "t.calculateArea"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "100", @FloatLiteral = false, @Image = "100", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "100", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 100, @ValueAsLong = 100] - | | +- Statement[] - | | +- Block[@containsComment = false] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- StatementExpression[] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Large triangle"", @FloatLiteral = false, @Image = ""Large triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Large triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- BreakStatement[] - | +- SwitchLabel[@Default = true] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A shape, possibly a small triangle"", @FloatLiteral = false, @Image = ""A shape, possibly a small triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A shape, possibly a small triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testTriangleRefined", @Modifiers = 16, @Name = "testTriangleRefined", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "testTriangleRefined", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Shape"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "s"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- GuardedPattern[@ParenthesisDepth = 0] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "t", @LambdaParameter = false, @LocalVariable = false, @Name = "t", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "t"] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- RelationalExpression[@Image = ">"] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "t.calculateArea"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "100", @FloatLiteral = false, @Image = "100", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "100", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 100, @ValueAsLong = 100] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Large triangle"", @FloatLiteral = false, @Image = ""Large triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Large triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""A shape, possibly a small triangle"", @FloatLiteral = false, @Image = ""A shape, possibly a small triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""A shape, possibly a small triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "testTriangleRefined2", @Modifiers = 16, @Name = "testTriangleRefined2", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "testTriangleRefined2", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Shape"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Shape", @ReferenceToClassSameCompilationUnit = true] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "s"] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- GuardedPattern[@ParenthesisDepth = 0] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] - | | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] - | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "t", @LambdaParameter = false, @LocalVariable = false, @Name = "t", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "t"] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- RelationalExpression[@Image = ">"] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "t.calculateArea"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "100", @FloatLiteral = false, @Image = "100", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "100", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 100, @ValueAsLong = 100] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Large triangle"", @FloatLiteral = false, @Image = ""Large triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Large triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "t", @LambdaParameter = false, @LocalVariable = false, @Name = "t", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "t"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Small triangle"", @FloatLiteral = false, @Image = ""Small triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Small triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledExpression[] - | +- SwitchLabel[@Default = true] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Non-triangle"", @FloatLiteral = false, @Image = ""Non-triangle"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Non-triangle"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] - +- ResultType[@Void = true, @returnsArray = false] - +- MethodDeclarator[@Image = "main", @ParameterCount = 1] - | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] - | | +- ReferenceType[@Array = true, @ArrayDepth = 1] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] - +- Block[@containsComment = false] - +- BlockStatement[@Allocation = true] - | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "large", @Volatile = false] - | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] - | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] - | +- VariableDeclarator[@Initializer = true, @Name = "large"] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "large", @LambdaParameter = false, @LocalVariable = true, @Name = "large", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "large"] - | +- VariableInitializer[] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "200", @FloatLiteral = false, @Image = "200", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "200", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 200, @ValueAsLong = 200] - +- BlockStatement[@Allocation = true] - | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "small", @Volatile = false] - | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Triangle"] - | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] - | +- VariableDeclarator[@Initializer = true, @Name = "small"] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "small", @LambdaParameter = false, @LocalVariable = true, @Name = "small", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "small"] - | +- VariableInitializer[] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Triangle", @ReferenceToClassSameCompilationUnit = true] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "10", @FloatLiteral = false, @Image = "10", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "10", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 10, @ValueAsLong = 10] - +- BlockStatement[@Allocation = true] - | +- LocalVariableDeclaration[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @VariableName = "rect", @Volatile = false] - | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Rectangle"] - | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Rectangle", @ReferenceToClassSameCompilationUnit = true] - | +- VariableDeclarator[@Initializer = true, @Name = "rect"] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "rect", @LambdaParameter = false, @LocalVariable = true, @Name = "rect", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "rect"] - | +- VariableInitializer[] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- AllocationExpression[@AnonymousClass = false] - | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Rectangle", @ReferenceToClassSameCompilationUnit = true] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testTriangle"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "large"] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testTriangle"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "small"] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testTriangle"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "rect"] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testTriangleRefined"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "large"] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testTriangleRefined"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "small"] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testTriangleRefined"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "rect"] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testTriangleRefined2"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "large"] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "testTriangleRefined2"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = false] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "small"] - +- BlockStatement[@Allocation = false] - +- Statement[] - +- StatementExpression[] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "testTriangleRefined2"] - +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - +- Arguments[@ArgumentCount = 1, @Size = 1] - +- ArgumentList[@Size = 1] - +- Expression[@StandAlonePrimitive = false] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - +- Name[@Image = "rect"] ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = "true"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "RefiningPatternsInSwitch", @CanonicalName = "RefiningPatternsInSwitch", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Image = "RefiningPatternsInSwitch", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "RefiningPatternsInSwitch", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "public", @Volatile = "false"] + +- ModifierList[] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "7"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "RefiningPatternsInSwitch$Shape", @CanonicalName = "RefiningPatternsInSwitch.Shape", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Image = "Shape", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "Shape", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- ClassOrInterfaceBody[@Empty = "true", @Size = "0"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "RefiningPatternsInSwitch$Rectangle", @CanonicalName = "RefiningPatternsInSwitch.Rectangle", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Image = "Rectangle", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "Rectangle", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- ExtendsList[@Empty = "false", @Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Shape", @TypeImage = "Shape"] + | +- ClassOrInterfaceBody[@Empty = "true", @Size = "0"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "RefiningPatternsInSwitch$Triangle", @CanonicalName = "RefiningPatternsInSwitch.Triangle", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Image = "Triangle", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "Triangle", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- ExtendsList[@Empty = "false", @Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Shape", @TypeImage = "Shape"] + | +- ClassOrInterfaceBody[@Empty = "false", @Size = "3"] + | +- FieldDeclaration[@Abstract = "false", @EffectiveVisibility = "private", @Final = "false", @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", @VariableName = "area", @Visibility = "private", @Volatile = "false"] + | | +- ModifierList[] + | | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] + | | +- VariableDeclarator[@Initializer = "false", @Name = "area"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "area", @LambdaParameter = "false", @LocalVariable = "false", @Name = "area", @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 = "area", @Visibility = "private", @Volatile = "false"] + | +- ConstructorDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "Triangle", @Name = "Triangle", @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", @Varargs = "false", @Visibility = "package", @Volatile = "false", @containsComment = "false"] + | | +- ModifierList[] + | | +- FormalParameters[@Empty = "false", @Size = "1"] + | | | +- 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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "area", @LambdaParameter = "false", @LocalVariable = "false", @Name = "area", @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 = "area", @Visibility = "local", @Volatile = "false"] + | | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | | +- ExpressionStatement[] + | | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Expression = "true", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "WRITE", @CompileTimeConstant = "false", @Expression = "true", @Image = "area", @Name = "area", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- ThisExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "area", @Name = "area", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- MethodDeclaration[@Abstract = "false", @Arity = "0", @EffectiveVisibility = "package", @Final = "false", @Image = "calculateArea", @MainMethod = "false", @MethodName = "calculateArea", @Name = "calculateArea", @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 = "false", @Volatile = "false"] + | +- ModifierList[] + | +- PrimitiveType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @Kind = "int", @PrimitiveType = "true", @TypeImage = "int"] + | +- FormalParameters[@Empty = "true", @Size = "0"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- ReturnStatement[] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "area", @Name = "area", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "testTriangle", @MainMethod = "false", @MethodName = "testTriangle", @Name = "testTriangle", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Shape", @TypeImage = "Shape"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @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 = "s", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "true"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchFallthroughBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- NullLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "false", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "true", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + | | +- BreakStatement[@Label = null] + | +- SwitchFallthroughBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Triangle", @TypeImage = "Triangle"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "t", @LambdaParameter = "false", @LocalVariable = "false", @Name = "t", @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 = "t", @Visibility = "local", @Volatile = "false"] + | | +- IfStatement[@Else = "false"] + | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = ">", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "calculateArea", @MethodName = "calculateArea", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "t", @Name = "t", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "100", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "100.0", @ValueAsFloat = "100.0", @ValueAsInt = "100", @ValueAsLong = "100"] + | | +- Block[@Empty = "false", @Size = "2", @containsComment = "false"] + | | +- ExpressionStatement[] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Large triangle", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Large triangle\"", @IntLiteral = "false", @Length = "14", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- BreakStatement[@Label = null] + | +- SwitchFallthroughBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "A shape, possibly a small triangle", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"A shape, possibly a small triangle\"", @IntLiteral = "false", @Length = "34", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "testTriangleRefined", @MainMethod = "false", @MethodName = "testTriangleRefined", @Name = "testTriangleRefined", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Shape", @TypeImage = "Shape"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @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 = "s", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- GuardedPattern[@ParenthesisDepth = "0"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Triangle", @TypeImage = "Triangle"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "t", @LambdaParameter = "false", @LocalVariable = "false", @Name = "t", @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 = "t", @Visibility = "local", @Volatile = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = ">", @ParenthesisDepth = "1", @Parenthesized = "true"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "calculateArea", @MethodName = "calculateArea", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "t", @Name = "t", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "100", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "100.0", @ValueAsFloat = "100.0", @ValueAsInt = "100", @ValueAsLong = "100"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Large triangle", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Large triangle\"", @IntLiteral = "false", @Length = "14", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "A shape, possibly a small triangle", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"A shape, possibly a small triangle\"", @IntLiteral = "false", @Length = "34", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "testTriangleRefined2", @MainMethod = "false", @MethodName = "testTriangleRefined2", @Name = "testTriangleRefined2", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Shape", @TypeImage = "Shape"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "s", @LambdaParameter = "false", @LocalVariable = "false", @Name = "s", @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 = "s", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- GuardedPattern[@ParenthesisDepth = "0"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Triangle", @TypeImage = "Triangle"] + | | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "t", @LambdaParameter = "false", @LocalVariable = "false", @Name = "t", @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 = "t", @Visibility = "local", @Volatile = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = ">", @ParenthesisDepth = "1", @Parenthesized = "true"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "calculateArea", @MethodName = "calculateArea", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "t", @Name = "t", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "100", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "100.0", @ValueAsFloat = "100.0", @ValueAsInt = "100", @ValueAsLong = "100"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Large triangle", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Large triangle\"", @IntLiteral = "false", @Length = "14", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Triangle", @TypeImage = "Triangle"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "t", @LambdaParameter = "false", @LocalVariable = "false", @Name = "t", @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 = "t", @Visibility = "local", @Volatile = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Small triangle", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Small triangle\"", @IntLiteral = "false", @Length = "14", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Non-triangle", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Non-triangle\"", @IntLiteral = "false", @Length = "12", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Final = "false", @Image = "main", @MainMethod = "true", @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[] + +- VoidType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "void"] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- 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[] + | +- ArrayType[@ArrayDepth = "1", @ArrayType = "true", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "String[]"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] + | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | +- ArrayTypeDim[@Varargs = "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[@Empty = "false", @Size = "12", @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 = "Triangle", @TypeImage = "Triangle"] + | +- VariableDeclarator[@Initializer = "true", @Name = "large"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "large", @LambdaParameter = "false", @LocalVariable = "true", @Name = "large", @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 = "large", @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 = "Triangle", @TypeImage = "Triangle"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "200", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "200.0", @ValueAsFloat = "200.0", @ValueAsInt = "200", @ValueAsLong = "200"] + +- 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 = "Triangle", @TypeImage = "Triangle"] + | +- VariableDeclarator[@Initializer = "true", @Name = "small"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "small", @LambdaParameter = "false", @LocalVariable = "true", @Name = "small", @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 = "small", @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 = "Triangle", @TypeImage = "Triangle"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "10", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "10.0", @ValueAsFloat = "10.0", @ValueAsInt = "10", @ValueAsLong = "10"] + +- 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 = "Rectangle", @TypeImage = "Rectangle"] + | +- VariableDeclarator[@Initializer = "true", @Name = "rect"] + | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "rect", @LambdaParameter = "false", @LocalVariable = "true", @Name = "rect", @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 = "rect", @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 = "Rectangle", @TypeImage = "Rectangle"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testTriangle", @MethodName = "testTriangle", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "large", @Name = "large", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testTriangle", @MethodName = "testTriangle", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "small", @Name = "small", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testTriangle", @MethodName = "testTriangle", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "rect", @Name = "rect", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testTriangleRefined", @MethodName = "testTriangleRefined", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "large", @Name = "large", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testTriangleRefined", @MethodName = "testTriangleRefined", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "small", @Name = "small", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testTriangleRefined", @MethodName = "testTriangleRefined", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "rect", @Name = "rect", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testTriangleRefined2", @MethodName = "testTriangleRefined2", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "large", @Name = "large", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testTriangleRefined2", @MethodName = "testTriangleRefined2", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "small", @Name = "small", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "testTriangleRefined2", @MethodName = "testTriangleRefined2", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ArgumentList[@Empty = "false", @Size = "1"] + +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "rect", @Name = "rect", @ParenthesisDepth = "0", @Parenthesized = "false"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.txt index 1a11900d39..056465cc5e 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java18p/ScopeOfPatternVariableDeclarations.txt @@ -1,241 +1,145 @@ -+- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] - +- TypeDeclaration[] - +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "ScopeOfPatternVariableDeclarations", @Default = false, @Final = false, @Image = "ScopeOfPatternVariableDeclarations", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "ScopeOfPatternVariableDeclarations", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false] - +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test", @Modifiers = 16, @Name = "test", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "test", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = true] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = false] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabeledBlock[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Character"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Character", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] - | | +- Block[@containsComment = false] - | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- IfStatement[@Else = false] - | | | +- Expression[@StandAlonePrimitive = false] - | | | | +- EqualityExpression[@Image = "==", @Operator = "=="] - | | | | +- PrimaryExpression[] - | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | | +- Name[@Image = "c.charValue"] - | | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "7", @FloatLiteral = false, @Image = "7", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "7", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 7, @ValueAsLong = 7] - | | | +- Statement[] - | | | +- Block[@containsComment = false] - | | | +- BlockStatement[@Allocation = false] - | | | +- Statement[] - | | | +- StatementExpression[] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | +- Name[@Image = "System.out.println"] - | | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | | +- ArgumentList[@Size = 1] - | | | +- Expression[@StandAlonePrimitive = false] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Ding!"", @FloatLiteral = false, @Image = ""Ding!"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Ding!"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Character"", @FloatLiteral = false, @Image = ""Character"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Character"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabeledThrowStatement[] - | | +- SwitchLabel[@Default = false] - | | | +- TypePattern[@ParenthesisDepth = 0] - | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Integer"] - | | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Integer", @ReferenceToClassSameCompilationUnit = false] - | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "i", @LambdaParameter = false, @LocalVariable = false, @Name = "i", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "i"] - | | +- ThrowStatement[@FirstClassOrInterfaceTypeImage = "IllegalStateException"] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- AllocationExpression[@AnonymousClass = false] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "IllegalStateException", @ReferenceToClassSameCompilationUnit = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- AdditiveExpression[@Image = "+", @Operator = "+"] - | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Invalid Integer argument of value "", @FloatLiteral = false, @Image = ""Invalid Integer argument of value "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Invalid Integer argument of value "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "i.intValue"] - | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | +- SwitchLabeledBlock[] - | +- SwitchLabel[@Default = true] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- BreakStatement[] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - | +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test2", @Modifiers = 16, @Name = "test2", @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = false, @Transient = false, @Void = true, @Volatile = false] - | +- ResultType[@Void = true, @returnsArray = false] - | +- MethodDeclarator[@Image = "test2", @ParameterCount = 1] - | | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | | +- FormalParameter[@Abstract = false, @Array = false, @ArrayDepth = 0, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Object"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Object", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "o", @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "o"] - | +- Block[@containsComment = false] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- SwitchStatement[@DefaultCase = true, @ExhaustiveEnumSwitch = false, @FallthroughSwitch = true] - | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "o"] - | +- SwitchLabel[@Default = false] - | | +- TypePattern[@ParenthesisDepth = 0] - | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Character"] - | | | +- ReferenceType[@Array = false, @ArrayDepth = 0] - | | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "Character", @ReferenceToClassSameCompilationUnit = false] - | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "c", @LambdaParameter = false, @LocalVariable = false, @Name = "c", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "c"] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- IfStatement[@Else = false] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- EqualityExpression[@Image = "==", @Operator = "=="] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "c.charValue"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "7", @FloatLiteral = false, @Image = "7", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "7", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 7, @ValueAsLong = 7] - | | +- Statement[] - | | +- Block[@containsComment = false] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.print"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Ding "", @FloatLiteral = false, @Image = ""Ding "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Ding "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- IfStatement[@Else = false] - | | +- Expression[@StandAlonePrimitive = false] - | | | +- EqualityExpression[@Image = "==", @Operator = "=="] - | | | +- PrimaryExpression[] - | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | | | +- Name[@Image = "c.charValue"] - | | | | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | | | | +- Arguments[@ArgumentCount = 0, @Size = 0] - | | | +- PrimaryExpression[] - | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "9", @FloatLiteral = false, @Image = "9", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "9", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 9, @ValueAsLong = 9] - | | +- Statement[] - | | +- Block[@containsComment = false] - | | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.print"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""Tab "", @FloatLiteral = false, @Image = ""Tab "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""Tab "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- BlockStatement[@Allocation = false] - | | +- Statement[] - | | +- StatementExpression[] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | | +- Name[@Image = "System.out.println"] - | | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | | +- Arguments[@ArgumentCount = 1, @Size = 1] - | | +- ArgumentList[@Size = 1] - | | +- Expression[@StandAlonePrimitive = false] - | | +- PrimaryExpression[] - | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""character"", @FloatLiteral = false, @Image = ""character"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""character"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - | +- SwitchLabel[@Default = true] - | +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "System.out.println"] - | +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 0, @Size = 0] - +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD] - +- MethodDeclaration[@Abstract = false, @Arity = 1, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "main", @Modifiers = 17, @Name = "main", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = true, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] - +- ResultType[@Void = true, @returnsArray = false] - +- MethodDeclarator[@Image = "main", @ParameterCount = 1] - | +- FormalParameters[@ParameterCount = 1, @Size = 1] - | +- FormalParameter[@Abstract = false, @Array = true, @ArrayDepth = 1, @Default = false, @ExplicitReceiverParameter = false, @Final = false, @Modifiers = 0, @Native = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeInferred = false, @Varargs = false, @Volatile = false] - | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "String"] - | | +- ReferenceType[@Array = true, @ArrayDepth = 1] - | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = true, @ArrayDepth = 1, @Image = "String", @ReferenceToClassSameCompilationUnit = false] - | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"] - +- Block[@containsComment = false] - +- BlockStatement[@Allocation = false] - | +- Statement[] - | +- StatementExpression[] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | | +- Name[@Image = "test"] - | +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - | +- Arguments[@ArgumentCount = 1, @Size = 1] - | +- ArgumentList[@Size = 1] - | +- Expression[@StandAlonePrimitive = true] - | +- PrimaryExpression[] - | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Literal[@CharLiteral = true, @DoubleLiteral = false, @EscapedStringLiteral = "'A'", @FloatLiteral = false, @Image = "'A'", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "'A'", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] - +- BlockStatement[@Allocation = false] - +- Statement[] - +- StatementExpression[] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - | +- Name[@Image = "test2"] - +- PrimarySuffix[@ArgumentCount = 1, @Arguments = true, @ArrayDereference = false] - +- Arguments[@ArgumentCount = 1, @Size = 1] - +- ArgumentList[@Size = 1] - +- Expression[@StandAlonePrimitive = true] - +- PrimaryExpression[] - +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] - +- Literal[@CharLiteral = true, @DoubleLiteral = false, @EscapedStringLiteral = "' '", @FloatLiteral = false, @Image = "' '", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "' '", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = "true"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "ScopeOfPatternVariableDeclarations", @CanonicalName = "ScopeOfPatternVariableDeclarations", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Image = "ScopeOfPatternVariableDeclarations", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "ScopeOfPatternVariableDeclarations", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "public", @Volatile = "false"] + +- ModifierList[] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "3"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "test", @MainMethod = "false", @MethodName = "test", @Name = "test", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Character", @TypeImage = "Character"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "c", @LambdaParameter = "false", @LocalVariable = "false", @Name = "c", @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 = "c", @Visibility = "local", @Volatile = "false"] + | | +- Block[@Empty = "false", @Size = "2", @containsComment = "false"] + | | +- IfStatement[@Else = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "==", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "charValue", @MethodName = "charValue", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "c", @Name = "c", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "7", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "7.0", @ValueAsFloat = "7.0", @ValueAsInt = "7", @ValueAsLong = "7"] + | | | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | | | +- ExpressionStatement[] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Ding!", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Ding!\"", @IntLiteral = "false", @Length = "5", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Character", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Character\"", @IntLiteral = "false", @Length = "9", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Integer", @TypeImage = "Integer"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "i", @LambdaParameter = "false", @LocalVariable = "false", @Name = "i", @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 = "i", @Visibility = "local", @Volatile = "false"] + | | +- ThrowStatement[] + | | +- 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 = "IllegalStateException", @TypeImage = "IllegalStateException"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "+", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Invalid Integer argument of value ", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Invalid Integer argument of value \"", @IntLiteral = "false", @Length = "34", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "intValue", @MethodName = "intValue", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "i", @Name = "i", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ArgumentList[@Empty = "true", @Size = "0"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- BreakStatement[@Label = null] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "package", @Final = "false", @Image = "test2", @MainMethod = "false", @MethodName = "test2", @Name = "test2", @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"] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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 = "Object", @TypeImage = "Object"] + | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @Image = "o", @LambdaParameter = "false", @LocalVariable = "false", @Name = "o", @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 = "o", @Visibility = "local", @Volatile = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "true"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "o", @Name = "o", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchFallthroughBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- PatternExpression[@CompileTimeConstant = "false", @Expression = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypePattern[@Abstract = "false", @EffectiveVisibility = "package", @Final = "false", @Native = "false", @PackagePrivate = "true", @ParenthesisDepth = "0", @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 = "Character", @TypeImage = "Character"] + | | | +- VariableDeclaratorId[@Abstract = "false", @ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @Image = "c", @LambdaParameter = "false", @LocalVariable = "false", @Name = "c", @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 = "c", @Visibility = "local", @Volatile = "false"] + | | +- IfStatement[@Else = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "==", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "charValue", @MethodName = "charValue", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "c", @Name = "c", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "7", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "7.0", @ValueAsFloat = "7.0", @ValueAsInt = "7", @ValueAsLong = "7"] + | | | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | | | +- ExpressionStatement[] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "print", @MethodName = "print", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Ding ", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Ding \"", @IntLiteral = "false", @Length = "5", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- IfStatement[@Else = "false"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Expression = "true", @Operator = "==", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "charValue", @MethodName = "charValue", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "c", @Name = "c", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | | +- NumericLiteral[@Base = "10", @BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "9", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false", @ValueAsDouble = "9.0", @ValueAsFloat = "9.0", @ValueAsInt = "9", @ValueAsLong = "9"] + | | | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | | | +- ExpressionStatement[] + | | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "print", @MethodName = "print", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "Tab ", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"Tab \"", @IntLiteral = "false", @Length = "4", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@BooleanLiteral = "false", @CharLiteral = "false", @CompileTimeConstant = "true", @ConstValue = "character", @DoubleLiteral = "false", @Empty = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\"character\"", @IntLiteral = "false", @Length = "9", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "true", @TextBlock = "false"] + | +- SwitchFallthroughBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "println", @MethodName = "println", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Expression = "true", @Image = "out", @Name = "out", @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 = "System", @TypeImage = "System"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Final = "false", @Image = "main", @MainMethod = "true", @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[] + +- VoidType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "void"] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- 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[] + | +- ArrayType[@ArrayDepth = "1", @ArrayType = "true", @ClassOrInterfaceType = "false", @PrimitiveType = "false", @TypeImage = "String[]"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "String", @TypeImage = "String"] + | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | +- ArrayTypeDim[@Varargs = "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[@Empty = "false", @Size = "2", @containsComment = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test", @MethodName = "test", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- CharLiteral[@BooleanLiteral = "false", @CharLiteral = "true", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\'A\'", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] + +- ExpressionStatement[] + +- MethodCall[@CompileTimeConstant = "false", @Expression = "true", @Image = "test2", @MethodName = "test2", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ArgumentList[@Empty = "false", @Size = "1"] + +- CharLiteral[@BooleanLiteral = "false", @CharLiteral = "true", @CompileTimeConstant = "true", @DoubleLiteral = "false", @Expression = "true", @FloatLiteral = "false", @Image = "\'\\t\'", @IntLiteral = "false", @LongLiteral = "false", @NullLiteral = "false", @NumericLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @StringLiteral = "false"] From 686b7fb29ec6eb4ee4131f82ce7bf72f1d405977 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 16:36:57 +0100 Subject: [PATCH 29/89] [java] Move standardized preview features to be regular features Since the old preview language versions are not supported anymore. --- .../ast/internal/LanguageLevelChecker.java | 76 +++++++++---------- .../pmd/lang/java/ast/Java17TreeDumpTest.java | 4 +- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/LanguageLevelChecker.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/LanguageLevelChecker.java index f575141699..bccb292b84 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/LanguageLevelChecker.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/LanguageLevelChecker.java @@ -119,52 +119,24 @@ public class LanguageLevelChecker { */ private enum PreviewFeature implements LanguageFeature { /** - * @see JEP 359: Records (Preview) - * @see JEP 384: Records (Second Preview) - * @see JEP 395: Records - */ - RECORD_DECLARATIONS(14, 15, true), - - /** - * @see JEP 305: Pattern Matching for instanceof (Preview) - * @see JEP 375: Pattern Matching for instanceof (Second Preview) - * @see JEP 394: Pattern Matching for instanceof - */ - TYPE_PATTERNS_IN_INSTANCEOF(14, 15, true), - - /** - * Part of the records JEP 394. - * @see #RECORD_DECLARATIONS - * @see JLS changes for Static Members of Inner Classes - */ - STATIC_LOCAL_TYPE_DECLARATIONS(15, 15, true), - - /** - * @see JEP 360: Sealed Classes (Preview) - * @see JEP 397: Sealed Classes (Second Preview) - * @see JEP 409: Sealed Classes - */ - SEALED_CLASSES(15, 16, true), - - /** - * @see JEP 406: Pattern Matching for switch (Preview) - * @see JEP 420: Pattern Matching for switch (Second Preview) + * @see JEP 406: Pattern Matching for switch (Preview) (Java 17) + * @see JEP 420: Pattern Matching for switch (Second Preview) (Java 18) */ PATTERN_MATCHING_FOR_SWITCH(17, 18, false), /** * Part of pattern matching for switch * @see #PATTERN_MATCHING_FOR_SWITCH - * @see JEP 406: Pattern Matching for switch (Preview) - * @see JEP 420: Pattern Matching for switch (Second Preview) + * @see JEP 406: Pattern Matching for switch (Preview) (Java 17) + * @see JEP 420: Pattern Matching for switch (Second Preview) (Java 18) */ GUARDED_PATTERNS(17, 18, false), /** * Part of pattern matching for switch * @see #PATTERN_MATCHING_FOR_SWITCH - * @see JEP 406: Pattern Matching for switch (Preview) - * @see JEP 420: Pattern Matching for switch (Second Preview) + * @see JEP 406: Pattern Matching for switch (Preview) (Java 17) + * @see JEP 420: Pattern Matching for switch (Second Preview) (Java 18) */ NULL_CASE_LABELS(17, 18, false), @@ -332,6 +304,34 @@ public class LanguageLevelChecker { */ SPACE_STRING_ESCAPES(15), + /** + * @see JEP 359: Records (Preview) (Java 14) + * @see JEP 384: Records (Second Preview) (Java 15) + * @see JEP 395: Records (Java 16) + */ + RECORD_DECLARATIONS(16), + + /** + * @see JEP 305: Pattern Matching for instanceof (Preview) (Java 14) + * @see JEP 375: Pattern Matching for instanceof (Second Preview) (Java 15) + * @see JEP 394: Pattern Matching for instanceof (Java 16) + */ + TYPE_PATTERNS_IN_INSTANCEOF(16), + + /** + * Part of the records JEP 394. + * @see #RECORD_DECLARATIONS + * @see JLS changes for Static Members of Inner Classes (Java 16) + */ + STATIC_LOCAL_TYPE_DECLARATIONS(16), + + /** + * @see JEP 360: Sealed Classes (Preview) (Java 15) + * @see JEP 397: Sealed Classes (Second Preview) (Java 16) + * @see JEP 409: Sealed Classes (Java 17) + */ + SEALED_CLASSES(17), + ; // SUPPRESS CHECKSTYLE enum trailing semi is awesome private final int minJdkLevel; @@ -404,7 +404,7 @@ public class LanguageLevelChecker { @Override public Void visit(ASTRecordDeclaration node, T data) { - check(node, PreviewFeature.RECORD_DECLARATIONS, data); + check(node, RegularLanguageFeature.RECORD_DECLARATIONS, data); return null; } @@ -515,7 +515,7 @@ public class LanguageLevelChecker { @Override public Void visit(ASTTypePattern node, T data) { - check(node, PreviewFeature.TYPE_PATTERNS_IN_INSTANCEOF, data); + check(node, RegularLanguageFeature.TYPE_PATTERNS_IN_INSTANCEOF, data); return null; } @@ -600,9 +600,9 @@ public class LanguageLevelChecker { @Override public Void visitTypeDecl(ASTAnyTypeDeclaration node, T data) { if (node.getModifiers().hasAnyExplicitly(JModifier.SEALED, JModifier.NON_SEALED)) { - check(node, PreviewFeature.SEALED_CLASSES, data); + check(node, RegularLanguageFeature.SEALED_CLASSES, data); } else if (node.isLocal() && !node.isRegularClass()) { - check(node, PreviewFeature.STATIC_LOCAL_TYPE_DECLARATIONS, data); + check(node, RegularLanguageFeature.STATIC_LOCAL_TYPE_DECLARATIONS, data); } String simpleName = node.getSimpleName(); if ("var".equals(simpleName)) { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java index 19356ba1fa..c5a668a2d4 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java @@ -39,7 +39,7 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Sealed classes is a preview feature of JDK 16, you should select your language version accordingly")); + thrown.getMessage().contains("Sealed classes are a feature of Java 17, you should select your language version accordingly")); } @Test @@ -69,7 +69,7 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest { } }); Assert.assertTrue("Unexpected message: " + thrown.getMessage(), - thrown.getMessage().contains("Sealed classes is a preview feature of JDK 16, you should select your language version accordingly")); + thrown.getMessage().contains("Sealed classes are a feature of Java 17, you should select your language version accordingly")); } @Test From 19cba367f938a80ed88c453fc06054e115e18643 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 10 Mar 2022 16:42:43 +0100 Subject: [PATCH 30/89] [java] Simplify ASTPatternTest Backported from pmd/7.0.x --- .../net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt | 7 +++---- .../net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt | 7 +++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt index a5a1cfed5c..65cbcc16f4 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt @@ -11,11 +11,10 @@ import net.sourceforge.pmd.lang.java.ast.JavaVersion.* import java.io.IOException class ASTPatternTest : ParserTestSpec({ + val typePatternsVersions = JavaVersion.since(J16) parserTest("Test patterns only available on JDK16 or higher (including preview)", - javaVersions = JavaVersion.values().asList().minus(J16) - .minus(J17).minus(J17__PREVIEW) - .minus(J18).minus(J18__PREVIEW)) { + javaVersions = JavaVersion.except(typePatternsVersions)) { expectParseException("Pattern Matching for instanceof is only supported with JDK >= 16") { parseAstExpression("obj instanceof Class c") @@ -23,7 +22,7 @@ class ASTPatternTest : ParserTestSpec({ } - parserTest("Test simple patterns", javaVersions = listOf(J16, J17, J18)) { + parserTest("Test simple patterns", javaVersions = typePatternsVersions) { importedTypes += IOException::class.java diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt index e429a3b12e..d07e05bbee 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt @@ -47,6 +47,13 @@ enum class JavaVersion : Comparable { companion object { val Latest = values().last() val Earliest = values().first() + + fun since(v: JavaVersion) = v.rangeTo(Latest) + + fun except(v1: JavaVersion, vararg versions: JavaVersion) = + values().toList() - v1 - versions + + fun except(versions: List) = values().toList() - versions } } From e27e595e582ee3462db1a6bc07cd38a4476331eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 26 Feb 2022 23:56:44 +0100 Subject: [PATCH 31/89] Add back tests that disappeared by mistake --- .../pmd/lang/java/ast/ParserCornersTest.java | 14 +- .../java14/MultipleCaseLabels.java | 25 ++ .../java14/MultipleCaseLabels.txt | 113 ++++++ .../java14/SimpleSwitchExpressions.java | 35 ++ .../java14/SimpleSwitchExpressions.txt | 131 +++++++ .../java14/SwitchExpressions.java | 90 +++++ .../java14/SwitchExpressions.txt | 326 ++++++++++++++++++ .../jdkversiontests/java14/SwitchRules.java | 25 ++ .../jdkversiontests/java14/SwitchRules.txt | 113 ++++++ .../jdkversiontests/java14/TextBlocks.java | 113 ++++++ .../java14/YieldStatements.txt | 83 +++++ 11 files changed, 1061 insertions(+), 7 deletions(-) create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/MultipleCaseLabels.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/MultipleCaseLabels.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SimpleSwitchExpressions.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SimpleSwitchExpressions.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchExpressions.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchExpressions.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchRules.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchRules.txt create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/TextBlocks.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/YieldStatements.txt diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java index 1c28c9c3f1..422a620615 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java @@ -136,11 +136,11 @@ public class ParserCornersTest extends BaseJavaTreeDumpTest { */ @Test public void testGenericsProblem() { - String code = "public class Test {\n" + - " public void test() {\n" + - " String o = super. doStuff(\"\");\n" + - " }\n" + - "}"; + String code = "public class Test {\n" + + " public void test() {\n" + + " String o = super. doStuff(\"\");\n" + + " }\n" + + "}"; java5.parse(code); java7.parse(code); } @@ -266,10 +266,10 @@ public class ParserCornersTest extends BaseJavaTreeDumpTest { @Test public void testMethodReferenceConfused() { ASTCompilationUnit ast = java.parseResource("MethodReferenceConfused.java", "10"); - ASTVariableDeclaratorId someVarNameSameAsMethodReference = AstTestUtil.varId(ast, "someVarNameSameAsMethodReference"); + ASTVariableDeclaratorId varWithMethodName = AstTestUtil.varId(ast, "method"); ASTVariableDeclaratorId someObject = AstTestUtil.varId(ast, "someObject"); - assertThat(someVarNameSameAsMethodReference.getLocalUsages(), empty()); + assertThat(varWithMethodName.getLocalUsages(), empty()); assertThat(someObject.getLocalUsages(), hasSize(1)); ASTNamedReferenceExpr usage = someObject.getLocalUsages().get(0); assertThat(usage.getParent(), instanceOf(ASTCastExpression.class)); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/MultipleCaseLabels.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/MultipleCaseLabels.java new file mode 100644 index 0000000000..b578e8c475 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/MultipleCaseLabels.java @@ -0,0 +1,25 @@ +/** + * + * @see JEP 325: Switch Expressions (Preview) + */ +public class MultipleCaseLabels { + private static final int MONDAY = 1; + private static final int TUESDAY = 2; + private static final int WEDNESDAY = 3; + private static final int THURSDAY = 4; + private static final int FRIDAY = 5; + private static final int SATURDAY = 6; + private static final int SUNDAY = 7; + + + public static void main(String[] args) { + int day = THURSDAY; + + switch (day) { + case MONDAY, FRIDAY, SUNDAY: System.out.println(" 6"); break; + case TUESDAY : System.out.println(" 7"); break; + case THURSDAY, SATURDAY : System.out.println(" 8"); break; + case WEDNESDAY : System.out.println(" 9"); break; + } + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/MultipleCaseLabels.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/MultipleCaseLabels.txt new file mode 100644 index 0000000000..2c7b60fa5a --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/MultipleCaseLabels.txt @@ -0,0 +1,113 @@ ++- CompilationUnit[@PackageName = ""] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "MultipleCaseLabels", @CanonicalName = "MultipleCaseLabels", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "MultipleCaseLabels", @TopLevel = "true", @Visibility = "public"] + +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "8"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "MONDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "MONDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- 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"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "TUESDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "TUESDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- 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"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "WEDNESDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "WEDNESDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "THURSDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "THURSDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "4", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "4.0", @ValueAsFloat = "4.0", @ValueAsInt = "4", @ValueAsLong = "4"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "FRIDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "FRIDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "5", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "5.0", @ValueAsFloat = "5.0", @ValueAsInt = "5", @ValueAsLong = "5"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "SATURDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "SATURDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "6", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "6.0", @ValueAsFloat = "6.0", @ValueAsInt = "6", @ValueAsLong = "6"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "SUNDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "SUNDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "7", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "7.0", @ValueAsFloat = "7.0", @ValueAsInt = "7", @ValueAsLong = "7"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Image = "main", @MainMethod = "true", @Name = "main", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "true"] + +- ModifierList[@EffectiveModifiers = "{public, static}", @ExplicitModifiers = "{public, static}"] + +- VoidType[] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] + | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | +- ArrayType[@ArrayDepth = "1"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] + | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | +- ArrayTypeDim[@Varargs = "false"] + | +- 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[@Empty = "false", @Size = "2", @containsComment = "false"] + +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "day"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "day", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "THURSDAY", @Name = "THURSDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- SwitchStatement[@DefaultCase = "false", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "true"] + +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "day", @Name = "day", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- SwitchFallthroughBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "MONDAY", @Name = "MONDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "FRIDAY", @Name = "FRIDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "SUNDAY", @Name = "SUNDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ExpressionStatement[] + | | +- 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"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = " 6", @Empty = "false", @Image = "\" 6\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | +- BreakStatement[@Label = null] + +- SwitchFallthroughBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "TUESDAY", @Name = "TUESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ExpressionStatement[] + | | +- 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"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = " 7", @Empty = "false", @Image = "\" 7\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | +- BreakStatement[@Label = null] + +- SwitchFallthroughBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "THURSDAY", @Name = "THURSDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "SATURDAY", @Name = "SATURDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ExpressionStatement[] + | | +- 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"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = " 8", @Empty = "false", @Image = "\" 8\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | +- BreakStatement[@Label = null] + +- SwitchFallthroughBranch[@Default = "false"] + +- SwitchLabel[@Default = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "WEDNESDAY", @Name = "WEDNESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- 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"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = " 9", @Empty = "false", @Image = "\" 9\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + +- BreakStatement[@Label = null] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SimpleSwitchExpressions.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SimpleSwitchExpressions.java new file mode 100644 index 0000000000..c452ab0412 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SimpleSwitchExpressions.java @@ -0,0 +1,35 @@ +/** + * + * @see JEP 325: Switch Expressions (Preview) + */ +public class SimpleSwitchExpressions { + private static final int MONDAY = 1; + private static final int TUESDAY = 2; + private static final int WEDNESDAY = 3; + private static final int THURSDAY = 4; + private static final int FRIDAY = 5; + private static final int SATURDAY = 6; + private static final int SUNDAY = 7; + + + public static void main(String[] args) { + int day = FRIDAY; + + var numLetters = switch (day) { + case MONDAY, FRIDAY, SUNDAY -> 6; + case TUESDAY -> 7; + case THURSDAY, SATURDAY -> 8; + case WEDNESDAY -> 9; + default -> { + int k = day * 2; + int result = f(k); + yield result; + } + }; + System.out.printf("NumLetters: %d%n", numLetters); + } + + private static int f(int k) { + return k*3; + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SimpleSwitchExpressions.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SimpleSwitchExpressions.txt new file mode 100644 index 0000000000..419f680133 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SimpleSwitchExpressions.txt @@ -0,0 +1,131 @@ ++- CompilationUnit[@PackageName = ""] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "SimpleSwitchExpressions", @CanonicalName = "SimpleSwitchExpressions", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "SimpleSwitchExpressions", @TopLevel = "true", @Visibility = "public"] + +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "9"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "MONDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "MONDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- 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"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "TUESDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "TUESDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- 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"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "WEDNESDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "WEDNESDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "THURSDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "THURSDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "4", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "4.0", @ValueAsFloat = "4.0", @ValueAsInt = "4", @ValueAsLong = "4"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "FRIDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "FRIDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "5", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "5.0", @ValueAsFloat = "5.0", @ValueAsInt = "5", @ValueAsLong = "5"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "SATURDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "SATURDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "6", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "6.0", @ValueAsFloat = "6.0", @ValueAsInt = "6", @ValueAsLong = "6"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "SUNDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "SUNDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "7", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "7.0", @ValueAsFloat = "7.0", @ValueAsInt = "7", @ValueAsLong = "7"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Image = "main", @MainMethod = "true", @Name = "main", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "true"] + | +- ModifierList[@EffectiveModifiers = "{public, static}", @ExplicitModifiers = "{public, static}"] + | +- VoidType[] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] + | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | +- ArrayType[@ArrayDepth = "1"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] + | | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | | +- ArrayTypeDim[@Varargs = "false"] + | | +- 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[@Empty = "false", @Size = "3", @containsComment = "false"] + | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | +- PrimitiveType[@Kind = "int"] + | | +- VariableDeclarator[@Initializer = "true", @Name = "day"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "day", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "FRIDAY", @Name = "FRIDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "true", @Visibility = "local"] + | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | +- VariableDeclarator[@Initializer = "true", @Name = "numLetters"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "numLetters", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "local"] + | | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "day", @Name = "day", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "MONDAY", @Name = "MONDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "FRIDAY", @Name = "FRIDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "SUNDAY", @Name = "SUNDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "6", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "6.0", @ValueAsFloat = "6.0", @ValueAsInt = "6", @ValueAsLong = "6"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "TUESDAY", @Name = "TUESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "7", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "7.0", @ValueAsFloat = "7.0", @ValueAsInt = "7", @ValueAsLong = "7"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "THURSDAY", @Name = "THURSDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "SATURDAY", @Name = "SATURDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "8", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "8.0", @ValueAsFloat = "8.0", @ValueAsInt = "8", @ValueAsLong = "8"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "WEDNESDAY", @Name = "WEDNESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "9", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "9.0", @ValueAsFloat = "9.0", @ValueAsInt = "9", @ValueAsLong = "9"] + | | +- SwitchArrowBranch[@Default = "true"] + | | +- SwitchLabel[@Default = "true"] + | | +- Block[@Empty = "false", @Size = "3", @containsComment = "false"] + | | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | | +- PrimitiveType[@Kind = "int"] + | | | +- VariableDeclarator[@Initializer = "true", @Name = "k"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "k", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- InfixExpression[@CompileTimeConstant = "false", @Operator = "*", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "day", @Name = "day", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- 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"] + | | +- 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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "f", @MethodName = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "k", @Name = "k", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- YieldStatement[] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "result", @Name = "result", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Image = "printf", @MethodName = "printf", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "out", @Name = "out", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | +- ArgumentList[@Empty = "false", @Size = "2"] + | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "NumLetters: %d%n", @Empty = "false", @Image = "\"NumLetters: %d%n\"", @Length = "16", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "numLetters", @Name = "numLetters", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "private", @Image = "f", @Name = "f", @Overridden = "false", @Varargs = "false", @Visibility = "private", @Void = "false"] + +- ModifierList[@EffectiveModifiers = "{private, static}", @ExplicitModifiers = "{private, static}"] + +- PrimitiveType[@Kind = "int"] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- 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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "k", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + +- ReturnStatement[] + +- InfixExpression[@CompileTimeConstant = "false", @Operator = "*", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "k", @Name = "k", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchExpressions.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchExpressions.java new file mode 100644 index 0000000000..5b29acbd4a --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchExpressions.java @@ -0,0 +1,90 @@ +/** + * @see JEP 361: Switch Expressions (Standard) + */ +public class SwitchExpressions { + private enum Day { + MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; + } + + public static final int BAZ = 3; + + public static void main(String[] args) { + Day day = Day.THURSDAY; + + // SwitchStatement + switch (day) { + case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); + case TUESDAY -> System.out.println(7); + case THURSDAY, SATURDAY -> System.out.println(8); + case WEDNESDAY -> System.out.println(9); + } + + // SwitchExpression + int numLetters = switch (day) { + case MONDAY, FRIDAY, SUNDAY -> 6; + case TUESDAY -> 7; + case THURSDAY, SATURDAY -> 8; + case WEDNESDAY -> 9; + }; + System.out.printf("numLetters=%d%n", numLetters); + + howMany(1); + howMany(2); + howMany(3); + + howManyExpr(1); + howManyExpr(2); + howManyExpr(3); + + // SwitchExpression + int j = switch (day) { + case MONDAY -> 0; + case TUESDAY -> 1; + default -> { + int k = day.toString().length(); + int result = f(k); + yield result; + } + }; + System.out.printf("j=%d%n", j); + + String s = "Foo"; + // SwitchExpression + int result = switch (s) { + case "Foo": + yield 1; + case "Bar": + yield 2; + case "Baz": + yield SwitchExpressions.BAZ; + default: + System.out.println("Neither Foo nor Bar, hmmm..."); + yield 0; + }; + System.out.printf("result=%d%n", result); + } + + private static void howMany(int k) { + // SwitchStatement + switch (k) { + case 1 -> System.out.println("one"); + case 2 -> System.out.println("two"); + default -> System.out.println("many"); + } + } + + private static void howManyExpr(int k) { + System.out.println( + // SwitchExpression + switch (k) { + case 1 -> "one"; + case 2 -> "two"; + default -> "many"; + } + ); + } + + private static int f(int k) { + return k*2; + } +} \ No newline at end of file diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchExpressions.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchExpressions.txt new file mode 100644 index 0000000000..f0335fd52e --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchExpressions.txt @@ -0,0 +1,326 @@ ++- CompilationUnit[@PackageName = ""] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "SwitchExpressions", @CanonicalName = "SwitchExpressions", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "SwitchExpressions", @TopLevel = "true", @Visibility = "public"] + +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "6"] + +- EnumDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "SwitchExpressions$Day", @CanonicalName = "SwitchExpressions.Day", @EffectiveVisibility = "private", @Enum = "true", @Final = "true", @Interface = "false", @Local = "false", @Nested = "true", @PackageName = "", @Record = "false", @RegularClass = "false", @RegularInterface = "false", @SimpleName = "Day", @TopLevel = "false", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private}"] + | +- EnumBody[@Empty = "false", @SeparatorSemi = "true", @Size = "7", @TrailingComma = "false"] + | +- EnumConstant[@AnonymousClass = "false", @EffectiveVisibility = "private", @Image = "MONDAY", @MethodName = "new", @Name = "MONDAY", @Visibility = "public"] + | | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{}"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "MONDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "public"] + | +- EnumConstant[@AnonymousClass = "false", @EffectiveVisibility = "private", @Image = "TUESDAY", @MethodName = "new", @Name = "TUESDAY", @Visibility = "public"] + | | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{}"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "TUESDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "public"] + | +- EnumConstant[@AnonymousClass = "false", @EffectiveVisibility = "private", @Image = "WEDNESDAY", @MethodName = "new", @Name = "WEDNESDAY", @Visibility = "public"] + | | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{}"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "WEDNESDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "public"] + | +- EnumConstant[@AnonymousClass = "false", @EffectiveVisibility = "private", @Image = "THURSDAY", @MethodName = "new", @Name = "THURSDAY", @Visibility = "public"] + | | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{}"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "THURSDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "public"] + | +- EnumConstant[@AnonymousClass = "false", @EffectiveVisibility = "private", @Image = "FRIDAY", @MethodName = "new", @Name = "FRIDAY", @Visibility = "public"] + | | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{}"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "FRIDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "public"] + | +- EnumConstant[@AnonymousClass = "false", @EffectiveVisibility = "private", @Image = "SATURDAY", @MethodName = "new", @Name = "SATURDAY", @Visibility = "public"] + | | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{}"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "SATURDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "public"] + | +- EnumConstant[@AnonymousClass = "false", @EffectiveVisibility = "private", @Image = "SUNDAY", @MethodName = "new", @Name = "SUNDAY", @Visibility = "public"] + | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{}"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "true", @ExceptionBlockParameter = "false", @Field = "false", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "SUNDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "true", @Visibility = "public"] + +- FieldDeclaration[@EffectiveVisibility = "public", @Visibility = "public"] + | +- ModifierList[@EffectiveModifiers = "{public, static, final}", @ExplicitModifiers = "{public, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "BAZ"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "public", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "BAZ", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "public"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Image = "main", @MainMethod = "true", @Name = "main", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "true"] + | +- ModifierList[@EffectiveModifiers = "{public, static}", @ExplicitModifiers = "{public, static}"] + | +- VoidType[] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] + | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | +- ArrayType[@ArrayDepth = "1"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] + | | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | | +- ArrayTypeDim[@Varargs = "false"] + | | +- 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[@Empty = "false", @Size = "15", @containsComment = "false"] + | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Day"] + | | +- VariableDeclarator[@Initializer = "true", @Name = "day"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "day", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "THURSDAY", @Name = "THURSDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "Day"] + | +- SwitchStatement[@DefaultCase = "false", @EnumSwitch = "true", @ExhaustiveEnumSwitch = "true", @FallthroughSwitch = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "day", @Name = "day", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "MONDAY", @Name = "MONDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "FRIDAY", @Name = "FRIDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "SUNDAY", @Name = "SUNDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- 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"] + | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "6", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "6.0", @ValueAsFloat = "6.0", @ValueAsInt = "6", @ValueAsLong = "6"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "TUESDAY", @Name = "TUESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- 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"] + | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "7", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "7.0", @ValueAsFloat = "7.0", @ValueAsInt = "7", @ValueAsLong = "7"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "THURSDAY", @Name = "THURSDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "SATURDAY", @Name = "SATURDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- 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"] + | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "8", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "8.0", @ValueAsFloat = "8.0", @ValueAsInt = "8", @ValueAsLong = "8"] + | | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "WEDNESDAY", @Name = "WEDNESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- 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"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "9", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "9.0", @ValueAsFloat = "9.0", @ValueAsInt = "9", @ValueAsLong = "9"] + | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | +- PrimitiveType[@Kind = "int"] + | | +- VariableDeclarator[@Initializer = "true", @Name = "numLetters"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "numLetters", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "false", @EnumSwitch = "true", @ExhaustiveEnumSwitch = "true", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "day", @Name = "day", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "MONDAY", @Name = "MONDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "FRIDAY", @Name = "FRIDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "SUNDAY", @Name = "SUNDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "6", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "6.0", @ValueAsFloat = "6.0", @ValueAsInt = "6", @ValueAsLong = "6"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "TUESDAY", @Name = "TUESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "7", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "7.0", @ValueAsFloat = "7.0", @ValueAsInt = "7", @ValueAsLong = "7"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "THURSDAY", @Name = "THURSDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "SATURDAY", @Name = "SATURDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "8", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "8.0", @ValueAsFloat = "8.0", @ValueAsInt = "8", @ValueAsLong = "8"] + | | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "WEDNESDAY", @Name = "WEDNESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "9", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "9.0", @ValueAsFloat = "9.0", @ValueAsInt = "9", @ValueAsLong = "9"] + | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Image = "printf", @MethodName = "printf", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "out", @Name = "out", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "2"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "numLetters=%d%n", @Empty = "false", @Image = "\"numLetters=%d%n\"", @Length = "15", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "numLetters", @Name = "numLetters", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Image = "howMany", @MethodName = "howMany", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- 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"] + | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Image = "howMany", @MethodName = "howMany", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ArgumentList[@Empty = "false", @Size = "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"] + | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Image = "howMany", @MethodName = "howMany", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] + | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Image = "howManyExpr", @MethodName = "howManyExpr", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- 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"] + | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Image = "howManyExpr", @MethodName = "howManyExpr", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ArgumentList[@Empty = "false", @Size = "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"] + | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Image = "howManyExpr", @MethodName = "howManyExpr", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] + | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | +- PrimitiveType[@Kind = "int"] + | | +- VariableDeclarator[@Initializer = "true", @Name = "j"] + | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "j", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "true", @EnumSwitch = "true", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "day", @Name = "day", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "MONDAY", @Name = "MONDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- 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"] + | | +- SwitchArrowBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "TUESDAY", @Name = "TUESDAY", @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"] + | | +- SwitchArrowBranch[@Default = "true"] + | | +- SwitchLabel[@Default = "true"] + | | +- Block[@Empty = "false", @Size = "3", @containsComment = "false"] + | | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | | +- PrimitiveType[@Kind = "int"] + | | | +- VariableDeclarator[@Initializer = "true", @Name = "k"] + | | | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "k", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "length", @MethodName = "length", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "toString", @MethodName = "toString", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "day", @Name = "day", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | | +- ArgumentList[@Empty = "true", @Size = "0"] + | | +- 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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | | +- MethodCall[@CompileTimeConstant = "false", @Image = "f", @MethodName = "f", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "k", @Name = "k", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- YieldStatement[] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "result", @Name = "result", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ExpressionStatement[] + | | +- MethodCall[@CompileTimeConstant = "false", @Image = "printf", @MethodName = "printf", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "out", @Name = "out", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "2"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "j=%d%n", @Empty = "false", @Image = "\"j=%d%n\"", @Length = "6", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "j", @Name = "j", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] + | | +- VariableDeclarator[@Initializer = "true", @Name = "s"] + | | +- 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"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "Foo", @Empty = "false", @Image = "\"Foo\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "result", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "true", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "s", @Name = "s", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- SwitchFallthroughBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "Foo", @Empty = "false", @Image = "\"Foo\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | | | +- YieldStatement[] + | | | +- 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"] + | | +- SwitchFallthroughBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "Bar", @Empty = "false", @Image = "\"Bar\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | | | +- YieldStatement[] + | | | +- 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"] + | | +- SwitchFallthroughBranch[@Default = "false"] + | | | +- SwitchLabel[@Default = "false"] + | | | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "Baz", @Empty = "false", @Image = "\"Baz\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | | | +- YieldStatement[] + | | | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "BAZ", @Name = "BAZ", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "SwitchExpressions"] + | | +- SwitchFallthroughBranch[@Default = "true"] + | | +- SwitchLabel[@Default = "true"] + | | +- ExpressionStatement[] + | | | +- 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"] + | | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "Neither Foo nor Bar, hmmm...", @Empty = "false", @Image = "\"Neither Foo nor Bar, hmmm...\"", @Length = "28", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | | +- YieldStatement[] + | | +- 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"] + | +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Image = "printf", @MethodName = "printf", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- FieldAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "out", @Name = "out", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- TypeExpression[@CompileTimeConstant = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | +- ArgumentList[@Empty = "false", @Size = "2"] + | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "result=%d%n", @Empty = "false", @Image = "\"result=%d%n\"", @Length = "11", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "result", @Name = "result", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "private", @Image = "howMany", @Name = "howMany", @Overridden = "false", @Varargs = "false", @Visibility = "private", @Void = "true"] + | +- ModifierList[@EffectiveModifiers = "{private, static}", @ExplicitModifiers = "{private, static}"] + | +- VoidType[] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "k", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "k", @Name = "k", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "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"] + | | +- 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"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "one", @Empty = "false", @Image = "\"one\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- 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"] + | | +- 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"] + | | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | | +- ArgumentList[@Empty = "false", @Size = "1"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "two", @Empty = "false", @Image = "\"two\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- 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"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "many", @Empty = "false", @Image = "\"many\"", @Length = "4", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "private", @Image = "howManyExpr", @Name = "howManyExpr", @Overridden = "false", @Varargs = "false", @Visibility = "private", @Void = "true"] + | +- ModifierList[@EffectiveModifiers = "{private, static}", @ExplicitModifiers = "{private, static}"] + | +- VoidType[] + | +- FormalParameters[@Empty = "false", @Size = "1"] + | | +- 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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "k", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- ExpressionStatement[] + | +- 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"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "k", @Name = "k", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "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"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "one", @Empty = "false", @Image = "\"one\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | | +- SwitchLabel[@Default = "false"] + | | | +- 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"] + | | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "two", @Empty = "false", @Image = "\"two\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + | +- SwitchArrowBranch[@Default = "true"] + | +- SwitchLabel[@Default = "true"] + | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = "many", @Empty = "false", @Image = "\"many\"", @Length = "4", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "private", @Image = "f", @Name = "f", @Overridden = "false", @Varargs = "false", @Visibility = "private", @Void = "false"] + +- ModifierList[@EffectiveModifiers = "{private, static}", @ExplicitModifiers = "{private, static}"] + +- PrimitiveType[@Kind = "int"] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- 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", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "true", @LambdaParameter = "false", @LocalVariable = "false", @Name = "k", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + +- ReturnStatement[] + +- InfixExpression[@CompileTimeConstant = "false", @Operator = "*", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "k", @Name = "k", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- 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"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchRules.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchRules.java new file mode 100644 index 0000000000..844abf6bbb --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchRules.java @@ -0,0 +1,25 @@ +/** + * + * @see JEP 325: Switch Expressions (Preview) + */ +public class SwitchRules { + private static final int MONDAY = 1; + private static final int TUESDAY = 2; + private static final int WEDNESDAY = 3; + private static final int THURSDAY = 4; + private static final int FRIDAY = 5; + private static final int SATURDAY = 6; + private static final int SUNDAY = 7; + + public static void main(String[] args) { + int day = WEDNESDAY; + + switch (day) { + case MONDAY, FRIDAY, SUNDAY -> System.out.println(" 6"); + case TUESDAY -> System.out.println(" 7"); + case THURSDAY, SATURDAY -> System.out.println(" 8"); + case WEDNESDAY -> { System.out.println(" 9"); } + default -> throw new IllegalArgumentException(); + } + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchRules.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchRules.txt new file mode 100644 index 0000000000..1567458302 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/SwitchRules.txt @@ -0,0 +1,113 @@ ++- CompilationUnit[@PackageName = ""] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "SwitchRules", @CanonicalName = "SwitchRules", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "SwitchRules", @TopLevel = "true", @Visibility = "public"] + +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "8"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "MONDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "MONDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- 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"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "TUESDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "TUESDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- 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"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "WEDNESDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "WEDNESDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "3", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "3.0", @ValueAsFloat = "3.0", @ValueAsInt = "3", @ValueAsLong = "3"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "THURSDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "THURSDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "4", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "4.0", @ValueAsFloat = "4.0", @ValueAsInt = "4", @ValueAsLong = "4"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "FRIDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "FRIDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "5", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "5.0", @ValueAsFloat = "5.0", @ValueAsInt = "5", @ValueAsLong = "5"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "SATURDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "SATURDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "6", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "6.0", @ValueAsFloat = "6.0", @ValueAsInt = "6", @ValueAsLong = "6"] + +- FieldDeclaration[@EffectiveVisibility = "private", @Visibility = "private"] + | +- ModifierList[@EffectiveModifiers = "{private, static, final}", @ExplicitModifiers = "{private, static, final}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "SUNDAY"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "private", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "true", @Final = "true", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "false", @Name = "SUNDAY", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "private"] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "7", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "7.0", @ValueAsFloat = "7.0", @ValueAsInt = "7", @ValueAsLong = "7"] + +- MethodDeclaration[@Abstract = "false", @Arity = "1", @EffectiveVisibility = "public", @Image = "main", @MainMethod = "true", @Name = "main", @Overridden = "false", @Varargs = "false", @Visibility = "public", @Void = "true"] + +- ModifierList[@EffectiveModifiers = "{public, static}", @ExplicitModifiers = "{public, static}"] + +- VoidType[] + +- FormalParameters[@Empty = "false", @Size = "1"] + | +- FormalParameter[@EffectiveVisibility = "local", @Final = "false", @Varargs = "false", @Visibility = "local"] + | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | +- ArrayType[@ArrayDepth = "1"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "String"] + | | +- ArrayDimensions[@Empty = "false", @Size = "1"] + | | +- ArrayTypeDim[@Varargs = "false"] + | +- 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[@Empty = "false", @Size = "2", @containsComment = "false"] + +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "day"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "day", @PatternBinding = "false", @RecordComponent = "false", @ResourceDeclaration = "false", @TypeInferred = "false", @Visibility = "local"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "WEDNESDAY", @Name = "WEDNESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- SwitchStatement[@DefaultCase = "true", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false"] + +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "day", @Name = "day", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- SwitchArrowBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "MONDAY", @Name = "MONDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "FRIDAY", @Name = "FRIDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "SUNDAY", @Name = "SUNDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- 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"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = " 6", @Empty = "false", @Image = "\" 6\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + +- SwitchArrowBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "TUESDAY", @Name = "TUESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- 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"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = " 7", @Empty = "false", @Image = "\" 7\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + +- SwitchArrowBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "THURSDAY", @Name = "THURSDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "SATURDAY", @Name = "SATURDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- 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"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = " 8", @Empty = "false", @Image = "\" 8\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + +- SwitchArrowBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "true", @Image = "WEDNESDAY", @Name = "WEDNESDAY", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- ExpressionStatement[] + | +- 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"] + | | +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "System"] + | +- ArgumentList[@Empty = "false", @Size = "1"] + | +- StringLiteral[@CompileTimeConstant = "true", @ConstValue = " 9", @Empty = "false", @Image = "\" 9\"", @Length = "3", @ParenthesisDepth = "0", @Parenthesized = "false", @TextBlock = "false"] + +- SwitchArrowBranch[@Default = "true"] + +- SwitchLabel[@Default = "true"] + +- ThrowStatement[] + +- ConstructorCall[@AnonymousClass = "false", @CompileTimeConstant = "false", @DiamondTypeArgs = "false", @MethodName = "new", @ParenthesisDepth = "0", @Parenthesized = "false", @QualifiedInstanceCreation = "false"] + +- ClassOrInterfaceType[@FullyQualified = "false", @SimpleName = "IllegalArgumentException"] + +- ArgumentList[@Empty = "true", @Size = "0"] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/TextBlocks.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/TextBlocks.java new file mode 100644 index 0000000000..5ff553185f --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/TextBlocks.java @@ -0,0 +1,113 @@ +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; + +/** + * @see JEP 368: Text Blocks (Second Preview) + */ +public class TextBlocks { + + + public static void main(String[] args) throws Exception { + // note: there is trailing whitespace!! + String html = """ + + +

    Hello, world

    + + + """; + System.out.println(html); + + String query = """ + SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB` + WHERE `CITY` = 'INDIANAPOLIS' + ORDER BY `EMP_ID`, `LAST_NAME`; + """; + System.out.println(query); + + ScriptEngine engine = new ScriptEngineManager().getEngineByName("js"); + Object obj = engine.eval(""" + function hello() { + print('"Hello, world"'); + } + + hello(); + """); + + // Escape sequences + String htmlWithEscapes = """ + \r + \r +

    Hello, world

    \r + \r + \r + """; + System.out.println(htmlWithEscapes); + + String season = """ + winter"""; // the six characters w i n t e r + + String period = """ + winter + """; // the seven characters w i n t e r LF + + String greeting = + """ + Hi, "Bob" + """; // the ten characters H i , SP " B o b " LF + + String salutation = + """ + Hi, + "Bob" + """; // the eleven characters H i , LF SP " B o b " LF + + String empty = """ + """; // the empty string (zero length) + + String quote = """ + " + """; // the two characters " LF + + String backslash = """ + \\ + """; // the two characters \ LF + + String normalStringLiteral = "test"; + + String code = + """ + String text = \""" + A text block inside a text block + \"""; + """; + + // new escape sequences + String text = """ + Lorem ipsum dolor sit amet, consectetur adipiscing \ + elit, sed do eiusmod tempor incididunt ut labore \ + et dolore magna aliqua.\ + """; + System.out.println(text); + + String colors = """ + red \s + green\s + blue \s + """; + System.out.println(colors); + + // empty new line as first content + String emptyLine = """ + +test +"""; + System.out.println(emptyLine.replaceAll("\n", "")); + + // backslash escapes + String bs = """ + \\test + """; + System.out.println(bs.replaceAll("\n", "")); + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/YieldStatements.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/YieldStatements.txt new file mode 100644 index 0000000000..16419dfa5a --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/YieldStatements.txt @@ -0,0 +1,83 @@ ++- CompilationUnit[@PackageName = ""] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "YieldStatements", @CanonicalName = "YieldStatements", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Interface = "false", @Local = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "YieldStatements", @TopLevel = "true", @Visibility = "public"] + +- ModifierList[@EffectiveModifiers = "{public}", @ExplicitModifiers = "{public}"] + +- ClassOrInterfaceBody[@Empty = "false", @Size = "1"] + +- Initializer[@Static = "false"] + +- Block[@Empty = "false", @Size = "5", @containsComment = "false"] + +- LocalVariableDeclaration[@EffectiveVisibility = "local", @Final = "false", @TypeInferred = "false", @Visibility = "local"] + | +- ModifierList[@EffectiveModifiers = "{}", @ExplicitModifiers = "{}"] + | +- PrimitiveType[@Kind = "int"] + | +- VariableDeclarator[@Initializer = "true", @Name = "yield"] + | +- VariableDeclaratorId[@ArrayType = "false", @EffectiveVisibility = "local", @EnumConstant = "false", @ExceptionBlockParameter = "false", @Field = "false", @Final = "false", @ForLoopVariable = "false", @ForeachVariable = "false", @FormalParameter = "false", @LambdaParameter = "false", @LocalVariable = "true", @Name = "yield", @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"] + +- ExpressionStatement[] + | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "WRITE", @CompileTimeConstant = "false", @Image = "yield", @Name = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- 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[] + | +- MethodCall[@CompileTimeConstant = "false", @Image = "yield", @MethodName = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "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"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Image = "yield", @MethodName = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "2"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "a", @Name = "a", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "b", @Name = "b", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- VariableAccess[@AccessType = "WRITE", @CompileTimeConstant = "false", @Image = "yield", @Name = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "false", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "e", @Name = "e", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- SwitchArrowBranch[@Default = "false"] + +- SwitchLabel[@Default = "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"] + +- Block[@Empty = "false", @Size = "12", @containsComment = "true"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Image = "yield", @MethodName = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "false", @Size = "2"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "a", @Name = "a", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "b", @Name = "b", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "WRITE", @CompileTimeConstant = "false", @Image = "yield", @Name = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- 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"] + +- YieldStatement[] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "1", @Parenthesized = "true", @ValueAsDouble = "2.0", @ValueAsFloat = "2.0", @ValueAsInt = "2", @ValueAsLong = "2"] + +- YieldStatement[] + | +- UnaryExpression[@CompileTimeConstant = "false", @Operator = "++", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "WRITE", @CompileTimeConstant = "false", @Image = "bar", @Name = "bar", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- YieldStatement[] + | +- UnaryExpression[@CompileTimeConstant = "false", @Operator = "--", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "WRITE", @CompileTimeConstant = "false", @Image = "bar", @Name = "bar", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- UnaryExpression[@CompileTimeConstant = "false", @Operator = "++", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "WRITE", @CompileTimeConstant = "false", @Image = "yield", @Name = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- ExpressionStatement[] + | +- UnaryExpression[@CompileTimeConstant = "false", @Operator = "--", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "WRITE", @CompileTimeConstant = "false", @Image = "yield", @Name = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + +- IfStatement[@Else = "true"] + | +- BooleanLiteral[@CompileTimeConstant = "true", @ParenthesisDepth = "0", @Parenthesized = "false", @True = "true"] + | +- YieldStatement[] + | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "1", @Parenthesized = "true", @ValueAsDouble = "2.0", @ValueAsFloat = "2.0", @ValueAsInt = "2", @ValueAsLong = "2"] + | +- YieldStatement[] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "4", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "4.0", @ValueAsFloat = "4.0", @ValueAsInt = "4", @ValueAsLong = "4"] + +- ExpressionStatement[] + | +- AssignmentExpression[@CompileTimeConstant = "false", @Compound = "false", @Operator = "=", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "WRITE", @CompileTimeConstant = "false", @Image = "yield", @Name = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchExpression[@CompileTimeConstant = "false", @DefaultCase = "false", @EnumSwitch = "false", @ExhaustiveEnumSwitch = "false", @FallthroughSwitch = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- VariableAccess[@AccessType = "READ", @CompileTimeConstant = "false", @Image = "foo", @Name = "foo", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- SwitchArrowBranch[@Default = "false"] + | +- SwitchLabel[@Default = "false"] + | | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "4", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "0", @Parenthesized = "false", @ValueAsDouble = "4.0", @ValueAsFloat = "4.0", @ValueAsInt = "4", @ValueAsLong = "4"] + | +- Block[@Empty = "false", @Size = "1", @containsComment = "false"] + | +- YieldStatement[] + | +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "5", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "1", @Parenthesized = "true", @ValueAsDouble = "5.0", @ValueAsFloat = "5.0", @ValueAsInt = "5", @ValueAsLong = "5"] + +- YieldStatement[] + | +- LambdaExpression[@BlockBody = "true", @CompileTimeConstant = "false", @ExpressionBody = "false", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- LambdaParameterList[@Empty = "true", @Size = "0"] + | +- Block[@Empty = "true", @Size = "0", @containsComment = "false"] + +- ExpressionStatement[] + | +- MethodCall[@CompileTimeConstant = "false", @Image = "yield", @MethodName = "yield", @ParenthesisDepth = "0", @Parenthesized = "false"] + | +- ArgumentList[@Empty = "true", @Size = "0"] + +- YieldStatement[] + +- NumericLiteral[@Base = "10", @CompileTimeConstant = "true", @DoubleLiteral = "false", @FloatLiteral = "false", @Image = "2", @IntLiteral = "true", @Integral = "true", @LongLiteral = "false", @ParenthesisDepth = "1", @Parenthesized = "true", @ValueAsDouble = "2.0", @ValueAsFloat = "2.0", @ValueAsInt = "2", @ValueAsLong = "2"] From c84e1b033beb7dd8c7f3acad0e52bcc0687334a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 10 Mar 2022 22:07:12 +0100 Subject: [PATCH 32/89] Fix tests --- .../pmd/lang/java/ast/Java16TreeDumpTest.java | 15 +++++--- .../lang/java/types/TestUtilitiesForTypes.kt | 34 +++++++++++++++++-- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java index 7614137726..e783b552cd 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java @@ -4,6 +4,11 @@ package net.sourceforge.pmd.lang.java.ast; +import static net.sourceforge.pmd.lang.java.types.TestUtilitiesForTypesKt.hasType; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.not; + import java.util.List; import org.junit.Assert; @@ -16,7 +21,6 @@ import net.sourceforge.pmd.lang.java.BaseJavaTreeDumpTest; import net.sourceforge.pmd.lang.java.JavaParsingHelper; import net.sourceforge.pmd.lang.java.symbols.JElementSymbol; import net.sourceforge.pmd.lang.java.types.JPrimitiveType; -import net.sourceforge.pmd.lang.java.types.TypeTestUtil; public class Java16TreeDumpTest extends BaseJavaTreeDumpTest { private final JavaParsingHelper java16 = @@ -37,11 +41,12 @@ public class Java16TreeDumpTest extends BaseJavaTreeDumpTest { // extended tests for type resolution etc. ASTCompilationUnit ast = java16.parseResource("PatternMatchingInstanceof.java"); - NodeStream patterns = - ast.descendants(ASTTypePattern.class) - .filter(it -> BinaryOp.isInfixExprWithOperator(it, BinaryOp.INSTANCEOF)); + NodeStream patterns = ast.descendants(ASTTypePattern.class); + + assertThat(patterns.toList(), not(empty())); + for (ASTTypePattern expr : patterns) { - Assert.assertTrue(TypeTestUtil.isA(String.class, expr.getVarId())); + assertThat(expr.getVarId(), hasType(String.class)); } } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TestUtilitiesForTypes.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TestUtilitiesForTypes.kt index 6dd913262b..0b6178a9e0 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TestUtilitiesForTypes.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TestUtilitiesForTypes.kt @@ -16,6 +16,7 @@ import net.sourceforge.pmd.lang.java.JavaParsingHelper import net.sourceforge.pmd.lang.java.ast.* import net.sourceforge.pmd.lang.java.symbols.internal.asm.AsmSymbolResolver import net.sourceforge.pmd.lang.java.types.TypeOps.* +import org.hamcrest.Description import kotlin.String import kotlin.streams.toList import kotlin.test.assertTrue @@ -45,9 +46,9 @@ typealias TypePair = Pair fun JTypeMirror.getMethodsByName(name: String) = streamMethods { it.simpleName == name }.toList() fun JTypeMirror.shouldBeUnresolvedClass(canonicalName: String) = - this.shouldBeA { - it.symbol::getCanonicalName shouldBe canonicalName - } + this.shouldBeA { + it.symbol::getCanonicalName shouldBe canonicalName + } infix fun TypeNode.shouldHaveType(expected: JTypeMirror) { withClue(this) { @@ -55,6 +56,33 @@ infix fun TypeNode.shouldHaveType(expected: JTypeMirror) { } } + +/** + * A hamcrest matcher usable from Java. + */ +fun hasType(t: JTypeMirror): org.hamcrest.Matcher = + object : org.hamcrest.BaseMatcher() { + override fun describeTo(p0: Description) { + p0.appendText("a node with type $t") + } + + override fun matches(p0: Any?): Boolean = + p0 is TypeNode && TypeTestUtil.isA(t, p0) + } + +/** + * A hamcrest matcher usable from Java. + */ +fun hasType(t: Class<*>): org.hamcrest.Matcher = + object : org.hamcrest.BaseMatcher() { + override fun describeTo(p0: Description) { + p0.appendText("a node with type ${t.name}") + } + + override fun matches(p0: Any?): Boolean = + p0 is TypeNode && TypeTestUtil.isA(t, p0) + } + // pairs of type param name to value fun JMethodSig.subst(vararg mapping: Pair): JMethodSig { var subst = Substitution.EMPTY From 65a483c0032e002124e27fb83d0644684f20562c Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 11 Mar 2022 11:09:59 +0100 Subject: [PATCH 33/89] Update pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java --- .../pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java index 976aae10e0..5515c418c2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/AsmSymbolResolver.java @@ -121,7 +121,7 @@ public class AsmSymbolResolver implements SymbolResolver { return resolveFromInternalNameCannotFail(internalName, ClassStub.UNKNOWN_ARITY); } - @SuppressWarnings("PMD.CompareObjectsWithEquals") // SoftClassReference + @SuppressWarnings("PMD.CompareObjectsWithEquals") // ClassStub @NonNull ClassStub resolveFromInternalNameCannotFail(@NonNull String internalName, int observedArity) { return knownStubs.compute(internalName, (iname, prev) -> { if (prev != failed && prev != null) { From a7d29feb6258858054a52917eb433c1c7ed7c130 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 11 Mar 2022 11:19:43 +0100 Subject: [PATCH 34/89] [doc] Update release notes (#3812, #3836) --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8b6e8ffc93..41c47b92a5 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -52,6 +52,8 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is * apex-performance * [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() +* doc + * [#3812](https://github.com/pmd/pmd/issues/3812): \[doc] Documentation website table of contents broken on pages with many subheadings ### API Changes @@ -79,6 +81,7 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is ### External Contributions * [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() - [@filiprafalowicz](https://github.com/filiprafalowicz) +* [#3836](https://github.com/pmd/pmd/pull/3836): \[doc] Make TOC scrollable when too many subheadings - [@JerritEic](https://github.com/JerritEic) {% endtocmaker %} From 19bb54acdbda7d2f6838c8704b9be5694a2d024c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 14 Mar 2022 21:30:17 +0100 Subject: [PATCH 35/89] Minor cleanup --- .../java/net/sourceforge/pmd/lang/java/ast/BinaryOp.java | 3 +++ .../sourceforge/pmd/lang/java/internal/JavaAstUtils.java | 8 +------- 2 files changed, 4 insertions(+), 7 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 549fb1955a..0e53569546 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 @@ -86,6 +86,9 @@ public enum BinaryOp implements InternalInterfaces.OperatorLike { /** Modulo {@code "%"} operator. */ MOD("%"); + /** Set of {@code &&} and {@code ||}. Use with {@link #isInfixExprWithOperator(JavaNode, Set)}. */ + public static final Set CONDITIONAL_OPS = + CollectionUtil.immutableEnumSet(CONDITIONAL_AND, CONDITIONAL_OR); /** Set of {@code <}, {@code <=}, {@code >=} and {@code >}. Use with {@link #isInfixExprWithOperator(JavaNode, Set)}. */ public static final Set COMPARISON_OPS = CollectionUtil.immutableEnumSet(LE, GE, GT, LT); /** Set of {@code ==} and {@code !=}. Use with {@link #isInfixExprWithOperator(JavaNode, Set)}. */ 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 14b49e36b5..7365b6802f 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,7 +4,6 @@ package net.sourceforge.pmd.lang.java.internal; -import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTSwitchBranch; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.JavaNode; @@ -20,12 +19,7 @@ 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; + return BinaryOp.isInfixExprWithOperator(ifx, BinaryOp.CONDITIONAL_OPS); } public static int numAlternatives(ASTSwitchBranch n) { From 43220476233024cea0deecefc14b81634ebe5ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 14 Mar 2022 21:47:42 +0100 Subject: [PATCH 36/89] Move things from JavaRuleUtil to JavaAstUtils --- .../pmd/lang/java/ast/ASTAssignableExpr.java | 4 +- .../lang/java/ast/internal/JavaAstUtils.java | 696 ++++++++++++++++++ .../pmd/lang/java/internal/JavaAstUtils.java | 28 - .../java/metrics/internal/CycloVisitor.java | 2 +- .../metrics/internal/NpathBaseVisitor.java | 2 +- .../ArrayIsStoredDirectlyRule.java | 4 +- .../AvoidReassigningLoopVariablesRule.java | 10 +- .../ForLoopCanBeForeachRule.java | 14 +- .../MethodReturnsInternalArrayRule.java | 6 +- .../bestpractices/PreserveStackTraceRule.java | 9 +- .../SimplifiableTestAssertionRule.java | 10 +- .../UnusedFormalParameterRule.java | 3 +- .../UnusedLocalVariableRule.java | 3 +- .../bestpractices/UnusedPrivateFieldRule.java | 7 +- .../UseTryWithResourcesRule.java | 4 +- ...eclarationsShouldBeAtStartOfClassRule.java | 4 +- .../codestyle/IdenticalCatchBranchesRule.java | 4 +- .../codestyle/PrematureDeclarationRule.java | 3 +- .../rule/codestyle/UnnecessaryCastRule.java | 6 +- .../rule/codestyle/UnnecessaryReturnRule.java | 6 +- .../java/rule/design/ImmutableFieldRule.java | 8 +- .../java/rule/design/LawOfDemeterRule.java | 8 +- .../design/SimplifyBooleanReturnsRule.java | 8 +- .../rule/design/SimplifyConditionalRule.java | 4 +- .../java/rule/design/SingularFieldRule.java | 10 +- .../java/rule/design/UseUtilityClassRule.java | 4 +- .../design/UselessOverridingMethodRule.java | 8 +- .../errorprone/AssignmentInOperandRule.java | 4 +- .../rule/errorprone/BrokenNullCheckRule.java | 4 +- ...CloneMethodMustImplementCloneableRule.java | 4 +- .../rule/errorprone/CloseResourceRule.java | 19 +- ...ConstructorCallsOverridableMethodRule.java | 4 +- .../errorprone/IdempotentOperationsRule.java | 4 +- .../InvalidLogMessageFormatRule.java | 4 +- .../ProperCloneImplementationRule.java | 4 +- ...ingletonClassReturningNewInstanceRule.java | 4 +- .../lang/java/rule/internal/DataflowPass.java | 3 +- .../lang/java/rule/internal/JavaRuleUtil.java | 682 +---------------- .../java/rule/internal/StablePathMatcher.java | 3 +- .../DoubleCheckedLockingRule.java | 5 +- .../UnsynchronizedStaticFormatterRule.java | 4 +- .../ConsecutiveLiteralAppendsRule.java | 3 +- .../InefficientStringBufferingRule.java | 3 +- .../RedundantFieldInitializerRule.java | 4 +- .../UseStringBufferForStringAppendsRule.java | 4 +- .../performance/UselessStringValueOfRule.java | 6 +- .../internal/AbruptCompletionAnalysis.java | 8 +- .../table/internal/SymbolTableResolver.java | 4 +- .../lang/java/types/ast/PolyResolution.java | 4 +- .../java/ast/internal/JavaAstUtilTest.java | 44 ++ .../java/rule/internal/JavaRuleUtilTest.java | 27 - .../java/types/ast/ConversionContextTests.kt | 6 +- 52 files changed, 891 insertions(+), 845 deletions(-) create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtilTest.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAssignableExpr.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAssignableExpr.java index 2d763fb192..72ea5e9282 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAssignableExpr.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAssignableExpr.java @@ -8,7 +8,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; import net.sourceforge.pmd.lang.java.types.JVariableSig; @@ -98,7 +98,7 @@ public interface ASTAssignableExpr extends ASTPrimaryExpression { /** * The value is written to, possibly being read before or after. - * Also see {@link JavaRuleUtil#isVarAccessReadAndWrite(ASTNamedReferenceExpr)}. + * Also see {@link JavaAstUtils#isVarAccessReadAndWrite(ASTNamedReferenceExpr)}. */ WRITE } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java new file mode 100644 index 0000000000..ac4d64a5e3 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java @@ -0,0 +1,696 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast.internal; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import net.sourceforge.pmd.lang.ast.GenericToken; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTArgumentList; +import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; +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.ASTBooleanLiteral; +import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement; +import net.sourceforge.pmd.lang.java.ast.ASTCastExpression; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; +import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; +import net.sourceforge.pmd.lang.java.ast.ASTExpressionStatement; +import net.sourceforge.pmd.lang.java.ast.ASTFieldAccess; +import net.sourceforge.pmd.lang.java.ast.ASTForStatement; +import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; +import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters; +import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; +import net.sourceforge.pmd.lang.java.ast.ASTLabeledStatement; +import net.sourceforge.pmd.lang.java.ast.ASTList; +import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement; +import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; +import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral; +import net.sourceforge.pmd.lang.java.ast.ASTNumericLiteral; +import net.sourceforge.pmd.lang.java.ast.ASTStatement; +import net.sourceforge.pmd.lang.java.ast.ASTSuperExpression; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchBranch; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; +import net.sourceforge.pmd.lang.java.ast.ASTThisExpression; +import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; +import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; +import net.sourceforge.pmd.lang.java.ast.Annotatable; +import net.sourceforge.pmd.lang.java.ast.BinaryOp; +import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.JavaTokenKinds; +import net.sourceforge.pmd.lang.java.ast.QualifiableExpression; +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.symbols.JVariableSymbol; +import net.sourceforge.pmd.lang.java.symbols.internal.ast.AstLocalVarSym; +import net.sourceforge.pmd.lang.java.types.JMethodSig; +import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind; +import net.sourceforge.pmd.lang.java.types.JTypeMirror; +import net.sourceforge.pmd.lang.java.types.TypeTestUtil; +import net.sourceforge.pmd.util.CollectionUtil; +import net.sourceforge.pmd.util.OptionalBool; + +/** + * + */ +public final class JavaAstUtils { + + private JavaAstUtils() { + // utility class + } + + + public static boolean isConditional(JavaNode ifx) { + return BinaryOp.isInfixExprWithOperator(ifx, BinaryOp.CONDITIONAL_OPS); + } + + public static int numAlternatives(ASTSwitchBranch n) { + return n.isDefault() ? 1 : n.getLabel().getExprList().count(); + } + + /** + * Returns true if this is a numeric literal with the given int value. + * This also considers long literals. + */ + public static boolean isLiteralInt(JavaNode e, int value) { + return e instanceof ASTNumericLiteral + && ((ASTNumericLiteral) e).isIntegral() + && ((ASTNumericLiteral) e).getValueAsInt() == value; + } + + /** This is type-aware, so will not pick up on numeric addition. */ + public static boolean isStringConcatExpr(@Nullable JavaNode e) { + if (e instanceof ASTInfixExpression) { + ASTInfixExpression infix = (ASTInfixExpression) e; + return infix.getOperator() == BinaryOp.ADD && TypeTestUtil.isA(String.class, infix); + } + return false; + } + + /** + * If the parameter is an operand of a binary infix expression, + * returns the other operand. Otherwise returns null. + */ + public static @Nullable ASTExpression getOtherOperandIfInInfixExpr(@Nullable JavaNode e) { + if (e != null && e.getParent() instanceof ASTInfixExpression) { + return (ASTExpression) e.getParent().getChild(1 - e.getIndexInParent()); + } + return null; + } + + public static @Nullable ASTExpression getOtherOperandIfInAssignmentExpr(@Nullable JavaNode e) { + if (e != null && e.getParent() instanceof ASTAssignmentExpression) { + return (ASTExpression) e.getParent().getChild(1 - e.getIndexInParent()); + } + return null; + } + + /** + * Returns true if the node is a {@link ASTMethodDeclaration} that + * is a main method. + */ + public static boolean isMainMethod(JavaNode node) { + return node instanceof ASTMethodDeclaration + && ((ASTMethodDeclaration) node).isMainMethod(); + } + + public 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; + } + + /** + * Returns true if the formal parameters of the method or constructor + * match the given types exactly. Note that for varargs methods, the + * last param must have an array type (but it is not checked to be varargs). + * This will return false if we're not sure. + * + * @param node Method or ctor + * @param types List of types to match (may be empty) + * + * @throws NullPointerException If any of the classes is null, or the node is null + * @see TypeTestUtil#isExactlyA(Class, TypeNode) + */ + public static boolean hasParameters(ASTMethodOrConstructorDeclaration node, Class... types) { + ASTFormalParameters formals = node.getFormalParameters(); + if (formals.size() != types.length) { + return false; + } + for (int i = 0; i < formals.size(); i++) { + ASTFormalParameter fi = formals.get(i); + if (!TypeTestUtil.isExactlyA(types[i], fi)) { + return false; + } + } + return true; + } + + /** + * Returns true if the {@code throws} declaration of the method or constructor + * matches the given types exactly. + * + * @param node Method or ctor + * @param types List of exception types to match (may be empty) + * + * @throws NullPointerException If any of the classes is null, or the node is null + * @see TypeTestUtil#isExactlyA(Class, TypeNode) + */ + @SafeVarargs + public static boolean hasExceptionList(ASTMethodOrConstructorDeclaration node, Class... types) { + @NonNull List formals = ASTList.orEmpty(node.getThrowsList()); + if (formals.size() != types.length) { + return false; + } + for (int i = 0; i < formals.size(); i++) { + ASTClassOrInterfaceType fi = formals.get(i); + if (!TypeTestUtil.isExactlyA(types[i], fi)) { + return false; + } + } + return true; + } + + /** + * True if the variable is never used. Note that the visibility of + * the variable must be less than {@link Visibility#V_PRIVATE} for + * us to be sure of it. + */ + public static boolean isNeverUsed(ASTVariableDeclaratorId varId) { + return CollectionUtil.none(varId.getLocalUsages(), JavaAstUtils::isReadUsage); + } + + private static boolean isReadUsage(ASTNamedReferenceExpr expr) { + return expr.getAccessType() == AccessType.READ + // x++ as a method argument or used in other expression + || expr.getParent() instanceof ASTUnaryExpression + && !(expr.getParent().getParent() instanceof ASTExpressionStatement); + } + + /** + * True if the variable is incremented or decremented via a compound + * assignment operator, or a unary increment/decrement expression. + */ + public static boolean isVarAccessReadAndWrite(ASTNamedReferenceExpr expr) { + return expr.getAccessType() == AccessType.WRITE + && (!(expr.getParent() instanceof ASTAssignmentExpression) + || ((ASTAssignmentExpression) expr.getParent()).getOperator().isCompound()); + } + + /** + * True if the variable access is a non-compound assignment. + */ + public static boolean isVarAccessStrictlyWrite(ASTNamedReferenceExpr expr) { + return expr.getParent() instanceof ASTAssignmentExpression + && expr.getIndexInParent() == 0 + && !((ASTAssignmentExpression) expr.getParent()).getOperator().isCompound(); + } + + /** + * Returns the set of labels on this statement. + */ + public static Set getStatementLabels(ASTStatement node) { + if (!(node.getParent() instanceof ASTLabeledStatement)) { + return Collections.emptySet(); + } + + return node.ancestors().takeWhile(it -> it instanceof ASTLabeledStatement) + .toStream() + .map(it -> ((ASTLabeledStatement) it).getLabel()) + .collect(Collectors.toSet()); + } + + public static boolean isAnonymousClassCreation(@Nullable ASTExpression expression) { + return expression instanceof ASTConstructorCall + && ((ASTConstructorCall) expression).isAnonymousClass(); + } + + /** + * Will cut through argument lists, except those of enum constants + * and explicit invocation nodes. + */ + public static @NonNull ASTExpression getTopLevelExpr(ASTExpression expr) { + JavaNode last = expr.ancestorsOrSelf() + .takeWhile(it -> it instanceof ASTExpression + || it instanceof ASTArgumentList && it.getParent() instanceof ASTExpression) + .last(); + return (ASTExpression) Objects.requireNonNull(last); + } + + /** + * Returns the variable IDS corresponding to variables declared in + * the init clause of the loop. + */ + public static NodeStream getLoopVariables(ASTForStatement loop) { + return NodeStream.of(loop.getInit()) + .filterIs(ASTLocalVariableDeclaration.class) + .flatMap(ASTLocalVariableDeclaration::getVarIds); + } + + /** + * Whether one expression is the boolean negation of the other. Many + * forms are not yet supported. This method is symmetric so only needs + * to be called once. + */ + public static boolean areComplements(ASTExpression e1, ASTExpression e2) { + if (isBooleanNegation(e1)) { + return areEqual(unaryOperand(e1), e2); + } else if (isBooleanNegation(e2)) { + return areEqual(e1, unaryOperand(e2)); + } else if (e1 instanceof ASTInfixExpression && e2 instanceof ASTInfixExpression) { + ASTInfixExpression ifx1 = (ASTInfixExpression) e1; + ASTInfixExpression ifx2 = (ASTInfixExpression) e2; + if (ifx1.getOperator().getComplement() != ifx2.getOperator()) { + return false; + } + if (ifx1.getOperator().hasSamePrecedenceAs(BinaryOp.EQ)) { + // NOT(a == b, a != b) + // NOT(a == b, b != a) + return areEqual(ifx1.getLeftOperand(), ifx2.getLeftOperand()) + && areEqual(ifx1.getRightOperand(), ifx2.getRightOperand()) + || areEqual(ifx2.getLeftOperand(), ifx1.getLeftOperand()) + && areEqual(ifx2.getRightOperand(), ifx1.getRightOperand()); + } + // todo we could continue with de Morgan and such + } + return false; + } + + private static boolean areEqual(ASTExpression e1, ASTExpression e2) { + return tokenEquals(e1, e2); + } + + /** + * Returns true if both nodes have exactly the same tokens. + * + * @param node First node + * @param that Other node + */ + public static boolean tokenEquals(JavaNode node, JavaNode that) { + return tokenEquals(node, that, null); + } + + /** + * Returns true if both nodes have the same tokens, modulo some renaming + * function. The renaming function maps unqualified variables and type + * identifiers of the first node to the other. This should be used + * in nodes living in the same lexical scope, so that unqualified + * names mean the same thing. + * + * @param node First node + * @param other Other node + * @param varRenamer A renaming function. If null, no renaming is applied. + * Must not return null, if no renaming occurs, returns its argument. + */ + public static boolean tokenEquals(@NonNull JavaNode node, + @NonNull JavaNode other, + @Nullable Function varRenamer) { + // Since type and variable names obscure one another, + // it's ok to use a single renaming function. + + Iterator thisIt = GenericToken.range(node.getFirstToken(), node.getLastToken()); + Iterator thatIt = GenericToken.range(other.getFirstToken(), other.getLastToken()); + int lastKind = 0; + while (thisIt.hasNext()) { + if (!thatIt.hasNext()) { + return false; + } + JavaccToken o1 = thisIt.next(); + JavaccToken o2 = thatIt.next(); + if (o1.kind != o2.kind) { + return false; + } + + String mappedImage = o1.getImage(); + if (varRenamer != null + && o1.kind == JavaTokenKinds.IDENTIFIER + && lastKind != JavaTokenKinds.DOT + && lastKind != JavaTokenKinds.METHOD_REF + //method name + && o1.getNext() != null && o1.getNext().kind != JavaTokenKinds.LPAREN) { + mappedImage = varRenamer.apply(mappedImage); + } + + if (!o2.getImage().equals(mappedImage)) { + return false; + } + + lastKind = o1.kind; + } + return !thatIt.hasNext(); + } + + public static boolean isNullLiteral(ASTExpression node) { + return node instanceof ASTNullLiteral; + } + + /** Returns true if the node is a boolean literal with any value. */ + public static boolean isBooleanLiteral(JavaNode e) { + return e instanceof ASTBooleanLiteral; + } + + /** Returns true if the node is a boolean literal with the given constant value. */ + public static boolean isBooleanLiteral(JavaNode e, boolean value) { + return e instanceof ASTBooleanLiteral && ((ASTBooleanLiteral) e).isTrue() == value; + } + + public static boolean isBooleanNegation(JavaNode e) { + return e instanceof ASTUnaryExpression && ((ASTUnaryExpression) e).getOperator() == UnaryOp.NEGATION; + } + + /** + * If the argument is a unary expression, returns its operand, otherwise + * returns null. + */ + public static @Nullable ASTExpression unaryOperand(@Nullable ASTExpression e) { + return e instanceof ASTUnaryExpression ? ((ASTUnaryExpression) e).getOperand() + : null; + } + + /** + * Whether the expression is an access to a field of this instance, + * not inherited, qualified or not ({@code this.field} or just {@code field}). + */ + public static boolean isThisFieldAccess(ASTExpression e) { + if (!(e instanceof ASTNamedReferenceExpr)) { + return false; + } + JVariableSymbol sym = ((ASTNamedReferenceExpr) e).getReferencedSym(); + return sym instanceof JFieldSymbol + && !((JFieldSymbol) sym).isStatic() + // not inherited + && ((JFieldSymbol) sym).getEnclosingClass().equals(e.getEnclosingType().getSymbol()) + // correct syntactic form + && (e instanceof ASTVariableAccess || isSyntacticThisFieldAccess(e)); + } + + /** + * Whether the expression is a {@code this.field}, with no outer + * instance qualifier ({@code Outer.this.field}). The field symbol + * is not checked to resolve to a field declared in this class (it + * may be inherited) + */ + public static boolean isSyntacticThisFieldAccess(ASTExpression e) { + if (e instanceof ASTFieldAccess) { + ASTExpression qualifier = ((ASTFieldAccess) e).getQualifier(); + if (qualifier instanceof ASTThisExpression) { + // unqualified this + return ((ASTThisExpression) qualifier).getQualifier() == null; + } + } + return false; + } + + public static boolean hasAnyAnnotation(Annotatable node, Collection qualifiedNames) { + return qualifiedNames.stream().anyMatch(node::isAnnotationPresent); + } + + /** + * Returns true if the expression is the default field value for + * the given type. + */ + public static boolean isDefaultValue(JTypeMirror type, ASTExpression expr) { + if (type.isPrimitive()) { + if (type.isPrimitive(PrimitiveTypeKind.BOOLEAN)) { + return expr instanceof ASTBooleanLiteral && !((ASTBooleanLiteral) expr).isTrue(); + } else { + Object constValue = expr.getConstValue(); + return constValue instanceof Number && ((Number) constValue).doubleValue() == 0d + || constValue instanceof Character && constValue.equals('\u0000'); + } + } else { + return expr instanceof ASTNullLiteral; + } + } + + /** + * Returns true if the expression is a {@link ASTNamedReferenceExpr} + * that references the symbol. + */ + public static boolean isReferenceToVar(@Nullable ASTExpression expression, @NonNull JVariableSymbol symbol) { + return expression instanceof ASTNamedReferenceExpr + && symbol.equals(((ASTNamedReferenceExpr) expression).getReferencedSym()); + } + + public static boolean isUnqualifiedThis(ASTExpression e) { + return e instanceof ASTThisExpression && ((ASTThisExpression) e).getQualifier() == null; + } + + public static boolean isUnqualifiedSuper(ASTExpression e) { + return e instanceof ASTSuperExpression && ((ASTSuperExpression) e).getQualifier() == null; + } + + public static boolean isUnqualifiedThisOrSuper(ASTExpression e) { + return isUnqualifiedSuper(e) || isUnqualifiedThis(e); + } + + /** + * Returns true if the expression is a {@link ASTNamedReferenceExpr} + * that references any of the symbol in the set. + */ + public static boolean isReferenceToVar(@Nullable ASTExpression expression, @NonNull Set symbols) { + return expression instanceof ASTNamedReferenceExpr + && symbols.contains(((ASTNamedReferenceExpr) expression).getReferencedSym()); + } + + /** + * Returns true if both expressions refer to the same variable. + * A "variable" here can also means a field path, eg, {@code this.field.a}. + * This method unifies {@code this.field} and {@code field} if possible, + * and also considers {@code this}. + * + *

    Note that while this is more useful than just checking whether + * both expressions access the same symbol, it still does not mean that + * they both access the same value. The actual value is data-flow + * dependent. + */ + public static boolean isReferenceToSameVar(ASTExpression e1, ASTExpression e2) { + if (e1 instanceof ASTNamedReferenceExpr && e2 instanceof ASTNamedReferenceExpr) { + if (OptionalBool.YES != referenceSameSymbol((ASTNamedReferenceExpr) e1, (ASTNamedReferenceExpr) e2)) { + return false; + } + + if (e1.getClass() != e2.getClass()) { + // unify `this.f` and `f` + // note, we already know that the symbol is the same so there's no scoping problem + return isSyntacticThisFieldAccess(e1) || isSyntacticThisFieldAccess(e2); + } else if (e1 instanceof ASTFieldAccess && e2 instanceof ASTFieldAccess) { + return isReferenceToSameVar(((ASTFieldAccess) e1).getQualifier(), + ((ASTFieldAccess) e2).getQualifier()); + } + return e1 instanceof ASTVariableAccess && e2 instanceof ASTVariableAccess; + } else if (e1 instanceof ASTThisExpression || e2 instanceof ASTThisExpression) { + return e1.getClass() == e2.getClass(); + } + return false; + } + + private static OptionalBool referenceSameSymbol(ASTNamedReferenceExpr e1, ASTNamedReferenceExpr e2) { + if (!e1.getName().equals(e2.getName())) { + return OptionalBool.NO; + } + JVariableSymbol ref1 = e1.getReferencedSym(); + JVariableSymbol ref2 = e2.getReferencedSym(); + if (ref1 == null || ref2 == null) { + return OptionalBool.UNKNOWN; + } + return OptionalBool.definitely(ref1.equals(ref2)); + } + + /** + * Returns true if the expression is a reference to a local variable. + */ + public static boolean isReferenceToLocal(ASTExpression expr) { + return expr instanceof ASTVariableAccess + && ((ASTVariableAccess) expr).getReferencedSym() instanceof AstLocalVarSym; + } + + /** + * Returns true if the expression has the form `field`, or `this.field`, + * where `field` is a field declared in the enclosing class. Considers + * inherited fields. Assumes we're not in a static context. + */ + public static boolean isRefToFieldOfThisInstance(ASTExpression usage) { + if (!(usage instanceof ASTNamedReferenceExpr)) { + return false; + } + JVariableSymbol symbol = ((ASTNamedReferenceExpr) usage).getReferencedSym(); + if (!(symbol instanceof JFieldSymbol)) { + return false; + } + + if (usage instanceof ASTVariableAccess) { + return !Modifier.isStatic(((JFieldSymbol) symbol).getModifiers()); + } else if (usage instanceof ASTFieldAccess) { + return isUnqualifiedThisOrSuper(((ASTFieldAccess) usage).getQualifier()); + } + return false; + } + + /** + * Returns true if the expression is a reference to a field declared + * in this class (not a superclass), on any instance (not just `this`). + */ + public static boolean isRefToFieldOfThisClass(ASTExpression usage) { + if (!(usage instanceof ASTNamedReferenceExpr)) { + return false; + } + JVariableSymbol symbol = ((ASTNamedReferenceExpr) usage).getReferencedSym(); + if (!(symbol instanceof JFieldSymbol)) { + return false; + } + + if (usage instanceof ASTVariableAccess) { + return !Modifier.isStatic(((JFieldSymbol) symbol).getModifiers()); + } else if (usage instanceof ASTFieldAccess) { + return Objects.equals(((JFieldSymbol) symbol).getEnclosingClass(), + usage.getEnclosingType().getSymbol()); + } + return false; + } + + public static boolean isCallOnThisInstance(ASTMethodCall call) { + // syntactic approach. + if (call.getQualifier() != null) { + return isUnqualifiedThisOrSuper(call.getQualifier()); + } + + // unqualified call + JMethodSig mtype = call.getMethodType(); + return !mtype.getSymbol().isUnresolved() + && mtype.getSymbol().getEnclosingClass().equals(call.getEnclosingType().getSymbol()); + } + + public static ASTClassOrInterfaceType getThisOrSuperQualifier(ASTExpression expr) { + if (expr instanceof ASTThisExpression) { + return ((ASTThisExpression) expr).getQualifier(); + } else if (expr instanceof ASTSuperExpression) { + return ((ASTSuperExpression) expr).getQualifier(); + } + return null; + } + + public static ASTClassOrInterfaceType isUnqual(ASTExpression expr) { + if (expr instanceof ASTThisExpression) { + return ((ASTThisExpression) expr).getQualifier(); + } else if (expr instanceof ASTSuperExpression) { + return ((ASTSuperExpression) expr).getQualifier(); + } + return null; + } + + public static boolean isThisOrSuper(ASTExpression expr) { + return expr instanceof ASTThisExpression || expr instanceof ASTSuperExpression; + } + + /** + * 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 (isStringConcatExpr(e)) { + ASTInfixExpression infix = (ASTInfixExpression) e; + flattenOperandsRec(infix.getLeftOperand(), result); + flattenOperandsRec(infix.getRightOperand(), result); + } else { + result.add(e); + } + } + + /** + * Returns true if the node is the last child of its parent (or is the root node). + */ + public static boolean isLastChild(Node it) { + Node parent = it.getParent(); + return parent == null || it.getIndexInParent() == parent.getNumChildren() - 1; + } + + /** + * Returns a node stream of enclosing expressions in the same call chain. + * For instance in {@code a.b().c().d()}, called on {@code a}, this will + * yield {@code a.b()}, and {@code a.b().c()}. + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public static NodeStream followingCallChain(ASTExpression expr) { + return (NodeStream) expr.ancestors().takeWhile(it -> it instanceof QualifiableExpression); + } + + public static ASTExpression peelCasts(@Nullable ASTExpression expr) { + while (expr instanceof ASTCastExpression) { + expr = ((ASTCastExpression) expr).getOperand(); + } + return expr; + } + + public static boolean isArrayInitializer(ASTExpression expr) { + return expr instanceof ASTArrayAllocation && ((ASTArrayAllocation) expr).getArrayInitializer() != null; + } + + public static boolean isCloneMethod(ASTMethodDeclaration node) { + // this is enough as in valid code, this signature overrides Object#clone + // and the other things like visibility are checked by the compiler + return "clone".equals(node.getName()) + && node.getArity() == 0 + && !node.isStatic(); + } + + public static boolean isArrayLengthFieldAccess(ASTExpression node) { + if (node instanceof ASTFieldAccess) { + ASTFieldAccess field = (ASTFieldAccess) node; + return "length".equals(field.getName()) + && field.getQualifier().getTypeMirror().isArray(); + } + return false; + } + + /** + * @see ASTBreakStatement#getTarget() + */ + public static boolean mayBeBreakTarget(JavaNode it) { + return it instanceof ASTLoopStatement + || it instanceof ASTSwitchStatement + || it instanceof ASTLabeledStatement; + } +} 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 deleted file mode 100644 index 7365b6802f..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstUtils.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.internal; - -import net.sourceforge.pmd.lang.java.ast.ASTSwitchBranch; -import net.sourceforge.pmd.lang.java.ast.BinaryOp; -import net.sourceforge.pmd.lang.java.ast.JavaNode; - -/** - * - */ -public final class JavaAstUtils { - - private JavaAstUtils() { - // utility class - } - - - public static boolean isConditional(JavaNode ifx) { - return BinaryOp.isInfixExprWithOperator(ifx, BinaryOp.CONDITIONAL_OPS); - } - - 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/CycloVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/internal/CycloVisitor.java index cf85f027b0..547fe2b627 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 @@ -25,7 +25,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.internal.JavaAstUtils; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics.CycloOption; import net.sourceforge.pmd.lang.metrics.MetricOptions; 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 8c9396796e..57819d5db0 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 @@ -27,7 +27,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.ast.internal.JavaAstUtils; /** diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ArrayIsStoredDirectlyRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ArrayIsStoredDirectlyRule.java index 61803a3481..da45d86c47 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ArrayIsStoredDirectlyRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ArrayIsStoredDirectlyRule.java @@ -14,8 +14,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -68,7 +68,7 @@ public class ArrayIsStoredDirectlyRule extends AbstractJavaRulechainRule { // the RHS of an assignment if (usage.getParent() instanceof ASTAssignmentExpression && usage.getIndexInParent() == 1) { ASTAssignableExpr assigned = ((ASTAssignmentExpression) usage.getParent()).getLeftOperand(); - if (JavaRuleUtil.isRefToFieldOfThisInstance(assigned)) { + if (JavaAstUtils.isRefToFieldOfThisInstance(assigned)) { addViolation(context, usage.getParent(), usage.getName()); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AvoidReassigningLoopVariablesRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AvoidReassigningLoopVariablesRule.java index f6c8451f7b..a27232407a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AvoidReassigningLoopVariablesRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AvoidReassigningLoopVariablesRule.java @@ -32,8 +32,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.util.StringUtil.CaseConvention; @@ -91,7 +91,7 @@ public class AvoidReassigningLoopVariablesRule extends AbstractJavaRulechainRule if (behavior == ForReassignOption.ALLOW) { return data; } - NodeStream loopVars = JavaRuleUtil.getLoopVariables(loopStmt); + NodeStream loopVars = JavaAstUtils.getLoopVariables(loopStmt); if (behavior == ForReassignOption.DENY) { ASTForUpdate update = loopStmt.firstChild(ASTForUpdate.class); for (ASTVariableDeclaratorId loopVar : loopVars) { @@ -106,7 +106,7 @@ public class AvoidReassigningLoopVariablesRule extends AbstractJavaRulechainRule } } else { Set loopVarNames = loopVars.collect(Collectors.mapping(ASTVariableDeclaratorId::getName, Collectors.toSet())); - Set labels = JavaRuleUtil.getStatementLabels(loopStmt); + Set labels = JavaAstUtils.getStatementLabels(loopStmt); new ControlFlowCtx(false, loopVarNames, (RuleContext) data, labels, false, false).roamStatementsForExit(loopStmt.getBody()); } return null; @@ -211,8 +211,8 @@ public class AvoidReassigningLoopVariablesRule extends AbstractJavaRulechainRule final boolean onlyConsiderWrite = guarded || mayExit; node.descendants(ASTNamedReferenceExpr.class) .filter(it -> loopVarNames.contains(it.getName())) - .filter(it -> onlyConsiderWrite ? JavaRuleUtil.isVarAccessStrictlyWrite(it) - : JavaRuleUtil.isVarAccessReadAndWrite(it)) + .filter(it -> onlyConsiderWrite ? JavaAstUtils.isVarAccessStrictlyWrite(it) + : JavaAstUtils.isVarAccessReadAndWrite(it)) .forEach(it -> addViolation(ruleCtx, it, it.getName())); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java index 8b0beaeac1..59eb021efd 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java @@ -29,8 +29,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.BinaryOp; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; import net.sourceforge.pmd.lang.java.types.InvocationMatcher; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; @@ -97,7 +97,7 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRulechainRule { if (varIds.count() == 1) { ASTVariableDeclaratorId first = varIds.firstOrThrow(); if (ITERATOR_CALL.matchesCall(first.getInitializer()) - || JavaRuleUtil.isLiteralInt(first.getInitializer(), 0)) { + || JavaAstUtils.isLiteralInt(first.getInitializer(), 0)) { return first; } } @@ -146,7 +146,7 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRulechainRule { ASTInfixExpression condition = (ASTInfixExpression) guardCondition; BinaryOp op = condition.getOperator(); - if (!JavaRuleUtil.isReferenceToVar(condition.getLeftOperand(), indexVar.getSymbol())) { + if (!JavaAstUtils.isReferenceToVar(condition.getLeftOperand(), indexVar.getSymbol())) { return null; } @@ -159,7 +159,7 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRulechainRule { rhs = NodeStream.of(condition.getRightOperand()) .filterIs(ASTInfixExpression.class) .filter(it -> it.getOperator() == BinaryOp.SUB) - .filter(it -> JavaRuleUtil.isLiteralInt(it.getRightOperand(), 1)) + .filter(it -> JavaAstUtils.isLiteralInt(it.getRightOperand(), 1)) .map(ASTInfixExpression::getLeftOperand); } @@ -209,14 +209,14 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRulechainRule { } ASTArrayAccess arrayAccess = (ASTArrayAccess) usage.getParent(); return arrayAccess.getAccessType() == AccessType.READ - && JavaRuleUtil.isReferenceToSameVar(arrayAccess.getQualifier(), arrayVar); + && JavaAstUtils.isReferenceToSameVar(arrayAccess.getQualifier(), arrayVar); } private boolean isListGetIndex(ASTNamedReferenceExpr usage, ASTNamedReferenceExpr listVar) { return usage.getParent() instanceof ASTArgumentList && LIST_GET.matchesCall(usage.getParent().getParent()) - && JavaRuleUtil.isReferenceToSameVar(((ASTMethodCall) usage.getParent().getParent()).getQualifier(), listVar); + && JavaAstUtils.isReferenceToSameVar(((ASTMethodCall) usage.getParent().getParent()).getQualifier(), listVar); } @@ -231,7 +231,7 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRulechainRule { OccurrenceMatcher getMatcher) { for (ASTNamedReferenceExpr usage : index.getLocalUsages()) { - ASTExpression toplevel = JavaRuleUtil.getTopLevelExpr(usage); + ASTExpression toplevel = JavaAstUtils.getTopLevelExpr(usage); boolean isInUpdateOrCond = loop.getUpdate() == toplevel.getParent() || loop.getCondition() == toplevel; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MethodReturnsInternalArrayRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MethodReturnsInternalArrayRule.java index 692b073e81..496756de0a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MethodReturnsInternalArrayRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MethodReturnsInternalArrayRule.java @@ -17,8 +17,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; @@ -44,7 +44,7 @@ public class MethodReturnsInternalArrayRule extends AbstractJavaRulechainRule { if (expr instanceof ASTNamedReferenceExpr) { ASTNamedReferenceExpr reference = (ASTNamedReferenceExpr) expr; - if (JavaRuleUtil.isRefToFieldOfThisInstance(reference)) { + if (JavaAstUtils.isRefToFieldOfThisInstance(reference)) { addViolation(data, returnStmt, reference.getName()); } else { // considers static, non-final fields @@ -87,7 +87,7 @@ public class MethodReturnsInternalArrayRule extends AbstractJavaRulechainRule { // new int[0] ASTArrayTypeDim lastChild = ((ASTArrayAllocation) expr).getTypeNode().getDimensions().getLastChild(); if (lastChild instanceof ASTArrayDimExpr) { - return JavaRuleUtil.isLiteralInt(((ASTArrayDimExpr) lastChild).getLengthExpression(), 0); + return JavaAstUtils.isLiteralInt(((ASTArrayDimExpr) lastChild).getLengthExpression(), 0); } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PreserveStackTraceRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PreserveStackTraceRule.java index da585d0436..e79e3c7dfd 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PreserveStackTraceRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PreserveStackTraceRule.java @@ -26,6 +26,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.InvocationNode; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; @@ -82,7 +83,7 @@ public class PreserveStackTraceRule extends AbstractJavaRulechainRule { } else if (expr instanceof ASTCastExpression) { - ASTExpression innermost = JavaRuleUtil.peelCasts(expr); + ASTExpression innermost = JavaAstUtils.peelCasts(expr); return exprConsumesException(exceptionParam, innermost, mayBeSelf); } else if (expr instanceof ASTConditionalExpression) { @@ -121,7 +122,7 @@ public class PreserveStackTraceRule extends AbstractJavaRulechainRule { return true; } - if (JavaRuleUtil.followingCallChain(usage).any(it -> consumesExceptionNonRecursive(exceptionParam, it))) { + if (JavaAstUtils.followingCallChain(usage).any(it -> consumesExceptionNonRecursive(exceptionParam, it))) { return true; } } @@ -135,12 +136,12 @@ public class PreserveStackTraceRule extends AbstractJavaRulechainRule { private boolean assignmentRhsConsumesException(ASTVariableDeclaratorId exceptionParam, ASTVariableDeclaratorId lhsVariable, ASTNamedReferenceExpr usage) { if (usage.getIndexInParent() == 0) { - ASTExpression assignmentRhs = JavaRuleUtil.getOtherOperandIfInAssignmentExpr(usage); + ASTExpression assignmentRhs = JavaAstUtils.getOtherOperandIfInAssignmentExpr(usage); boolean rhsIsSelfReferential = NodeStream.of(assignmentRhs) .descendantsOrSelf() .filterIs(ASTVariableAccess.class) - .any(it -> JavaRuleUtil.isReferenceToVar(it, lhsVariable.getSymbol())); + .any(it -> JavaAstUtils.isReferenceToVar(it, lhsVariable.getSymbol())); return !rhsIsSelfReferential && exprConsumesException(exceptionParam, assignmentRhs, true); } return false; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/SimplifiableTestAssertionRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/SimplifiableTestAssertionRule.java index 0685338b75..64c6c60af9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/SimplifiableTestAssertionRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/SimplifiableTestAssertionRule.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; -import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isBooleanLiteral; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isBooleanLiteral; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -18,8 +18,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.rule.internal.TestFrameworksUtil; import net.sourceforge.pmd.lang.java.types.InvocationMatcher; import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind; @@ -47,8 +47,8 @@ public class SimplifiableTestAssertionRule extends AbstractJavaRulechainRule { if (eq != null) { boolean isPositive = isPositiveEqualityExpr(eq) == isAssertTrue; final String suggestion; - if (JavaRuleUtil.isNullLiteral(eq.getLeftOperand()) - || JavaRuleUtil.isNullLiteral(eq.getRightOperand())) { + if (JavaAstUtils.isNullLiteral(eq.getLeftOperand()) + || JavaAstUtils.isNullLiteral(eq.getRightOperand())) { // use assertNull/assertNonNull suggestion = isPositive ? "assertNull" : "assertNonNull"; } else { @@ -140,7 +140,7 @@ public class SimplifiableTestAssertionRule extends AbstractJavaRulechainRule { } private static ASTExpression getNegatedExprOperand(ASTExpression node) { - if (JavaRuleUtil.isBooleanNegation(node)) { + if (JavaAstUtils.isBooleanNegation(node)) { return ((ASTUnaryExpression) node).getOperand(); } return null; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java index a0d1b3e114..4c4aabe101 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java @@ -13,6 +13,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; import net.sourceforge.pmd.lang.java.ast.JModifier; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -50,7 +51,7 @@ public class UnusedFormalParameterRule extends AbstractJavaRulechainRule { private void check(ASTMethodOrConstructorDeclaration node, Object data) { for (ASTFormalParameter formal : node.getFormalParameters()) { ASTVariableDeclaratorId varId = formal.getVarId(); - if (JavaRuleUtil.isNeverUsed(varId) && !JavaRuleUtil.isExplicitUnusedVarName(varId.getName())) { + if (JavaAstUtils.isNeverUsed(varId) && !JavaRuleUtil.isExplicitUnusedVarName(varId.getName())) { addViolation(data, varId, new Object[] { node instanceof ASTMethodDeclaration ? "method" : "constructor", varId.getName(), }); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedLocalVariableRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedLocalVariableRule.java index 85934e797d..6fe8bf4d16 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedLocalVariableRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedLocalVariableRule.java @@ -8,6 +8,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.rule.RuleTargetSelector; @@ -22,7 +23,7 @@ public class UnusedLocalVariableRule extends AbstractJavaRule { @Override public Object visit(ASTLocalVariableDeclaration decl, Object data) { for (ASTVariableDeclaratorId varId : decl.getVarIds()) { - if (JavaRuleUtil.isNeverUsed(varId) + if (JavaAstUtils.isNeverUsed(varId) && !JavaRuleUtil.isExplicitUnusedVarName(varId.getName())) { addViolation(data, varId, varId.getName()); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedPrivateFieldRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedPrivateFieldRule.java index 7cba5376a1..5bad783f79 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedPrivateFieldRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedPrivateFieldRule.java @@ -14,6 +14,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaPropertyUtil; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; @@ -48,14 +49,14 @@ public class UnusedPrivateFieldRule extends AbstractJavaRulechainRule { public Object visitJavaNode(JavaNode node, Object data) { if (node instanceof ASTAnyTypeDeclaration) { ASTAnyTypeDeclaration type = (ASTAnyTypeDeclaration) node; - if (JavaRuleUtil.hasAnyAnnotation(type, INVALIDATING_CLASS_ANNOT)) { + if (JavaAstUtils.hasAnyAnnotation(type, INVALIDATING_CLASS_ANNOT)) { return null; } for (ASTFieldDeclaration field : type.getDeclarations().filterIs(ASTFieldDeclaration.class)) { if (!isIgnored(field)) { for (ASTVariableDeclaratorId varId : field.getVarIds()) { - if (JavaRuleUtil.isNeverUsed(varId)) { + if (JavaAstUtils.isNeverUsed(varId)) { addViolation(data, varId, varId.getName()); } } @@ -69,7 +70,7 @@ public class UnusedPrivateFieldRule extends AbstractJavaRulechainRule { return field.getVisibility() != Visibility.V_PRIVATE || JavaRuleUtil.isSerialPersistentFields(field) || JavaRuleUtil.isSerialVersionUID(field) - || JavaRuleUtil.hasAnyAnnotation(field, getProperty(IGNORED_FIELD_ANNOTATIONS)); + || JavaAstUtils.hasAnyAnnotation(field, getProperty(IGNORED_FIELD_ANNOTATIONS)); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseTryWithResourcesRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseTryWithResourcesRule.java index 380a6716f8..2c77c5890b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseTryWithResourcesRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseTryWithResourcesRule.java @@ -13,8 +13,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTFinallyClause; import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; import net.sourceforge.pmd.lang.java.ast.ASTTypeExpression; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; 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; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -45,7 +45,7 @@ public final class UseTryWithResourcesRule extends AbstractJavaRulechainRule { ASTExpression closeTarget = method.getQualifier(); if (!(closeTarget instanceof ASTTypeExpression) // ignore static method calls && TypeTestUtil.isA(AutoCloseable.class, closeTarget) - && (isJava9OrLater || JavaRuleUtil.isReferenceToLocal(closeTarget)) + && (isJava9OrLater || JavaAstUtils.isReferenceToLocal(closeTarget)) || hasAutoClosableArguments(method)) { addViolation(data, node); break; // only report the first closeable diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldDeclarationsShouldBeAtStartOfClassRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldDeclarationsShouldBeAtStartOfClassRule.java index 73358bdd17..faa68c07f0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldDeclarationsShouldBeAtStartOfClassRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldDeclarationsShouldBeAtStartOfClassRule.java @@ -15,8 +15,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTInitializer; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -87,7 +87,7 @@ public class FieldDeclarationsShouldBeAtStartOfClassRule extends AbstractJavaRul private boolean isInitializerOk(ASTFieldDeclaration fieldDeclaration) { if (getProperty(IGNORE_ANONYMOUS_CLASS_DECLARATIONS) && fieldDeclaration.getVarIds().count() == 1) { ASTExpression initializer = fieldDeclaration.getVarIds().firstOrThrow().getInitializer(); - return JavaRuleUtil.isAnonymousClassCreation(initializer); + return JavaAstUtils.isAnonymousClassCreation(initializer); } return false; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/IdenticalCatchBranchesRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/IdenticalCatchBranchesRule.java index cd4e60a876..75d476bf93 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/IdenticalCatchBranchesRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/IdenticalCatchBranchesRule.java @@ -11,9 +11,9 @@ import java.util.Set; import net.sourceforge.pmd.lang.java.ast.ASTCatchClause; import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; /** @@ -33,7 +33,7 @@ public class IdenticalCatchBranchesRule extends AbstractJavaRulechainRule { String e1Name = st1.getParameter().getName(); String e2Name = st2.getParameter().getName(); - return JavaRuleUtil.tokenEquals(st1.getBody(), st2.getBody(), name -> name.equals(e1Name) ? e2Name : name); + return JavaAstUtils.tokenEquals(st1.getBody(), st2.getBody(), name -> name.equals(e1Name) ? e2Name : name); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/PrematureDeclarationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/PrematureDeclarationRule.java index edc05e1d4c..54496473c4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/PrematureDeclarationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/PrematureDeclarationRule.java @@ -21,6 +21,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTStatement; import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; @@ -58,7 +59,7 @@ public class PrematureDeclarationRule extends AbstractJavaRulechainRule { for (ASTVariableDeclaratorId id : node) { ASTExpression initializer = id.getInitializer(); - if (JavaRuleUtil.isNeverUsed(id) // avoid the duplicate with unused variables + if (JavaAstUtils.isNeverUsed(id) // avoid the duplicate with unused variables || cannotBeMoved(initializer) || JavaRuleUtil.hasSideEffect(initializer, emptySet())) { continue; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryCastRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryCastRule.java index 4773e620c5..6cad24aebc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryCastRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryCastRule.java @@ -29,9 +29,9 @@ import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodReference; import net.sourceforge.pmd.lang.java.ast.BinaryOp; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.types.JTypeMirror; import net.sourceforge.pmd.lang.java.types.TypeConversion; import net.sourceforge.pmd.lang.java.types.TypeOps; @@ -157,7 +157,7 @@ public class UnnecessaryCastRule extends AbstractJavaRulechainRule { } else if (context.hasKind(ExprContextKind.STRING) && isInfixExprWithOperator(castExpr.getParent(), ADD)) { // inside string concatenation - return !TypeTestUtil.isA(String.class, JavaRuleUtil.getOtherOperandIfInInfixExpr(castExpr)) + return !TypeTestUtil.isA(String.class, JavaAstUtils.getOtherOperandIfInInfixExpr(castExpr)) && !TypeTestUtil.isA(String.class, operandType); } else if (context.hasKind(ExprContextKind.NUMERIC) && castExpr.getParent() instanceof ASTInfixExpression) { @@ -170,7 +170,7 @@ public class UnnecessaryCastRule extends AbstractJavaRulechainRule { return castExpr == parent.getLeftOperand() && !TypeOps.isStrictSubtype(operandType.unbox(), operandType.getTypeSystem().INT); } else if (isInfixExprWithOperator(parent, BINARY_PROMOTED_OPS)) { - ASTExpression otherOperand = JavaRuleUtil.getOtherOperandIfInInfixExpr(castExpr); + ASTExpression otherOperand = JavaAstUtils.getOtherOperandIfInInfixExpr(castExpr); JTypeMirror otherType = otherOperand.getTypeMirror(); // Ie, the type that is taken by the binary promotion diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryReturnRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryReturnRule.java index 74110e7693..9b9f98b405 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryReturnRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryReturnRule.java @@ -19,8 +19,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression; import net.sourceforge.pmd.lang.java.ast.ASTSwitchFallthroughBranch; import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; public class UnnecessaryReturnRule extends AbstractJavaRulechainRule { @@ -63,11 +63,11 @@ public class UnnecessaryReturnRule extends AbstractJavaRulechainRule { // test is in the test file. JavaNode parent = it.getParent(); - if (JavaRuleUtil.isLastChild(it)) { + if (JavaAstUtils.isLastChild(it)) { if (parent instanceof ASTSwitchArrowBranch) { return !isBranchOfSwitchExpr((ASTSwitchBranch) parent); } else if (parent instanceof ASTSwitchFallthroughBranch) { - return JavaRuleUtil.isLastChild(parent) && !isBranchOfSwitchExpr((ASTSwitchBranch) parent); + return JavaAstUtils.isLastChild(parent) && !isBranchOfSwitchExpr((ASTSwitchBranch) parent); } else { return !(parent instanceof ASTLoopStatement); // returns break the loop so are not unnecessary (though it could be replaced by break) } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java index 7e4c211046..cdeab9b9b7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java @@ -20,12 +20,12 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; import net.sourceforge.pmd.lang.java.ast.JModifier; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass.AssignmentEntry; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass.DataflowResult; import net.sourceforge.pmd.lang.java.rule.internal.JavaPropertyUtil; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.util.CollectionUtil; @@ -58,9 +58,9 @@ public class ImmutableFieldRule extends AbstractJavaRulechainRule { ASTAnyTypeDeclaration enclosingType = field.getEnclosingType(); if (field.getEffectiveVisibility().isAtMost(Visibility.V_PRIVATE) && !field.getModifiers().hasAny(JModifier.VOLATILE, JModifier.STATIC, JModifier.FINAL) - && !JavaRuleUtil.hasAnyAnnotation(field, INVALIDATING_FIELD_ANNOTS) - && !JavaRuleUtil.hasAnyAnnotation(enclosingType, INVALIDATING_CLASS_ANNOT) - && !JavaRuleUtil.hasAnyAnnotation(field, getProperty(IGNORED_ANNOTS))) { + && !JavaAstUtils.hasAnyAnnotation(field, INVALIDATING_FIELD_ANNOTS) + && !JavaAstUtils.hasAnyAnnotation(enclosingType, INVALIDATING_CLASS_ANNOT) + && !JavaAstUtils.hasAnyAnnotation(field, getProperty(IGNORED_ANNOTS))) { DataflowResult dataflow = DataflowPass.getDataflowResult(field.getRoot()); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java index 93a9b4d937..fa100cfbc0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java @@ -6,12 +6,12 @@ package net.sourceforge.pmd.lang.java.rule.design; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.INSTANCEOF; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.isInfixExprWithOperator; -import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isArrayLengthFieldAccess; -import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isCallOnThisInstance; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isArrayLengthFieldAccess; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isCallOnThisInstance; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isRefToFieldOfThisClass; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isThisOrSuper; import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isGetterCall; import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isNullChecked; -import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isRefToFieldOfThisClass; -import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isThisOrSuper; import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; import java.util.LinkedHashMap; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanReturnsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanReturnsRule.java index d4b9628987..24f4bb9f11 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanReturnsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanReturnsRule.java @@ -14,8 +14,8 @@ import static net.sourceforge.pmd.lang.java.ast.BinaryOp.LT; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.NE; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.isInfixExprWithOperator; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.opsWithGreaterPrecedence; -import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.areComplements; -import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isBooleanLiteral; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.areComplements; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isBooleanLiteral; import java.util.EnumSet; import java.util.Set; @@ -33,8 +33,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind; public class SimplifyBooleanReturnsRule extends AbstractJavaRulechainRule { @@ -157,7 +157,7 @@ public class SimplifyBooleanReturnsRule extends AbstractJavaRulechainRule { // == -> != || isInfixExprWithOperator(e, NEGATABLE_OPS) // !! -> - || JavaRuleUtil.isBooleanNegation(e)) { + || JavaAstUtils.isBooleanNegation(e)) { return false; } else if (isInfixExprWithOperator(e, CONDITIONAL_OR) || isInfixExprWithOperator(e, CONDITIONAL_AND)) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java index a5312867cf..e465af2da8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java @@ -9,8 +9,8 @@ import static net.sourceforge.pmd.lang.java.ast.BinaryOp.CONDITIONAL_OR; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.INSTANCEOF; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.NE; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.isInfixExprWithOperator; -import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.getOtherOperandIfInInfixExpr; -import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isBooleanNegation; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.getOtherOperandIfInInfixExpr; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isBooleanNegation; import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isNullCheck; import net.sourceforge.pmd.lang.java.ast.ASTExpression; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java index c386d8e357..542602f76c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java @@ -25,12 +25,12 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass.DataflowResult; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass.ReachingDefinitionSet; import net.sourceforge.pmd.lang.java.rule.internal.JavaPropertyUtil; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -73,14 +73,14 @@ public class SingularFieldRule extends AbstractJavaRulechainRule { @Override public Object visitJavaNode(JavaNode node, Object data) { ASTAnyTypeDeclaration enclosingType = (ASTAnyTypeDeclaration) node; - if (JavaRuleUtil.hasAnyAnnotation(enclosingType, INVALIDATING_CLASS_ANNOT)) { + if (JavaAstUtils.hasAnyAnnotation(enclosingType, INVALIDATING_CLASS_ANNOT)) { return null; } DataflowResult dataflow = null; for (ASTFieldDeclaration fieldDecl : enclosingType.getDeclarations(ASTFieldDeclaration.class)) { if (!mayBeSingular(fieldDecl) - || JavaRuleUtil.hasAnyAnnotation(fieldDecl, getProperty(IGNORED_FIELD_ANNOTATIONS))) { + || JavaAstUtils.hasAnyAnnotation(fieldDecl, getProperty(IGNORED_FIELD_ANNOTATIONS))) { continue; } for (ASTVariableDeclaratorId varId : fieldDecl.getVarIds()) { @@ -101,7 +101,7 @@ public class SingularFieldRule extends AbstractJavaRulechainRule { } private boolean isSingularField(ASTAnyTypeDeclaration fieldOwner, ASTVariableDeclaratorId varId, DataflowResult dataflow) { - if (JavaRuleUtil.isNeverUsed(varId)) { + if (JavaAstUtils.isNeverUsed(varId)) { return false; // don't report unused field } @@ -109,7 +109,7 @@ public class SingularFieldRule extends AbstractJavaRulechainRule { //They're valid if they don't escape the scope of their method, eg by being in a nested class or lambda Map> usagesByScope = new HashMap<>(); for (ASTNamedReferenceExpr usage : varId.getLocalUsages()) { - if (usage.getEnclosingType() != fieldOwner || !JavaRuleUtil.isThisFieldAccess(usage)) { + if (usage.getEnclosingType() != fieldOwner || !JavaAstUtils.isThisFieldAccess(usage)) { return false; // give up } ASTBodyDeclaration enclosing = getEnclosingBodyDecl(fieldOwner, usage); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java index 3238515b0f..69bb0b3468 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java @@ -18,8 +18,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMemberValuePair; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; 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 UseUtilityClassRule extends AbstractJavaRulechainRule { @@ -35,7 +35,7 @@ public class UseUtilityClassRule extends AbstractJavaRulechainRule { @Override public Object visit(ASTClassOrInterfaceDeclaration klass, Object data) { - if (JavaRuleUtil.hasAnyAnnotation(klass, IGNORED_CLASS_ANNOT) + if (JavaAstUtils.hasAnyAnnotation(klass, IGNORED_CLASS_ANNOT) || TypeTestUtil.isA("junit.framework.TestSuite", klass) // suite method is ok || klass.isInterface() || klass.isAbstract() diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UselessOverridingMethodRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UselessOverridingMethodRule.java index 8c6dbf41b7..cd764b2d86 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UselessOverridingMethodRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UselessOverridingMethodRule.java @@ -20,8 +20,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.ast.ASTStatement; import net.sourceforge.pmd.lang.java.ast.ASTSuperExpression; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JExecutableSymbol; import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol; import net.sourceforge.pmd.lang.java.types.OverloadSelectionResult; @@ -53,7 +53,7 @@ public class UselessOverridingMethodRule extends AbstractJavaRulechainRule { // We can also skip the 'clone' method as they are generally // 'useless' but as it is considered a 'good practice' to // implement them anyway ( see bug 1522517) - || JavaRuleUtil.isCloneMethod(node)) { + || JavaAstUtils.isCloneMethod(node)) { return null; } @@ -78,7 +78,7 @@ public class UselessOverridingMethodRule extends AbstractJavaRulechainRule { if (methodCall.getQualifier() instanceof ASTSuperExpression && methodCall.getArguments().size() == node.getArity() // might be disambiguating: Interface.super.foo() - && JavaRuleUtil.isUnqualifiedSuper(methodCall.getQualifier())) { + && JavaAstUtils.isUnqualifiedSuper(methodCall.getQualifier())) { OverloadSelectionResult overload = methodCall.getOverloadSelectionInfo(); if (!overload.isFailed() @@ -97,7 +97,7 @@ public class UselessOverridingMethodRule extends AbstractJavaRulechainRule { ASTArgumentList arg = methodCall.getArguments(); int i = 0; for (ASTFormalParameter formal : node.getFormalParameters()) { - if (!JavaRuleUtil.isReferenceToVar(arg.getChild(i), formal.getVarId().getSymbol())) { + if (!JavaAstUtils.isReferenceToVar(arg.getChild(i), formal.getVarId().getSymbol())) { return false; } i++; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AssignmentInOperandRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AssignmentInOperandRule.java index 459eb99466..c59a86ce1a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AssignmentInOperandRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AssignmentInOperandRule.java @@ -15,8 +15,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertySource; @@ -69,7 +69,7 @@ public class AssignmentInOperandRule extends AbstractJavaRulechainRule { } private void checkAssignment(ASTExpression impureExpr, RuleContext ctx) { - ASTExpression toplevel = JavaRuleUtil.getTopLevelExpr(impureExpr); + ASTExpression toplevel = JavaAstUtils.getTopLevelExpr(impureExpr); JavaNode parent = toplevel.getParent(); if (parent instanceof ASTExpressionStatement) { // that's ok diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BrokenNullCheckRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BrokenNullCheckRule.java index 237154dd30..d11a28d370 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BrokenNullCheckRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/BrokenNullCheckRule.java @@ -11,8 +11,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.QualifiableExpression; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.rule.internal.StablePathMatcher; public class BrokenNullCheckRule extends AbstractJavaRulechainRule { @@ -46,7 +46,7 @@ public class BrokenNullCheckRule extends AbstractJavaRulechainRule { return; } - ASTExpression otherChild = JavaRuleUtil.getOtherOperandIfInInfixExpr(nullLit); + ASTExpression otherChild = JavaAstUtils.getOtherOperandIfInInfixExpr(nullLit); StablePathMatcher pathToNullVar = StablePathMatcher.matching(otherChild); if (pathToNullVar == null) { // cannot be matched, because it's not stable diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloneMethodMustImplementCloneableRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloneMethodMustImplementCloneableRule.java index e58eea9a7e..103dec3703 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloneMethodMustImplementCloneableRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloneMethodMustImplementCloneableRule.java @@ -9,8 +9,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTBlock; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; 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; /** @@ -30,7 +30,7 @@ public class CloneMethodMustImplementCloneableRule extends AbstractJavaRulechain @Override public Object visit(final ASTMethodDeclaration node, final Object data) { - if (!JavaRuleUtil.isCloneMethod(node)) { + if (!JavaAstUtils.isCloneMethod(node)) { return data; } ASTBlock body = node.getBody(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java index 10d57663bb..c67cde6a40 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java @@ -46,6 +46,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.TypeNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; @@ -339,7 +340,7 @@ public class CloseResourceRule extends AbstractJavaRule { for (ASTFormalParameter param : methodParams) { if ((isResourceTypeOrSubtype(param) || wrappedVarName.getParent() instanceof ASTVariableDeclarator || wrappedVarName.getParent() instanceof ASTAssignmentExpression) - && JavaRuleUtil.isReferenceToVar(wrappedVarName, param.getVarId().getSymbol())) { + && JavaAstUtils.isReferenceToVar(wrappedVarName, param.getVarId().getSymbol())) { return true; } } @@ -494,7 +495,7 @@ public class CloseResourceRule extends AbstractJavaRule { List usedVars = getResourcesSpecifiedInTryWith(tryWithResource); for (ASTVariableAccess res : usedVars) { - if (JavaRuleUtil.isReferenceToVar(res, varId.getSymbol())) { + if (JavaAstUtils.isReferenceToVar(res, varId.getSymbol())) { return true; } } @@ -530,7 +531,7 @@ public class CloseResourceRule extends AbstractJavaRule { private boolean isMethodCallOnVariable(ASTExpression expr, ASTVariableDeclaratorId variable) { if (expr instanceof ASTMethodCall) { ASTMethodCall methodCall = (ASTMethodCall) expr; - return JavaRuleUtil.isReferenceToVar(methodCall.getQualifier(), variable.getSymbol()); + return JavaAstUtils.isReferenceToVar(methodCall.getQualifier(), variable.getSymbol()); } return false; } @@ -558,8 +559,8 @@ public class CloseResourceRule extends AbstractJavaRule { ASTExpression left = equalityExpr.getLeftOperand(); ASTExpression right = equalityExpr.getRightOperand(); - if (JavaRuleUtil.isReferenceToVar(left, var.getSymbol()) && isNullLiteral(right) - || JavaRuleUtil.isReferenceToVar(right, var.getSymbol()) && isNullLiteral(left)) { + if (JavaAstUtils.isReferenceToVar(left, var.getSymbol()) && isNullLiteral(right) + || JavaAstUtils.isReferenceToVar(right, var.getSymbol()) && isNullLiteral(left)) { return true; } } @@ -575,7 +576,7 @@ public class CloseResourceRule extends AbstractJavaRule { InvocationMatcher matcher = InvocationMatcher.parse("java.util.Objects#nonNull(_)"); if (matcher.matchesCall(expression)) { ASTMethodCall methodCall = (ASTMethodCall) expression; - return JavaRuleUtil.isReferenceToVar(methodCall.getArguments().get(0), var.getSymbol()); + return JavaAstUtils.isReferenceToVar(methodCall.getArguments().get(0), var.getSymbol()); } return false; @@ -648,7 +649,7 @@ public class CloseResourceRule extends AbstractJavaRule { .descendants(ASTReturnStatement.class).crossFindBoundaries() .descendants(ASTVariableAccess.class) .filter(access -> !(access.getParent() instanceof ASTMethodCall)) - .filter(access -> JavaRuleUtil.isReferenceToVar(access, variable.getSymbol())) + .filter(access -> JavaAstUtils.isReferenceToVar(access, variable.getSymbol())) .nonEmpty(); } @@ -729,7 +730,7 @@ public class CloseResourceRule extends AbstractJavaRule { private boolean isNotSelfAssignment(ASTAssignmentExpression assignment) { return assignment.getRightOperand().descendantsOrSelf().filterIs(ASTVariableAccess.class).filter(access -> { - return JavaRuleUtil.isReferenceToSameVar(access, assignment.getLeftOperand()); + return JavaAstUtils.isReferenceToSameVar(access, assignment.getLeftOperand()); }).isEmpty(); } @@ -762,6 +763,6 @@ public class CloseResourceRule extends AbstractJavaRule { } ASTAssignmentExpression assignment = (ASTAssignmentExpression) statement.getExpr(); - return JavaRuleUtil.isReferenceToVar(assignment.getLeftOperand(), variable.getSymbol()); + return JavaAstUtils.isReferenceToVar(assignment.getLeftOperand(), variable.getSymbol()); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConstructorCallsOverridableMethodRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConstructorCallsOverridableMethodRule.java index be9137dfc1..6858631354 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConstructorCallsOverridableMethodRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConstructorCallsOverridableMethodRule.java @@ -17,9 +17,9 @@ import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JExecutableSymbol; import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol; import net.sourceforge.pmd.lang.java.types.JMethodSig; @@ -133,7 +133,7 @@ public final class ConstructorCallsOverridableMethodRule extends AbstractJavaRul private static boolean isCallOnThisInstance(ASTMethodCall call) { ASTExpression qualifier = call.getQualifier(); - return qualifier == null || JavaRuleUtil.isUnqualifiedThis(qualifier); + return qualifier == null || JavaAstUtils.isUnqualifiedThis(qualifier); } private static boolean isOverridable(JExecutableSymbol method) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/IdempotentOperationsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/IdempotentOperationsRule.java index 8909e215bb..99bec16148 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/IdempotentOperationsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/IdempotentOperationsRule.java @@ -6,8 +6,8 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression; import net.sourceforge.pmd.lang.java.ast.AssignmentOp; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; public class IdempotentOperationsRule extends AbstractJavaRulechainRule { @@ -18,7 +18,7 @@ public class IdempotentOperationsRule extends AbstractJavaRulechainRule { @Override public Object visit(ASTAssignmentExpression node, Object data) { if (node.getOperator() == AssignmentOp.ASSIGN - && JavaRuleUtil.isReferenceToSameVar(node.getLeftOperand(), node.getRightOperand())) { + && JavaAstUtils.isReferenceToSameVar(node.getLeftOperand(), node.getRightOperand())) { addViolation(data, node); } return null; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidLogMessageFormatRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidLogMessageFormatRule.java index dc74dea8b2..6ca1ca428e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidLogMessageFormatRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/InvalidLogMessageFormatRule.java @@ -19,12 +19,12 @@ import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass.AssignmentEntry; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass.DataflowResult; import net.sourceforge.pmd.lang.java.rule.internal.DataflowPass.ReachingDefinitionSet; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; import net.sourceforge.pmd.util.CollectionUtil; @@ -72,7 +72,7 @@ public class InvalidLogMessageFormatRule extends AbstractJavaRulechainRule { int providedArguments = args.size() - (messageParam.getIndexInParent() + 1); - if (providedArguments == 1 && JavaRuleUtil.isArrayInitializer(args.getLastChild())) { + if (providedArguments == 1 && JavaAstUtils.isArrayInitializer(args.getLastChild())) { providedArguments = ((ASTArrayAllocation) args.getLastChild()).getArrayInitializer().length(); } else if (TypeTestUtil.isA(Throwable.class, args.getLastChild()) && providedArguments > expectedArguments) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ProperCloneImplementationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ProperCloneImplementationRule.java index 0fd9e1cead..700fd33e28 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ProperCloneImplementationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ProperCloneImplementationRule.java @@ -11,8 +11,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.JModifier; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; public class ProperCloneImplementationRule extends AbstractJavaRulechainRule { @@ -23,7 +23,7 @@ public class ProperCloneImplementationRule extends AbstractJavaRulechainRule { @Override public Object visit(ASTMethodDeclaration method, Object data) { - if (JavaRuleUtil.isCloneMethod(method) && !method.isAbstract()) { + if (JavaAstUtils.isCloneMethod(method) && !method.isAbstract()) { ASTAnyTypeDeclaration enclosingType = method.getEnclosingType(); if (isNotFinal(enclosingType) && hasAnyAllocationOfClass(method, enclosingType)) { addViolation(data, method); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/SingletonClassReturningNewInstanceRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/SingletonClassReturningNewInstanceRule.java index 0ef09faa5e..7975519f17 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/SingletonClassReturningNewInstanceRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/SingletonClassReturningNewInstanceRule.java @@ -10,8 +10,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; public class SingletonClassReturningNewInstanceRule extends AbstractJavaRulechainRule { @@ -37,6 +37,6 @@ public class SingletonClassReturningNewInstanceRule extends AbstractJavaRulechai } private boolean returnsLocalVariables(NodeStream returns) { - return returns.children(ASTVariableAccess.class).filter(JavaRuleUtil::isReferenceToLocal).nonEmpty(); + return returns.children(ASTVariableAccess.class).filter(JavaAstUtils::isReferenceToLocal).nonEmpty(); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/DataflowPass.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/DataflowPass.java index f78ef363d9..c5c070249a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/DataflowPass.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/DataflowPass.java @@ -78,6 +78,7 @@ import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; import net.sourceforge.pmd.lang.java.ast.QualifiableExpression; import net.sourceforge.pmd.lang.java.ast.TypeNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.bestpractices.UnusedAssignmentRule; import net.sourceforge.pmd.lang.java.rule.design.SingularFieldRule; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; @@ -877,7 +878,7 @@ public final class DataflowPass { private boolean isRelevantField(ASTExpression lhs) { return lhs instanceof ASTNamedReferenceExpr - && (trackThisInstance() && JavaRuleUtil.isThisFieldAccess(lhs) + && (trackThisInstance() && JavaAstUtils.isThisFieldAccess(lhs) || trackStaticFields() && isStaticFieldOfThisClass(((ASTNamedReferenceExpr) lhs).getReferencedSym())); } 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 9c89da1100..0513eb29ca 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,64 +10,27 @@ import static net.sourceforge.pmd.util.CollectionUtil.immutableSetOf; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectStreamField; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import net.sourceforge.pmd.lang.ast.GenericToken; -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.ast.NodeStream; -import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTArgumentList; import net.sourceforge.pmd.lang.java.ast.ASTArrayAccess; -import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr; 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.ASTBodyDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral; -import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement; -import net.sourceforge.pmd.lang.java.ast.ASTCastExpression; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTExpression; -import net.sourceforge.pmd.lang.java.ast.ASTExpressionStatement; -import net.sourceforge.pmd.lang.java.ast.ASTFieldAccess; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTForStatement; -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters; import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTInitializer; -import net.sourceforge.pmd.lang.java.ast.ASTLabeledStatement; -import net.sourceforge.pmd.lang.java.ast.ASTList; -import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement; import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral; -import net.sourceforge.pmd.lang.java.ast.ASTNumericLiteral; -import net.sourceforge.pmd.lang.java.ast.ASTStatement; -import net.sourceforge.pmd.lang.java.ast.ASTSuperExpression; -import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; -import net.sourceforge.pmd.lang.java.ast.ASTThisExpression; import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; -import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; @@ -75,21 +38,12 @@ import net.sourceforge.pmd.lang.java.ast.Annotatable; import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.JModifier; import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.ast.JavaTokenKinds; -import net.sourceforge.pmd.lang.java.ast.QualifiableExpression; 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.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; -import net.sourceforge.pmd.lang.java.symbols.internal.ast.AstLocalVarSym; import net.sourceforge.pmd.lang.java.types.InvocationMatcher; import net.sourceforge.pmd.lang.java.types.InvocationMatcher.CompoundInvocationMatcher; -import net.sourceforge.pmd.lang.java.types.JMethodSig; -import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind; -import net.sourceforge.pmd.lang.java.types.JTypeMirror; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; -import net.sourceforge.pmd.util.CollectionUtil; -import net.sourceforge.pmd.util.OptionalBool; /** * Utilities shared between rules. @@ -168,49 +122,12 @@ public final class JavaRuleUtil { return false; } - return isLiteralInt(comparand, expectedValue); + return JavaAstUtils.isLiteralInt(comparand, expectedValue); } return false; } - /** - * Returns true if this is a numeric literal with the given int value. - * This also considers long literals. - */ - public static boolean isLiteralInt(JavaNode e, int value) { - return e instanceof ASTNumericLiteral - && ((ASTNumericLiteral) e).isIntegral() - && ((ASTNumericLiteral) e).getValueAsInt() == value; - } - - /** This is type-aware, so will not pick up on numeric addition. */ - public static boolean isStringConcatExpr(@Nullable JavaNode e) { - if (e instanceof ASTInfixExpression) { - ASTInfixExpression infix = (ASTInfixExpression) e; - return infix.getOperator() == BinaryOp.ADD && TypeTestUtil.isA(String.class, infix); - } - return false; - } - - /** - * If the parameter is an operand of a binary infix expression, - * returns the other operand. Otherwise returns null. - */ - public static @Nullable ASTExpression getOtherOperandIfInInfixExpr(@Nullable JavaNode e) { - if (e != null && e.getParent() instanceof ASTInfixExpression) { - return (ASTExpression) e.getParent().getChild(1 - e.getIndexInParent()); - } - return null; - } - - public static @Nullable ASTExpression getOtherOperandIfInAssignmentExpr(@Nullable JavaNode e) { - if (e != null && e.getParent() instanceof ASTAssignmentExpression) { - return (ASTExpression) e.getParent().getChild(1 - e.getIndexInParent()); - } - return null; - } - /** * Returns true if the expression is a stringbuilder (or stringbuffer) * append call, or a constructor call for one of these classes. @@ -236,15 +153,6 @@ public final class JavaRuleUtil { || TypeTestUtil.isExactlyA(StringBuffer.class, node); } - /** - * Returns true if the node is a {@link ASTMethodDeclaration} that - * is a main method. - */ - public static boolean isMainMethod(JavaNode node) { - return node instanceof ASTMethodDeclaration - && ((ASTMethodDeclaration) node).isMainMethod(); - } - /** * Returns true if the node is a utility class, according to this * custom definition. @@ -269,7 +177,7 @@ public final class JavaRuleUtil { if (declNode instanceof ASTFieldDeclaration || declNode instanceof ASTMethodDeclaration) { - hasAny = isNonPrivate(declNode) && !isMainMethod(declNode); + hasAny = isNonPrivate(declNode) && !JavaAstUtils.isMainMethod(declNode); if (!((AccessNode) declNode).hasModifiers(JModifier.STATIC)) { return false; } @@ -371,13 +279,13 @@ public final class JavaRuleUtil { ASTAnyTypeDeclaration enclosing = node.getEnclosingType(); if (startsWithCamelCaseWord(node.getName(), "get")) { - return hasField(enclosing, node.getName().substring(3)); + return JavaAstUtils.hasField(enclosing, node.getName().substring(3)); } else if (startsWithCamelCaseWord(node.getName(), "is") && TypeTestUtil.isA(boolean.class, node.getResultTypeNode())) { - return hasField(enclosing, node.getName().substring(2)); + return JavaAstUtils.hasField(enclosing, node.getName().substring(2)); } - return hasField(enclosing, node.getName()); + return JavaAstUtils.hasField(enclosing, node.getName()); } /** Attempts to determine if the method is a setter. */ @@ -390,149 +298,10 @@ public final class JavaRuleUtil { ASTAnyTypeDeclaration enclosing = node.getEnclosingType(); if (startsWithCamelCaseWord(node.getName(), "set")) { - return hasField(enclosing, node.getName().substring(3)); + return JavaAstUtils.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; - } - - /** - * Returns true if the formal parameters of the method or constructor - * match the given types exactly. Note that for varargs methods, the - * last param must have an array type (but it is not checked to be varargs). - * This will return false if we're not sure. - * - * @param node Method or ctor - * @param types List of types to match (may be empty) - * - * @throws NullPointerException If any of the classes is null, or the node is null - * @see TypeTestUtil#isExactlyA(Class, TypeNode) - */ - public static boolean hasParameters(ASTMethodOrConstructorDeclaration node, Class... types) { - ASTFormalParameters formals = node.getFormalParameters(); - if (formals.size() != types.length) { - return false; - } - for (int i = 0; i < formals.size(); i++) { - ASTFormalParameter fi = formals.get(i); - if (!TypeTestUtil.isExactlyA(types[i], fi)) { - return false; - } - } - return true; - } - - /** - * Returns true if the {@code throws} declaration of the method or constructor - * matches the given types exactly. - * - * @param node Method or ctor - * @param types List of exception types to match (may be empty) - * - * @throws NullPointerException If any of the classes is null, or the node is null - * @see TypeTestUtil#isExactlyA(Class, TypeNode) - */ - @SafeVarargs - public static boolean hasExceptionList(ASTMethodOrConstructorDeclaration node, Class... types) { - @NonNull List formals = ASTList.orEmpty(node.getThrowsList()); - if (formals.size() != types.length) { - return false; - } - for (int i = 0; i < formals.size(); i++) { - ASTClassOrInterfaceType fi = formals.get(i); - if (!TypeTestUtil.isExactlyA(types[i], fi)) { - return false; - } - } - return true; - } - - /** - * True if the variable is never used. Note that the visibility of - * the variable must be less than {@link Visibility#V_PRIVATE} for - * us to be sure of it. - */ - public static boolean isNeverUsed(ASTVariableDeclaratorId varId) { - return CollectionUtil.none(varId.getLocalUsages(), JavaRuleUtil::isReadUsage); - } - - private static boolean isReadUsage(ASTNamedReferenceExpr expr) { - return expr.getAccessType() == AccessType.READ - // x++ as a method argument or used in other expression - || expr.getParent() instanceof ASTUnaryExpression - && !(expr.getParent().getParent() instanceof ASTExpressionStatement); - } - - /** - * True if the variable is incremented or decremented via a compound - * assignment operator, or a unary increment/decrement expression. - */ - public static boolean isVarAccessReadAndWrite(ASTNamedReferenceExpr expr) { - return expr.getAccessType() == AccessType.WRITE - && (!(expr.getParent() instanceof ASTAssignmentExpression) - || ((ASTAssignmentExpression) expr.getParent()).getOperator().isCompound()); - } - - /** - * True if the variable access is a non-compound assignment. - */ - public static boolean isVarAccessStrictlyWrite(ASTNamedReferenceExpr expr) { - return expr.getParent() instanceof ASTAssignmentExpression - && expr.getIndexInParent() == 0 - && !((ASTAssignmentExpression) expr.getParent()).getOperator().isCompound(); - } - - /** - * Returns the set of labels on this statement. - */ - public static Set getStatementLabels(ASTStatement node) { - if (!(node.getParent() instanceof ASTLabeledStatement)) { - return Collections.emptySet(); - } - - return node.ancestors().takeWhile(it -> it instanceof ASTLabeledStatement) - .toStream() - .map(it -> ((ASTLabeledStatement) it).getLabel()) - .collect(Collectors.toSet()); - } - - public static boolean isAnonymousClassCreation(@Nullable ASTExpression expression) { - return expression instanceof ASTConstructorCall - && ((ASTConstructorCall) expression).isAnonymousClass(); - } - - /** - * Will cut through argument lists, except those of enum constants - * and explicit invocation nodes. - */ - public static @NonNull ASTExpression getTopLevelExpr(ASTExpression expr) { - return (ASTExpression) expr.ancestorsOrSelf() - .takeWhile(it -> it instanceof ASTExpression - || it instanceof ASTArgumentList && it.getParent() instanceof ASTExpression) - .last(); - } - - /** - * Returns the variable IDS corresponding to variables declared in - * the init clause of the loop. - */ - public static NodeStream getLoopVariables(ASTForStatement loop) { - return NodeStream.of(loop.getInit()) - .filterIs(ASTLocalVariableDeclaration.class) - .flatMap(ASTLocalVariableDeclaration::getVarIds); + return JavaAstUtils.hasField(enclosing, node.getName()); } // TODO at least UnusedPrivateMethod has some serialization-related logic. @@ -561,383 +330,8 @@ public final class JavaRuleUtil { public static boolean isSerializationReadObject(ASTMethodDeclaration node) { return node.getVisibility() == Visibility.V_PRIVATE && "readObject".equals(node.getName()) - && hasExceptionList(node, InvalidObjectException.class) - && hasParameters(node, ObjectInputStream.class); - } - - /** - * Whether one expression is the boolean negation of the other. Many - * forms are not yet supported. This method is symmetric so only needs - * to be called once. - */ - public static boolean areComplements(ASTExpression e1, ASTExpression e2) { - if (isBooleanNegation(e1)) { - return areEqual(unaryOperand(e1), e2); - } else if (isBooleanNegation(e2)) { - return areEqual(e1, unaryOperand(e2)); - } else if (e1 instanceof ASTInfixExpression && e2 instanceof ASTInfixExpression) { - ASTInfixExpression ifx1 = (ASTInfixExpression) e1; - ASTInfixExpression ifx2 = (ASTInfixExpression) e2; - if (ifx1.getOperator().getComplement() != ifx2.getOperator()) { - return false; - } - if (ifx1.getOperator().hasSamePrecedenceAs(BinaryOp.EQ)) { - // NOT(a == b, a != b) - // NOT(a == b, b != a) - return areEqual(ifx1.getLeftOperand(), ifx2.getLeftOperand()) - && areEqual(ifx1.getRightOperand(), ifx2.getRightOperand()) - || areEqual(ifx2.getLeftOperand(), ifx1.getLeftOperand()) - && areEqual(ifx2.getRightOperand(), ifx1.getRightOperand()); - } - // todo we could continue with de Morgan and such - } - return false; - } - - private static boolean areEqual(ASTExpression e1, ASTExpression e2) { - return tokenEquals(e1, e2); - } - - /** - * Returns true if both nodes have exactly the same tokens. - * - * @param node First node - * @param that Other node - */ - public static boolean tokenEquals(JavaNode node, JavaNode that) { - return tokenEquals(node, that, null); - } - - /** - * Returns true if both nodes have the same tokens, modulo some renaming - * function. The renaming function maps unqualified variables and type - * identifiers of the first node to the other. This should be used - * in nodes living in the same lexical scope, so that unqualified - * names mean the same thing. - * - * @param node First node - * @param other Other node - * @param varRenamer A renaming function. If null, no renaming is applied. - * Must not return null, if no renaming occurs, returns its argument. - */ - public static boolean tokenEquals(@NonNull JavaNode node, - @NonNull JavaNode other, - @Nullable Function varRenamer) { - // Since type and variable names obscure one another, - // it's ok to use a single renaming function. - - Iterator thisIt = GenericToken.range(node.getFirstToken(), node.getLastToken()); - Iterator thatIt = GenericToken.range(other.getFirstToken(), other.getLastToken()); - int lastKind = 0; - while (thisIt.hasNext()) { - if (!thatIt.hasNext()) { - return false; - } - JavaccToken o1 = thisIt.next(); - JavaccToken o2 = thatIt.next(); - if (o1.kind != o2.kind) { - return false; - } - - String mappedImage = o1.getImage(); - if (varRenamer != null - && o1.kind == JavaTokenKinds.IDENTIFIER - && lastKind != JavaTokenKinds.DOT - && lastKind != JavaTokenKinds.METHOD_REF - //method name - && o1.getNext() != null && o1.getNext().kind != JavaTokenKinds.LPAREN) { - mappedImage = varRenamer.apply(mappedImage); - } - - if (!o2.getImage().equals(mappedImage)) { - return false; - } - - lastKind = o1.kind; - } - return !thatIt.hasNext(); - } - - public static boolean isNullLiteral(ASTExpression node) { - return node instanceof ASTNullLiteral; - } - - - /** Returns true if the node is a boolean literal with any value. */ - public static boolean isBooleanLiteral(JavaNode e) { - return e instanceof ASTBooleanLiteral; - } - - /** Returns true if the node is a boolean literal with the given constant value. */ - public static boolean isBooleanLiteral(JavaNode e, boolean value) { - return e instanceof ASTBooleanLiteral && ((ASTBooleanLiteral) e).isTrue() == value; - } - - public static boolean isBooleanNegation(JavaNode e) { - return e instanceof ASTUnaryExpression && ((ASTUnaryExpression) e).getOperator() == UnaryOp.NEGATION; - } - - /** - * If the argument is a unary expression, returns its operand, otherwise - * returns null. - */ - public static @Nullable ASTExpression unaryOperand(@Nullable ASTExpression e) { - return e instanceof ASTUnaryExpression ? ((ASTUnaryExpression) e).getOperand() - : null; - } - - - /** - * Whether the expression is an access to a field of this instance, - * not inherited, qualified or not ({@code this.field} or just {@code field}). - */ - public static boolean isThisFieldAccess(ASTExpression e) { - if (!(e instanceof ASTNamedReferenceExpr)) { - return false; - } - JVariableSymbol sym = ((ASTNamedReferenceExpr) e).getReferencedSym(); - return sym instanceof JFieldSymbol - && !((JFieldSymbol) sym).isStatic() - // not inherited - && ((JFieldSymbol) sym).getEnclosingClass().equals(e.getEnclosingType().getSymbol()) - // correct syntactic form - && (e instanceof ASTVariableAccess || isSyntacticThisFieldAccess(e)); - } - - /** - * Whether the expression is a {@code this.field}, with no outer - * instance qualifier ({@code Outer.this.field}). The field symbol - * is not checked to resolve to a field declared in this class (it - * may be inherited) - */ - public static boolean isSyntacticThisFieldAccess(ASTExpression e) { - if (e instanceof ASTFieldAccess) { - ASTExpression qualifier = ((ASTFieldAccess) e).getQualifier(); - if (qualifier instanceof ASTThisExpression) { - // unqualified this - return ((ASTThisExpression) qualifier).getQualifier() == null; - } - } - return false; - } - - public static boolean hasAnyAnnotation(Annotatable node, Collection qualifiedNames) { - return qualifiedNames.stream().anyMatch(node::isAnnotationPresent); - } - - - /** - * Returns true if the expression is the default field value for - * the given type. - */ - public static boolean isDefaultValue(JTypeMirror type, ASTExpression expr) { - if (type.isPrimitive()) { - if (type.isPrimitive(PrimitiveTypeKind.BOOLEAN)) { - return expr instanceof ASTBooleanLiteral && !((ASTBooleanLiteral) expr).isTrue(); - } else { - Object constValue = expr.getConstValue(); - return constValue instanceof Number && ((Number) constValue).doubleValue() == 0d - || constValue instanceof Character && constValue.equals('\u0000'); - } - } else { - return expr instanceof ASTNullLiteral; - } - } - - /** - * Returns true if the expression is a {@link ASTNamedReferenceExpr} - * that references the symbol. - */ - public static boolean isReferenceToVar(@Nullable ASTExpression expression, @NonNull JVariableSymbol symbol) { - return expression instanceof ASTNamedReferenceExpr - && symbol.equals(((ASTNamedReferenceExpr) expression).getReferencedSym()); - } - - public static boolean isUnqualifiedThis(ASTExpression e) { - return e instanceof ASTThisExpression && ((ASTThisExpression) e).getQualifier() == null; - } - - public static boolean isUnqualifiedSuper(ASTExpression e) { - return e instanceof ASTSuperExpression && ((ASTSuperExpression) e).getQualifier() == null; - } - - public static boolean isUnqualifiedThisOrSuper(ASTExpression e) { - return isUnqualifiedSuper(e) || isUnqualifiedThis(e); - } - - /** - * Returns true if the expression is a {@link ASTNamedReferenceExpr} - * that references any of the symbol in the set. - */ - public static boolean isReferenceToVar(@Nullable ASTExpression expression, @NonNull Set symbols) { - return expression instanceof ASTNamedReferenceExpr - && symbols.contains(((ASTNamedReferenceExpr) expression).getReferencedSym()); - } - - /** - * Returns true if both expressions refer to the same variable. - * A "variable" here can also means a field path, eg, {@code this.field.a}. - * This method unifies {@code this.field} and {@code field} if possible, - * and also considers {@code this}. - * - *

    Note that while this is more useful than just checking whether - * both expressions access the same symbol, it still does not mean that - * they both access the same value. The actual value is data-flow - * dependent. - */ - public static boolean isReferenceToSameVar(ASTExpression e1, ASTExpression e2) { - if (e1 instanceof ASTNamedReferenceExpr && e2 instanceof ASTNamedReferenceExpr) { - if (OptionalBool.YES != referenceSameSymbol((ASTNamedReferenceExpr) e1, (ASTNamedReferenceExpr) e2)) { - return false; - } - - if (e1.getClass() != e2.getClass()) { - // unify `this.f` and `f` - // note, we already know that the symbol is the same so there's no scoping problem - return isSyntacticThisFieldAccess(e1) || isSyntacticThisFieldAccess(e2); - } else if (e1 instanceof ASTFieldAccess && e2 instanceof ASTFieldAccess) { - return isReferenceToSameVar(((ASTFieldAccess) e1).getQualifier(), - ((ASTFieldAccess) e2).getQualifier()); - } - return e1 instanceof ASTVariableAccess && e2 instanceof ASTVariableAccess; - } else if (e1 instanceof ASTThisExpression || e2 instanceof ASTThisExpression) { - return e1.getClass() == e2.getClass(); - } - return false; - } - - private static OptionalBool referenceSameSymbol(ASTNamedReferenceExpr e1, ASTNamedReferenceExpr e2) { - if (!e1.getName().equals(e2.getName())) { - return OptionalBool.NO; - } - JVariableSymbol ref1 = e1.getReferencedSym(); - JVariableSymbol ref2 = e2.getReferencedSym(); - if (ref1 == null || ref2 == null) { - return OptionalBool.UNKNOWN; - } - return OptionalBool.definitely(ref1.equals(ref2)); - } - - /** - * Returns true if the expression is a reference to a local variable. - */ - public static boolean isReferenceToLocal(ASTExpression expr) { - return expr instanceof ASTVariableAccess - && ((ASTVariableAccess) expr).getReferencedSym() instanceof AstLocalVarSym; - } - - /** - * Returns true if the expression has the form `field`, or `this.field`, - * where `field` is a field declared in the enclosing class. Considers - * inherited fields. Assumes we're not in a static context. - */ - public static boolean isRefToFieldOfThisInstance(ASTExpression usage) { - if (!(usage instanceof ASTNamedReferenceExpr)) { - return false; - } - JVariableSymbol symbol = ((ASTNamedReferenceExpr) usage).getReferencedSym(); - if (!(symbol instanceof JFieldSymbol)) { - return false; - } - - if (usage instanceof ASTVariableAccess) { - return !Modifier.isStatic(((JFieldSymbol) symbol).getModifiers()); - } else if (usage instanceof ASTFieldAccess) { - return isUnqualifiedThisOrSuper(((ASTFieldAccess) usage).getQualifier()); - } - return false; - } - - /** - * Returns true if the expression is a reference to a field declared - * in this class (not a superclass), on any instance (not just `this`). - */ - public static boolean isRefToFieldOfThisClass(ASTExpression usage) { - if (!(usage instanceof ASTNamedReferenceExpr)) { - return false; - } - JVariableSymbol symbol = ((ASTNamedReferenceExpr) usage).getReferencedSym(); - if (!(symbol instanceof JFieldSymbol)) { - return false; - } - - if (usage instanceof ASTVariableAccess) { - return !Modifier.isStatic(((JFieldSymbol) symbol).getModifiers()); - } else if (usage instanceof ASTFieldAccess) { - return Objects.equals(((JFieldSymbol) symbol).getEnclosingClass(), - usage.getEnclosingType().getSymbol()); - } - return false; - } - - public static boolean isCallOnThisInstance(ASTMethodCall call) { - // syntactic approach. - if (call.getQualifier() != null) { - return JavaRuleUtil.isUnqualifiedThisOrSuper(call.getQualifier()); - } - - // unqualified call - JMethodSig mtype = call.getMethodType(); - return !mtype.getSymbol().isUnresolved() - && mtype.getSymbol().getEnclosingClass().equals(call.getEnclosingType().getSymbol()); - } - - public static ASTClassOrInterfaceType getThisOrSuperQualifier(ASTExpression expr) { - if (expr instanceof ASTThisExpression) { - return ((ASTThisExpression) expr).getQualifier(); - } else if (expr instanceof ASTSuperExpression) { - return ((ASTSuperExpression) expr).getQualifier(); - } - return null; - } - - public static ASTClassOrInterfaceType isUnqual(ASTExpression expr) { - if (expr instanceof ASTThisExpression) { - return ((ASTThisExpression) expr).getQualifier(); - } else if (expr instanceof ASTSuperExpression) { - return ((ASTSuperExpression) expr).getQualifier(); - } - return null; - } - - public static boolean isThisOrSuper(ASTExpression expr) { - return expr instanceof ASTThisExpression || expr instanceof ASTSuperExpression; - } - - /** - * 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); - } - - /** - * Returns true if the node is the last child of its parent (or is the root node). - */ - public static boolean isLastChild(Node it) { - Node parent = it.getParent(); - return parent == null || it.getIndexInParent() == parent.getNumChildren() - 1; + && JavaAstUtils.hasExceptionList(node, InvalidObjectException.class) + && JavaAstUtils.hasParameters(node, ObjectInputStream.class); } @@ -966,12 +360,12 @@ public final class JavaRuleUtil { private static boolean hasSideEffectNonRecursive(ASTExpression e, Set localVarsToTrack) { if (e instanceof ASTAssignmentExpression) { ASTAssignableExpr lhs = ((ASTAssignmentExpression) e).getLeftOperand(); - return isNonLocalLhs(lhs) || isReferenceToVar(lhs, localVarsToTrack); + return isNonLocalLhs(lhs) || JavaAstUtils.isReferenceToVar(lhs, localVarsToTrack); } else if (e instanceof ASTUnaryExpression) { ASTUnaryExpression unary = (ASTUnaryExpression) e; ASTExpression lhs = unary.getOperand(); return !unary.getOperator().isPure() - && (isNonLocalLhs(lhs) || isReferenceToVar(lhs, localVarsToTrack)); + && (isNonLocalLhs(lhs) || JavaAstUtils.isReferenceToVar(lhs, localVarsToTrack)); } // when there are throw statements, @@ -983,7 +377,7 @@ public final class JavaRuleUtil { } private static boolean isNonLocalLhs(ASTExpression lhs) { - return lhs instanceof ASTArrayAccess || !isReferenceToLocal(lhs); + return lhs instanceof ASTArrayAccess || !JavaAstUtils.isReferenceToLocal(lhs); } /** @@ -993,23 +387,6 @@ public final class JavaRuleUtil { return isGetterCall(call) || KNOWN_PURE_METHODS.anyMatch(call); } - /** - * Returns a node stream of enclosing expressions in the same call chain. - * For instance in {@code a.b().c().d()}, called on {@code a}, this will - * yield {@code a.b()}, and {@code a.b().c()}. - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - public static NodeStream followingCallChain(ASTExpression expr) { - return (NodeStream) expr.ancestors().takeWhile(it -> it instanceof QualifiableExpression); - } - - public static ASTExpression peelCasts(@Nullable ASTExpression expr) { - while (expr instanceof ASTCastExpression) { - expr = ((ASTCastExpression) expr).getOperand(); - } - return expr; - } - public static @Nullable ASTVariableDeclaratorId getReferencedNode(ASTNamedReferenceExpr expr) { JVariableSymbol referencedSym = expr.getReferencedSym(); return referencedSym == null ? null : referencedSym.tryGetNode(); @@ -1040,7 +417,7 @@ public final class JavaRuleUtil { if (condition.getOperator().hasSamePrecedenceAs(BinaryOp.EQ)) { ASTNullLiteral nullLit = condition.firstChild(ASTNullLiteral.class); if (nullLit != null) { - return matcher.matches(getOtherOperandIfInInfixExpr(nullLit)); + return matcher.matches(JavaAstUtils.getOtherOperandIfInInfixExpr(nullLit)); } } } @@ -1054,40 +431,11 @@ public final class JavaRuleUtil { if (expr.getParent() instanceof ASTInfixExpression) { ASTInfixExpression infx = (ASTInfixExpression) expr.getParent(); if (infx.getOperator().hasSamePrecedenceAs(BinaryOp.EQ)) { - return getOtherOperandIfInInfixExpr(expr) instanceof ASTNullLiteral; + return JavaAstUtils.getOtherOperandIfInInfixExpr(expr) instanceof ASTNullLiteral; } } return false; } - public static boolean isArrayInitializer(ASTExpression expr) { - return expr instanceof ASTArrayAllocation && ((ASTArrayAllocation) expr).getArrayInitializer() != null; - } - public static boolean isCloneMethod(ASTMethodDeclaration node) { - // this is enough as in valid code, this signature overrides Object#clone - // and the other things like visibility are checked by the compiler - return "clone".equals(node.getName()) - && node.getArity() == 0 - && !node.isStatic(); - } - - public static boolean isArrayLengthFieldAccess(ASTExpression node) { - if (node instanceof ASTFieldAccess) { - ASTFieldAccess field = (ASTFieldAccess) node; - return "length".equals(field.getName()) - && field.getQualifier().getTypeMirror().isArray(); - } - return false; - } - - - /** - * @see {@link ASTBreakStatement#getTarget()} - */ - public static boolean mayBeBreakTarget(JavaNode it) { - return it instanceof ASTLoopStatement - || it instanceof ASTSwitchStatement - || it instanceof ASTLabeledStatement; - } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/StablePathMatcher.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/StablePathMatcher.java index 65977f2dba..a43309b1e8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/StablePathMatcher.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/StablePathMatcher.java @@ -17,6 +17,7 @@ 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.ASTVariableAccess; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; /** @@ -77,7 +78,7 @@ public final class StablePathMatcher { return Objects.equals(((ASTVariableAccess) e).getReferencedSym(), owner); } else if (e instanceof ASTFieldAccess) { ASTFieldAccess fieldAccess = (ASTFieldAccess) e; - return JavaRuleUtil.isUnqualifiedThis(fieldAccess.getQualifier()) + return JavaAstUtils.isUnqualifiedThis(fieldAccess.getQualifier()) && Objects.equals(fieldAccess.getReferencedSym(), owner); } return false; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/DoubleCheckedLockingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/DoubleCheckedLockingRule.java index d12ba811a4..69ae5e12ff 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/DoubleCheckedLockingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/DoubleCheckedLockingRule.java @@ -19,6 +19,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.ast.ASTSynchronizedStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; @@ -99,7 +100,7 @@ public class DoubleCheckedLockingRule extends AbstractJavaRule { if (JavaRuleUtil.isNullCheck(is2.getCondition(), returnVariable)) { List assignments = is2.findDescendantsOfType(ASTAssignmentExpression.class); if (assignments.size() == 1 - && JavaRuleUtil.isReferenceToVar(assignments.get(0).getLeftOperand(), returnVariable)) { + && JavaAstUtils.isReferenceToVar(assignments.get(0).getLeftOperand(), returnVariable)) { addViolation(data, node); } @@ -125,7 +126,7 @@ public class DoubleCheckedLockingRule extends AbstractJavaRule { return (initializer == null || isVolatileFieldReference(initializer)) && method.descendants(ASTAssignmentExpression.class) - .filter(it -> JavaRuleUtil.isReferenceToVar(it.getLeftOperand(), local)) + .filter(it -> JavaAstUtils.isReferenceToVar(it.getLeftOperand(), local)) .all(it -> isVolatileFieldReference(it.getRightOperand())); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/UnsynchronizedStaticFormatterRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/UnsynchronizedStaticFormatterRule.java index 50e2d95ec1..90a0c2d7fe 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/UnsynchronizedStaticFormatterRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/UnsynchronizedStaticFormatterRule.java @@ -18,8 +18,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTSynchronizedStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.JModifier; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; 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; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -89,7 +89,7 @@ public class UnsynchronizedStaticFormatterRule extends AbstractJavaRulechainRule ASTSynchronizedStatement syncStatement = ref.ancestors(ASTSynchronizedStatement.class).first(); if (syncStatement != null) { ASTExpression lockExpression = syncStatement.getLockExpression(); - if (JavaRuleUtil.isReferenceToSameVar(lockExpression, methodCall.getQualifier())) { + if (JavaAstUtils.isReferenceToSameVar(lockExpression, methodCall.getQualifier())) { continue; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java index 948cae7590..479f2d91b5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java @@ -31,6 +31,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.InvocationNode; import net.sourceforge.pmd.lang.java.ast.TypeNode; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; 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; @@ -226,7 +227,7 @@ public class ConsecutiveLiteralAppendsRule extends AbstractJavaRulechainRule { * Const.WORLD) */ private boolean isAdditive(InvocationNode n) { - return JavaRuleUtil.isStringConcatExpr(n.getArguments().getFirstChild()); + return JavaAstUtils.isStringConcatExpr(n.getArguments().getFirstChild()); } /** diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InefficientStringBufferingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InefficientStringBufferingRule.java index fe7324d427..dc62ef5fa7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InefficientStringBufferingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InefficientStringBufferingRule.java @@ -11,6 +11,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTList; import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; @@ -46,7 +47,7 @@ public class InefficientStringBufferingRule extends AbstractJavaRulechainRule { private void checkArgument(ASTArgumentList argList, RuleContext ctx) { ASTExpression arg = ASTList.singleOrNull(argList); - if (JavaRuleUtil.isStringConcatExpr(arg) + if (JavaAstUtils.isStringConcatExpr(arg) // ignore concatenations that produce constants && !arg.isCompileTimeConstant()) { addViolation(ctx, arg); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/RedundantFieldInitializerRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/RedundantFieldInitializerRule.java index 9970dd31ea..066cdd929e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/RedundantFieldInitializerRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/RedundantFieldInitializerRule.java @@ -10,8 +10,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.JModifier; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; /** * Detects redundant field initializers, i.e. the field initializer expressions @@ -32,7 +32,7 @@ public class RedundantFieldInitializerRule extends AbstractJavaRulechainRule { for (ASTVariableDeclaratorId varId : fieldDeclaration.getVarIds()) { ASTExpression init = varId.getInitializer(); if (init != null) { - if (!isWhitelisted(init) && JavaRuleUtil.isDefaultValue(varId.getTypeMirror(), init)) { + if (!isWhitelisted(init) && JavaAstUtils.isDefaultValue(varId.getTypeMirror(), init)) { addViolation(data, varId); } } 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 cd4140bff7..035ec89884 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 @@ -13,8 +13,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.AccessType; import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression; import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; 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 { @@ -56,7 +56,7 @@ public class UseStringBufferForStringAppendsRule extends AbstractJavaRulechainRu } int usageOnRightHandSide = - JavaRuleUtil.flattenOperands(assignment.getRightOperand()) + JavaAstUtils.flattenOperands(assignment.getRightOperand()) .filterIs(ASTNamedReferenceExpr.class) .filterMatching(ASTNamedReferenceExpr::getReferencedSym, node.getSymbol()) .count(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UselessStringValueOfRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UselessStringValueOfRule.java index 0720956404..fac29d3bf3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UselessStringValueOfRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UselessStringValueOfRule.java @@ -9,8 +9,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; import net.sourceforge.pmd.lang.rule.RuleTargetSelector; @@ -24,7 +24,7 @@ public class UselessStringValueOfRule extends AbstractJavaRule { @Override public Object visit(ASTMethodCall node, Object data) { - if (JavaRuleUtil.isStringConcatExpr(node.getParent())) { + if (JavaAstUtils.isStringConcatExpr(node.getParent())) { ASTExpression valueOfArg = getValueOfArg(node); if (valueOfArg == null) { return data; //not a valueOf call @@ -33,7 +33,7 @@ public class UselessStringValueOfRule extends AbstractJavaRule { return data; } - ASTExpression sibling = JavaRuleUtil.getOtherOperandIfInInfixExpr(node); + ASTExpression sibling = JavaAstUtils.getOtherOperandIfInInfixExpr(node); if (TypeTestUtil.isExactlyA(String.class, sibling) && !valueOfArg.getTypeMirror().isArray() // In `String.valueOf(a) + String.valueOf(b)`, diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/AbruptCompletionAnalysis.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/AbruptCompletionAnalysis.java index 2b36936c86..6bd9eb3061 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/AbruptCompletionAnalysis.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/AbruptCompletionAnalysis.java @@ -39,7 +39,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.ASTYieldStatement; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.symbols.table.internal.AbruptCompletionAnalysis.ReachabilityVisitor.VisitResult; /** @@ -184,7 +184,7 @@ final class AbruptCompletionAnalysis { recordReachableNode(node, data); boolean bodyCompletesNormally = node.getBody().acceptVisitor(this, data); - boolean isNotDoWhileTrue = !JavaRuleUtil.isBooleanLiteral(node.getCondition(), true); + boolean isNotDoWhileTrue = !JavaAstUtils.isBooleanLiteral(node.getCondition(), true); return isNotDoWhileTrue && (bodyCompletesNormally || data.containsContinue(node)) || data.containsBreak(node); @@ -246,7 +246,7 @@ final class AbruptCompletionAnalysis { recordReachableNode(node, data); node.getBody().acceptVisitor(this, data); - boolean isNotWhileTrue = !JavaRuleUtil.isBooleanLiteral(node.getCondition(), true); + boolean isNotWhileTrue = !JavaAstUtils.isBooleanLiteral(node.getCondition(), true); return isNotWhileTrue || data.containsBreak(node); } @@ -258,7 +258,7 @@ final class AbruptCompletionAnalysis { node.getBody().acceptVisitor(this, data); boolean isNotForTrue = node.getCondition() != null - && !JavaRuleUtil.isBooleanLiteral(node.getCondition(), true); + && !JavaAstUtils.isBooleanLiteral(node.getCondition(), true); return isNotForTrue || data.containsBreak(node); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SymbolTableResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SymbolTableResolver.java index 22b4b73746..58f120a9c0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SymbolTableResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SymbolTableResolver.java @@ -69,8 +69,8 @@ import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.ast.InternalApiBridge; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.internal.JavaAstProcessor; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.table.JSymbolTable; import net.sourceforge.pmd.lang.java.symbols.table.internal.PatternBindingsUtil.BindSet; import net.sourceforge.pmd.lang.java.types.JClassType; @@ -673,7 +673,7 @@ public final class SymbolTableResolver { private boolean hasNoBreakContainingStmt(ASTLoopStatement node) { Set containingStatements = node.ancestorsOrSelf() - .filter(JavaRuleUtil::mayBeBreakTarget) + .filter(JavaAstUtils::mayBeBreakTarget) .collect(Collectors.toSet()); return node.getBody() .descendants(ASTBreakStatement.class) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/ast/PolyResolution.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/ast/PolyResolution.java index 10bc683b79..0baf61a9c0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/ast/PolyResolution.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/ast/PolyResolution.java @@ -51,7 +51,7 @@ import net.sourceforge.pmd.lang.java.ast.InternalApiBridge; import net.sourceforge.pmd.lang.java.ast.InvocationNode; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.TypeNode; -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.lang.java.types.JClassType; import net.sourceforge.pmd.lang.java.types.JMethodSig; import net.sourceforge.pmd.lang.java.types.JPrimitiveType; @@ -541,7 +541,7 @@ final class PolyResolution { // numeric contexts, maybe BinaryOp op = ((ASTInfixExpression) papa).getOperator(); JTypeMirror nodeType = ((ASTExpression) node).getTypeMirror(); - JTypeMirror otherType = JavaRuleUtil.getOtherOperandIfInInfixExpr(node).getTypeMirror(); + JTypeMirror otherType = JavaAstUtils.getOtherOperandIfInInfixExpr(node).getTypeMirror(); JTypeMirror ctxType = ((ASTInfixExpression) papa).getTypeMirror(); switch (op) { case CONDITIONAL_OR: diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtilTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtilTest.java new file mode 100644 index 0000000000..ee1cbc5913 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtilTest.java @@ -0,0 +1,44 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast.internal; + +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.flattenOperands; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isStringConcatExpr; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.Test; + +import net.sourceforge.pmd.lang.java.BaseParserTest; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; +import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; +import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; + +public class JavaAstUtilTest extends BaseParserTest { + + @Test + public void testFlattenConcatOperands() { + ASTExpression e = parseExpr("s1+s2+s3"); + + assertTrue(isStringConcatExpr(e)); + assertEquals(e.descendants(ASTVariableAccess.class).toList(), + flattenOperands(e).toList()); + } + + @Test + public void testFlattenConcatOperandsRespectsTyping() { + ASTInfixExpression e = (ASTInfixExpression) parseExpr("i+j+s2+s3"); + assertTrue(isStringConcatExpr(e)); + ASTInfixExpression left = (ASTInfixExpression) e.getLeftOperand(); + assertTrue(isStringConcatExpr(left)); + + // This is (i+j) + // vvvvvvvvvvvvvvvvvvvvv + assertEquals(listOf(left.getLeftOperand(), left.getRightOperand(), e.getRightOperand()), + flattenOperands(e).toList()); + } + +} 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 0f3652301c..be99b14c6a 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 @@ -6,8 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.internal; import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.containsCamelCaseWord; 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; @@ -15,9 +13,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.Test; import net.sourceforge.pmd.lang.java.BaseParserTest; -import net.sourceforge.pmd.lang.java.ast.ASTExpression; -import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; -import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; public class JavaRuleUtilTest extends BaseParserTest { @@ -45,26 +40,4 @@ public class JavaRuleUtilTest extends BaseParserTest { assertThrows(AssertionError.class, () -> containsCamelCaseWord("fnei", "a"), "not capitalized"); } - @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/kotlin/net/sourceforge/pmd/lang/java/types/ast/ConversionContextTests.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/ast/ConversionContextTests.kt index 0ef9ac198f..ac5d2c52e4 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/ast/ConversionContextTests.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/ast/ConversionContextTests.kt @@ -10,7 +10,7 @@ import io.kotest.matchers.shouldBe import net.sourceforge.pmd.lang.ast.test.component6 import net.sourceforge.pmd.lang.ast.test.shouldBe import net.sourceforge.pmd.lang.java.ast.* -import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils import net.sourceforge.pmd.lang.java.types.STRING import net.sourceforge.pmd.lang.java.types.parseWithTypeInferenceSpy import net.sourceforge.pmd.lang.java.types.shouldHaveType @@ -239,7 +239,9 @@ class ConversionContextTests : ProcessorTestSpec({ spy.shouldBeOk { concats.forEach { withClue(it) { - JavaRuleUtil.isStringConcatExpr(it) shouldBe true + JavaAstUtils.isStringConcatExpr( + it + ) shouldBe true it.leftOperand.conversionContext::getTargetType shouldBe ts.STRING it.rightOperand.conversionContext::getTargetType shouldBe ts.STRING } From e3005e279a6ce99b081a34f3c98e618217ebbbf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 14 Mar 2022 21:49:01 +0100 Subject: [PATCH 37/89] Move things from BinaryOp --- .../pmd/lang/java/ast/BinaryOp.java | 29 +++---------------- .../lang/java/ast/internal/JavaAstUtils.java | 24 ++++++++++++++- .../ForLoopCanBeForeachRule.java | 2 +- .../SimplifiableTestAssertionRule.java | 2 +- .../rule/codestyle/UnnecessaryCastRule.java | 2 +- .../java/rule/design/LawOfDemeterRule.java | 2 +- .../design/SimplifyBooleanReturnsRule.java | 2 +- .../rule/design/SimplifyConditionalRule.java | 2 +- 8 files changed, 33 insertions(+), 32 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 0e53569546..a740fa67da 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 @@ -86,14 +86,14 @@ public enum BinaryOp implements InternalInterfaces.OperatorLike { /** Modulo {@code "%"} operator. */ MOD("%"); - /** Set of {@code &&} and {@code ||}. Use with {@link #isInfixExprWithOperator(JavaNode, Set)}. */ + /** Set of {@code &&} and {@code ||}. Use with {@link net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ public static final Set CONDITIONAL_OPS = CollectionUtil.immutableEnumSet(CONDITIONAL_AND, CONDITIONAL_OR); - /** Set of {@code <}, {@code <=}, {@code >=} and {@code >}. Use with {@link #isInfixExprWithOperator(JavaNode, Set)}. */ + /** Set of {@code <}, {@code <=}, {@code >=} and {@code >}. Use with {@link net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ public static final Set COMPARISON_OPS = CollectionUtil.immutableEnumSet(LE, GE, GT, LT); - /** Set of {@code ==} and {@code !=}. Use with {@link #isInfixExprWithOperator(JavaNode, Set)}. */ + /** Set of {@code ==} and {@code !=}. Use with {@link net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ public static final Set EQUALITY_OPS = CollectionUtil.immutableEnumSet(EQ, NE); - /** Set of {@code <<}, {@code >>} and {@code >>>}. Use with {@link #isInfixExprWithOperator(JavaNode, Set)}. */ + /** Set of {@code <<}, {@code >>} and {@code >>>}. Use with {@link net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ public static final Set SHIFT_OPS = CollectionUtil.immutableEnumSet(LEFT_SHIFT, RIGHT_SHIFT, UNSIGNED_RIGHT_SHIFT); private final String code; @@ -212,25 +212,4 @@ public enum BinaryOp implements InternalInterfaces.OperatorLike { } - /** - * Tests if the node is an {@link ASTInfixExpression} with one of the given operators. - */ - public static boolean isInfixExprWithOperator(@Nullable JavaNode e, Set operators) { - if (e instanceof ASTInfixExpression) { - ASTInfixExpression infix = (ASTInfixExpression) e; - return operators.contains(infix.getOperator()); - } - 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/ast/internal/JavaAstUtils.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java index ac4d64a5e3..7214dbeb30 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java @@ -86,7 +86,7 @@ public final class JavaAstUtils { public static boolean isConditional(JavaNode ifx) { - return BinaryOp.isInfixExprWithOperator(ifx, BinaryOp.CONDITIONAL_OPS); + return isInfixExprWithOperator(ifx, BinaryOp.CONDITIONAL_OPS); } public static int numAlternatives(ASTSwitchBranch n) { @@ -693,4 +693,26 @@ public final class JavaAstUtils { || it instanceof ASTSwitchStatement || it instanceof ASTLabeledStatement; } + + /** + * Tests if the node is an {@link ASTInfixExpression} with one of the given operators. + */ + public static boolean isInfixExprWithOperator(@Nullable JavaNode e, Set operators) { + if (e instanceof ASTInfixExpression) { + ASTInfixExpression infix = (ASTInfixExpression) e; + return operators.contains(infix.getOperator()); + } + 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/bestpractices/ForLoopCanBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java index 59eb021efd..542ebadedb 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java @@ -139,7 +139,7 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRulechainRule { * @return The name, or null if it couldn't be found or the guard condition is not safe to refactor (then abort) */ private @Nullable ASTNamedReferenceExpr findIterableFromCondition(ASTExpression guardCondition, ASTVariableDeclaratorId indexVar) { - if (!BinaryOp.isInfixExprWithOperator(guardCondition, BinaryOp.COMPARISON_OPS)) { + if (!JavaAstUtils.isInfixExprWithOperator(guardCondition, BinaryOp.COMPARISON_OPS)) { return null; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/SimplifiableTestAssertionRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/SimplifiableTestAssertionRule.java index 64c6c60af9..cf477cbc77 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/SimplifiableTestAssertionRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/SimplifiableTestAssertionRule.java @@ -129,7 +129,7 @@ public class SimplifiableTestAssertionRule extends AbstractJavaRulechainRule { private ASTInfixExpression asEqualityExpr(ASTExpression node) { - if (BinaryOp.isInfixExprWithOperator(node, BinaryOp.EQUALITY_OPS)) { + if (JavaAstUtils.isInfixExprWithOperator(node, BinaryOp.EQUALITY_OPS)) { return (ASTInfixExpression) node; } return null; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryCastRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryCastRule.java index 6cad24aebc..5d422e65fd 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryCastRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryCastRule.java @@ -14,7 +14,7 @@ import static net.sourceforge.pmd.lang.java.ast.BinaryOp.MOD; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.MUL; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.SHIFT_OPS; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.SUB; -import static net.sourceforge.pmd.lang.java.ast.BinaryOp.isInfixExprWithOperator; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isInfixExprWithOperator; import java.util.EnumSet; import java.util.Set; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java index fa100cfbc0..d6aa57e247 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java @@ -5,9 +5,9 @@ package net.sourceforge.pmd.lang.java.rule.design; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.INSTANCEOF; -import static net.sourceforge.pmd.lang.java.ast.BinaryOp.isInfixExprWithOperator; import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isArrayLengthFieldAccess; import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isCallOnThisInstance; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isInfixExprWithOperator; import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isRefToFieldOfThisClass; import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isThisOrSuper; import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isGetterCall; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanReturnsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanReturnsRule.java index 24f4bb9f11..ae0a84cd17 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanReturnsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanReturnsRule.java @@ -12,10 +12,10 @@ import static net.sourceforge.pmd.lang.java.ast.BinaryOp.GT; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.LE; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.LT; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.NE; -import static net.sourceforge.pmd.lang.java.ast.BinaryOp.isInfixExprWithOperator; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.opsWithGreaterPrecedence; import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.areComplements; import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isBooleanLiteral; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isInfixExprWithOperator; import java.util.EnumSet; import java.util.Set; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java index e465af2da8..fb44ca8fca 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java @@ -8,9 +8,9 @@ import static net.sourceforge.pmd.lang.java.ast.BinaryOp.CONDITIONAL_AND; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.CONDITIONAL_OR; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.INSTANCEOF; import static net.sourceforge.pmd.lang.java.ast.BinaryOp.NE; -import static net.sourceforge.pmd.lang.java.ast.BinaryOp.isInfixExprWithOperator; import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.getOtherOperandIfInInfixExpr; import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isBooleanNegation; +import static net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils.isInfixExprWithOperator; import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isNullCheck; import net.sourceforge.pmd.lang.java.ast.ASTExpression; From 114f3f6fcee1faf9964cc4affbc5a3f97f5d296e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 14 Mar 2022 21:50:29 +0100 Subject: [PATCH 38/89] Cleanup --- .../pmd/lang/java/ast/BinaryOp.java | 9 +++++---- .../lang/java/ast/internal/JavaAstUtils.java | 20 ++++++++----------- .../java/types/ast/ConversionContextTests.kt | 4 +--- 3 files changed, 14 insertions(+), 19 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 a740fa67da..e660e51ed8 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 java.util.Set; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils; import net.sourceforge.pmd.util.CollectionUtil; /** @@ -86,14 +87,14 @@ public enum BinaryOp implements InternalInterfaces.OperatorLike { /** Modulo {@code "%"} operator. */ MOD("%"); - /** Set of {@code &&} and {@code ||}. Use with {@link net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ + /** Set of {@code &&} and {@code ||}. Use with {@link JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ public static final Set CONDITIONAL_OPS = CollectionUtil.immutableEnumSet(CONDITIONAL_AND, CONDITIONAL_OR); - /** Set of {@code <}, {@code <=}, {@code >=} and {@code >}. Use with {@link net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ + /** Set of {@code <}, {@code <=}, {@code >=} and {@code >}. Use with {@link JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ public static final Set COMPARISON_OPS = CollectionUtil.immutableEnumSet(LE, GE, GT, LT); - /** Set of {@code ==} and {@code !=}. Use with {@link net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ + /** Set of {@code ==} and {@code !=}. Use with {@link JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ public static final Set EQUALITY_OPS = CollectionUtil.immutableEnumSet(EQ, NE); - /** Set of {@code <<}, {@code >>} and {@code >>>}. Use with {@link net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ + /** Set of {@code <<}, {@code >>} and {@code >>>}. Use with {@link JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */ public static final Set SHIFT_OPS = CollectionUtil.immutableEnumSet(LEFT_SHIFT, RIGHT_SHIFT, UNSIGNED_RIGHT_SHIFT); private final String code; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java index 7214dbeb30..36030e8252 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/JavaAstUtils.java @@ -65,6 +65,7 @@ import net.sourceforge.pmd.lang.java.ast.JavaTokenKinds; import net.sourceforge.pmd.lang.java.ast.QualifiableExpression; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.java.ast.UnaryOp; +import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; import net.sourceforge.pmd.lang.java.symbols.internal.ast.AstLocalVarSym; @@ -76,7 +77,10 @@ import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.OptionalBool; /** - * + * Common utility functions to work with the Java AST. See also + * {@link TypeTestUtil}. Only add here things that are not specific to + * rules (use {@link JavaRuleUtil} for that). This API may be eventually + * published. */ public final class JavaAstUtils { @@ -602,15 +606,6 @@ public final class JavaAstUtils { return null; } - public static ASTClassOrInterfaceType isUnqual(ASTExpression expr) { - if (expr instanceof ASTThisExpression) { - return ((ASTThisExpression) expr).getQualifier(); - } else if (expr instanceof ASTSuperExpression) { - return ((ASTSuperExpression) expr).getQualifier(); - } - return null; - } - public static boolean isThisOrSuper(ASTExpression expr) { return expr instanceof ASTThisExpression || expr instanceof ASTSuperExpression; } @@ -640,11 +635,12 @@ public final class JavaAstUtils { } /** - * Returns true if the node is the last child of its parent (or is the root node). + * Returns true if the node is the last child of its parent. Returns + * false if this is the root node. */ public static boolean isLastChild(Node it) { Node parent = it.getParent(); - return parent == null || it.getIndexInParent() == parent.getNumChildren() - 1; + return parent != null && it.getIndexInParent() == parent.getNumChildren() - 1; } /** diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/ast/ConversionContextTests.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/ast/ConversionContextTests.kt index ac5d2c52e4..b17eeae84e 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/ast/ConversionContextTests.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/ast/ConversionContextTests.kt @@ -239,9 +239,7 @@ class ConversionContextTests : ProcessorTestSpec({ spy.shouldBeOk { concats.forEach { withClue(it) { - JavaAstUtils.isStringConcatExpr( - it - ) shouldBe true + JavaAstUtils.isStringConcatExpr(it) shouldBe true it.leftOperand.conversionContext::getTargetType shouldBe ts.STRING it.rightOperand.conversionContext::getTargetType shouldBe ts.STRING } From 0fbcfec9b1d52f3263eefdf4900b0a6ae95475c6 Mon Sep 17 00:00:00 2001 From: Bailey Tjiong Date: Tue, 15 Mar 2022 01:28:15 +0100 Subject: [PATCH 39/89] Change the top and bottom edit buttons --- docs/_includes/footer.html | 36 ++- docs/_includes/header.html | 23 ++ docs/_layouts/page.html | 18 +- docs/css/customstyles.css | 490 +++++++++++++++++++++---------------- 4 files changed, 339 insertions(+), 228 deletions(-) create mode 100644 docs/_includes/header.html diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html index 12d9065323..5a66147c2c 100755 --- a/docs/_includes/footer.html +++ b/docs/_includes/footer.html @@ -1,9 +1,31 @@

    -
    - -
    +
    +
    + {% if site.github_editme_path %} This documentation is written in + markdown.
    + If there is something missing or can be improved, edit this page on + github and create a PR: {% unless page.editmepath == false %} + Edit on GitHub + {% endunless %} {% endif %} +
    +
    +
    + +
    diff --git a/docs/_includes/header.html b/docs/_includes/header.html new file mode 100644 index 0000000000..2be3e3a82d --- /dev/null +++ b/docs/_includes/header.html @@ -0,0 +1,23 @@ +
    +
    +
    + + » {{page.title}} {% if site.github_editme_path %} {% assign + editmepath = page.path %} {% if page.editmepath %} {% assign + editmepath = page.editmepath %} {% endif %}{% unless page.editmepath + == false %} + Edit on GitHub + {% endunless %} {% endif %} +
    +
    + +
    +
    diff --git a/docs/_layouts/page.html b/docs/_layouts/page.html index 8ae8f8d2fe..05c08da182 100644 --- a/docs/_layouts/page.html +++ b/docs/_layouts/page.html @@ -2,6 +2,8 @@ layout: default --- +{% include header.html %} +

    {{ page.title }}

    @@ -33,19 +35,6 @@ layout: default {% if page.summary %}
    {{page.summary}}
    {% endif %} - - {% if site.github_editme_path %} - - {% assign editmepath = page.path %} - {% if page.editmepath %} - {% assign editmepath = page.editmepath %} - {% endif %} - {% unless page.editmepath == false %} - Edit me - {% endunless %} - - {% endif %} -
    {{content}} @@ -63,9 +52,7 @@ layout: default {% if site.github_editme_path %} - This documentation is written in markdown. If there is something missing or can be improved, edit this page on github and create a PR: {% unless page.editmepath == false %} - Edit me - {% endunless %} - {% endif %} - - {% include disqus.html %} diff --git a/docs/css/customstyles.css b/docs/css/customstyles.css index ccbad65535..e37d5d5c5d 100644 --- a/docs/css/customstyles.css +++ b/docs/css/customstyles.css @@ -1330,3 +1330,7 @@ h4.panel-title { .post-content h2 { display: inline-block; } + +a.edit-header { + font-size: 15px; +} diff --git a/docs/js/customscripts.js b/docs/js/customscripts.js index af3ae18f51..1d7eb0fbd3 100644 --- a/docs/js/customscripts.js +++ b/docs/js/customscripts.js @@ -1,68 +1,93 @@ - -$('#mysidebar').height($(".nav").height()); +$('#mysidebar').height($('.nav').height()); // Detect small devices and move the TOC in line -function moveToc(){ - if(window.innerWidth < 1350){ - $( "#toc" ).detach().appendTo("#inline-toc").removeClass("affix"); +function moveToc() { + if (window.innerWidth < 1350) { + $('#toc').detach().appendTo('#inline-toc').removeClass('affix'); } else { - $( "#toc" ).detach().appendTo(".toc-col").addClass("affix"); + $('#toc').detach().appendTo('.toc-col').addClass('affix'); } } -$( document ).ready(function() { +$(document).ready(function () { + $('#toc').toc({ + minimumHeaders: 0, + listType: 'ul', + showSpeed: 0, + headers: 'h2,h3,h4', + }); //this script says, if the height of the viewport is greater than 800px, then insert affix class, which makes the nav bar float in a fixed // position as your scroll. if you have a lot of nav items, this height may not work for you. var h = $(window).height(); //console.log (h); if (h > 600) { - $( "#mysidebar" ).attr("class", "nav affix"); + $('#mysidebar').attr('class', 'nav affix'); } // activate tooltips. although this is a bootstrap js function, it must be activated this way in your theme. $('[data-toggle="tooltip"]').tooltip({ - placement : 'top' + placement: 'top', }); /** * AnchorJS */ anchors.add('h2,h3,h4,h5'); + + // Add an "Edit on GitHub" button to each header (except h1) + let url = $('div.post-content').attr('data-github-edit-url'); + + $('div.post-content') + .find(':header:not(h1)') + .append( + ' ✏️️' + ); + // Check if TOC needs to be moved on page load moveToc(); - }); // needed for nav tabs on pages. See Formatting > Nav tabs for more details. // script from http://stackoverflow.com/questions/10523433/how-do-i-keep-the-current-tab-active-with-twitter-bootstrap-after-a-page-reload -$(function() { +$(function () { var json, tabsState; - $('a[data-toggle="pill"], a[data-toggle="tab"]').on('shown.bs.tab', function(e) { - var href, json, parentId, tabsState; + $('a[data-toggle="pill"], a[data-toggle="tab"]').on( + 'shown.bs.tab', + function (e) { + var href, json, parentId, tabsState; - tabsState = localStorage.getItem("tabs-state"); - json = JSON.parse(tabsState || "{}"); - parentId = $(e.target).parents("ul.nav.nav-pills, ul.nav.nav-tabs").attr("id"); - href = $(e.target).attr('href'); - json[parentId] = href; + tabsState = localStorage.getItem('tabs-state'); + json = JSON.parse(tabsState || '{}'); + parentId = $(e.target) + .parents('ul.nav.nav-pills, ul.nav.nav-tabs') + .attr('id'); + href = $(e.target).attr('href'); + json[parentId] = href; - return localStorage.setItem("tabs-state", JSON.stringify(json)); + return localStorage.setItem('tabs-state', JSON.stringify(json)); + } + ); + + tabsState = localStorage.getItem('tabs-state'); + json = JSON.parse(tabsState || '{}'); + + $.each(json, function (containerId, href) { + return $('#' + containerId + ' a[href=' + href + ']').tab('show'); }); - tabsState = localStorage.getItem("tabs-state"); - json = JSON.parse(tabsState || "{}"); - - $.each(json, function(containerId, href) { - return $("#" + containerId + " a[href=" + href + "]").tab('show'); - }); - - $("ul.nav.nav-pills, ul.nav.nav-tabs").each(function() { + $('ul.nav.nav-pills, ul.nav.nav-tabs').each(function () { var $this = $(this); - if (!json[$this.attr("id")]) { - return $this.find("a[data-toggle=tab]:first, a[data-toggle=pill]:first").tab("show"); + if (!json[$this.attr('id')]) { + return $this + .find('a[data-toggle=tab]:first, a[data-toggle=pill]:first') + .tab('show'); } }); }); // Check if TOC needs to be moved on window resizing -$(window).resize(function () {moveToc();}); \ No newline at end of file +$(window).resize(function () { + moveToc(); +}); From c082649ddab6f6055048b07d68099215c0e7b35d Mon Sep 17 00:00:00 2001 From: Bailey Tjiong Date: Tue, 15 Mar 2022 14:23:27 +0100 Subject: [PATCH 41/89] Remove h2 inline-block styling --- docs/css/customstyles.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/css/customstyles.css b/docs/css/customstyles.css index e37d5d5c5d..2e3e43e250 100644 --- a/docs/css/customstyles.css +++ b/docs/css/customstyles.css @@ -1327,10 +1327,6 @@ h4.panel-title { height: 100px; } -.post-content h2 { - display: inline-block; -} - a.edit-header { font-size: 15px; } From 5b31bae47c890ee02dfd1e94cca271f3885408c8 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 17 Mar 2022 11:13:28 +0100 Subject: [PATCH 42/89] Add @MetaBF as a contributor --- .all-contributorsrc | 9 +++ docs/pages/pmd/projectdocs/credits.md | 107 +++++++++++++------------- 2 files changed, 63 insertions(+), 53 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 7d94f872d8..992b42b86c 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -6566,6 +6566,15 @@ "contributions": [ "bug" ] + }, + { + "login": "MetaBF", + "name": "MetaBF", + "avatar_url": "https://avatars.githubusercontent.com/u/101029254?v=4", + "profile": "https://github.com/MetaBF", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index 6656093239..48d387d595 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -457,481 +457,482 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
    Matías Fraga

    💻 🐛
    Maxime Robert

    💻 🐛 +
    MetaBF

    🐛
    Michael

    🐛
    Michael Bell

    🐛
    Michael Bernstein

    🐛
    Michael Clay

    🐛 -
    Michael Dombrowski

    🐛 +
    Michael Dombrowski

    🐛
    Michael Hausegger

    🐛
    Michael Hoefer

    🐛
    Michael Möbius

    🐛
    Michael N. Lipp

    🐛
    Michael Pellegrini

    🐛
    Michal Kordas

    🐛 -
    Michał Borek

    🐛 +
    Michał Borek

    🐛
    Michał Kuliński

    🐛
    Miguel Núñez Díaz-Montes

    🐛
    Mihai Ionut

    🐛
    Mirek Hankus

    🐛
    Mladjan Gadzic

    🐛
    MrAngry52

    🐛 -
    Muminur Choudhury

    🐛 +
    Muminur Choudhury

    🐛
    Mykhailo Palahuta

    💻 🐛
    Nagendra Kumar Singh

    🐛
    Nahuel Barrios

    🐛
    Nathan Braun

    🐛
    Nathan Reynolds

    🐛
    Nathan Reynolds

    🐛 -
    Nathanaël

    🐛 +
    Nathanaël

    🐛
    Nazdravi

    🐛
    Neha-Dhonde

    🐛
    Nicholas Doyle

    🐛
    Nick Butcher

    🐛
    Nico Gallinal

    🐛
    Nicola Dal Maso

    🐛 -
    Nicolas Filotto

    💻 +
    Nicolas Filotto

    💻
    Nikita Chursin

    🐛
    Niklas Baudy

    🐛
    Nikolas Havrikov

    🐛
    Nilesh Virkar

    🐛
    Nimit Patel

    🐛
    Niranjan Harpale

    🐛 -
    Noah Sussman

    🐛 +
    Noah Sussman

    🐛
    Noah0120

    🐛
    Noam Tamim

    🐛
    Noel Grandin

    🐛
    Olaf Haalstra

    🐛
    Oleg Pavlenko

    🐛
    Oleksii Dykov

    💻 -
    Oliver Eikemeier

    🐛 +
    Oliver Eikemeier

    🐛
    Olivier Parent

    💻 🐛
    Ollie Abbey

    💻 🐛
    OverDrone

    🐛
    Ozan Gulle

    💻 🐛
    PUNEET JAIN

    🐛
    Parbati Bose

    🐛 -
    Paul Berg

    🐛 +
    Paul Berg

    🐛
    Pavel Bludov

    🐛
    Pavel Mička

    🐛
    Pedro Nuno Santos

    🐛
    Pedro Rijo

    🐛
    Pelisse Romain

    💻 📖 🐛
    Pete Davids

    🐛 -
    Peter Bruin

    🐛 +
    Peter Bruin

    🐛
    Peter Chittum

    💻 🐛
    Peter Cudmore

    🐛
    Peter Kasson

    🐛
    Peter Kofler

    🐛
    Pham Hai Trung

    🐛
    Philip Graf

    💻 🐛 -
    Philip Hachey

    🐛 +
    Philip Hachey

    🐛
    Philippe Ozil

    🐛
    Phinehas Artemix

    🐛
    Phokham Nonava

    🐛
    Piotr Szymański

    🐛
    Piotrek Żygieło

    💻 🐛
    Pranay Jaiswal

    🐛 -
    Prasad Kamath

    🐛 +
    Prasad Kamath

    🐛
    Prasanna

    🐛
    Presh-AR

    🐛
    Puneet1726

    🐛
    Rafael Cortês

    🐛
    RaheemShaik999

    🐛
    RajeshR

    💻 🐛 -
    Ramachandra Mohan

    🐛 +
    Ramachandra Mohan

    🐛
    Raquel Pau

    🐛
    Ravikiran Janardhana

    🐛
    Reda Benhemmouche

    🐛
    Renato Oliveira

    💻 🐛
    Rich DiCroce

    🐛
    Riot R1cket

    🐛 -
    Rishabh Jain

    🐛 +
    Rishabh Jain

    🐛
    RishabhDeep Singh

    🐛
    Robbie Martinus

    💻 🐛
    Robert Henry

    🐛
    Robert Painsi

    🐛
    Robert Russell

    🐛
    Robert Sösemann

    💻 📖 📢 🐛 -
    Robert Whitebit

    🐛 +
    Robert Whitebit

    🐛
    Robin Richtsfeld

    🐛
    Robin Stocker

    💻 🐛
    Robin Wils

    🐛
    RochusOest

    🐛
    Rodolfo Noviski

    🐛
    Rodrigo Casara

    🐛 -
    Rodrigo Fernandes

    🐛 +
    Rodrigo Fernandes

    🐛
    Roman Salvador

    💻 🐛
    Ronald Blaschke

    🐛
    Róbert Papp

    🐛
    Saikat Sengupta

    🐛
    Saksham Handu

    🐛
    Saladoc

    🐛 -
    Salesforce Bob Lightning

    🐛 +
    Salesforce Bob Lightning

    🐛
    Sam Carlberg

    🐛
    Satoshi Kubo

    🐛
    Scott Kennedy

    🐛
    Scott Wells

    🐛 💻
    Sebastian Bögl

    🐛
    Sebastian Schuberth

    🐛 -
    Sebastian Schwarz

    🐛 +
    Sebastian Schwarz

    🐛
    Sergey Gorbaty

    🐛
    Sergey Kozlov

    🐛
    Sergey Yanzin

    💻 🐛
    Shubham

    💻 🐛
    Simon Xiao

    🐛
    Srinivasan Venkatachalam

    🐛 -
    Stanislav Gromov

    🐛 +
    Stanislav Gromov

    🐛
    Stanislav Myachenkov

    💻
    Stefan Birkner

    🐛
    Stefan Bohn

    🐛
    Stefan Endrullis

    🐛
    Stefan Klöss-Schuster

    🐛
    Stefan Wolf

    🐛 -
    Stephan H. Wissel

    🐛 +
    Stephan H. Wissel

    🐛
    Stephen

    🐛
    Stephen Friedrich

    🐛
    Steve Babula

    💻
    Stexxe

    🐛
    Stian Lågstad

    🐛
    StuartClayton5

    🐛 -
    Supun Arunoda

    🐛 +
    Supun Arunoda

    🐛
    Suren Abrahamyan

    🐛
    SwatiBGupta1110

    🐛
    SyedThoufich

    🐛
    Szymon Sasin

    🐛
    T-chuangxin

    🐛
    TERAI Atsuhiro

    🐛 -
    TIOBE Software

    💻 🐛 +
    TIOBE Software

    💻 🐛
    Taylor Smock

    🐛
    Techeira Damián

    💻 🐛
    Ted Husted

    🐛
    TehBakker

    🐛
    The Gitter Badger

    🐛
    Theodoor

    🐛 -
    Thiago Henrique Hüpner

    🐛 +
    Thiago Henrique Hüpner

    🐛
    Thibault Meyer

    🐛
    Thomas Güttler

    🐛
    Thomas Jones-Low

    🐛
    Thomas Smith

    💻 🐛
    ThrawnCA

    🐛
    Thunderforge

    💻 🐛 -
    Tim van der Lippe

    🐛 +
    Tim van der Lippe

    🐛
    Tobias Weimer

    💻 🐛
    Tom Daly

    🐛
    Tomer Figenblat

    🐛
    Tomi De Lucca

    💻 🐛
    Torsten Kleiber

    🐛
    TrackerSB

    🐛 -
    Ullrich Hafner

    🐛 +
    Ullrich Hafner

    🐛
    Utku Cuhadaroglu

    💻 🐛
    Valentin Brandl

    🐛
    Valeria

    🐛
    Vasily Anisimov

    🐛
    Vickenty Fesunov

    🐛
    Victor Noël

    🐛 -
    Vincent Galloy

    💻 +
    Vincent Galloy

    💻
    Vincent HUYNH

    🐛
    Vincent Maurin

    🐛
    Vincent Privat

    🐛
    Vishhwas

    🐛
    Vitaly

    🐛
    Vitaly Polonetsky

    🐛 -
    Vojtech Polivka

    🐛 +
    Vojtech Polivka

    🐛
    Vsevolod Zholobov

    🐛
    Vyom Yadav

    💻
    Wang Shidong

    🐛
    Waqas Ahmed

    🐛
    Wayne J. Earl

    🐛
    Wchenghui

    🐛 -
    Will Winder

    🐛 +
    Will Winder

    🐛
    William Brockhus

    💻 🐛
    Wilson Kurniawan

    🐛
    Wim Deblauwe

    🐛
    Woongsik Choi

    🐛
    XenoAmess

    💻 🐛
    Yang

    💻 -
    YaroslavTER

    🐛 +
    YaroslavTER

    🐛
    Young Chan

    💻 🐛
    YuJin Kim

    🐛
    Yuri Dolzhenko

    🐛
    Yurii Dubinka

    🐛
    Zoltan Farkas

    🐛
    Zustin

    🐛 -
    aaronhurst-google

    🐛 +
    aaronhurst-google

    🐛
    alexmodis

    🐛
    andreoss

    🐛
    andrey81inmd

    💻 🐛
    anicoara

    🐛
    arunprasathav

    🐛
    asiercamara

    🐛 -
    astillich-igniti

    💻 +
    astillich-igniti

    💻
    avesolovksyy

    🐛
    avishvat

    🐛
    avivmu

    🐛
    axelbarfod1

    🐛
    b-3-n

    🐛
    balbhadra9

    🐛 -
    base23de

    🐛 +
    base23de

    🐛
    bergander

    🐛
    berkam

    💻 🐛
    breizh31

    🐛
    caesarkim

    🐛
    carolyujing

    🐛
    cesares-basilico

    🐛 -
    chrite

    🐛 +
    chrite

    🐛
    cobratbq

    🐛
    coladict

    🐛
    cosmoJFH

    🐛
    cristalp

    🐛
    crunsk

    🐛
    cwholmes

    🐛 -
    cyberjj999

    🐛 +
    cyberjj999

    🐛
    cyw3

    🐛
    d1ss0nanz

    🐛
    danbrycefairsailcom

    🐛
    dariansanity

    🐛
    darrenmiliband

    🐛
    davidburstrom

    🐛 -
    dbirkman-paloalto

    🐛 +
    dbirkman-paloalto

    🐛
    deepak-patra

    🐛
    dependabot[bot]

    💻 🐛
    dinesh150

    🐛
    diziaq

    🐛
    dreaminpast123

    🐛
    duanyanan

    🐛 -
    dutt-sanjay

    🐛 +
    dutt-sanjay

    🐛
    dylanleung

    🐛
    dzeigler

    🐛
    ekkirala

    🐛
    emersonmoura

    🐛
    fairy

    🐛
    filiprafalowicz

    💻 -
    foxmason

    🐛 +
    foxmason

    🐛
    frankegabor

    🐛
    frankl

    🐛
    freafrea

    🐛
    fsapatin

    🐛
    gracia19

    🐛
    guo fei

    🐛 -
    gurmsc5

    🐛 +
    gurmsc5

    🐛
    gwilymatgearset

    💻 🐛
    haigsn

    🐛
    hemanshu070

    🐛
    henrik242

    🐛
    hongpuwu

    🐛
    hvbtup

    💻 🐛 -
    igniti GmbH

    🐛 +
    igniti GmbH

    🐛
    ilovezfs

    🐛
    itaigilo

    🐛
    jakivey32

    🐛
    jbennett2091

    🐛
    jcamerin

    🐛
    jkeener1

    🐛 -
    jmetertea

    🐛 +
    jmetertea

    🐛
    johnra2

    💻
    josemanuelrolon

    💻 🐛
    kabroxiko

    💻 🐛
    karwer

    🐛
    kaulonline

    🐛
    kdaemonv

    🐛 -
    kenji21

    💻 🐛 +
    kenji21

    💻 🐛
    kfranic

    🐛
    khalidkh

    🐛
    krzyk

    🐛
    lasselindqvist

    🐛
    lihuaib

    🐛
    lonelyma1021

    🐛 -
    lpeddy

    🐛 +
    lpeddy

    🐛
    lujiefsi

    💻
    lyriccoder

    🐛
    marcelmore

    🐛
    matchbox

    🐛
    matthiaskraaz

    🐛
    meandonlyme

    🐛 -
    mikesive

    🐛 +
    mikesive

    🐛
    milossesic

    🐛
    mriddell95

    🐛
    mrlzh

    🐛
    msloan

    🐛
    mucharlaravalika

    🐛
    mvenneman

    🐛 -
    nareshl119

    🐛 +
    nareshl119

    🐛
    nicolas-harraudeau-sonarsource

    🐛
    noerremark

    🐛
    novsirion

    🐛
    oggboy

    🐛
    oinume

    🐛
    orimarko

    💻 🐛 -
    pallavi agarwal

    🐛 +
    pallavi agarwal

    🐛
    parksungrin

    🐛
    patpatpat123

    🐛
    patriksevallius

    🐛
    pbrajesh1

    🐛
    phoenix384

    🐛
    piotrszymanski-sc

    💻 -
    plan3d

    🐛 +
    plan3d

    🐛
    poojasix

    🐛
    prabhushrikant

    🐛
    pujitha8783

    🐛
    r-r-a-j

    🐛
    raghujayjunk

    🐛
    rajeshveera

    🐛 -
    rajeswarreddy88

    🐛 +
    rajeswarreddy88

    🐛
    recdevs

    🐛
    reudismam

    💻 🐛
    rijkt

    🐛
    rillig-tk

    🐛
    rmohan20

    💻 🐛
    rxmicro

    🐛 -
    ryan-gustafson

    💻 🐛 +
    ryan-gustafson

    💻 🐛
    sabi0

    🐛
    scais

    🐛
    sebbASF

    🐛
    sergeygorbaty

    💻
    shilko2013

    🐛
    simeonKondr

    🐛 -
    snajberk

    🐛 +
    snajberk

    🐛
    sniperrifle2004

    🐛
    snuyanzin

    🐛 💻
    sratz

    🐛
    stonio

    🐛
    sturton

    💻 🐛
    sudharmohan

    🐛 -
    suruchidawar

    🐛 +
    suruchidawar

    🐛
    svenfinitiv

    🐛
    tashiscool

    🐛
    test-git-hook

    🐛
    testation21

    💻 🐛
    thanosa

    🐛
    tiandiyixian

    🐛 -
    tobwoerk

    🐛 +
    tobwoerk

    🐛
    tprouvot

    🐛
    trentchilders

    🐛
    triandicAnt

    🐛
    trishul14

    🐛
    tsui

    🐛
    winhkey

    🐛 -
    witherspore

    🐛 +
    witherspore

    🐛
    wjljack

    🐛
    wuchiuwong

    🐛
    xingsong

    🐛
    xioayuge

    🐛
    xnYi9wRezm

    💻 🐛
    xuanuy

    🐛 -
    xyf0921

    🐛 +
    xyf0921

    🐛
    yalechen-cyw3

    🐛
    yasuharu-sato

    🐛
    zenglian

    🐛
    zgrzyt93

    💻 🐛
    zh3ng

    🐛
    zt_soft

    🐛 -
    ztt79

    🐛 +
    ztt79

    🐛
    zzzzfeng

    🐛
    Árpád Magosányi

    🐛
    任贵杰

    🐛 From 4a805f4284d47b6a660e8cfca719f67056fb2d29 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 17 Mar 2022 11:14:54 +0100 Subject: [PATCH 43/89] [java] Fix ClassWithOnlyPrivateConstructorsShouldBeFinal with multiple classes Fixes #3851 --- docs/pages/release_notes.md | 2 ++ .../src/main/resources/category/java/design.xml | 16 +++++++++++----- ...sWithOnlyPrivateConstructorsShouldBeFinal.xml | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index ae817d64cb..2e198cd082 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -57,6 +57,8 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is * [#3299](https://github.com/pmd/pmd/issues/3299): \[core] Deprecate system properties of PMDCommandLineInterface * doc * [#3812](https://github.com/pmd/pmd/issues/3812): \[doc] Documentation website table of contents broken on pages with many subheadings +* java-design + * [#3851](https://github.com/pmd/pmd/issues/3851): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal - false negative when a compilation unit contains two class declarations ### API Changes diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index 1b30305f92..f071a261f9 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -338,11 +338,17 @@ is invoked by a inner class. diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml index f7c9e75d8b..8d6ffe733b 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml @@ -170,6 +170,21 @@ public class Outer { private abstract class Base { private void run() {} } +} + ]]> + + + + [java] ClassWithOnlyPrivateConstructorsShouldBeFinal - false negative when a compilation unit contains two class declarations #3851 + 1 + 1 + From b22990a6683a03cb3ddfa1c709013d5a56c3e55e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 17 Mar 2022 11:56:27 +0100 Subject: [PATCH 44/89] [java] Fix ImmutableField with conditionally assignment in ctors Fixes #3850 --- docs/pages/release_notes.md | 2 ++ .../java/rule/design/ImmutableFieldRule.java | 27 ++++++++----------- .../java/rule/design/xml/ImmutableField.xml | 27 ++++++++++++++++--- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index ae817d64cb..1eff821893 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -57,6 +57,8 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is * [#3299](https://github.com/pmd/pmd/issues/3299): \[core] Deprecate system properties of PMDCommandLineInterface * doc * [#3812](https://github.com/pmd/pmd/issues/3812): \[doc] Documentation website table of contents broken on pages with many subheadings +* java-design + * [#3850](https://github.com/pmd/pmd/issues/3850): \[java] ImmutableField - false negative when field assigned in constructor conditionally ### API Changes diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java index 95936b2b45..76fb6639f1 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java @@ -16,9 +16,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; import net.sourceforge.pmd.lang.java.ast.ASTForStatement; -import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; @@ -60,11 +58,15 @@ public class ImmutableFieldRule extends AbstractLombokAwareRule { continue; } - FieldImmutabilityType type = initializedInConstructor(field, entry.getValue(), new HashSet<>(constructors)); + List usages = entry.getValue(); + FieldImmutabilityType type = initializedInConstructor(field, usages, new HashSet<>(constructors)); if (type == FieldImmutabilityType.MUTABLE) { continue; } - if (type == FieldImmutabilityType.IMMUTABLE || type == FieldImmutabilityType.CHECKDECL && initializedWhenDeclared(field)) { + if (initializedWhenDeclared(field) && usages.isEmpty()) { + addViolation(data, field.getNode(), field.getImage()); + } + if (type == FieldImmutabilityType.IMMUTABLE || type == FieldImmutabilityType.CHECKDECL && !initializedWhenDeclared(field)) { addViolation(data, field.getNode(), field.getImage()); } } @@ -90,14 +92,7 @@ public class ImmutableFieldRule extends AbstractLombokAwareRule { methodInitCount++; continue; } - // Check for assigns in if-statements, which can depend on - // constructor - // args or other runtime knowledge and can be a valid reason - // to instantiate - // in one constructor only - if (node.getFirstParentOfType(ASTIfStatement.class) != null) { - methodInitCount++; - } + if (inAnonymousInnerClass(node)) { methodInitCount++; } else if (node.getFirstParentOfType(ASTLambdaExpression.class) != null) { @@ -106,15 +101,15 @@ public class ImmutableFieldRule extends AbstractLombokAwareRule { consSet.add(constructor); } } else { - if (node.getFirstParentOfType(ASTMethodDeclaration.class) != null) { - methodInitCount++; - } else if (node.getFirstParentOfType(ASTLambdaExpression.class) != null) { + if (node.getFirstParentOfType(ASTLambdaExpression.class) != null) { lambdaUsage++; + } else { + methodInitCount++; } } } } - if (usages.isEmpty() || methodInitCount == 0 && lambdaUsage == 0 && consSet.isEmpty()) { + if (usages.isEmpty() || methodInitCount == 0 && lambdaUsage == 0 && allConstructors.equals(consSet)) { result = FieldImmutabilityType.CHECKDECL; } else { allConstructors.removeAll(consSet); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml index bd207fa1ad..359a1ce214 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml @@ -294,7 +294,7 @@ public final class Foo { 0 Bug 1740480, assignment in single constructor based on constructor argument check - 0 + 1 + 2 0) { @@ -548,6 +549,26 @@ public class TestFinal { while (random.nextBoolean()) e = e.add(BigInteger.ONE); } +} + ]]> + + + + [java] ImmutableField - false negative when field assigned in constructor conditionally #3850 + 1 + 3 + From cb8386f98e49044a1e118ef8b62d9c82fc96b8a1 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 17 Mar 2022 12:04:54 +0100 Subject: [PATCH 45/89] Suppress ClassWithOnlyPrivateConstructorsShouldBeFinal Can't just make this class final, as it is public API. --- .../java/net/sourceforge/pmd/lang/metrics/MetricOptions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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..ccce918879 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 @@ -17,7 +17,7 @@ import java.util.Set; * @author Clément Fournier * @since 6.0.0 */ -public class MetricOptions { +public class MetricOptions { // NOPMD: this class should be final, but is public API private static final Map POOL = new HashMap<>(); private static final MetricOptions EMPTY_OPTIONS; From 5f9e2d4426769d9798f88f2eb824180e776fb556 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 17 Mar 2022 12:29:48 +0100 Subject: [PATCH 46/89] [ci] Fix project-list for spring We modify (among other files) AutowiredAnnotationBeanPostProcessor.java but only, when we intend to build the project. This leads to the situation, that the baseline was created against the modified file, but PRs use the unmodified file. This is because the regression-tester does a "git reset --hard" before running PMD. --- .ci/files/project-list.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.ci/files/project-list.xml b/.ci/files/project-list.xml index d50d3f2c2b..8757b1d38a 100644 --- a/.ci/files/project-list.xml +++ b/.ci/files/project-list.xml @@ -39,10 +39,6 @@ mvn dependency:build-classpath -DincludeScope=test -Dmdep.outputFile=classpath.t .*/build/generated-sources/.* classpath.txt ]]> From fbcfebd1a9854cef1a543bad4bb16cf402635c6d Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 18 Mar 2022 15:48:08 +0100 Subject: [PATCH 47/89] [ci] Add apex projects for regression testing Refs #2693 Dangerfile is copied from pmd/7.0.x and adjusted slightly: autogen is used now for both branches again. --- ...{all-java.xml => all-regression-rules.xml} | 13 ++- .ci/files/project-list.xml | 22 ++++ .ci/inc/regression-tester.inc | 2 +- Dangerfile | 108 ++++++++++++------ 4 files changed, 109 insertions(+), 36 deletions(-) rename .ci/files/{all-java.xml => all-regression-rules.xml} (54%) diff --git a/.ci/files/all-java.xml b/.ci/files/all-regression-rules.xml similarity index 54% rename from .ci/files/all-java.xml rename to .ci/files/all-regression-rules.xml index 2a4f1345dc..12fceb6fec 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-regression-rules.xml @@ -1,10 +1,19 @@ - - Every java rule in PMD which is used for the regression tests with pmdtester + Every apex and java rule in PMD which is used for the regression tests with pmdtester + + + + + + + + + diff --git a/.ci/files/project-list.xml b/.ci/files/project-list.xml index d50d3f2c2b..7c29d72150 100644 --- a/.ci/files/project-list.xml +++ b/.ci/files/project-list.xml @@ -145,4 +145,26 @@ EOF jdk-11+28 src/java.base + + + Schedul-o-matic-9000 + git + https://github.com/SalesforceLabs/Schedul-o-matic-9000 + 6b1229ba43b38931fbbab5924bc9b9611d19a786 + + + + fflib-apex-common + git + https://github.com/apex-enterprise-patterns/fflib-apex-common + 991bcbc20b017935405499c115309cadd1f8af9b + + + + apex-link + git + https://github.com/nawforce/apex-link + v2.3.0 + samples + diff --git a/.ci/inc/regression-tester.inc b/.ci/inc/regression-tester.inc index 3fe7fa0e89..d2fff0d45e 100644 --- a/.ci/inc/regression-tester.inc +++ b/.ci/inc/regression-tester.inc @@ -48,7 +48,7 @@ function regression_tester_uploadBaseline() { --mode single \ --local-git-repo ./pmd \ --patch-branch "${baseline_branch}" \ - --patch-config ./pmd/.ci/files/all-java.xml \ + --patch-config ./pmd/.ci/files/all-regression-rules.xml \ --list-of-project ./pmd/.ci/files/project-list.xml --html-flag \ --error-recovery pushd target/reports || { echo "Directory 'target/reports' doesn't exist"; exit 1; } diff --git a/Dangerfile b/Dangerfile index 5a861d8567..735dc7d737 100644 --- a/Dangerfile +++ b/Dangerfile @@ -1,26 +1,68 @@ require 'pmdtester' require 'time' require 'logger' +require 'fileutils' @logger = Logger.new(STDOUT) +def get_args(base_branch, autogen = TRUE, patch_config = './pmd/.ci/files/all-regression-rules.xml') + ['--local-git-repo', './pmd', + '--list-of-project', './pmd/.ci/files/project-list.xml', + '--base-branch', base_branch, + '--patch-branch', 'HEAD', + '--patch-config', patch_config, + '--mode', 'online', + autogen ? '--auto-gen-config' : '--filter-with-patch-config', + '--keep-reports', + '--error-recovery', + '--baseline-download-url', 'https://pmd-code.org/pmd-regression-tester/', + # '--debug', + ] +end + def run_pmdtester Dir.chdir('..') do - branch_name = "#{ENV['PMD_CI_BRANCH']}" - argv = ['--local-git-repo', './pmd', - '--list-of-project', './pmd/.ci/files/project-list.xml', - '--base-branch', branch_name, - '--patch-branch', 'HEAD', - '--patch-config', './pmd/.ci/files/all-java.xml', - '--mode', 'online', - '--auto-gen-config', - '--error-recovery', - '--baseline-download-url', 'https://pmd-code.org/pmd-regression-tester/', - #'--debug', - ] begin - @summary = PmdTester::Runner.new(argv).run - upload_report + @base_branch = ENV['PMD_CI_BRANCH'] + @logger.info "\n\n--------------------------------------" + @logger.info "Run against PR base #{@base_branch}" + @summary = PmdTester::Runner.new(get_args(@base_branch)).run + + unless Dir.exist?('target/reports/diff') + message("No regression tested rules have been changed.", sticky: true) + return + end + + # move the generated report out of the way + FileUtils.mv 'target/reports/diff', 'target/diff1' + message1 = create_message + + # run against master branch (if the PR is not already against master) + unless ENV['PMD_CI_BRANCH'] == 'master' + @base_branch = 'master' + @logger.info "\n\n--------------------------------------" + @logger.info "Run against #{@base_branch}" + @summary = PmdTester::Runner.new(get_args(@base_branch)).run + + # move the generated report out of the way + FileUtils.mv 'target/reports/diff', 'target/diff2' + message2 = create_message + end + + report_url = upload_report + + if report_url + message1 += "[Full report](#{report_url}/diff1/index.html)" + # set value of sticky to true and the message is kept after new commits are submitted to the PR + message(message1, sticky: true) + + if message2 + message2 += "[Full report](#{report_url}/diff2/index.html)" + # set value of sticky to true and the message is kept after new commits are submitted to the PR + message(message2, sticky: true) + end + end + rescue StandardError => e warn("Running pmdtester failed, this message is mainly used to remind the maintainers of PMD.") @logger.error "Running pmdtester failed: #{e.inspect}" @@ -28,34 +70,34 @@ def run_pmdtester end end -def upload_report - Dir.chdir('target/reports') do - tar_filename = "pr-#{ENV['PMD_CI_PULL_REQUEST_NUMBER']}-diff-report-#{Time.now.strftime("%Y-%m-%dT%H-%M-%SZ")}.tar.gz" - unless Dir.exist?('diff/') - message("No java rules are changed!", sticky: true) - return - end +def create_message + "Compared to #{@base_branch}:\n"\ + "This changeset " \ + "changes #{@summary[:violations][:changed]} violations,\n" \ + "introduces #{@summary[:violations][:new]} new violations, " \ + "#{@summary[:errors][:new]} new errors and " \ + "#{@summary[:configerrors][:new]} new configuration errors,\n" \ + "removes #{@summary[:violations][:removed]} violations, "\ + "#{@summary[:errors][:removed]} errors and " \ + "#{@summary[:configerrors][:removed]} configuration errors.\n" +end - `tar czf #{tar_filename} diff/` +def upload_report + Dir.chdir('target') do + tar_filename = "pr-#{ENV['PMD_CI_PULL_REQUEST_NUMBER']}-diff-report-#{Time.now.strftime("%Y-%m-%dT%H-%M-%SZ")}.tar.gz" + + `tar czf #{tar_filename} diff1/ diff2/` tar_size = (10 * File.size(tar_filename) / 1024 / 1024)/10.0 @logger.info "Uploading file #{tar_filename} (#{tar_size}mb) now..." report_url = `curl -u #{ENV['PMD_CI_CHUNK_TOKEN']} -T #{tar_filename} https://chunk.io` if $?.success? + report_url.chomp! @logger.info "Successfully uploaded #{tar_filename} to #{report_url}" - - # set value of sticky to true and the message is kept after new commits are submitted to the PR - message("This changeset " \ - "changes #{@summary[:violations][:changed]} violations,\n" \ - "introduces #{@summary[:violations][:new]} new violations, " \ - "#{@summary[:errors][:new]} new errors and " \ - "#{@summary[:configerrors][:new]} new configuration errors,\n" \ - "removes #{@summary[:violations][:removed]} violations, "\ - "#{@summary[:errors][:removed]} errors and " \ - "#{@summary[:configerrors][:removed]} configuration errors.\n" \ - "[Full report](#{report_url.chomp}/diff/index.html)", sticky: true) + report_url else @logger.error "Error while uploading #{tar_filename} to chunk.io: #{report_url}" warn("Uploading the diff report failed, this message is mainly used to remind the maintainers of PMD.") + nil end end end From 67928910df25574ec41821b60d352e5f32bfe971 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 18 Mar 2022 15:51:15 +0100 Subject: [PATCH 48/89] REVERT ME - Use pmtester from pmd/pmd-regression-tester#103 And also make a change in core to run it --- Gemfile | 3 ++- Gemfile.lock | 24 ++++++++++++------- .../main/java/net/sourceforge/pmd/PMD.java | 1 + 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 5e0616a5b4..0216265f49 100644 --- a/Gemfile +++ b/Gemfile @@ -2,8 +2,9 @@ source 'https://rubygems.org/' # bleeding edge from git #gem 'pmdtester', :git => 'https://github.com/pmd/pmd-regression-tester.git', branch: 'master' +gem 'pmdtester', :git => 'https://github.com/adangel/pmd-regression-tester.git', branch: 'auto-gen-config-all' -gem 'pmdtester' +#gem 'pmdtester' gem 'danger' # This group is only needed for rendering release notes (docs/render_release_notes.rb) diff --git a/Gemfile.lock b/Gemfile.lock index 3c5a1abe22..b1fcd6da80 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,16 @@ +GIT + remote: https://github.com/adangel/pmd-regression-tester.git + revision: 44a62cd72a839e821a8160429c873f5dad362c83 + branch: auto-gen-config-all + specs: + pmdtester (1.3.1.pre.SNAPSHOT) + differ (~> 0.1) + liquid (~> 5.2) + logger-colors (~> 1.0) + nokogiri (~> 1.13) + rufus-scheduler (~> 3.8) + slop (~> 4.6) + GEM remote: https://rubygems.org/ specs: @@ -12,7 +25,7 @@ GEM concurrent-ruby (1.1.9) cork (0.3.0) colored2 (~> 3.1) - danger (8.4.5) + danger (8.5.0) claide (~> 1.0) claide-plugins (>= 0.9.2) colored2 (~> 3.1) @@ -75,13 +88,6 @@ GEM faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) open4 (1.3.4) - pmdtester (1.3.0) - differ (~> 0.1) - liquid (>= 4.0) - logger-colors (~> 1.0) - nokogiri (>= 1.11.0.rc4) - rufus-scheduler (~> 3.5) - slop (~> 4.6) public_suffix (4.0.6) raabro (1.4.0) racc (1.6.0) @@ -108,7 +114,7 @@ PLATFORMS DEPENDENCIES danger liquid (>= 4.0.0) - pmdtester + pmdtester! rouge (>= 1.7, < 4) safe_yaml (>= 1.0) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index 714bfb0e64..f26772032f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -63,6 +63,7 @@ import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter; */ public class PMD { + private static final Logger LOG = Logger.getLogger(PMD.class.getName()); /** From 16fb7a546ac9a58358933e812c19223fd1ff9f66 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 18 Mar 2022 16:34:48 +0100 Subject: [PATCH 49/89] Use forked repos and tag "pmd-regression-test" --- .ci/files/project-list.xml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.ci/files/project-list.xml b/.ci/files/project-list.xml index 7c29d72150..7b8ed638ad 100644 --- a/.ci/files/project-list.xml +++ b/.ci/files/project-list.xml @@ -149,15 +149,23 @@ EOF Schedul-o-matic-9000 git + https://github.com/pmd/Schedul-o-matic-9000 + + pmd-regression-test fflib-apex-common git + https://github.com/pmd/fflib-apex-common + + pmd-regression-test From f2db24ffbbf9d3fa3d733beac7a747a45ecdea4f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 18 Mar 2022 17:04:02 +0100 Subject: [PATCH 50/89] Use new caches in CI build --- .github/workflows/build.yml | 4 ++-- .github/workflows/troubleshooting.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dd481af5a0..566fc4f2fd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,9 +33,9 @@ jobs: ~/.cache ~/work/pmd/target/repositories vendor/bundle - key: v2-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} + key: v3-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} restore-keys: | - v2-${{ runner.os }}- + v3-${{ runner.os }}- - name: Set up Ruby 2.7 uses: ruby/setup-ruby@v1 with: diff --git a/.github/workflows/troubleshooting.yml b/.github/workflows/troubleshooting.yml index 4554ddedf7..dc8f796c12 100644 --- a/.github/workflows/troubleshooting.yml +++ b/.github/workflows/troubleshooting.yml @@ -21,9 +21,9 @@ jobs: ~/.cache ~/work/pmd/target/repositories vendor/bundle - key: v2-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} + key: v3-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} restore-keys: | - v2-${{ runner.os }}- + v3-${{ runner.os }}- - name: Set up Ruby 2.7 uses: ruby/setup-ruby@v1 with: From 656ec30c8880b28fa8ee9029e884b80a6d4363b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 19 Mar 2022 15:57:57 +0100 Subject: [PATCH 51/89] Add new DOM xpath rule for xml --- pmd-core/pom.xml | 1 - .../lang/rule/xpath/SaxonXPathRuleQuery.java | 6 +- .../pmd/lang/xpath/PMDFunctions.java | 30 +++- pmd-xml/pom.xml | 5 + .../lang/xml/ast/AbstractDomNodeProxy.java | 3 + .../pmd/lang/xml/ast/XmlNodeWrapper.java | 7 + .../pmd/lang/xml/ast/XmlParser.java | 6 + .../pmd/lang/xml/rule/DomXPathRule.java | 55 +++++++ .../pmd/lang/xml/rule/SaxonDomXPathQuery.java | 154 ++++++++++++++++++ .../pmd/lang/xml/rule/XmlXPathRuleTest.java | 7 +- 10 files changed, 264 insertions(+), 10 deletions(-) create mode 100644 pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java create mode 100644 pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml index 7f85c7240c..407f03410e 100644 --- a/pmd-core/pom.xml +++ b/pmd-core/pom.xml @@ -150,7 +150,6 @@ net.sourceforge.saxon saxon dom - runtime diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java index 2a8815798c..eafc895205 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java @@ -177,7 +177,11 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { } - private ValueRepresentation getRepresentation(final PropertyDescriptor descriptor, final Object value) { + /** + * Internal: this has been moved in PMD 7. + */ + @InternalApi + public static ValueRepresentation getRepresentation(final PropertyDescriptor descriptor, final Object value) { if (descriptor.isMultiValue()) { return getSequenceRepresentation((List) value); } else { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java index 54853ea1f9..3c878d917b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java @@ -4,17 +4,24 @@ package net.sourceforge.pmd.lang.xpath; +import java.util.logging.Logger; + import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.xpath.internal.FileNameXPathFunction; import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; +import net.sf.saxon.dom.NodeWrapper; import net.sf.saxon.expr.XPathContext; +import net.sf.saxon.om.Item; @InternalApi @Deprecated public final class PMDFunctions { + + private static final Logger LOG = Logger.getLogger(PMDFunctions.class.getName()); + private PMDFunctions() { } public static boolean matches(String s, String pattern1) { @@ -34,17 +41,32 @@ public final class PMDFunctions { } public static boolean matches(String s, String pattern1, String pattern2, String pattern3, String pattern4, - String pattern5) { + String pattern5) { return MatchesFunction.matches(s, pattern1, pattern2, pattern3, pattern4, pattern5); } public static boolean matches(String s, String pattern1, String pattern2, String pattern3, String pattern4, - String pattern5, String pattern6) { + String pattern5, String pattern6) { return MatchesFunction.matches(s, pattern1, pattern2, pattern3, pattern4, pattern5, pattern6); } public static String fileName(final XPathContext context) { - Node ctxNode = ((ElementNode) context.getContextItem()).getUnderlyingNode(); - return FileNameXPathFunction.getFileName(ctxNode); + Item contextItem = context.getContextItem(); + Node node = itemToNode(contextItem); + return node == null ? null : FileNameXPathFunction.getFileName(node); + } + + private static Node itemToNode(Object item) { + if (item instanceof Node) { + return (Node) item; + } else if (item instanceof ElementNode) { // todo pmd 7 remove this branch as ElementNode extends NodeWrapper + return itemToNode(((ElementNode) item).getUnderlyingNode()); + } else if (item instanceof NodeWrapper) { + return itemToNode(((NodeWrapper) item).getUnderlyingNode()); + } else if (item instanceof org.w3c.dom.Node) { + return itemToNode(((org.w3c.dom.Node) item).getUserData("pmd.node")); + } + LOG.fine("Cannot call pmd:filename on " + item); + return null; } } diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml index 7de7c95fcd..475136345d 100644 --- a/pmd-xml/pom.xml +++ b/pmd-xml/pom.xml @@ -47,6 +47,11 @@ commons-io commons-io + + net.sourceforge.saxon + saxon + dom + junit diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/AbstractDomNodeProxy.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/AbstractDomNodeProxy.java index 1d29bac077..40669b710f 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/AbstractDomNodeProxy.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/AbstractDomNodeProxy.java @@ -19,7 +19,10 @@ import net.sourceforge.pmd.lang.ast.AbstractNode; * * @author Clément Fournier * @since 6.1.0 + * + * @deprecated Will be removed in PMD 7, use subclasses as PMD Nodes but not DOM nodes. */ +@Deprecated public abstract class AbstractDomNodeProxy extends AbstractNode implements org.w3c.dom.Node { protected final org.w3c.dom.Node node; diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java index 2e70d3ce8b..d642c87d42 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java @@ -24,6 +24,8 @@ import net.sourceforge.pmd.util.CompoundIterator; /** * Proxy wrapping an XML DOM node ({@link org.w3c.dom.Node}) to implement PMD interfaces. + * Note: you should only use it as a PMD {@link Node}, the DOM Node implementation + * is inconsistent. If you need a dom node, call {@link #getNode()}. * * @author Clément Fournier * @since 6.1.0 @@ -36,9 +38,14 @@ public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode { public XmlNodeWrapper(XmlParser parser, org.w3c.dom.Node domNode) { super(domNode); + domNode.setUserData("pmd.node", this, null); this.parser = parser; } + protected XmlNode wrap(org.w3c.dom.Node domNode) { + return parser.wrapDomNode(domNode); + } + @Override public void jjtClose() { diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java index 4f0f9286aa..7fc7d0103c 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java @@ -90,9 +90,15 @@ public class XmlParser { * The root should implement {@link RootNode}. */ public static class RootXmlNode extends XmlNodeWrapper implements RootNode { + RootXmlNode(XmlParser parser, Node domNode) { super(parser, domNode); } + + @Override + public XmlNode wrap(Node domNode) { + return super.wrap(domNode); + } } } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java new file mode 100644 index 0000000000..00ad33c5c7 --- /dev/null +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -0,0 +1,55 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.xml.rule; + +import java.util.List; + +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.rule.AbstractRule; +import net.sourceforge.pmd.lang.xml.ast.XmlParser.RootXmlNode; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; + +public class DomXPathRule extends AbstractRule { + + SaxonDomXPathQuery query; + + private static final PropertyDescriptor XPATH_EXPR + = PropertyFactory.stringProperty("xpath") + .desc("An XPath 2.0 expression that will be evaluated against the root DOM") + .defaultValue("") // no default value + .build(); + + + public DomXPathRule() { + definePropertyDescriptor(XPATH_EXPR); + } + + + public DomXPathRule(String xpath) { + this(); + setProperty(XPATH_EXPR, xpath); + } + + @Override + public void apply(List nodes, RuleContext ctx) { + for (Node n : nodes) { + RootXmlNode root = (RootXmlNode) n; + SaxonDomXPathQuery query = getXPathQuery(); + for (Node foundNode : query.evaluate(root, this)) { + ctx.addViolation(foundNode); + } + } + } + + private SaxonDomXPathQuery getXPathQuery() { + if (query == null) { + query = new SaxonDomXPathQuery(getProperty(XPATH_EXPR), getPropertyDescriptors()); + } + return query; + } + +} diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java new file mode 100644 index 0000000000..78a2b46b0f --- /dev/null +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java @@ -0,0 +1,154 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.xml.rule; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; + +import org.apache.commons.lang3.exception.ContextedRuntimeException; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; +import net.sourceforge.pmd.lang.xml.ast.XmlNode; +import net.sourceforge.pmd.lang.xml.ast.XmlParser.RootXmlNode; +import net.sourceforge.pmd.lang.xpath.Initializer; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertySource; +import net.sourceforge.pmd.util.DataMap; +import net.sourceforge.pmd.util.DataMap.DataKey; +import net.sourceforge.pmd.util.DataMap.SimpleDataKey; + +import net.sf.saxon.Configuration; +import net.sf.saxon.dom.DocumentWrapper; +import net.sf.saxon.dom.NodeWrapper; +import net.sf.saxon.om.NamePool; +import net.sf.saxon.om.NamespaceConstant; +import net.sf.saxon.om.ValueRepresentation; +import net.sf.saxon.sxpath.IndependentContext; +import net.sf.saxon.sxpath.XPathDynamicContext; +import net.sf.saxon.sxpath.XPathEvaluator; +import net.sf.saxon.sxpath.XPathExpression; +import net.sf.saxon.sxpath.XPathStaticContext; +import net.sf.saxon.sxpath.XPathVariable; +import net.sf.saxon.trans.XPathException; + +final class SaxonDomXPathQuery { + + private static final NamePool NAME_POOL = new NamePool(); + + private static final SimpleDataKey SAXON_DOM_WRAPPER + = DataMap.simpleDataKey("pmd.saxon.dom.wrapper"); + + private final String xpath; + private final XPathExpression xpathExpression; + private final Map, XPathVariable> xpathVariables; + + private final Configuration configuration; + + public SaxonDomXPathQuery(String xpath, List> properties) { + this.xpath = xpath; + final XPathEvaluator xpathEvaluator = new XPathEvaluator(); + final XPathStaticContext xpathStaticContext = xpathEvaluator.getStaticContext(); + ((IndependentContext) xpathStaticContext).declareNamespace("fn", NamespaceConstant.FN); + configuration = xpathStaticContext.getConfiguration(); + configuration.setNamePool(NAME_POOL); + + // Register PMD functions + Initializer.initialize((IndependentContext) xpathStaticContext); + + this.xpathVariables = makeXPathVariables(properties, xpathStaticContext); + + try { + this.xpathExpression = xpathEvaluator.createExpression(xpath); + } catch (final XPathException e) { + throw new ContextedRuntimeException(e) + .addContextValue("XPath", xpath); + } + } + + private Map, XPathVariable> makeXPathVariables(List> accessibleProperties, XPathStaticContext xpathStaticContext) { + Map, XPathVariable> xpathVariables = new HashMap<>(); + for (final PropertyDescriptor propertyDescriptor : accessibleProperties) { + final String name = propertyDescriptor.name(); + if (!isExcludedProperty(name)) { + final XPathVariable xpathVariable = xpathStaticContext.declareVariable(null, name); + xpathVariables.put(propertyDescriptor, xpathVariable); + } + } + return Collections.unmodifiableMap(xpathVariables); + } + + private boolean isExcludedProperty(String name) { + return "xpath".equals(name) + || "violationSuppressRegex".equals(name) + || "violationSuppressXPath".equals(name); + } + + @Override + public String toString() { + return xpath; + } + + public List evaluate(RootXmlNode root, PropertySource propertyValues) { + DocumentWrapper wrapper = getSaxonDomWrapper(root); + XPathDynamicContext dynamicContext = createDynamicContext(wrapper, propertyValues); + try { + List result = new ArrayList<>(); + for (Object item : xpathExpression.evaluate(dynamicContext)) { + if (item instanceof NodeWrapper) { + NodeWrapper nodeInfo = (NodeWrapper) item; + Object domNode = nodeInfo.getUnderlyingNode(); + if (domNode instanceof org.w3c.dom.Node) { + XmlNode wrapped = root.wrap((org.w3c.dom.Node) domNode); + result.add(wrapped); + } + } + } + return result; + } catch (XPathException e) { + throw new ContextedRuntimeException(e) + .addContextValue("XPath", xpath); + } + + } + + private DocumentWrapper getSaxonDomWrapper(RootXmlNode node) { + DataMap> userMap = node.getUserMap(); + if (userMap.isSet(SAXON_DOM_WRAPPER)) { + return userMap.get(SAXON_DOM_WRAPPER); + } + org.w3c.dom.Node domRoot = node.getNode(); + DocumentWrapper wrapper = new DocumentWrapper( + domRoot, domRoot.getBaseURI(), configuration + ); + userMap.set(SAXON_DOM_WRAPPER, wrapper); + return wrapper; + } + + private XPathDynamicContext createDynamicContext(final DocumentWrapper elementNode, PropertySource properties) { + final XPathDynamicContext dynamicContext = xpathExpression.createDynamicContext(elementNode); + + // Set variable values on the dynamic context + for (final Entry, XPathVariable> entry : xpathVariables.entrySet()) { + Object value = properties.getProperty(entry.getKey()); + Objects.requireNonNull(value, "null property value for " + entry.getKey()); + final ValueRepresentation saxonValue = SaxonXPathRuleQuery.getRepresentation(entry.getKey(), entry.getValue()); + try { + dynamicContext.setVariable(entry.getValue(), saxonValue); + } catch (XPathException e) { + throw new ContextedRuntimeException(e) + .addContextValue("Variable", entry.getValue()) + .addContextValue("XPath", xpath); + } + } + return dynamicContext; + } + +} diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java index ef22aa88d8..aa7f7e63e4 100644 --- a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java @@ -9,9 +9,8 @@ import static net.sourceforge.pmd.lang.ast.test.TestUtilsKt.assertSize; import org.junit.Test; import net.sourceforge.pmd.Report; +import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; import net.sourceforge.pmd.lang.xml.XmlLanguageModule; import net.sourceforge.pmd.lang.xml.XmlParsingHelper; @@ -19,8 +18,8 @@ public class XmlXPathRuleTest { final XmlParsingHelper xml = XmlParsingHelper.XML; - private XPathRule makeXPath(String expression) { - XPathRule rule = new XPathRule(XPathVersion.XPATH_2_0, expression); + private Rule makeXPath(String expression) { + DomXPathRule rule = new DomXPathRule(expression); rule.setLanguage(LanguageRegistry.getLanguage(XmlLanguageModule.NAME)); rule.setMessage("XPath Rule Failed"); return rule; From 00d391261d90afb005aac22dd9e1beaccb13766a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 19 Mar 2022 16:50:55 +0100 Subject: [PATCH 52/89] More tests, handle namespaces We have to reparse the expression with the correct URI if the input document has an unnamed URI. --- .../net/sourceforge/pmd/util/DataMap.java | 2 +- .../pmd/lang/xml/ast/XmlParser.java | 7 +- .../pmd/lang/xml/rule/SaxonDomXPathQuery.java | 157 ++++++++++++++---- .../pmd/lang/xml/rule/XmlXPathRuleTest.java | 38 +++++ 4 files changed, 169 insertions(+), 35 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java index 05d4bcd2c5..65bb9d6873 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java @@ -46,7 +46,7 @@ public final class DataMap { * @return Value associated with the key (nullable) */ @SuppressWarnings("unchecked") - public T get(DataKey key) { + public T get(DataKey key) { return (T) map.get(key); } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java index 7fc7d0103c..2bf8d097f9 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java @@ -91,7 +91,7 @@ public class XmlParser { */ public static class RootXmlNode extends XmlNodeWrapper implements RootNode { - RootXmlNode(XmlParser parser, Node domNode) { + RootXmlNode(XmlParser parser, Document domNode) { super(parser, domNode); } @@ -99,6 +99,11 @@ public class XmlParser { public XmlNode wrap(Node domNode) { return super.wrap(domNode); } + + @Override + public Document getNode() { + return (Document) super.getNode(); + } } } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java index 78a2b46b0f..5fb2ea1111 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java @@ -12,7 +12,9 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ContextedRuntimeException; +import org.w3c.dom.Document; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; @@ -28,9 +30,16 @@ import net.sourceforge.pmd.util.DataMap.SimpleDataKey; import net.sf.saxon.Configuration; import net.sf.saxon.dom.DocumentWrapper; import net.sf.saxon.dom.NodeWrapper; +import net.sf.saxon.om.Axis; +import net.sf.saxon.om.AxisIterator; +import net.sf.saxon.om.EmptyIterator; +import net.sf.saxon.om.Item; import net.sf.saxon.om.NamePool; import net.sf.saxon.om.NamespaceConstant; +import net.sf.saxon.om.NodeInfo; +import net.sf.saxon.om.SingleNodeIterator; import net.sf.saxon.om.ValueRepresentation; +import net.sf.saxon.pattern.NodeTest; import net.sf.saxon.sxpath.IndependentContext; import net.sf.saxon.sxpath.XPathDynamicContext; import net.sf.saxon.sxpath.XPathEvaluator; @@ -38,42 +47,59 @@ import net.sf.saxon.sxpath.XPathExpression; import net.sf.saxon.sxpath.XPathStaticContext; import net.sf.saxon.sxpath.XPathVariable; import net.sf.saxon.trans.XPathException; +import net.sf.saxon.type.Type; final class SaxonDomXPathQuery { private static final NamePool NAME_POOL = new NamePool(); - private static final SimpleDataKey SAXON_DOM_WRAPPER + private static final SimpleDataKey SAXON_DOM_WRAPPER = DataMap.simpleDataKey("pmd.saxon.dom.wrapper"); private final String xpath; - private final XPathExpression xpathExpression; - private final Map, XPathVariable> xpathVariables; + /** Cached xpath expression for URI of "". */ + private final XPathExpressionWithProperties xpathExpressionDefaultNs; + + /** Cached xpath expression for URI of {@link #lastUri}, overwritten if lastUri changes. */ + private XPathExpressionWithProperties xpathExpressionLastNs; + private String lastUri; private final Configuration configuration; public SaxonDomXPathQuery(String xpath, List> properties) { this.xpath = xpath; - final XPathEvaluator xpathEvaluator = new XPathEvaluator(); - final XPathStaticContext xpathStaticContext = xpathEvaluator.getStaticContext(); - ((IndependentContext) xpathStaticContext).declareNamespace("fn", NamespaceConstant.FN); - configuration = xpathStaticContext.getConfiguration(); + configuration = new Configuration(); configuration.setNamePool(NAME_POOL); - // Register PMD functions - Initializer.initialize((IndependentContext) xpathStaticContext); + xpathExpressionDefaultNs = makeXPathExpression(this.xpath, "", properties); + } - this.xpathVariables = makeXPathVariables(properties, xpathStaticContext); + private XPathExpressionWithProperties makeXPathExpression(String xpath, String defaultUri, List> properties) { + final IndependentContext xpathStaticContext = new IndependentContext(configuration); + xpathStaticContext.declareNamespace("fn", NamespaceConstant.FN); + xpathStaticContext.setDefaultElementNamespace(defaultUri); + + + // Register PMD functions + Initializer.initialize(xpathStaticContext); + + Map, XPathVariable> xpathVariables = declareXPathVariables(properties, xpathStaticContext); try { - this.xpathExpression = xpathEvaluator.createExpression(xpath); + final XPathEvaluator xpathEvaluator = new XPathEvaluator(configuration); + xpathEvaluator.setStaticContext(xpathStaticContext); + XPathExpression expression = xpathEvaluator.createExpression(xpath); + return new XPathExpressionWithProperties( + expression, + xpathVariables + ); } catch (final XPathException e) { throw new ContextedRuntimeException(e) .addContextValue("XPath", xpath); } } - private Map, XPathVariable> makeXPathVariables(List> accessibleProperties, XPathStaticContext xpathStaticContext) { + private Map, XPathVariable> declareXPathVariables(List> accessibleProperties, XPathStaticContext xpathStaticContext) { Map, XPathVariable> xpathVariables = new HashMap<>(); for (final PropertyDescriptor propertyDescriptor : accessibleProperties) { final String name = propertyDescriptor.name(); @@ -97,11 +123,12 @@ final class SaxonDomXPathQuery { } public List evaluate(RootXmlNode root, PropertySource propertyValues) { - DocumentWrapper wrapper = getSaxonDomWrapper(root); - XPathDynamicContext dynamicContext = createDynamicContext(wrapper, propertyValues); + PmdDocumentWrapper wrapper = getSaxonDomWrapper(root); + XPathExpressionWithProperties expression = getCachedXPathExpr(propertyValues, wrapper); + try { List result = new ArrayList<>(); - for (Object item : xpathExpression.evaluate(dynamicContext)) { + for (Item item : expression.evaluate(wrapper, propertyValues)) { if (item instanceof NodeWrapper) { NodeWrapper nodeInfo = (NodeWrapper) item; Object domNode = nodeInfo.getUnderlyingNode(); @@ -119,36 +146,100 @@ final class SaxonDomXPathQuery { } - private DocumentWrapper getSaxonDomWrapper(RootXmlNode node) { + private XPathExpressionWithProperties getCachedXPathExpr(PropertySource propertyValues, PmdDocumentWrapper wrapper) { + XPathExpressionWithProperties expression; + if (StringUtils.isEmpty(wrapper.getURI())) { + expression = this.xpathExpressionDefaultNs; + } else if (xpathExpressionLastNs != null && Objects.equals(wrapper.getURI(), lastUri)) { + expression = xpathExpressionLastNs; + } else { + expression = makeXPathExpression(this.xpath, wrapper.getURI(), propertyValues.getPropertyDescriptors()); + xpathExpressionLastNs = expression; + lastUri = wrapper.getURI(); + } + return expression; + } + + private PmdDocumentWrapper getSaxonDomWrapper(RootXmlNode node) { DataMap> userMap = node.getUserMap(); if (userMap.isSet(SAXON_DOM_WRAPPER)) { return userMap.get(SAXON_DOM_WRAPPER); } - org.w3c.dom.Node domRoot = node.getNode(); - DocumentWrapper wrapper = new DocumentWrapper( + Document domRoot = node.getNode(); + PmdDocumentWrapper wrapper = new PmdDocumentWrapper( domRoot, domRoot.getBaseURI(), configuration ); userMap.set(SAXON_DOM_WRAPPER, wrapper); return wrapper; } - private XPathDynamicContext createDynamicContext(final DocumentWrapper elementNode, PropertySource properties) { - final XPathDynamicContext dynamicContext = xpathExpression.createDynamicContext(elementNode); + private static final class PmdDocumentWrapper extends DocumentWrapper { - // Set variable values on the dynamic context - for (final Entry, XPathVariable> entry : xpathVariables.entrySet()) { - Object value = properties.getProperty(entry.getKey()); - Objects.requireNonNull(value, "null property value for " + entry.getKey()); - final ValueRepresentation saxonValue = SaxonXPathRuleQuery.getRepresentation(entry.getKey(), entry.getValue()); - try { - dynamicContext.setVariable(entry.getValue(), saxonValue); - } catch (XPathException e) { - throw new ContextedRuntimeException(e) - .addContextValue("Variable", entry.getValue()) - .addContextValue("XPath", xpath); - } + private final NodeInfo rootNode; + + public PmdDocumentWrapper(org.w3c.dom.Document doc, String baseURI, Configuration config) { + super(doc, baseURI, config); + this.rootNode = makeWrapper(doc.getDocumentElement(), this, this, 0); + } + + @Override + public AxisIterator iterateAxis(byte axisNumber) { + if (axisNumber == Axis.CHILD) { + return SingleNodeIterator.makeIterator(rootNode); + } + return super.iterateAxis(axisNumber); + } + + @Override + public AxisIterator iterateAxis(byte axisNumber, NodeTest nodeTest) { + if (axisNumber == Axis.CHILD && nodeTest.getPrimitiveType() == Type.ELEMENT) { + // need to override this part + return nodeTest.matches(rootNode) + ? SingleNodeIterator.makeIterator(rootNode) + : EmptyIterator.getInstance(); + } + return super.iterateAxis(axisNumber, nodeTest); + } + + @Override + public String getURI() { + return rootNode.getURI(); + } + } + + static final class XPathExpressionWithProperties { + + final XPathExpression expr; + final Map, XPathVariable> xpathVariables; + + XPathExpressionWithProperties(XPathExpression expr, Map, XPathVariable> xpathVariables) { + this.expr = expr; + this.xpathVariables = xpathVariables; + } + + @SuppressWarnings("unchecked") + private List evaluate(final PmdDocumentWrapper elementNode, PropertySource properties) throws XPathException { + XPathDynamicContext dynamicContext = createDynamicContext(elementNode, properties); + return (List) expr.evaluate(dynamicContext); + } + + private XPathDynamicContext createDynamicContext(final DocumentWrapper elementNode, PropertySource properties) { + final XPathDynamicContext dynamicContext = expr.createDynamicContext(elementNode); + + // Set variable values on the dynamic context + for (final Entry, XPathVariable> entry : xpathVariables.entrySet()) { + Object value = properties.getProperty(entry.getKey()); + Objects.requireNonNull(value, "null property value for " + entry.getKey()); + final ValueRepresentation saxonValue = SaxonXPathRuleQuery.getRepresentation(entry.getKey(), entry.getValue()); + try { + dynamicContext.setVariable(entry.getValue(), saxonValue); + } catch (XPathException e) { + throw new ContextedRuntimeException(e) + .addContextValue("Variable", entry.getValue()); + } + } + return dynamicContext; } - return dynamicContext; } } diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java index aa7f7e63e4..7d7df8082d 100644 --- a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java @@ -35,4 +35,42 @@ public class XmlXPathRuleTest { assertSize(report, 1); } + @Test + public void testTextFunctionInXpath() { + // https://github.com/pmd/pmd/issues/915 + Report report = xml.executeRule(makeXPath("//app[text()[1]='app2']"), + "app2"); + + assertSize(report, 1); + } + + @Test + public void testRootNode() { + // https://github.com/pmd/pmd/issues/3413#issuecomment-1072614398 + // Note that the test is *:Flow, because Saxon DOM is namespace sensitive, and the xmlns + // attribute is interpreted as the ns of the document + Report report = xml.executeRule(makeXPath("/*:Flow"), + "\n" + + ""); + + assertSize(report, 1); + } + + @Test + public void testNoNamespaceRoot() { + Report report = xml.executeRule(makeXPath("/Flow"), + "\n" + + ""); + + assertSize(report, 1); + } + + @Test + public void testNamespaceDescendant() { + Report report = xml.executeRule(makeXPath("//a"), + ""); + + assertSize(report, 1); + } + } From 0011865cf9e0b38b1af7745ed5b84c1d508ef7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 19 Mar 2022 17:25:22 +0100 Subject: [PATCH 53/89] Add a property for the default namespace --- .../pmd/lang/xml/rule/DomXPathRule.java | 62 ++++++++++++++++++- .../pmd/lang/xml/rule/SaxonDomXPathQuery.java | 43 +++++-------- .../pmd/lang/xml/rule/XmlXPathRuleTest.java | 60 ++++++++++++++++-- 3 files changed, 130 insertions(+), 35 deletions(-) diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java index 00ad33c5c7..ed1f09f0ce 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -9,10 +9,55 @@ import java.util.List; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.AbstractRule; +import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.xml.ast.XmlParser.RootXmlNode; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; +/** + * XPath rule that executes an expression on the DOM directly, and not + * on the PMD AST wrapper. The XPath expressions adheres to the XPath + * (2.0) spec, so they can be tested in any existing XPath testing tools + * instead of just the PMD designer (google "xpath test"). Usage of this + * class is strongly recommended over the standard {@link XPathRule}, which + * is mostly useful in other PMD languages. + * + *

    The XPath expression is namespace-sensitive. If the tested XML documents + * use a schema ({@code xmlns} attribute on the root), you should set the property + * {@code defaultNsUri} on the rule with the value of the {@code xmlns} attribute. + * Otherwise node tests won't match unless you use a wildcard URI prefix ({@code *:nodeName}). + * + *

    For instance for the document + *

    {@code
    + * 
    + * 
    + * }
    + * the XPath query {@code //foo} will not match anything, while {@code //*:foo} + * will. If you set the property {@code defaultNsUri} to {@code "http://company.com/aschema"}, + * then {@code //foo} will be expanded to {@code //Q{http://company.com/aschema}foo}, + * and match the {@code foo} node. The behaviour is equivalent in the following + * document: + *
    {@code
    + * 
    + * 
    + * }
    + * + *

    However, for the document + *

    {@code
    + * 
    + * 
    + * }
    + * the XPath queries {@code //foo} and {@code //*:foo} both match, because + * {@code //foo} is expanded to {@code //Q{}foo} (local name foo, empty URI), + * and the document has no default namespace (= the empty default namespace). + * + *

    Note that explicitly specifying URIs with {@code Q{...}localName} + * as in this documentation is XPath 3.1 syntax and will only be available + * in PMD 7. + * + * @since PMD 6.44.0 + * @author Clément Fournier + */ public class DomXPathRule extends AbstractRule { SaxonDomXPathQuery query; @@ -23,15 +68,28 @@ public class DomXPathRule extends AbstractRule { .defaultValue("") // no default value .build(); + private static final PropertyDescriptor DEFAULT_NS_URI + = PropertyFactory.stringProperty("defaultNsUri") + .desc("A URI for the default namespace of node tests in the XPath expression." + + "This is provided to match documents based on their declared schema.") + .defaultValue("") + .build(); + public DomXPathRule() { definePropertyDescriptor(XPATH_EXPR); + definePropertyDescriptor(DEFAULT_NS_URI); } public DomXPathRule(String xpath) { + this(xpath, ""); + } + + public DomXPathRule(String xpath, String defaultNsUri) { this(); setProperty(XPATH_EXPR, xpath); + setProperty(DEFAULT_NS_URI, defaultNsUri); } @Override @@ -47,7 +105,9 @@ public class DomXPathRule extends AbstractRule { private SaxonDomXPathQuery getXPathQuery() { if (query == null) { - query = new SaxonDomXPathQuery(getProperty(XPATH_EXPR), getPropertyDescriptors()); + query = new SaxonDomXPathQuery(getProperty(XPATH_EXPR), + getProperty(DEFAULT_NS_URI), + getPropertyDescriptors()); } return query; } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java index 5fb2ea1111..f2fda5dd28 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java @@ -12,7 +12,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ContextedRuntimeException; import org.w3c.dom.Document; @@ -58,20 +57,16 @@ final class SaxonDomXPathQuery { private final String xpath; /** Cached xpath expression for URI of "". */ - private final XPathExpressionWithProperties xpathExpressionDefaultNs; + private final XPathExpressionWithProperties xpathExpression; - /** Cached xpath expression for URI of {@link #lastUri}, overwritten if lastUri changes. */ - private XPathExpressionWithProperties xpathExpressionLastNs; - private String lastUri; private final Configuration configuration; - public SaxonDomXPathQuery(String xpath, List> properties) { + public SaxonDomXPathQuery(String xpath, String defaultNsUri, List> properties) { this.xpath = xpath; configuration = new Configuration(); configuration.setNamePool(NAME_POOL); - - xpathExpressionDefaultNs = makeXPathExpression(this.xpath, "", properties); + xpathExpression = makeXPathExpression(this.xpath, defaultNsUri, properties); } private XPathExpressionWithProperties makeXPathExpression(String xpath, String defaultUri, List> properties) { @@ -124,7 +119,7 @@ final class SaxonDomXPathQuery { public List evaluate(RootXmlNode root, PropertySource propertyValues) { PmdDocumentWrapper wrapper = getSaxonDomWrapper(root); - XPathExpressionWithProperties expression = getCachedXPathExpr(propertyValues, wrapper); + XPathExpressionWithProperties expression = this.xpathExpression; try { List result = new ArrayList<>(); @@ -146,20 +141,6 @@ final class SaxonDomXPathQuery { } - private XPathExpressionWithProperties getCachedXPathExpr(PropertySource propertyValues, PmdDocumentWrapper wrapper) { - XPathExpressionWithProperties expression; - if (StringUtils.isEmpty(wrapper.getURI())) { - expression = this.xpathExpressionDefaultNs; - } else if (xpathExpressionLastNs != null && Objects.equals(wrapper.getURI(), lastUri)) { - expression = xpathExpressionLastNs; - } else { - expression = makeXPathExpression(this.xpath, wrapper.getURI(), propertyValues.getPropertyDescriptors()); - xpathExpressionLastNs = expression; - lastUri = wrapper.getURI(); - } - return expression; - } - private PmdDocumentWrapper getSaxonDomWrapper(RootXmlNode node) { DataMap> userMap = node.getUserMap(); if (userMap.isSet(SAXON_DOM_WRAPPER)) { @@ -228,18 +209,24 @@ final class SaxonDomXPathQuery { // Set variable values on the dynamic context for (final Entry, XPathVariable> entry : xpathVariables.entrySet()) { - Object value = properties.getProperty(entry.getKey()); - Objects.requireNonNull(value, "null property value for " + entry.getKey()); - final ValueRepresentation saxonValue = SaxonXPathRuleQuery.getRepresentation(entry.getKey(), entry.getValue()); + ValueRepresentation saxonValue = getSaxonValue(properties, entry); + XPathVariable variable = entry.getValue(); try { - dynamicContext.setVariable(entry.getValue(), saxonValue); + dynamicContext.setVariable(variable, saxonValue); } catch (XPathException e) { throw new ContextedRuntimeException(e) - .addContextValue("Variable", entry.getValue()); + .addContextValue("Variable", variable); } } return dynamicContext; } + + private ValueRepresentation getSaxonValue(PropertySource properties, Entry, XPathVariable> entry) { + Object value = properties.getProperty(entry.getKey()); + Objects.requireNonNull(value, "null property value for " + entry.getKey()); + final ValueRepresentation saxonValue = SaxonXPathRuleQuery.getRepresentation(entry.getKey(), value); + return saxonValue; + } } } diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java index 7d7df8082d..68a7fda3cd 100644 --- a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java @@ -16,10 +16,15 @@ import net.sourceforge.pmd.lang.xml.XmlParsingHelper; public class XmlXPathRuleTest { + private static final String A_URI = "http://soap.sforce.com/2006/04/metadata"; final XmlParsingHelper xml = XmlParsingHelper.XML; private Rule makeXPath(String expression) { - DomXPathRule rule = new DomXPathRule(expression); + return makeXPath(expression, ""); + } + + private Rule makeXPath(String expression, String nsUri) { + DomXPathRule rule = new DomXPathRule(expression, nsUri); rule.setLanguage(LanguageRegistry.getLanguage(XmlLanguageModule.NAME)); rule.setMessage("XPath Rule Failed"); return rule; @@ -45,10 +50,8 @@ public class XmlXPathRuleTest { } @Test - public void testRootNode() { + public void testRootNodeWildcardUri() { // https://github.com/pmd/pmd/issues/3413#issuecomment-1072614398 - // Note that the test is *:Flow, because Saxon DOM is namespace sensitive, and the xmlns - // attribute is interpreted as the ns of the document Report report = xml.executeRule(makeXPath("/*:Flow"), "\n" + ""); @@ -66,11 +69,56 @@ public class XmlXPathRuleTest { } @Test - public void testNamespaceDescendant() { + public void testNamespaceDescendantWrongDefaultUri() { Report report = xml.executeRule(makeXPath("//a"), - ""); + ""); + + assertSize(report, 0); + } + + @Test + public void testNamespaceDescendantOkUri() { + Report report = xml.executeRule(makeXPath("//a", A_URI), + ""); + + assertSize(report, 1); + + report = xml.executeRule(makeXPath("//*:a"), + ""); assertSize(report, 1); } + @Test + public void testNamespaceDescendantWildcardUri() { + Report report = xml.executeRule(makeXPath("//*:a"), + ""); + + assertSize(report, 1); + } + + @Test + public void testNamespacePrefixDescendantWildcardUri() { + Report report = xml.executeRule(makeXPath("//*:Flow"), + ""); + + assertSize(report, 1); + } + + @Test + public void testNamespacePrefixDescendantOkUri() { + Report report = xml.executeRule(makeXPath("//Flow", A_URI), + ""); + + assertSize(report, 1); + } + + @Test + public void testNamespacePrefixDescendantWrongUri() { + Report report = xml.executeRule(makeXPath("//Flow", "wrongURI"), + ""); + + assertSize(report, 0); + } + } From 3385809abd5ba068f4e65a6f18ff7a1e7deae01b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 19 Mar 2022 21:24:52 +0100 Subject: [PATCH 54/89] Add functions to replace xpath rule --- .../pmd/lang/xpath/PMDFunctions.java | 11 +++++++ .../pmd/lang/xml/rule/DomXPathRule.java | 33 ++++++++++++++++--- .../pmd/lang/xml/rule/XmlXPathRuleTest.java | 9 +++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java index 3c878d917b..6416aeedbb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.xpath; +import java.util.Objects; import java.util.logging.Logger; import net.sourceforge.pmd.annotation.InternalApi; @@ -56,6 +57,16 @@ public final class PMDFunctions { return node == null ? null : FileNameXPathFunction.getFileName(node); } + public static int beginLine(Item item) { + Node node = Objects.requireNonNull(itemToNode(item), "not a node " + item); + return node.getBeginLine(); + } + + public static int endLine(Item item) { + Node node = Objects.requireNonNull(itemToNode(item), "not a node " + item); + return node.getEndLine(); + } + private static Node itemToNode(Object item) { if (item instanceof Node) { return (Node) item; diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java index ed1f09f0ce..89b72b128a 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -22,10 +22,35 @@ import net.sourceforge.pmd.properties.PropertyFactory; * class is strongly recommended over the standard {@link XPathRule}, which * is mostly useful in other PMD languages. * - *

    The XPath expression is namespace-sensitive. If the tested XML documents - * use a schema ({@code xmlns} attribute on the root), you should set the property - * {@code defaultNsUri} on the rule with the value of the {@code xmlns} attribute. - * Otherwise node tests won't match unless you use a wildcard URI prefix ({@code *:nodeName}). + *

    Differences with {@link XPathRule}

    + * + * This rule and {@link XPathRule} do not accept exactly the same queries, + * because {@link XPathRule} implements the XPath spec in an ad-hoc way. + * The main differences are: + *
      + *
    • {@link XPathRule} uses elements to represent text nodes. + * This is contrary to the XPath spec, in which element and text nodes + * are different kinds of nodes. To replace the query {@code //elt/text[@Image="abc"]}, + * use the XPath function {@code text()}, eg {@code //elt[text()="abc"]}. + *
    • {@link XPathRule} adds additional attributes to each element + * (eg {@code @BeginLine} and {@code @Image}). These attributes are not + * XML attributes, so they are not accessible using DomXPathRule rule. + * Instead, use the XPath functions {@code pmd:beginLine(node)} and {@code pmd:beginLine(node)}. + * For instance, replace {@code //elt[@EndLine - @BeginLine > 10]} with + * {@code elt[pmd:endLine(.) - pmd:beginLine(.) > 10]}. + *
    • {@link XPathRule} uses an element called {@code "document"} as the + * root node of every XML AST. This node does not have the correct node kind, + * as it's an element, not a document. To replace {@code /document/RootNode}, + * use just {@code /RootNode}. + *
    + * + *

    Namespace-sensitivity

    + * + *

    Another large difference is that this rule is namespace-sensitive. + * If the tested XML documents use a schema ({@code xmlns} attribute on the root), + * you should set the property {@code defaultNsUri} on the rule with + * the value of the {@code xmlns} attribute. Otherwise node tests won't + * match unless you use a wildcard URI prefix ({@code *:nodeName}). * *

    For instance for the document *

    {@code
    diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java
    index 68a7fda3cd..24b107b784 100644
    --- a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java
    +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java
    @@ -121,4 +121,13 @@ public class XmlXPathRuleTest {
             assertSize(report, 0);
         }
     
    +    @Test
    +    public void testLocationFuns() {
    +        Rule rule = makeXPath("//Flow[pmd:beginLine(.) != pmd:endLine(.)]");
    +        Report report = xml.executeRule(rule, "");
    +        assertSize(report, 0);
    +        report = xml.executeRule(rule, "\n\n");
    +        assertSize(report, 1);
    +    }
    +
     }
    
    From 6520ecff81f00caac1f99e537ac3915fc3eb1109 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= 
    Date: Sat, 19 Mar 2022 21:39:57 +0100
    Subject: [PATCH 55/89] Add tests in pmd-core
    
    ---
     .../sourceforge/pmd/lang/ast/DummyNode.java   | 19 +++++++
     .../lang/ast/xpath/DocumentNavigatorTest.java | 10 +---
     .../pmd/lang/rule/XPathRuleTest.java          | 50 +++++++++++++++++++
     3 files changed, 71 insertions(+), 8 deletions(-)
    
    diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java
    index 10ddb52a1d..c94c647ca0 100644
    --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java
    +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java
    @@ -4,7 +4,12 @@
     
     package net.sourceforge.pmd.lang.ast;
     
    +import java.nio.file.Paths;
    +
    +import net.sourceforge.pmd.lang.ast.xpath.internal.FileNameXPathFunction;
    +
     public class DummyNode extends AbstractNode {
    +
         private final boolean findBoundary;
         private final String xpathName;
     
    @@ -55,4 +60,18 @@ public class DummyNode extends AbstractNode {
         public boolean isFindBoundary() {
             return findBoundary;
         }
    +
    +    public static class DummyRootNode extends DummyNode implements RootNode {
    +
    +        public DummyRootNode() {
    +            this("afile.txt");
    +        }
    +
    +        public DummyRootNode(String fileName) {
    +            super(0);
    +            // remove prefixed path segments.
    +            String simpleFileName = Paths.get(fileName).getFileName().toString();
    +            getUserMap().set(FileNameXPathFunction.FILE_NAME_KEY, simpleFileName);
    +        }
    +    }
     }
    diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigatorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigatorTest.java
    index f6158c45b6..17250d877a 100644
    --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigatorTest.java
    +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigatorTest.java
    @@ -11,20 +11,14 @@ import static org.junit.Assert.fail;
     import org.junit.Test;
     
     import net.sourceforge.pmd.lang.ast.DummyNode;
    +import net.sourceforge.pmd.lang.ast.DummyNode.DummyRootNode;
     import net.sourceforge.pmd.lang.ast.Node;
    -import net.sourceforge.pmd.lang.ast.RootNode;
     
     /**
      * Unit test for {@link DocumentNavigator}
      */
     public class DocumentNavigatorTest {
     
    -    private static class DummyRootNode extends DummyNode implements RootNode {
    -        DummyRootNode(int id) {
    -            super(id);
    -        }
    -    }
    -
         @Test
         public void getDocumentNode() {
             DocumentNavigator nav = new DocumentNavigator();
    @@ -36,7 +30,7 @@ public class DocumentNavigatorTest {
                 assertNotNull(e);
             }
     
    -        Node root = new DummyRootNode(1);
    +        Node root = new DummyRootNode();
             Node n = new DummyNode(1);
             root.jjtAddChild(n, 0);
             n.jjtSetParent(root);
    diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java
    index 6a869b3c0f..58665dd494 100644
    --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java
    +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java
    @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.rule;
     
     import static java.util.Collections.singletonList;
     import static org.hamcrest.MatcherAssert.assertThat;
    +import static org.hamcrest.Matchers.hasSize;
     import static org.junit.Assert.assertEquals;
     
     import org.hamcrest.Matchers;
    @@ -13,11 +14,13 @@ import org.junit.Assert;
     import org.junit.Rule;
     import org.junit.Test;
     
    +import net.sourceforge.pmd.Report;
     import net.sourceforge.pmd.RuleContext;
     import net.sourceforge.pmd.junit.JavaUtilLoggingRule;
     import net.sourceforge.pmd.lang.DummyLanguageModule;
     import net.sourceforge.pmd.lang.LanguageRegistry;
     import net.sourceforge.pmd.lang.ast.DummyNode;
    +import net.sourceforge.pmd.lang.ast.DummyNode.DummyRootNode;
     import net.sourceforge.pmd.lang.ast.DummyNodeWithDeprecatedAttribute;
     import net.sourceforge.pmd.lang.ast.DummyNodeWithListAndEnum;
     import net.sourceforge.pmd.lang.ast.xpath.Attribute;
    @@ -154,6 +157,47 @@ public class XPathRuleTest {
             return xpr;
         }
     
    +
    +    public XPathRule makeXPath(String xpathExpr) {
    +        XPathRule xpr = new XPathRule(XPathVersion.XPATH_2_0, xpathExpr);
    +        xpr.setName("name");
    +        xpr.setMessage("gotcha");
    +        return xpr;
    +    }
    +
    +    @Test
    +    public void testFileNameInXpath() {
    +        Report report = executeRule(makeXPath("//*[pmd:fileName() = 'Foo.cls']"),
    +                                    newRoot("src/Foo.cls"));
    +
    +        assertThat(report.getViolations(), hasSize(1));
    +    }
    +
    +    @Test
    +    public void testBeginLine() {
    +        Report report = executeRule(makeXPath("//*[pmd:beginLine(.)=1]"),
    +                                    newRoot("src/Foo.cls"));
    +
    +        assertThat(report.getViolations(), hasSize(1));
    +    }
    +
    +    @Test
    +    public void testEndLine() {
    +        Report report = executeRule(makeXPath("//*[pmd:endLine(.)=1]"),
    +                                    newRoot("src/Foo.cls"));
    +
    +        assertThat(report.getViolations(), hasSize(1));
    +    }
    +
    +
    +    public Report executeRule(net.sourceforge.pmd.Rule rule, DummyNode node) {
    +        RuleContext ctx = new RuleContext();
    +        ctx.setReport(new Report());
    +        ctx.setLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getDefaultVersion());
    +        eval(ctx, rule, node);
    +        return ctx.getReport();
    +    }
    +
         public void eval(RuleContext ctx, net.sourceforge.pmd.Rule rule, DummyNode node) {
             ctx.setCurrentRule(rule);
             rule.apply(singletonList(node), ctx);
    @@ -166,5 +210,11 @@ public class XPathRuleTest {
             return dummy;
         }
     
    +    public DummyNode.DummyRootNode newRoot(String fileName) {
    +        DummyRootNode dummy = new DummyRootNode(fileName);
    +        dummy.setCoords(1, 1, 1, 2);
    +        return dummy;
    +    }
    +
     
     }
    
    From da775bfb9bc853c74e0a5c9c71f8321ffe8ae443 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= 
    Date: Sun, 20 Mar 2022 13:01:35 +0100
    Subject: [PATCH 56/89] Cleanups
    
    ---
     .../java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java | 6 +++++-
     .../net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java  | 3 ++-
     .../sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java | 8 ++++----
     .../sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java   | 8 ++++++++
     4 files changed, 19 insertions(+), 6 deletions(-)
    
    diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java
    index 6416aeedbb..5fb1a48c15 100644
    --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java
    +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java
    @@ -22,6 +22,10 @@ import net.sf.saxon.om.Item;
     public final class PMDFunctions {
     
         private static final Logger LOG = Logger.getLogger(PMDFunctions.class.getName());
    +    /** Used by the XML module to associate PMD nodes with DOM nodes. */
    +    @Deprecated
    +    @InternalApi
    +    public static final String PMD_NODE_USER_DATA = "pmd.node";
     
         private PMDFunctions() { }
     
    @@ -75,7 +79,7 @@ public final class PMDFunctions {
             } else if (item instanceof NodeWrapper) {
                 return itemToNode(((NodeWrapper) item).getUnderlyingNode());
             } else if (item instanceof org.w3c.dom.Node) {
    -            return itemToNode(((org.w3c.dom.Node) item).getUserData("pmd.node"));
    +            return itemToNode(((org.w3c.dom.Node) item).getUserData(PMD_NODE_USER_DATA));
             }
             LOG.fine("Cannot call pmd:filename on " + item);
             return null;
    diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java
    index d642c87d42..3e3b7642d4 100644
    --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java
    +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java
    @@ -19,6 +19,7 @@ import org.w3c.dom.Text;
     import net.sourceforge.pmd.lang.ast.Node;
     import net.sourceforge.pmd.lang.ast.xpath.Attribute;
     import net.sourceforge.pmd.lang.dfa.DataFlowNode;
    +import net.sourceforge.pmd.lang.xpath.PMDFunctions;
     import net.sourceforge.pmd.util.CompoundIterator;
     
     
    @@ -38,7 +39,7 @@ public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode {
     
         public XmlNodeWrapper(XmlParser parser, org.w3c.dom.Node domNode) {
             super(domNode);
    -        domNode.setUserData("pmd.node", this, null);
    +        domNode.setUserData(PMDFunctions.PMD_NODE_USER_DATA, this, null);
             this.parser = parser;
         }
     
    diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java
    index f2fda5dd28..a840b16a96 100644
    --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java
    +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java
    @@ -55,14 +55,15 @@ final class SaxonDomXPathQuery {
         private static final SimpleDataKey SAXON_DOM_WRAPPER
             = DataMap.simpleDataKey("pmd.saxon.dom.wrapper");
     
    +    /** The XPath expression as a string. */
         private final String xpath;
    -    /** Cached xpath expression for URI of "". */
    +    /** The executable XPath expression. */
         private final XPathExpressionWithProperties xpathExpression;
     
     
         private final Configuration configuration;
     
    -    public SaxonDomXPathQuery(String xpath, String defaultNsUri, List> properties) {
    +    SaxonDomXPathQuery(String xpath, String defaultNsUri, List> properties) {
             this.xpath = xpath;
             configuration = new Configuration();
             configuration.setNamePool(NAME_POOL);
    @@ -119,11 +120,10 @@ final class SaxonDomXPathQuery {
     
         public List evaluate(RootXmlNode root, PropertySource propertyValues) {
             PmdDocumentWrapper wrapper = getSaxonDomWrapper(root);
    -        XPathExpressionWithProperties expression = this.xpathExpression;
     
             try {
                 List result = new ArrayList<>();
    -            for (Item item : expression.evaluate(wrapper, propertyValues)) {
    +            for (Item item : this.xpathExpression.evaluate(wrapper, propertyValues)) {
                     if (item instanceof NodeWrapper) {
                         NodeWrapper nodeInfo = (NodeWrapper) item;
                         Object domNode = nodeInfo.getUnderlyingNode();
    diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java
    index 24b107b784..c7c3b366bd 100644
    --- a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java
    +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java
    @@ -121,6 +121,14 @@ public class XmlXPathRuleTest {
             assertSize(report, 0);
         }
     
    +    @Test
    +    public void testRootExpr() {
    +        Report report = xml.executeRule(makeXPath("/"),
    +                                        "");
    +
    +        assertSize(report, 1);
    +    }
    +
         @Test
         public void testLocationFuns() {
             Rule rule = makeXPath("//Flow[pmd:beginLine(.) != pmd:endLine(.)]");
    
    From ccf9a9f13bc92312699c9c6d10cf382ec8dabc99 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= 
    Date: Sun, 20 Mar 2022 13:09:48 +0100
    Subject: [PATCH 57/89] XPath fun doc
    
    ---
     docs/_data/xpath_funs.yml | 37 +++++++++++++++++++++++++++++++++++--
     1 file changed, 35 insertions(+), 2 deletions(-)
    
    diff --git a/docs/_data/xpath_funs.yml b/docs/_data/xpath_funs.yml
    index 1936d7cfb4..8f76da9f9e 100644
    --- a/docs/_data/xpath_funs.yml
    +++ b/docs/_data/xpath_funs.yml
    @@ -7,7 +7,12 @@ aliases:
         type: "xs:string"
         description: "The qualified name of a Java class, possibly with pairs of brackets to indicate an array type.
                       Can also be a primitive type name."
    +  - &node_param
    +    name: element
    +    type: "xs:element"
    +    description: "Any element node"
       - &needs_typenode "The context node must be a {% jdoc jast::TypeNode %}"
    +  - ¬_ctx_dependent "The function is not context-dependent, but takes a node as its first parameter."
     
     langs:
       - name: "Any language"
    @@ -15,16 +20,44 @@ langs:
         funs:
           - name: fileName
             returnType: "xs:string"
    -        shortDescription: "Returns the current filename"
    +        shortDescription: "Returns the simple name of the current file"
             description: "Returns the current simple filename without path but including the extension.
                           This can be used to write rules that check filename naming conventions.
    -                      
    +
                           

    This function is available since PMD 6.38.0.

    " notes: "The function can be called on any node." examples: - code: "//b[pmd:fileName() = 'Foo.xml']" outcome: "Matches any `<b>` tags in files called `Foo.xml`." + - name: beginLine + returnType: "xs:int" + parameters: + - *node_param + shortDescription: "Returns the begin line of the given node" + description: "Returns the begin line of the given node in the source text. + Line numbers are 1-based. + +

    This function is available since PMD 6.44.0.

    " + notes: *not_ctx_dependent + examples: + - code: "//b[pmd:beginLine(.) > 5]" + outcome: "Matches any `<b>` node which starts after the fifth line." + + - name: endLine + returnType: "xs:int" + parameters: + - *node_param + shortDescription: "Returns the end line of the given node" + description: "Returns the end line of the given node in the source text. + Line numbers are 1-based. + +

    This function is available since PMD 6.44.0.

    " + notes: *not_ctx_dependent + examples: + - code: "//b[pmd:endLine(.) == pmd:beginLine(.)]" + outcome: "Matches any `<b>` node which doesn't span more than one line." + - name: "Java" ns: "pmd-java" From 104397fde8fb770ae5ec7221ba880bb3857f7472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 20 Mar 2022 13:52:03 +0100 Subject: [PATCH 58/89] More doc --- docs/pages/pmd/languages/xml.md | 69 +++++++++++++++++++ .../pmd/lang/xml/rule/DomXPathRule.java | 3 + 2 files changed, 72 insertions(+) create mode 100644 docs/pages/pmd/languages/xml.md diff --git a/docs/pages/pmd/languages/xml.md b/docs/pages/pmd/languages/xml.md new file mode 100644 index 0000000000..daff0d7195 --- /dev/null +++ b/docs/pages/pmd/languages/xml.md @@ -0,0 +1,69 @@ +--- +title: XML +permalink: pmd_languages_xml.html +last_updated: March 2021 (6.33.0) +--- + +## The XML language module + +PMD has an XML language module which exposes the [DOM](https://de.wikipedia.org/wiki/Document_Object_Model) +of an XML document as an AST. Different flavours of XML are represented by separate +language instances, which all use the same parser under the hood. The following +table lists the languages currently provided by the `pmd-xml` maven module. + +| Language ID | Description | +|-------------|-----------------------------------| +| xml | Generic XML language | +| pom | Maven Project Object Model (POM) | +| wsdl | Web Services Description Language | +| xsl | Extensible Stylesheet Language | + +Each of those languages has a separate rule index. + +### File attribution + +Any file ending with `.xml` is associated with the `xml` language. Other XML flavours +use more specific extensions, like `.xsl`. + +Some XML-based file formats do not conventionally use a `.xml` extension. To associate +these files with the XML language, you need to use the `--force-language xml` command-line +arguments, for instance: +``` +$ ./run.sh pmd -d /home/me/src/xml-file.ext -f text -R ruleset.xml --force-language xml +``` +Please refer to [PMD CLI reference](pmd_userdocs_cli_reference.html#analyze-other-xml-formats). + + +### XPath rules in XML + +While other languages use {% jdoc core::lang.rule.XPathRule %} to create XPath rules, +the use of this class is not recommended for XML languages. Instead, since 6.44.0, you +are advised to use {% xml::lang.xml.rule.DomXPathRule %}. This rule class interprets +XPath queries exactly as regular XPath, while `XPathRule` works on a wrapper for the +DOM which is inconsistent with the XPath spec. Since `DomXPathRule` conforms to the +XPath spec, you can test XML queries in any stock XPath testing tool, or use resources +like StackOverflow to write XPath queries. + +{% include note.html content="The Rule Designer only works with `XPathRule`, and the tree it prints is inconsistent with the DOM representation used by `DomXPathRule`. You can use an online free XPath testing tool to test your query instead." %} + +Here's an example declaration of a `DomXPathRule`: +``` + + + + + + + + + +``` +The most important change is the `class` attribute, which doesn't point to `XPathRule` +but to `DomXPathRule`. Please see the Javadoc for {% xml::lang.xml.rule.DomXPathRule %} +for more info about the differences with `XPathRule`. + diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java index 89b72b128a..895f17cc58 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -44,6 +44,9 @@ import net.sourceforge.pmd.properties.PropertyFactory; * use just {@code /RootNode}. * * + *

    Additionally, this rule only supports XPath 2.0, with no option + * for configuration. This will be bumped to XPath 3.1 in PMD 7. + * *

    Namespace-sensitivity

    * *

    Another large difference is that this rule is namespace-sensitive. From 01b6aab95a59fde8781adc556977cf5e2256abd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 20 Mar 2022 13:52:12 +0100 Subject: [PATCH 59/89] Test PIs and comments --- .../pmd/lang/xml/rule/DomXPathRule.java | 20 ++++++++ .../pmd/lang/xml/rule/SaxonDomXPathQuery.java | 51 ++----------------- .../pmd/lang/xml/rule/XmlXPathRuleTest.java | 47 +++++++++++++++++ 3 files changed, 72 insertions(+), 46 deletions(-) diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java index 895f17cc58..1f7d3bfce9 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -42,6 +42,26 @@ import net.sourceforge.pmd.properties.PropertyFactory; * root node of every XML AST. This node does not have the correct node kind, * as it's an element, not a document. To replace {@code /document/RootNode}, * use just {@code /RootNode}. + *

  • {@link XPathRule} ignores comments and processing instructions + * (eg FXML's {@code }). + * This rule makes them accessible with the regular XPath syntax. + * The following finds all comments in the file: + *
    {@code
    + *  //comment()
    + * }
    + * The following finds only top-level comments starting with "prefix": + *
    {@code
    + *  /comment()[fn:starts-with(fn:string(.), "prefix")]
    + * }
    + * Note the use of {@code fn:string}. + * + * As an example of matching processing instructions, the following + * fetches all {@code } processing instructions. + *
    {@code
    + *  /processing-instruction('import')
    + * }
    + * The string value of the instruction can be found with {@code fn:string}. + *
  • * * *

    Additionally, this rule only supports XPath 2.0, with no option diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java index a840b16a96..eff1553907 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java @@ -29,16 +29,10 @@ import net.sourceforge.pmd.util.DataMap.SimpleDataKey; import net.sf.saxon.Configuration; import net.sf.saxon.dom.DocumentWrapper; import net.sf.saxon.dom.NodeWrapper; -import net.sf.saxon.om.Axis; -import net.sf.saxon.om.AxisIterator; -import net.sf.saxon.om.EmptyIterator; import net.sf.saxon.om.Item; import net.sf.saxon.om.NamePool; import net.sf.saxon.om.NamespaceConstant; -import net.sf.saxon.om.NodeInfo; -import net.sf.saxon.om.SingleNodeIterator; import net.sf.saxon.om.ValueRepresentation; -import net.sf.saxon.pattern.NodeTest; import net.sf.saxon.sxpath.IndependentContext; import net.sf.saxon.sxpath.XPathDynamicContext; import net.sf.saxon.sxpath.XPathEvaluator; @@ -46,13 +40,12 @@ import net.sf.saxon.sxpath.XPathExpression; import net.sf.saxon.sxpath.XPathStaticContext; import net.sf.saxon.sxpath.XPathVariable; import net.sf.saxon.trans.XPathException; -import net.sf.saxon.type.Type; final class SaxonDomXPathQuery { private static final NamePool NAME_POOL = new NamePool(); - private static final SimpleDataKey SAXON_DOM_WRAPPER + private static final SimpleDataKey SAXON_DOM_WRAPPER = DataMap.simpleDataKey("pmd.saxon.dom.wrapper"); /** The XPath expression as a string. */ @@ -119,7 +112,7 @@ final class SaxonDomXPathQuery { } public List evaluate(RootXmlNode root, PropertySource propertyValues) { - PmdDocumentWrapper wrapper = getSaxonDomWrapper(root); + DocumentWrapper wrapper = getSaxonDomWrapper(root); try { List result = new ArrayList<>(); @@ -141,53 +134,19 @@ final class SaxonDomXPathQuery { } - private PmdDocumentWrapper getSaxonDomWrapper(RootXmlNode node) { + private DocumentWrapper getSaxonDomWrapper(RootXmlNode node) { DataMap> userMap = node.getUserMap(); if (userMap.isSet(SAXON_DOM_WRAPPER)) { return userMap.get(SAXON_DOM_WRAPPER); } Document domRoot = node.getNode(); - PmdDocumentWrapper wrapper = new PmdDocumentWrapper( + DocumentWrapper wrapper = new DocumentWrapper( domRoot, domRoot.getBaseURI(), configuration ); userMap.set(SAXON_DOM_WRAPPER, wrapper); return wrapper; } - private static final class PmdDocumentWrapper extends DocumentWrapper { - - private final NodeInfo rootNode; - - public PmdDocumentWrapper(org.w3c.dom.Document doc, String baseURI, Configuration config) { - super(doc, baseURI, config); - this.rootNode = makeWrapper(doc.getDocumentElement(), this, this, 0); - } - - @Override - public AxisIterator iterateAxis(byte axisNumber) { - if (axisNumber == Axis.CHILD) { - return SingleNodeIterator.makeIterator(rootNode); - } - return super.iterateAxis(axisNumber); - } - - @Override - public AxisIterator iterateAxis(byte axisNumber, NodeTest nodeTest) { - if (axisNumber == Axis.CHILD && nodeTest.getPrimitiveType() == Type.ELEMENT) { - // need to override this part - return nodeTest.matches(rootNode) - ? SingleNodeIterator.makeIterator(rootNode) - : EmptyIterator.getInstance(); - } - return super.iterateAxis(axisNumber, nodeTest); - } - - @Override - public String getURI() { - return rootNode.getURI(); - } - } - static final class XPathExpressionWithProperties { final XPathExpression expr; @@ -199,7 +158,7 @@ final class SaxonDomXPathQuery { } @SuppressWarnings("unchecked") - private List evaluate(final PmdDocumentWrapper elementNode, PropertySource properties) throws XPathException { + private List evaluate(final DocumentWrapper elementNode, PropertySource properties) throws XPathException { XPathDynamicContext dynamicContext = createDynamicContext(elementNode, properties); return (List) expr.evaluate(dynamicContext); } diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java index c7c3b366bd..6a863e699f 100644 --- a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java @@ -17,6 +17,17 @@ import net.sourceforge.pmd.lang.xml.XmlParsingHelper; public class XmlXPathRuleTest { private static final String A_URI = "http://soap.sforce.com/2006/04/metadata"; + private static final String FXML_IMPORTS = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + ""; final XmlParsingHelper xml = XmlParsingHelper.XML; private Rule makeXPath(String expression) { @@ -129,6 +140,42 @@ public class XmlXPathRuleTest { assertSize(report, 1); } + @Test + public void testProcessingInstructions() { + Report report = xml.executeRule(makeXPath("/child::processing-instruction()", "http://javafx.com/javafx/8"), + FXML_IMPORTS); + + assertSize(report, 5); + } + + @Test + public void testProcessingInstructionsNamed() { + Report report = xml.executeRule(makeXPath("/child::processing-instruction('import')"), + FXML_IMPORTS); + + assertSize(report, 5); + } + + @Test + public void testProcessingInstructionXML() { + // does not create a PI + Report report = xml.executeRule(makeXPath("/child::processing-instruction('xml')", "http://javafx.com/javafx/8"), + FXML_IMPORTS); + + assertSize(report, 0); + } + + @Test + public void testComments() { + Report report = xml.executeRule(makeXPath("/child::comment()[fn:starts-with(fn:string(.), 'suppress')]"), + "\n" + + "\n" + + "\n" + + ""); + + assertSize(report, 1); + } + @Test public void testLocationFuns() { Rule rule = makeXPath("//Flow[pmd:beginLine(.) != pmd:endLine(.)]"); From 6b2effb5e73ce6281a9b5a551e4e7429dc42646e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 20 Mar 2022 14:10:17 +0100 Subject: [PATCH 60/89] More doc --- docs/_data/sidebars/pmd_sidebar.yml | 3 +++ docs/pages/pmd/languages/xml.md | 18 ++++++++++++------ .../pmd/lang/xml/rule/SaxonDomXPathQuery.java | 5 ++--- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index cf4d32d421..b2e6cf83ec 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -355,6 +355,9 @@ entries: - title: Visualforce url: /pmd_languages_visualforce.html output: web, pdf + - title: XML and derived languages + url: /pmd_languages_xml.html + output: web, pdf - title: Developer Documentation output: web, pdf folderitems: diff --git a/docs/pages/pmd/languages/xml.md b/docs/pages/pmd/languages/xml.md index daff0d7195..5ac637165d 100644 --- a/docs/pages/pmd/languages/xml.md +++ b/docs/pages/pmd/languages/xml.md @@ -1,5 +1,5 @@ --- -title: XML +title: Processing XML files permalink: pmd_languages_xml.html last_updated: March 2021 (6.33.0) --- @@ -18,7 +18,9 @@ table lists the languages currently provided by the `pmd-xml` maven module. | wsdl | Web Services Description Language | | xsl | Extensible Stylesheet Language | -Each of those languages has a separate rule index. +Each of those languages has a separate rule index, and may provide domain-specific +[XPath functions](pmd_userdocs_extending_writing_xpath_rules.html#pmd-extension-functions). +At their core they use the same parsing facilities though. ### File attribution @@ -31,7 +33,8 @@ arguments, for instance: ``` $ ./run.sh pmd -d /home/me/src/xml-file.ext -f text -R ruleset.xml --force-language xml ``` -Please refer to [PMD CLI reference](pmd_userdocs_cli_reference.html#analyze-other-xml-formats). +Please refer to [PMD CLI reference](pmd_userdocs_cli_reference.html#analyze-other-xml-formats) +for more examples. ### XPath rules in XML @@ -41,13 +44,16 @@ the use of this class is not recommended for XML languages. Instead, since 6.44. are advised to use {% xml::lang.xml.rule.DomXPathRule %}. This rule class interprets XPath queries exactly as regular XPath, while `XPathRule` works on a wrapper for the DOM which is inconsistent with the XPath spec. Since `DomXPathRule` conforms to the -XPath spec, you can test XML queries in any stock XPath testing tool, or use resources -like StackOverflow to write XPath queries. +XPath spec, you can +- test XML queries in any stock XPath testing tool, or use resources like StackOverflow + to help you write XPath queries. +- match XML comments and processing instructions +- use standard XPath functions like `text()` or `fn:string` {% include note.html content="The Rule Designer only works with `XPathRule`, and the tree it prints is inconsistent with the DOM representation used by `DomXPathRule`. You can use an online free XPath testing tool to test your query instead." %} Here's an example declaration of a `DomXPathRule`: -``` +```xml , XPathVariable> entry) { + private static ValueRepresentation getSaxonValue(PropertySource properties, Entry, XPathVariable> entry) { Object value = properties.getProperty(entry.getKey()); Objects.requireNonNull(value, "null property value for " + entry.getKey()); - final ValueRepresentation saxonValue = SaxonXPathRuleQuery.getRepresentation(entry.getKey(), value); - return saxonValue; + return SaxonXPathRuleQuery.getRepresentation(entry.getKey(), value); } } From f7442094a4d32d609d523ed41077e24e07c989f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 20 Mar 2022 17:21:46 +0100 Subject: [PATCH 61/89] Test namespace fn --- .../pmd/lang/xml/rule/XmlXPathRuleTest.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java index 6a863e699f..68aee20c20 100644 --- a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java @@ -176,6 +176,36 @@ public class XmlXPathRuleTest { assertSize(report, 1); } + @Test + public void testXmlNsFunctions() { + // https://github.com/pmd/pmd/issues/2766 + Report report = xml.executeRule( + makeXPath("/manifest[namespace-uri-for-prefix('android', .) = 'http://schemas.android.com/apk/res/android']"), + "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + ""); + + assertSize(report, 1); + } + @Test public void testLocationFuns() { Rule rule = makeXPath("//Flow[pmd:beginLine(.) != pmd:endLine(.)]"); From 463f68facaf93b6ee3375a05e42e1df685312d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 22 Mar 2022 19:34:13 +0100 Subject: [PATCH 62/89] Cleanup doc --- docs/_data/xpath_funs.yml | 24 ++++++++++++++---------- docs/_includes/custom/xpath_fun_doc.html | 4 ++++ docs/pages/pmd/languages/xml.md | 4 ++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/docs/_data/xpath_funs.yml b/docs/_data/xpath_funs.yml index 8f76da9f9e..86041d65cc 100644 --- a/docs/_data/xpath_funs.yml +++ b/docs/_data/xpath_funs.yml @@ -13,6 +13,7 @@ aliases: description: "Any element node" - &needs_typenode "The context node must be a {% jdoc jast::TypeNode %}" - ¬_ctx_dependent "The function is not context-dependent, but takes a node as its first parameter." + - &needs_node_ctx "The requires the context node to be an element" langs: - name: "Any language" @@ -21,11 +22,12 @@ langs: - name: fileName returnType: "xs:string" shortDescription: "Returns the simple name of the current file" - description: "Returns the current simple filename without path but including the extension. - This can be used to write rules that check filename naming conventions. + description: | + Returns the current simple file name, without path but including the extension. + This can be used to write rules that check file naming conventions. -

    This function is available since PMD 6.38.0.

    " - notes: "The function can be called on any node." + since: 6.38.0 + notes: *needs_node_ctx examples: - code: "//b[pmd:fileName() = 'Foo.xml']" outcome: "Matches any `<b>` tags in files called `Foo.xml`." @@ -35,10 +37,11 @@ langs: parameters: - *node_param shortDescription: "Returns the begin line of the given node" - description: "Returns the begin line of the given node in the source text. - Line numbers are 1-based. + description: | + Returns the line where the node starts in the source file. + Line numbers are 1-based. -

    This function is available since PMD 6.44.0.

    " + since: 6.44.0 notes: *not_ctx_dependent examples: - code: "//b[pmd:beginLine(.) > 5]" @@ -49,10 +52,11 @@ langs: parameters: - *node_param shortDescription: "Returns the end line of the given node" - description: "Returns the end line of the given node in the source text. - Line numbers are 1-based. + description: | + Returns the line where the node ends in the source file. + Line numbers are 1-based. -

    This function is available since PMD 6.44.0.

    " + since: 6.44.0 notes: *not_ctx_dependent examples: - code: "//b[pmd:endLine(.) == pmd:beginLine(.)]" diff --git a/docs/_includes/custom/xpath_fun_doc.html b/docs/_includes/custom/xpath_fun_doc.html index 12a7781adf..555f1e2f01 100644 --- a/docs/_includes/custom/xpath_fun_doc.html +++ b/docs/_includes/custom/xpath_fun_doc.html @@ -50,6 +50,10 @@
    {{ fun.description | render_markdown }}
    + {% if fun.since %} +
    Since
    +
    PMD {{ fun.since }}
    + {% endif %}
    Remarks
    {{ fun.notes | render_markdown }}
    diff --git a/docs/pages/pmd/languages/xml.md b/docs/pages/pmd/languages/xml.md index 5ac637165d..5774985f1b 100644 --- a/docs/pages/pmd/languages/xml.md +++ b/docs/pages/pmd/languages/xml.md @@ -41,7 +41,7 @@ for more examples. While other languages use {% jdoc core::lang.rule.XPathRule %} to create XPath rules, the use of this class is not recommended for XML languages. Instead, since 6.44.0, you -are advised to use {% xml::lang.xml.rule.DomXPathRule %}. This rule class interprets +are advised to use {% jdoc xml::lang.xml.rule.DomXPathRule %}. This rule class interprets XPath queries exactly as regular XPath, while `XPathRule` works on a wrapper for the DOM which is inconsistent with the XPath spec. Since `DomXPathRule` conforms to the XPath spec, you can @@ -70,6 +70,6 @@ Here's an example declaration of a `DomXPathRule`: ``` The most important change is the `class` attribute, which doesn't point to `XPathRule` -but to `DomXPathRule`. Please see the Javadoc for {% xml::lang.xml.rule.DomXPathRule %} +but to `DomXPathRule`. Please see the Javadoc for {% jdoc xml::lang.xml.rule.DomXPathRule %} for more info about the differences with `XPathRule`. From 37e701a90578c137b20074fd6261b0cec6a4c8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 22 Mar 2022 19:44:00 +0100 Subject: [PATCH 63/89] Add startCol/endCol functions Rename beginLine to startLine --- docs/_data/xpath_funs.yml | 45 ++++++++++++++++--- .../pmd/lang/xpath/PMDFunctions.java | 15 ++++++- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/docs/_data/xpath_funs.yml b/docs/_data/xpath_funs.yml index 86041d65cc..3626563d24 100644 --- a/docs/_data/xpath_funs.yml +++ b/docs/_data/xpath_funs.yml @@ -12,7 +12,9 @@ aliases: type: "xs:element" description: "Any element node" - &needs_typenode "The context node must be a {% jdoc jast::TypeNode %}" - - ¬_ctx_dependent "The function is not context-dependent, but takes a node as its first parameter." + - &coord_fun_note | + The function is not context-dependent, but takes a node as its first parameter. + The function is only available in XPath 2.0. - &needs_node_ctx "The requires the context node to be an element" langs: @@ -32,19 +34,19 @@ langs: - code: "//b[pmd:fileName() = 'Foo.xml']" outcome: "Matches any `<b>` tags in files called `Foo.xml`." - - name: beginLine + - name: startLine returnType: "xs:int" parameters: - *node_param - shortDescription: "Returns the begin line of the given node" + shortDescription: "Returns the start line of the given node" description: | Returns the line where the node starts in the source file. Line numbers are 1-based. since: 6.44.0 - notes: *not_ctx_dependent + notes: *coord_fun_note examples: - - code: "//b[pmd:beginLine(.) > 5]" + - code: "//b[pmd:startLine(.) > 5]" outcome: "Matches any `<b>` node which starts after the fifth line." - name: endLine @@ -57,11 +59,40 @@ langs: Line numbers are 1-based. since: 6.44.0 - notes: *not_ctx_dependent + notes: *coord_fun_note examples: - - code: "//b[pmd:endLine(.) == pmd:beginLine(.)]" + - code: "//b[pmd:endLine(.) == pmd:startLine(.)]" outcome: "Matches any `<b>` node which doesn't span more than one line." + - name: startColumn + returnType: "xs:int" + parameters: + - *node_param + shortDescription: "Returns the start column of the given node (inclusive)" + description: | + Returns the column number where the node starts in the source file. + Column numbers are 1-based. The start column is inclusive. + + since: 6.44.0 + notes: *coord_fun_note + examples: + - code: "//b[pmd:startColumn(.) = 1]" + outcome: "Matches any `<b>` node which starts on the first column of a line" + + - name: endColumn + returnType: "xs:int" + parameters: + - *node_param + shortDescription: "Returns the end column of the given node (exclusive)" + description: | + Returns the column number where the node ends in the source file. + Column numbers are 1-based. The end column is exclusive. + + since: 6.44.0 + notes: *coord_fun_note + examples: + - code: "//b[pmd:startLine(.) = pmd:endLine(.) and pmd:endColumn(.) - pmd:startColumn(.) = 1]" + outcome: "Matches any `<b>` node which spans exactly one character" - name: "Java" ns: "pmd-java" diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java index 5fb1a48c15..e4d99dcd4a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java @@ -15,6 +15,7 @@ import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; import net.sf.saxon.dom.NodeWrapper; import net.sf.saxon.expr.XPathContext; import net.sf.saxon.om.Item; +import net.sf.saxon.om.NodeInfo; @InternalApi @@ -61,16 +62,26 @@ public final class PMDFunctions { return node == null ? null : FileNameXPathFunction.getFileName(node); } - public static int beginLine(Item item) { + public static int startLine(NodeInfo item) { Node node = Objects.requireNonNull(itemToNode(item), "not a node " + item); return node.getBeginLine(); } - public static int endLine(Item item) { + public static int endLine(NodeInfo item) { Node node = Objects.requireNonNull(itemToNode(item), "not a node " + item); return node.getEndLine(); } + public static int startColumn(NodeInfo item) { + Node node = Objects.requireNonNull(itemToNode(item), "not a node " + item); + return node.getBeginColumn(); + } + + public static int endColumn(NodeInfo item) { + Node node = Objects.requireNonNull(itemToNode(item), "not a node " + item); + return node.getEndColumn() + 1; // exclusive + } + private static Node itemToNode(Object item) { if (item instanceof Node) { return (Node) item; From 291be974c186fc3d31ae70b2ba8e9469ef9ab00f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 22 Mar 2022 19:46:21 +0100 Subject: [PATCH 64/89] Fix header for pmd: funs --- docs/_data/sidebars/pmd_sidebar.yml | 2 +- docs/_data/xpath_funs.yml | 3 ++- docs/_includes/custom/xpath_fun_doc.html | 4 ++++ .../pmd/lang/rule/XPathRuleTest.java | 17 ++++++++++++++++- .../pmd/lang/xml/rule/DomXPathRule.java | 4 ++-- .../pmd/lang/xml/rule/XmlXPathRuleTest.java | 2 +- 6 files changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index b2e6cf83ec..b1ef194b08 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -355,7 +355,7 @@ entries: - title: Visualforce url: /pmd_languages_visualforce.html output: web, pdf - - title: XML and derived languages + - title: XML and XML dialects url: /pmd_languages_xml.html output: web, pdf - title: Developer Documentation diff --git a/docs/_data/xpath_funs.yml b/docs/_data/xpath_funs.yml index 3626563d24..ce0125f372 100644 --- a/docs/_data/xpath_funs.yml +++ b/docs/_data/xpath_funs.yml @@ -18,8 +18,9 @@ aliases: - &needs_node_ctx "The requires the context node to be an element" langs: - - name: "Any language" + - name: "All languages" ns: "pmd" + header: "Functions available to all languages are in the namespace `pmd`." funs: - name: fileName returnType: "xs:string" diff --git a/docs/_includes/custom/xpath_fun_doc.html b/docs/_includes/custom/xpath_fun_doc.html index 555f1e2f01..fb8ba0d64c 100644 --- a/docs/_includes/custom/xpath_fun_doc.html +++ b/docs/_includes/custom/xpath_fun_doc.html @@ -4,7 +4,11 @@ ### {{ lang.name }} +{% if lang.header %} +{{ lang.header | render_markdown }} +{% else %} {{ lang.name }} functions are in the namespace `{{ lang.ns }}`. +{% endif %}
    diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java index 58665dd494..c462bce699 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java @@ -175,7 +175,15 @@ public class XPathRuleTest { @Test public void testBeginLine() { - Report report = executeRule(makeXPath("//*[pmd:beginLine(.)=1]"), + Report report = executeRule(makeXPath("//*[pmd:startLine(.)=1]"), + newRoot("src/Foo.cls")); + + assertThat(report.getViolations(), hasSize(1)); + } + + @Test + public void testBeginCol() { + Report report = executeRule(makeXPath("//*[pmd:startColumn(.)=1]"), newRoot("src/Foo.cls")); assertThat(report.getViolations(), hasSize(1)); @@ -189,6 +197,13 @@ public class XPathRuleTest { assertThat(report.getViolations(), hasSize(1)); } + @Test + public void testEndColumn() { + Report report = executeRule(makeXPath("//*[pmd:endColumn(.)=1]"), + newRoot("src/Foo.cls")); + + assertThat(report.getViolations(), hasSize(1)); + } public Report executeRule(net.sourceforge.pmd.Rule rule, DummyNode node) { RuleContext ctx = new RuleContext(); diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java index 1f7d3bfce9..d1317e11f6 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -35,9 +35,9 @@ import net.sourceforge.pmd.properties.PropertyFactory; *
  • {@link XPathRule} adds additional attributes to each element * (eg {@code @BeginLine} and {@code @Image}). These attributes are not * XML attributes, so they are not accessible using DomXPathRule rule. - * Instead, use the XPath functions {@code pmd:beginLine(node)} and {@code pmd:beginLine(node)}. + * Instead, use the XPath functions {@code pmd:startLine(node)}, {@code pmd:endLine(node)} and related. * For instance, replace {@code //elt[@EndLine - @BeginLine > 10]} with - * {@code elt[pmd:endLine(.) - pmd:beginLine(.) > 10]}. + * {@code elt[pmd:endLine(.) - pmd:startLine(.) > 10]}. *
  • {@link XPathRule} uses an element called {@code "document"} as the * root node of every XML AST. This node does not have the correct node kind, * as it's an element, not a document. To replace {@code /document/RootNode}, diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java index 68aee20c20..f7d4ff0d63 100644 --- a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java @@ -208,7 +208,7 @@ public class XmlXPathRuleTest { @Test public void testLocationFuns() { - Rule rule = makeXPath("//Flow[pmd:beginLine(.) != pmd:endLine(.)]"); + Rule rule = makeXPath("//Flow[pmd:startLine(.) != pmd:endLine(.)]"); Report report = xml.executeRule(rule, ""); assertSize(report, 0); report = xml.executeRule(rule, "\n\n"); From 5bfc2546d997fb76cac50e8d073d5636198e814c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 22 Mar 2022 21:35:03 +0100 Subject: [PATCH 65/89] Fix tests --- .../test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java index c462bce699..1917f7b767 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java @@ -199,7 +199,7 @@ public class XPathRuleTest { @Test public void testEndColumn() { - Report report = executeRule(makeXPath("//*[pmd:endColumn(.)=1]"), + Report report = executeRule(makeXPath("//*[pmd:endColumn(.)>1]"), newRoot("src/Foo.cls")); assertThat(report.getViolations(), hasSize(1)); From af9547af7d4bde3f70789b4cc1daae5b73949a98 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 24 Mar 2022 12:13:01 +0100 Subject: [PATCH 66/89] [doc] Minor fixes (styling mostly) Don't show edit buttons for generated pages --- docs/_includes/footer.html | 9 ++++----- docs/_includes/header.html | 6 +++--- docs/_includes/toc.html | 12 ------------ docs/_layouts/page.html | 2 +- docs/css/customstyles.css | 4 ---- docs/css/pmd-customstyles.css | 4 ++++ docs/js/customscripts.js | 19 ++++++++++--------- docs/pages/pmd/devdocs/building.md | 4 ++-- 8 files changed, 24 insertions(+), 36 deletions(-) delete mode 100644 docs/_includes/toc.html diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html index 5a66147c2c..8fb9a7b49b 100755 --- a/docs/_includes/footer.html +++ b/docs/_includes/footer.html @@ -1,19 +1,18 @@
    + {% if site.github_editme_path and page.editmepath != false %}
    + {% endif %}
  • + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + From 2f65275db3e7c2731e44c5837c02995859421d7f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 24 Mar 2022 14:27:34 +0100 Subject: [PATCH 69/89] Bump maven from 3.8.4 to 3.8.5 --- .mvn/wrapper/maven-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 8c79a83ae4..db95c131dd 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar From 83680f90ff8876a93753e1e5c65101170c129b80 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 24 Mar 2022 14:32:46 +0100 Subject: [PATCH 70/89] [doc] Update release notes (#3817) --- docs/pages/release_notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8b6e8ffc93..3e7e8c3573 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -50,6 +50,8 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is ### Fixed Issues +* apex + * [#3817](https://github.com/pmd/pmd/pull/3817): \[apex] Add designer bindings to display main attributes * apex-performance * [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() From 819e6236c49f36774ccac8f4cea14d58c651c211 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 24 Mar 2022 15:23:57 +0100 Subject: [PATCH 71/89] Fix tests and compile errors --- .../pmd/lang/apex/internal/ApexDesignerBindings.java | 2 +- .../sourceforge/pmd/AbstractRuleSetFactoryTest.java | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/internal/ApexDesignerBindings.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/internal/ApexDesignerBindings.java index 80dcb9bd65..375e566f18 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/internal/ApexDesignerBindings.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/internal/ApexDesignerBindings.java @@ -12,7 +12,7 @@ import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.ast.ApexParserVisitorAdapter; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.ast.xpath.Attribute; +import net.sourceforge.pmd.lang.rule.xpath.Attribute; import net.sourceforge.pmd.util.designerbindings.DesignerBindings.DefaultDesignerBindings; public class ApexDesignerBindings extends DefaultDesignerBindings { diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java index b8f6df5739..ad284d14db 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java @@ -18,6 +18,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -27,7 +28,6 @@ import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; import java.util.regex.Pattern; - import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; @@ -293,7 +293,15 @@ public abstract class AbstractRuleSetFactoryTest { private List getRuleSetFileNames(String language, String propertiesPath) throws IOException { List ruleSetFileNames = new ArrayList<>(); Properties properties = new Properties(); - try (InputStream is = getClass().getResourceAsStream(propertiesPath)) { + @SuppressWarnings("PMD.CloseResource") + InputStream input = getClass().getResourceAsStream(propertiesPath); + if (input == null) { + // this might happen if a language is only support by CPD, but not + // by PMD + System.err.println("No ruleset found for language " + language); + return Collections.emptyList(); + } + try (InputStream is = input) { properties.load(is); } String fileNames = properties.getProperty("rulesets.filenames"); From b1f85585d4e8881c6f97dd4300c5c902f3c26266 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 24 Mar 2022 16:18:51 +0100 Subject: [PATCH 72/89] Revert "REVERT ME - Use pmtester from pmd/pmd-regression-tester#103" This reverts commit 67928910df25574ec41821b60d352e5f32bfe971. --- Gemfile | 3 +-- Gemfile.lock | 24 +++++++------------ .../main/java/net/sourceforge/pmd/PMD.java | 1 - 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/Gemfile b/Gemfile index 0216265f49..5e0616a5b4 100644 --- a/Gemfile +++ b/Gemfile @@ -2,9 +2,8 @@ source 'https://rubygems.org/' # bleeding edge from git #gem 'pmdtester', :git => 'https://github.com/pmd/pmd-regression-tester.git', branch: 'master' -gem 'pmdtester', :git => 'https://github.com/adangel/pmd-regression-tester.git', branch: 'auto-gen-config-all' -#gem 'pmdtester' +gem 'pmdtester' gem 'danger' # This group is only needed for rendering release notes (docs/render_release_notes.rb) diff --git a/Gemfile.lock b/Gemfile.lock index b1fcd6da80..3c5a1abe22 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,16 +1,3 @@ -GIT - remote: https://github.com/adangel/pmd-regression-tester.git - revision: 44a62cd72a839e821a8160429c873f5dad362c83 - branch: auto-gen-config-all - specs: - pmdtester (1.3.1.pre.SNAPSHOT) - differ (~> 0.1) - liquid (~> 5.2) - logger-colors (~> 1.0) - nokogiri (~> 1.13) - rufus-scheduler (~> 3.8) - slop (~> 4.6) - GEM remote: https://rubygems.org/ specs: @@ -25,7 +12,7 @@ GEM concurrent-ruby (1.1.9) cork (0.3.0) colored2 (~> 3.1) - danger (8.5.0) + danger (8.4.5) claide (~> 1.0) claide-plugins (>= 0.9.2) colored2 (~> 3.1) @@ -88,6 +75,13 @@ GEM faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) open4 (1.3.4) + pmdtester (1.3.0) + differ (~> 0.1) + liquid (>= 4.0) + logger-colors (~> 1.0) + nokogiri (>= 1.11.0.rc4) + rufus-scheduler (~> 3.5) + slop (~> 4.6) public_suffix (4.0.6) raabro (1.4.0) racc (1.6.0) @@ -114,7 +108,7 @@ PLATFORMS DEPENDENCIES danger liquid (>= 4.0.0) - pmdtester! + pmdtester rouge (>= 1.7, < 4) safe_yaml (>= 1.0) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java index f26772032f..714bfb0e64 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java @@ -63,7 +63,6 @@ import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter; */ public class PMD { - private static final Logger LOG = Logger.getLogger(PMD.class.getName()); /** From 2f5f7f3c927179a836378826f06961ba94513fc8 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 24 Mar 2022 16:22:58 +0100 Subject: [PATCH 73/89] [doc] Update release notes (#2693) --- docs/pages/release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8f3f873967..1d6a7a90b0 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -56,6 +56,7 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is * apex-performance * [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() * core + * [#2693](https://github.com/pmd/pmd/issues/2693): \[ci] Add integration tests with real open-source projects * [#3299](https://github.com/pmd/pmd/issues/3299): \[core] Deprecate system properties of PMDCommandLineInterface * doc * [#2504](https://github.com/pmd/pmd/issues/2504): \[doc] Improve "Edit me on github" button From 0081e61cfd5d519864bef892203c72afff32d1ad Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 24 Mar 2022 16:46:42 +0100 Subject: [PATCH 74/89] Update pmdtester to 1.4.0 --- Gemfile | 6 +++--- Gemfile.lock | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Gemfile b/Gemfile index 5e0616a5b4..031779070e 100644 --- a/Gemfile +++ b/Gemfile @@ -10,9 +10,9 @@ gem 'danger' # this happens during release (.ci/build.sh and do-release.sh) # but also during regular builds (.ci/build.sh) group :release_notes_preprocessing do - gem 'liquid', '>=4.0.0' - gem 'safe_yaml', '>=1.0' - gem 'rouge', '>= 1.7', '< 4' + gem 'liquid' + gem 'safe_yaml' + gem 'rouge' end # vim: syntax=ruby diff --git a/Gemfile.lock b/Gemfile.lock index 3c5a1abe22..751d2e9be4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,10 +9,10 @@ GEM nap open4 (~> 1.3) colored2 (3.1.2) - concurrent-ruby (1.1.9) + concurrent-ruby (1.1.10) cork (0.3.0) colored2 (~> 3.1) - danger (8.4.5) + danger (8.5.0) claide (~> 1.0) claide-plugins (>= 0.9.2) colored2 (~> 3.1) @@ -58,11 +58,11 @@ GEM raabro (~> 1.4) git (1.10.2) rchardet (~> 1.8) - kramdown (2.3.1) + kramdown (2.3.2) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) - liquid (5.2.0) + liquid (5.3.0) logger-colors (1.0.0) mini_portile2 (2.8.0) multipart-post (2.1.1) @@ -75,12 +75,12 @@ GEM faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) open4 (1.3.4) - pmdtester (1.3.0) + pmdtester (1.4.0) differ (~> 0.1) - liquid (>= 4.0) + liquid (~> 5.2) logger-colors (~> 1.0) - nokogiri (>= 1.11.0.rc4) - rufus-scheduler (~> 3.5) + nokogiri (~> 1.13) + rufus-scheduler (~> 3.8) slop (~> 4.6) public_suffix (4.0.6) raabro (1.4.0) @@ -107,10 +107,10 @@ PLATFORMS DEPENDENCIES danger - liquid (>= 4.0.0) + liquid pmdtester - rouge (>= 1.7, < 4) - safe_yaml (>= 1.0) + rouge + safe_yaml BUNDLED WITH 2.1.4 From 8b073b9dd5b9b928c7b20fe31c64733fed79d672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 24 Mar 2022 19:12:28 +0100 Subject: [PATCH 75/89] Apply suggestions from code review Co-authored-by: Andreas Dangel --- docs/pages/pmd/languages/xml.md | 2 +- .../main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/pmd/languages/xml.md b/docs/pages/pmd/languages/xml.md index 5774985f1b..ddd7d34a6d 100644 --- a/docs/pages/pmd/languages/xml.md +++ b/docs/pages/pmd/languages/xml.md @@ -1,7 +1,7 @@ --- title: Processing XML files permalink: pmd_languages_xml.html -last_updated: March 2021 (6.33.0) +last_updated: March 2022 (6.44.0) --- ## The XML language module diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java index e4d99dcd4a..3c73ee45f7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java @@ -92,7 +92,7 @@ public final class PMDFunctions { } else if (item instanceof org.w3c.dom.Node) { return itemToNode(((org.w3c.dom.Node) item).getUserData(PMD_NODE_USER_DATA)); } - LOG.fine("Cannot call pmd:filename on " + item); + LOG.fine("Cannot call function on " + item); return null; } } From 9a43a09a370702305d1328631605d46dd139f7b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 24 Mar 2022 19:11:48 +0100 Subject: [PATCH 76/89] Pr review --- .../java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java | 2 +- .../net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java index d1317e11f6..f3440dd83f 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -69,7 +69,7 @@ import net.sourceforge.pmd.properties.PropertyFactory; * *

    Namespace-sensitivity

    * - *

    Another large difference is that this rule is namespace-sensitive. + *

    Another important difference is that this rule is namespace-sensitive. * If the tested XML documents use a schema ({@code xmlns} attribute on the root), * you should set the property {@code defaultNsUri} on the rule with * the value of the {@code xmlns} attribute. Otherwise node tests won't diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java index abfbb0290b..3e8ee8eb27 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java @@ -102,6 +102,7 @@ final class SaxonDomXPathQuery { private boolean isExcludedProperty(String name) { return "xpath".equals(name) + || "defaultNsUri".equals(name) || "violationSuppressRegex".equals(name) || "violationSuppressXPath".equals(name); } From ed33ff403b8c7f876e341026ee642846664001a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 24 Mar 2022 19:35:50 +0100 Subject: [PATCH 77/89] Restore new xpath funs --- .../lang/rule/xpath/impl/XPathHandler.java | 2 +- .../internal/CoordinateXPathFunction.java | 90 +++++++++++++++++++ .../xpath/internal/DefaultXPathFunctions.java | 11 ++- 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathHandler.java index 7ca9d5893c..0ef25b7884 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathHandler.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/impl/XPathHandler.java @@ -28,7 +28,7 @@ public interface XPathHandler { static XPathHandler noFunctionDefinitions() { - return () -> DefaultXPathFunctions.getDefaultFunctions(); + return DefaultXPathFunctions::getDefaultFunctions; } /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java new file mode 100644 index 0000000000..e44bc933cf --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java @@ -0,0 +1,90 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.xpath.internal; + +import java.util.function.ToIntFunction; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.rule.xpath.impl.AbstractXPathFunctionDef; + +import net.sf.saxon.expr.XPathContext; +import net.sf.saxon.lib.ExtensionFunctionCall; +import net.sf.saxon.om.Sequence; +import net.sf.saxon.pattern.NodeKindTest; +import net.sf.saxon.trans.XPathException; +import net.sf.saxon.tree.wrapper.AbstractNodeWrapper; +import net.sf.saxon.type.Type; +import net.sf.saxon.value.Int64Value; +import net.sf.saxon.value.SequenceType; + +/** + * A function that returns the current file name. + * + * @author Clément Fournier + */ +public final class CoordinateXPathFunction extends AbstractXPathFunctionDef { + + public static final CoordinateXPathFunction START_LINE = + new CoordinateXPathFunction("startLine", Node::getBeginLine); + public static final CoordinateXPathFunction END_LINE = + new CoordinateXPathFunction("endLine", Node::getEndLine); + public static final CoordinateXPathFunction START_COLUMN = + new CoordinateXPathFunction("startColumn", Node::getBeginColumn); + public static final CoordinateXPathFunction END_COLUMN = + new CoordinateXPathFunction("endColumn", Node::getEndColumn); + + private static final SequenceType[] A_SINGLE_ELEMENT = { + NodeKindTest.makeNodeKindTest(Type.ELEMENT).one() + }; + private static final String PMD_NODE_USER_DATA = "pmd.node"; + private final ToIntFunction getter; + + private CoordinateXPathFunction(String localName, ToIntFunction getter) { + super(localName); + this.getter = getter; + } + + @Override + public SequenceType[] getArgumentTypes() { + return A_SINGLE_ELEMENT; + } + + @Override + public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { + return SequenceType.SINGLE_INTEGER; + } + + @Override + public ExtensionFunctionCall makeCallExpression() { + return new ExtensionFunctionCall() { + + @Override + public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { + Node node = itemToNode(arguments[0]); + if (node == null) { + throw new XPathException( + "Cannot call function '" + getFunctionQName().getLocalPart() + + "' on argument " + arguments[0] + ); + } + return Int64Value.makeIntegerValue(getter.applyAsInt(node)); + } + }; + } + + + private static Node itemToNode(Object item) { + if (item instanceof Node) { + return (Node) item; + } else if (item instanceof AstElementNode) { + return itemToNode(((AstElementNode) item).getUnderlyingNode()); + } else if (item instanceof AbstractNodeWrapper) { + return itemToNode(((AbstractNodeWrapper) item).getUnderlyingNode()); + } else if (item instanceof org.w3c.dom.Node) { + return itemToNode(((org.w3c.dom.Node) item).getUserData(PMD_NODE_USER_DATA)); + } + return null; + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DefaultXPathFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DefaultXPathFunctions.java index bf0a074f70..bfd58f98fa 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DefaultXPathFunctions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/DefaultXPathFunctions.java @@ -16,11 +16,20 @@ import net.sf.saxon.lib.ExtensionFunctionDefinition; */ public final class DefaultXPathFunctions { + private static final Set DEFAULTS = + CollectionUtil.immutableSetOf( + FileNameXPathFunction.INSTANCE, + CoordinateXPathFunction.START_LINE, + CoordinateXPathFunction.START_COLUMN, + CoordinateXPathFunction.END_LINE, + CoordinateXPathFunction.END_COLUMN + ); + private DefaultXPathFunctions() { // utility class } public static Set getDefaultFunctions() { - return CollectionUtil.setOf(FileNameXPathFunction.INSTANCE); + return DEFAULTS; } } From 6343cfe0ce69cd260f583768c9932b55a08a6817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 24 Mar 2022 19:36:52 +0100 Subject: [PATCH 78/89] Remove comment about required xpath ver We don't support jaxen anymore --- docs/_data/xpath_funs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/_data/xpath_funs.yml b/docs/_data/xpath_funs.yml index 1dff9ade95..5a33bdd259 100644 --- a/docs/_data/xpath_funs.yml +++ b/docs/_data/xpath_funs.yml @@ -14,7 +14,6 @@ aliases: - &needs_typenode "The context node must be a {% jdoc jast::TypeNode %}" - &coord_fun_note | The function is not context-dependent, but takes a node as its first parameter. - The function is only available in XPath 2.0. - &needs_node_ctx "The requires the context node to be an element" langs: From a26a42f623e3382a7fa7fef5c8627e2ff4f308dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 24 Mar 2022 19:45:43 +0100 Subject: [PATCH 79/89] Fix xml module --- .../internal/CoordinateXPathFunction.java | 19 ++------ .../xpath/internal/FileNameXPathFunction.java | 8 +++- .../internal/XPathElementToNodeHelper.java | 36 ++++++++++++++ .../lang/xml/ast/internal/XmlNodeWrapper.java | 8 ++++ .../pmd/lang/xml/rule/DomXPathRule.java | 19 ++++---- .../pmd/lang/xml/rule/SaxonDomXPathQuery.java | 47 ++++++++++++------- 6 files changed, 91 insertions(+), 46 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/XPathElementToNodeHelper.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java index e44bc933cf..31d41783e2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/CoordinateXPathFunction.java @@ -14,7 +14,6 @@ import net.sf.saxon.lib.ExtensionFunctionCall; import net.sf.saxon.om.Sequence; import net.sf.saxon.pattern.NodeKindTest; import net.sf.saxon.trans.XPathException; -import net.sf.saxon.tree.wrapper.AbstractNodeWrapper; import net.sf.saxon.type.Type; import net.sf.saxon.value.Int64Value; import net.sf.saxon.value.SequenceType; @@ -36,9 +35,9 @@ public final class CoordinateXPathFunction extends AbstractXPathFunctionDef { new CoordinateXPathFunction("endColumn", Node::getEndColumn); private static final SequenceType[] A_SINGLE_ELEMENT = { - NodeKindTest.makeNodeKindTest(Type.ELEMENT).one() + NodeKindTest.makeNodeKindTest(Type.ELEMENT).one(), }; - private static final String PMD_NODE_USER_DATA = "pmd.node"; + public static final String PMD_NODE_USER_DATA = "pmd.node"; private final ToIntFunction getter; private CoordinateXPathFunction(String localName, ToIntFunction getter) { @@ -62,7 +61,7 @@ public final class CoordinateXPathFunction extends AbstractXPathFunctionDef { @Override public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { - Node node = itemToNode(arguments[0]); + Node node = XPathElementToNodeHelper.itemToNode(arguments[0]); if (node == null) { throw new XPathException( "Cannot call function '" + getFunctionQName().getLocalPart() @@ -75,16 +74,4 @@ public final class CoordinateXPathFunction extends AbstractXPathFunctionDef { } - private static Node itemToNode(Object item) { - if (item instanceof Node) { - return (Node) item; - } else if (item instanceof AstElementNode) { - return itemToNode(((AstElementNode) item).getUnderlyingNode()); - } else if (item instanceof AbstractNodeWrapper) { - return itemToNode(((AbstractNodeWrapper) item).getUnderlyingNode()); - } else if (item instanceof org.w3c.dom.Node) { - return itemToNode(((org.w3c.dom.Node) item).getUserData(PMD_NODE_USER_DATA)); - } - return null; - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/FileNameXPathFunction.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/FileNameXPathFunction.java index 7605b11856..eecea9211a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/FileNameXPathFunction.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/FileNameXPathFunction.java @@ -47,7 +47,13 @@ public final class FileNameXPathFunction extends AbstractXPathFunctionDef { @Override public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException { - Node node = ((AstElementNode) context.getContextItem()).getUnderlyingNode(); + Node node = XPathElementToNodeHelper.itemToNode(context.getContextItem()); + if (node == null) { + throw new XPathException( + "Cannot call function '" + getFunctionQName().getLocalPart() + + "' with context item " + context.getContextItem() + ); + } RootNode root = node.getRoot(); Objects.requireNonNull(root, "No root node in tree?"); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/XPathElementToNodeHelper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/XPathElementToNodeHelper.java new file mode 100644 index 0000000000..043582d713 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/XPathElementToNodeHelper.java @@ -0,0 +1,36 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.xpath.internal; + +import net.sourceforge.pmd.lang.ast.Node; + +import net.sf.saxon.tree.wrapper.AbstractNodeWrapper; + +/** + * A function that returns the current file name. + * + * @author Clément Fournier + */ +public final class XPathElementToNodeHelper { + + public static final String PMD_NODE_USER_DATA = "pmd.node"; + + private XPathElementToNodeHelper() { + + } + + static Node itemToNode(Object item) { + if (item instanceof Node) { + return (Node) item; + } else if (item instanceof AstElementNode) { + return itemToNode(((AstElementNode) item).getUnderlyingNode()); + } else if (item instanceof AbstractNodeWrapper) { + return itemToNode(((AbstractNodeWrapper) item).getUnderlyingNode()); + } else if (item instanceof org.w3c.dom.Node) { + return itemToNode(((org.w3c.dom.Node) item).getUserData(PMD_NODE_USER_DATA)); + } + return null; + } +} diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/internal/XmlNodeWrapper.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/internal/XmlNodeWrapper.java index 66781e3cf6..a1aac7985f 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/internal/XmlNodeWrapper.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/internal/XmlNodeWrapper.java @@ -20,6 +20,7 @@ import org.w3c.dom.Text; import net.sourceforge.pmd.internal.util.IteratorUtil; import net.sourceforge.pmd.lang.rule.xpath.Attribute; +import net.sourceforge.pmd.lang.rule.xpath.internal.CoordinateXPathFunction; import net.sourceforge.pmd.lang.xml.ast.XmlNode; import net.sourceforge.pmd.util.DataMap; import net.sourceforge.pmd.util.DataMap.DataKey; @@ -47,8 +48,15 @@ class XmlNodeWrapper implements XmlNode { super(); this.node = domNode; this.parser = parser; + + domNode.setUserData(CoordinateXPathFunction.PMD_NODE_USER_DATA, this, null); } + protected XmlNode wrap(org.w3c.dom.Node domNode) { + return parser.wrapDomNode(domNode); + } + + @Override public XmlNode getParent() { org.w3c.dom.Node parent = node.getParentNode(); diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java index f3440dd83f..1e4dfc9849 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -4,13 +4,11 @@ package net.sourceforge.pmd.lang.xml.rule; -import java.util.List; - import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.AbstractRule; import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.lang.xml.ast.XmlParser.RootXmlNode; +import net.sourceforge.pmd.lang.xml.ast.internal.XmlParserImpl.RootXmlNode; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -141,13 +139,11 @@ public class DomXPathRule extends AbstractRule { } @Override - public void apply(List nodes, RuleContext ctx) { - for (Node n : nodes) { - RootXmlNode root = (RootXmlNode) n; - SaxonDomXPathQuery query = getXPathQuery(); - for (Node foundNode : query.evaluate(root, this)) { - ctx.addViolation(foundNode); - } + public void apply(Node node, RuleContext ctx) { + RootXmlNode root = (RootXmlNode) node; + SaxonDomXPathQuery query = getXPathQuery(); + for (Node foundNode : query.evaluate(root, this)) { + ctx.addViolation(foundNode); } } @@ -155,7 +151,8 @@ public class DomXPathRule extends AbstractRule { if (query == null) { query = new SaxonDomXPathQuery(getProperty(XPATH_EXPR), getProperty(DEFAULT_NS_URI), - getPropertyDescriptors()); + getPropertyDescriptors(), + getLanguage().getDefaultVersion().getLanguageVersionHandler().getXPathHandler()); } return query; } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java index 3e8ee8eb27..74f70fa3a3 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/SaxonDomXPathQuery.java @@ -16,10 +16,10 @@ import org.apache.commons.lang3.exception.ContextedRuntimeException; import org.w3c.dom.Document; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; +import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler; +import net.sourceforge.pmd.lang.rule.xpath.internal.DomainConversion; import net.sourceforge.pmd.lang.xml.ast.XmlNode; -import net.sourceforge.pmd.lang.xml.ast.XmlParser.RootXmlNode; -import net.sourceforge.pmd.lang.xpath.Initializer; +import net.sourceforge.pmd.lang.xml.ast.internal.XmlParserImpl.RootXmlNode; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertySource; import net.sourceforge.pmd.util.DataMap; @@ -28,11 +28,12 @@ import net.sourceforge.pmd.util.DataMap.SimpleDataKey; import net.sf.saxon.Configuration; import net.sf.saxon.dom.DocumentWrapper; -import net.sf.saxon.dom.NodeWrapper; +import net.sf.saxon.lib.ExtensionFunctionDefinition; +import net.sf.saxon.lib.NamespaceConstant; +import net.sf.saxon.om.AtomicSequence; import net.sf.saxon.om.Item; import net.sf.saxon.om.NamePool; -import net.sf.saxon.om.NamespaceConstant; -import net.sf.saxon.om.ValueRepresentation; +import net.sf.saxon.om.StructuredQName; import net.sf.saxon.sxpath.IndependentContext; import net.sf.saxon.sxpath.XPathDynamicContext; import net.sf.saxon.sxpath.XPathEvaluator; @@ -40,6 +41,7 @@ import net.sf.saxon.sxpath.XPathExpression; import net.sf.saxon.sxpath.XPathStaticContext; import net.sf.saxon.sxpath.XPathVariable; import net.sf.saxon.trans.XPathException; +import net.sf.saxon.tree.wrapper.AbstractNodeWrapper; final class SaxonDomXPathQuery { @@ -50,14 +52,19 @@ final class SaxonDomXPathQuery { /** The XPath expression as a string. */ private final String xpath; + private final XPathHandler xpathHandler; /** The executable XPath expression. */ private final XPathExpressionWithProperties xpathExpression; private final Configuration configuration; - SaxonDomXPathQuery(String xpath, String defaultNsUri, List> properties) { + SaxonDomXPathQuery(String xpath, + String defaultNsUri, + List> properties, + XPathHandler xpathHandler) { this.xpath = xpath; + this.xpathHandler = xpathHandler; configuration = new Configuration(); configuration.setNamePool(NAME_POOL); xpathExpression = makeXPathExpression(this.xpath, defaultNsUri, properties); @@ -69,8 +76,13 @@ final class SaxonDomXPathQuery { xpathStaticContext.setDefaultElementNamespace(defaultUri); - // Register PMD functions - Initializer.initialize(xpathStaticContext); + + + for (ExtensionFunctionDefinition fun : xpathHandler.getRegisteredExtensionFunctions()) { + StructuredQName qname = fun.getFunctionQName(); + xpathStaticContext.declareNamespace(qname.getPrefix(), qname.getURI()); + this.configuration.registerExtensionFunction(fun); + } Map, XPathVariable> xpathVariables = declareXPathVariables(properties, xpathStaticContext); @@ -118,8 +130,8 @@ final class SaxonDomXPathQuery { try { List result = new ArrayList<>(); for (Item item : this.xpathExpression.evaluate(wrapper, propertyValues)) { - if (item instanceof NodeWrapper) { - NodeWrapper nodeInfo = (NodeWrapper) item; + if (item instanceof AbstractNodeWrapper) { + AbstractNodeWrapper nodeInfo = (AbstractNodeWrapper) item; Object domNode = nodeInfo.getUnderlyingNode(); if (domNode instanceof org.w3c.dom.Node) { XmlNode wrapped = root.wrap((org.w3c.dom.Node) domNode); @@ -158,18 +170,17 @@ final class SaxonDomXPathQuery { this.xpathVariables = xpathVariables; } - @SuppressWarnings("unchecked") private List evaluate(final DocumentWrapper elementNode, PropertySource properties) throws XPathException { XPathDynamicContext dynamicContext = createDynamicContext(elementNode, properties); - return (List) expr.evaluate(dynamicContext); + return expr.evaluate(dynamicContext); } - private XPathDynamicContext createDynamicContext(final DocumentWrapper elementNode, PropertySource properties) { - final XPathDynamicContext dynamicContext = expr.createDynamicContext(elementNode); + private XPathDynamicContext createDynamicContext(final DocumentWrapper elementNode, PropertySource properties) throws XPathException { + final XPathDynamicContext dynamicContext = expr.createDynamicContext(elementNode.getRootNode()); // Set variable values on the dynamic context for (final Entry, XPathVariable> entry : xpathVariables.entrySet()) { - ValueRepresentation saxonValue = getSaxonValue(properties, entry); + AtomicSequence saxonValue = getSaxonValue(properties, entry); XPathVariable variable = entry.getValue(); try { dynamicContext.setVariable(variable, saxonValue); @@ -181,10 +192,10 @@ final class SaxonDomXPathQuery { return dynamicContext; } - private static ValueRepresentation getSaxonValue(PropertySource properties, Entry, XPathVariable> entry) { + private static AtomicSequence getSaxonValue(PropertySource properties, Entry, XPathVariable> entry) { Object value = properties.getProperty(entry.getKey()); Objects.requireNonNull(value, "null property value for " + entry.getKey()); - return SaxonXPathRuleQuery.getRepresentation(entry.getKey(), value); + return DomainConversion.convert(value); } } From 6549c585a0be267c604657d0fcf392762e256837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 24 Mar 2022 22:07:28 +0100 Subject: [PATCH 80/89] Update release notes --- docs/pages/release_notes.md | 45 +++++++++++++++++++ .../pmd/lang/xml/rule/DomXPathRule.java | 2 + 2 files changed, 47 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index ae817d64cb..282bf63c6a 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -14,6 +14,51 @@ This is a {{ site.pmd.release_type }} release. ### New and noteworthy +#### Better XML XPath support + +The new rule class {% jdoc xml::lang.xml.rule.DomXPathRule %} is intended to replace +usage of the `XPathRule` for XML rules. This rule executes the XPath query in a different +way, which sticks to the XPath specification. This means the expression is interpreted +the same way in PMD as in all other XPath development tools that stick to the standard. +You can for instance test the expression in an online XPath editor. + +Prefer using this class to define XPath rules: replace the value of the `class` +attribute with `net.sourceforge.pmd.lang.xml.rule.DomXPathRule` like so: +```xml + + + + + + + + + +``` + +The rule is more powerful than `XPathRule`, as it can now handle XML namespaces, +comments and processing instructions. Please refer to the Javadoc of {% jdoc xml::lang.xml.rule.DomXPathRule %} +for information about the differences with `XPathRule` and examples. + +`XPathRule` is still perfectly supported for all other languages, including Apex and Java. + +#### New XPath functions + +The new XPath functions `pmd:startLine`, `pmd:endLine`, `pmd:startColumn`, +and `pmd:endColumn` are now available in XPath rules for all languages. They +replace the node attributes `@BeginLine`, `@EndLine` and such. These attributes +will be deprecated in a future release. + +Please refer to [the documentation](https://pmd.github.io/latest/pmd_userdocs_extending_writing_xpath_rules.html#pmd-extension-functions) of these functions for more information, including usage samples. + +Note that the function `pmd:endColumn` returns an exclusive index, while the +attribute `@EndColumn` is inclusive. This is for forward compatibility with PMD 7, +which uses exclusive end indices. #### New programmatic API diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java index f3440dd83f..57ba692d0a 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/rule/DomXPathRule.java @@ -127,6 +127,8 @@ public class DomXPathRule extends AbstractRule { public DomXPathRule() { definePropertyDescriptor(XPATH_EXPR); definePropertyDescriptor(DEFAULT_NS_URI); + // for compatibility, but is ignored. + definePropertyDescriptor(XPathRule.VERSION_DESCRIPTOR); } From 6e1e8a6adc741650549ef8542485085350a5841d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 24 Mar 2022 22:24:26 +0100 Subject: [PATCH 81/89] Deprecate xpath attrs for lines/cols --- docs/pages/release_notes.md | 8 +++++++- .../src/main/java/net/sourceforge/pmd/lang/ast/Node.java | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 282bf63c6a..192d0023e2 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -52,7 +52,8 @@ for information about the differences with `XPathRule` and examples. The new XPath functions `pmd:startLine`, `pmd:endLine`, `pmd:startColumn`, and `pmd:endColumn` are now available in XPath rules for all languages. They replace the node attributes `@BeginLine`, `@EndLine` and such. These attributes -will be deprecated in a future release. +are now deprecated for removal (from the XPath API, not the Java getter). + Please refer to [the documentation](https://pmd.github.io/latest/pmd_userdocs_extending_writing_xpath_rules.html#pmd-extension-functions) of these functions for more information, including usage samples. @@ -124,6 +125,11 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is The whole class however was deprecated long ago already with 6.30.0. It is internal API and should not be used. +* The XPath attributes `@BeginLine`, `@EndLine`, `@BeginColumn` and `@EndColumn`, +available on all nodes, are deprecated. They should be replaced with calls to the +new functions `pmd:startLine`, `pmd:endLine`, `pmd:startColumn`, and `pmd:endColumn`. +See [New XPath functions](#new-xpath-functions). + #### Experimental APIs * Together with the [new programmatic API](#new-programmatic-api) the interface diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java index 5beb352e6d..c54c7e5b46 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java @@ -178,13 +178,17 @@ public interface Node { */ boolean hasImageEqualTo(String image); + @DeprecatedAttribute(replaceWith = "pmd:startLine(.)") int getBeginLine(); + @DeprecatedAttribute(replaceWith = "pmd:startColumn(.)") int getBeginColumn(); + @DeprecatedAttribute(replaceWith = "pmd:endLine(.)") int getEndLine(); // FIXME should not be inclusive + @DeprecatedAttribute(replaceWith = "pmd:endColumn(.)") int getEndColumn(); From 586a9011468f4a0a16b3babe29c9ad8efe368bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 24 Mar 2022 22:24:31 +0100 Subject: [PATCH 82/89] REVERTME Revert "Deprecate xpath attrs for lines/cols" This reverts commit 6e1e8a6adc741650549ef8542485085350a5841d. Note for future: I tried to deprecate the XPath attributes for `@BeginLine`, `@EndLine` etc, but there's a rule I can't port easily without XPath 3: OneDeclarationPerLine. It has this thing: ``` distinct-values(FieldDeclaration/VariableExpression/@BeginLine) ``` In XPath 3 you can write this ``` distinct-values(FieldDeclaration/VariableExpression ! pmd:startLine) ``` But I'm not sure how to do this in XPath 2, so I've reverted the commit, we can do that later. --- docs/pages/release_notes.md | 8 +------- .../src/main/java/net/sourceforge/pmd/lang/ast/Node.java | 4 ---- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 192d0023e2..282bf63c6a 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -52,8 +52,7 @@ for information about the differences with `XPathRule` and examples. The new XPath functions `pmd:startLine`, `pmd:endLine`, `pmd:startColumn`, and `pmd:endColumn` are now available in XPath rules for all languages. They replace the node attributes `@BeginLine`, `@EndLine` and such. These attributes -are now deprecated for removal (from the XPath API, not the Java getter). - +will be deprecated in a future release. Please refer to [the documentation](https://pmd.github.io/latest/pmd_userdocs_extending_writing_xpath_rules.html#pmd-extension-functions) of these functions for more information, including usage samples. @@ -125,11 +124,6 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is The whole class however was deprecated long ago already with 6.30.0. It is internal API and should not be used. -* The XPath attributes `@BeginLine`, `@EndLine`, `@BeginColumn` and `@EndColumn`, -available on all nodes, are deprecated. They should be replaced with calls to the -new functions `pmd:startLine`, `pmd:endLine`, `pmd:startColumn`, and `pmd:endColumn`. -See [New XPath functions](#new-xpath-functions). - #### Experimental APIs * Together with the [new programmatic API](#new-programmatic-api) the interface diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java index c54c7e5b46..5beb352e6d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java @@ -178,17 +178,13 @@ public interface Node { */ boolean hasImageEqualTo(String image); - @DeprecatedAttribute(replaceWith = "pmd:startLine(.)") int getBeginLine(); - @DeprecatedAttribute(replaceWith = "pmd:startColumn(.)") int getBeginColumn(); - @DeprecatedAttribute(replaceWith = "pmd:endLine(.)") int getEndLine(); // FIXME should not be inclusive - @DeprecatedAttribute(replaceWith = "pmd:endColumn(.)") int getEndColumn(); From cdf19cf24bf37d6d10735dcec7808a4d2389754f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 25 Mar 2022 08:10:47 +0100 Subject: [PATCH 83/89] [doc] Update release notes (#2766, #3863, #3864) --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 282bf63c6a..ed24fe01e8 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -102,6 +102,9 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is * [#3299](https://github.com/pmd/pmd/issues/3299): \[core] Deprecate system properties of PMDCommandLineInterface * doc * [#3812](https://github.com/pmd/pmd/issues/3812): \[doc] Documentation website table of contents broken on pages with many subheadings +* xml + * [#2766](https://github.com/pmd/pmd/issues/2766): \[xml] XMLNS prefix is not pre-declared in xpath query + * [#3863](https://github.com/pmd/pmd/issues/3863): \[xml] Make XPath rules work exactly as in the XPath spec ### API Changes From 5537ca3abbd5d6d084b53b403613900a9181f019 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 25 Mar 2022 08:48:22 +0100 Subject: [PATCH 84/89] [doc] Regenerate contributors list --- docs/pages/pmd/projectdocs/credits.md | 106 +++++++++++++------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index a884a39099..98d12f8cb2 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -462,477 +462,477 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d

    - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + From 2f856fee3397d7eb7fa322c5612482c42f1e9d92 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 25 Mar 2022 09:41:11 +0100 Subject: [PATCH 85/89] Update docs/pages/pmd/userdocs/cli_reference.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Clément Fournier --- docs/pages/pmd/userdocs/cli_reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/userdocs/cli_reference.md b/docs/pages/pmd/userdocs/cli_reference.md index 1e650d8d50..f0a8819a7a 100644 --- a/docs/pages/pmd/userdocs/cli_reference.md +++ b/docs/pages/pmd/userdocs/cli_reference.md @@ -207,7 +207,7 @@ Example: * [apex](pmd_rules_apex.html) (Salesforce Apex) * [java](pmd_rules_java.html) - * [Supported Versions](pmd_languages_java.html) + * [Supported Versions](pmd_languages_java_versions.html) * [ecmascript](pmd_rules_ecmascript.html) (JavaScript) * [jsp](pmd_rules_jsp.html) * [modelica](pmd_rules_modelica.html) From 6cf3efe6a6d126f5a0c72d15c8c748baa19dbf7f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 27 Mar 2022 16:51:50 +0200 Subject: [PATCH 86/89] Prepare pmd release 6.44.0 --- docs/_config.yml | 4 ++-- docs/pages/next_major_development.md | 36 ++++++++++++++++++++++++++++ docs/pages/release_notes.md | 5 ++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/docs/_config.yml b/docs/_config.yml index ab0e7e5ddf..206dec5716 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,9 +1,9 @@ repository: pmd/pmd pmd: - version: 6.44.0-SNAPSHOT + version: 6.44.0 previous_version: 6.43.0 - date: 26-March-2022 + date: 27-March-2022 release_type: minor # release types: major, minor, bugfix diff --git a/docs/pages/next_major_development.md b/docs/pages/next_major_development.md index 9de6faa57d..e3a78af4e1 100644 --- a/docs/pages/next_major_development.md +++ b/docs/pages/next_major_development.md @@ -125,6 +125,42 @@ the breaking API changes will be performed in 7.0.0. an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0, we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %} +#### 6.44.0 + +##### Deprecated API + +* Several members of {% jdoc core::PMD %} have been newly deprecated, including: + - `PMD#EOL`: use `System#lineSeparator()` + - `PMD#SUPPRESS_MARKER`: use {% jdoc core::PMDConfiguration#DEFAULT_SUPPRESS_MARKER %} + - `PMD#processFiles`: use the new programmatic API + - `PMD#getApplicableFiles`: is internal +* {% jdoc !!core::PMDConfiguration#prependClasspath(java.lang.String) %} is deprecated + in favour of {% jdoc core::PMDConfiguration#prependAuxClasspath(java.lang.String) %}. +* {% jdoc !!core::PMDConfiguration#setRuleSets(java.lang.String) %} and + {% jdoc core::PMDConfiguration#getRuleSets() %} are deprecated. Use instead + {% jdoc core::PMDConfiguration#setRuleSets(java.util.List) %}, + {% jdoc core::PMDConfiguration#addRuleSet(java.lang.String) %}, + and {% jdoc core::PMDConfiguration#getRuleSetPaths() %}. +* Several members of {% jdoc test::cli.BaseCLITest %} have been deprecated with replacements. +* Several members of {% jdoc core::cli.PMDCommandLineInterface %} have been explicitly deprecated. + The whole class however was deprecated long ago already with 6.30.0. It is internal API and should + not be used. + +* In modelica, the rule classes {% jdoc modelica::lang.modelica.rule.AmbiguousResolutionRule %} + and {% jdoc modelica::lang.modelica.rule.ConnectUsingNonConnector %} have been deprecated, + since they didn't comply to the usual rule class naming conventions yet. + The replacements are in the subpackage `bestpractices`. + +##### Experimental APIs + +* Together with the new programmatic API the interface + {% jdoc core::lang.document.TextFile %} has been added as *experimental*. It intends + to replace {% jdoc core::util.datasource.DataSource %} and {% jdoc core::cpd.SourceCode %} in the long term. + + This interface will change in PMD 7 to support read/write operations + and other things. You don't need to use it in PMD 6, as {% jdoc core::lang.document.FileCollector %} + decouples you from this. A file collector is available through {% jdoc !!core::PmdAnalysis#files() %}. + #### 6.43.0 ##### Deprecated API diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 6ed191125f..c5bfae59d1 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -171,5 +171,10 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is * [#3811](https://github.com/pmd/pmd/pull/3811): \[doc] Improve "Edit me on github" button - [@btjiong](https://github.com/btjiong) * [#3836](https://github.com/pmd/pmd/pull/3836): \[doc] Make TOC scrollable when too many subheadings - [@JerritEic](https://github.com/JerritEic) +### Stats +* 124 commits +* 23 closed tickets & PRs +* Days since last release: 29 + {% endtocmaker %} From 6859f8db364f2836920c05ce7c2e6cf6e7476df2 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 27 Mar 2022 17:01:54 +0200 Subject: [PATCH 87/89] [maven-release-plugin] prepare release pmd_releases/6.44.0 --- pmd-apex-jorje/pom.xml | 2 +- pmd-apex/pom.xml | 2 +- pmd-core/pom.xml | 2 +- pmd-cpp/pom.xml | 2 +- pmd-cs/pom.xml | 2 +- pmd-dart/pom.xml | 2 +- pmd-dist/pom.xml | 2 +- pmd-doc/pom.xml | 2 +- pmd-fortran/pom.xml | 2 +- pmd-go/pom.xml | 2 +- pmd-groovy/pom.xml | 2 +- pmd-java/pom.xml | 2 +- pmd-java8/pom.xml | 2 +- pmd-javascript/pom.xml | 2 +- pmd-jsp/pom.xml | 2 +- pmd-kotlin/pom.xml | 2 +- pmd-lang-test/pom.xml | 2 +- pmd-lua/pom.xml | 2 +- pmd-matlab/pom.xml | 2 +- pmd-modelica/pom.xml | 2 +- pmd-objectivec/pom.xml | 2 +- pmd-perl/pom.xml | 2 +- pmd-php/pom.xml | 2 +- pmd-plsql/pom.xml | 2 +- pmd-python/pom.xml | 2 +- pmd-ruby/pom.xml | 2 +- pmd-scala-modules/pmd-scala-common/pom.xml | 2 +- pmd-scala-modules/pmd-scala_2.12/pom.xml | 2 +- pmd-scala-modules/pmd-scala_2.13/pom.xml | 2 +- pmd-scala/pom.xml | 2 +- pmd-swift/pom.xml | 2 +- pmd-test/pom.xml | 2 +- pmd-visualforce/pom.xml | 2 +- pmd-vm/pom.xml | 2 +- pmd-xml/pom.xml | 2 +- pom.xml | 6 +++--- 36 files changed, 38 insertions(+), 38 deletions(-) diff --git a/pmd-apex-jorje/pom.xml b/pmd-apex-jorje/pom.xml index 43fe5cc859..be475493eb 100644 --- a/pmd-apex-jorje/pom.xml +++ b/pmd-apex-jorje/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index 6bc824665a..fc2ba24031 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml index 407f03410e..4777730a4f 100644 --- a/pmd-core/pom.xml +++ b/pmd-core/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-cpp/pom.xml b/pmd-cpp/pom.xml index 94683e767c..11543904a7 100644 --- a/pmd-cpp/pom.xml +++ b/pmd-cpp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-cs/pom.xml b/pmd-cs/pom.xml index 15c5bd6a27..89b400dbb0 100644 --- a/pmd-cs/pom.xml +++ b/pmd-cs/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-dart/pom.xml b/pmd-dart/pom.xml index 81cb0f2eb5..f2c07c41f7 100644 --- a/pmd-dart/pom.xml +++ b/pmd-dart/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 2e8c86c31d..69d391e2b2 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index 4d4b61918f..8463f04177 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-fortran/pom.xml b/pmd-fortran/pom.xml index bd2ef253c2..55ce8291cb 100644 --- a/pmd-fortran/pom.xml +++ b/pmd-fortran/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-go/pom.xml b/pmd-go/pom.xml index 9d97a707f0..34d9f01759 100644 --- a/pmd-go/pom.xml +++ b/pmd-go/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-groovy/pom.xml b/pmd-groovy/pom.xml index f24f07db38..5d5c279c47 100644 --- a/pmd-groovy/pom.xml +++ b/pmd-groovy/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index 59b511121b..89ed3e4663 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-java8/pom.xml b/pmd-java8/pom.xml index c8ff815351..89c0a1b78f 100644 --- a/pmd-java8/pom.xml +++ b/pmd-java8/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml index 2e85b2a9f6..4c59c9125d 100644 --- a/pmd-javascript/pom.xml +++ b/pmd-javascript/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml index c6f9c98403..0fa2cdfbaa 100644 --- a/pmd-jsp/pom.xml +++ b/pmd-jsp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-kotlin/pom.xml b/pmd-kotlin/pom.xml index 59e9a0968e..2aaf5dfbd3 100644 --- a/pmd-kotlin/pom.xml +++ b/pmd-kotlin/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index ef6c67969a..f228d2e7c3 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -12,7 +12,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-lua/pom.xml b/pmd-lua/pom.xml index 9053517bb1..dad08e6495 100644 --- a/pmd-lua/pom.xml +++ b/pmd-lua/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-matlab/pom.xml b/pmd-matlab/pom.xml index 4749644676..99e2f44a0b 100644 --- a/pmd-matlab/pom.xml +++ b/pmd-matlab/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-modelica/pom.xml b/pmd-modelica/pom.xml index 3b94ff1440..7ff224dbf7 100644 --- a/pmd-modelica/pom.xml +++ b/pmd-modelica/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-objectivec/pom.xml b/pmd-objectivec/pom.xml index 44d6b89069..a327ad8411 100644 --- a/pmd-objectivec/pom.xml +++ b/pmd-objectivec/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-perl/pom.xml b/pmd-perl/pom.xml index c80890ab1f..0cdffaa08c 100644 --- a/pmd-perl/pom.xml +++ b/pmd-perl/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-php/pom.xml b/pmd-php/pom.xml index 59457decc2..21d5314926 100644 --- a/pmd-php/pom.xml +++ b/pmd-php/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml index 817c323a25..e8080a421a 100644 --- a/pmd-plsql/pom.xml +++ b/pmd-plsql/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-python/pom.xml b/pmd-python/pom.xml index 465d86c3d6..700ee6d797 100644 --- a/pmd-python/pom.xml +++ b/pmd-python/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-ruby/pom.xml b/pmd-ruby/pom.xml index 113add2caf..f6e0d8ac7a 100644 --- a/pmd-ruby/pom.xml +++ b/pmd-ruby/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-scala-modules/pmd-scala-common/pom.xml b/pmd-scala-modules/pmd-scala-common/pom.xml index ec70ba3f96..f74e8d8a32 100644 --- a/pmd-scala-modules/pmd-scala-common/pom.xml +++ b/pmd-scala-modules/pmd-scala-common/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../.. diff --git a/pmd-scala-modules/pmd-scala_2.12/pom.xml b/pmd-scala-modules/pmd-scala_2.12/pom.xml index 33ebf0f415..5bdc8c3b42 100644 --- a/pmd-scala-modules/pmd-scala_2.12/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.12/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 6.44.0-SNAPSHOT + 6.44.0 ../pmd-scala-common diff --git a/pmd-scala-modules/pmd-scala_2.13/pom.xml b/pmd-scala-modules/pmd-scala_2.13/pom.xml index bcfc48229f..ce16d894d0 100644 --- a/pmd-scala-modules/pmd-scala_2.13/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.13/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 6.44.0-SNAPSHOT + 6.44.0 ../pmd-scala-common diff --git a/pmd-scala/pom.xml b/pmd-scala/pom.xml index c24a3c0e80..3b211f56c9 100644 --- a/pmd-scala/pom.xml +++ b/pmd-scala/pom.xml @@ -9,7 +9,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-swift/pom.xml b/pmd-swift/pom.xml index aaf923bd66..0006dc0c83 100644 --- a/pmd-swift/pom.xml +++ b/pmd-swift/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml index fa505dce52..efce5e15d5 100644 --- a/pmd-test/pom.xml +++ b/pmd-test/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml index 3774bdb5ed..710821dbc9 100644 --- a/pmd-visualforce/pom.xml +++ b/pmd-visualforce/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-vm/pom.xml b/pmd-vm/pom.xml index f120804c9a..944340b89e 100644 --- a/pmd-vm/pom.xml +++ b/pmd-vm/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml index 475136345d..8000b4e297 100644 --- a/pmd-xml/pom.xml +++ b/pmd-xml/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 ../ diff --git a/pom.xml b/pom.xml index 7a4c72e0da..9e2f329b3b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 net.sourceforge.pmd pmd - 6.44.0-SNAPSHOT + 6.44.0 pom PMD @@ -55,7 +55,7 @@ scm:git:git://github.com/pmd/pmd.git scm:git:ssh://git@github.com/pmd/pmd.git https://github.com/pmd/pmd - HEAD + pmd_releases/6.44.0 @@ -76,7 +76,7 @@ - 2022-02-26T09:01:07Z + 2022-03-27T14:51:59Z 7 From be3e941a081cac3541a9134ef78102b55ac2e746 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 27 Mar 2022 17:01:59 +0200 Subject: [PATCH 88/89] [maven-release-plugin] prepare for next development iteration --- pmd-apex-jorje/pom.xml | 2 +- pmd-apex/pom.xml | 2 +- pmd-core/pom.xml | 2 +- pmd-cpp/pom.xml | 2 +- pmd-cs/pom.xml | 2 +- pmd-dart/pom.xml | 2 +- pmd-dist/pom.xml | 2 +- pmd-doc/pom.xml | 2 +- pmd-fortran/pom.xml | 2 +- pmd-go/pom.xml | 2 +- pmd-groovy/pom.xml | 2 +- pmd-java/pom.xml | 2 +- pmd-java8/pom.xml | 2 +- pmd-javascript/pom.xml | 2 +- pmd-jsp/pom.xml | 2 +- pmd-kotlin/pom.xml | 2 +- pmd-lang-test/pom.xml | 2 +- pmd-lua/pom.xml | 2 +- pmd-matlab/pom.xml | 2 +- pmd-modelica/pom.xml | 2 +- pmd-objectivec/pom.xml | 2 +- pmd-perl/pom.xml | 2 +- pmd-php/pom.xml | 2 +- pmd-plsql/pom.xml | 2 +- pmd-python/pom.xml | 2 +- pmd-ruby/pom.xml | 2 +- pmd-scala-modules/pmd-scala-common/pom.xml | 2 +- pmd-scala-modules/pmd-scala_2.12/pom.xml | 2 +- pmd-scala-modules/pmd-scala_2.13/pom.xml | 2 +- pmd-scala/pom.xml | 2 +- pmd-swift/pom.xml | 2 +- pmd-test/pom.xml | 2 +- pmd-visualforce/pom.xml | 2 +- pmd-vm/pom.xml | 2 +- pmd-xml/pom.xml | 2 +- pom.xml | 6 +++--- 36 files changed, 38 insertions(+), 38 deletions(-) diff --git a/pmd-apex-jorje/pom.xml b/pmd-apex-jorje/pom.xml index be475493eb..5697071519 100644 --- a/pmd-apex-jorje/pom.xml +++ b/pmd-apex-jorje/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index fc2ba24031..add57cacad 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml index 4777730a4f..3a5b8baa85 100644 --- a/pmd-core/pom.xml +++ b/pmd-core/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-cpp/pom.xml b/pmd-cpp/pom.xml index 11543904a7..9a2e1f73d6 100644 --- a/pmd-cpp/pom.xml +++ b/pmd-cpp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-cs/pom.xml b/pmd-cs/pom.xml index 89b400dbb0..16a218ffcb 100644 --- a/pmd-cs/pom.xml +++ b/pmd-cs/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-dart/pom.xml b/pmd-dart/pom.xml index f2c07c41f7..6cb0d6cf73 100644 --- a/pmd-dart/pom.xml +++ b/pmd-dart/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 69d391e2b2..1575d40f66 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index 8463f04177..120154f459 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-fortran/pom.xml b/pmd-fortran/pom.xml index 55ce8291cb..18a3d0d28a 100644 --- a/pmd-fortran/pom.xml +++ b/pmd-fortran/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-go/pom.xml b/pmd-go/pom.xml index 34d9f01759..ca4d6d83c7 100644 --- a/pmd-go/pom.xml +++ b/pmd-go/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-groovy/pom.xml b/pmd-groovy/pom.xml index 5d5c279c47..61baf2b8c9 100644 --- a/pmd-groovy/pom.xml +++ b/pmd-groovy/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index 89ed3e4663..246d4e724b 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-java8/pom.xml b/pmd-java8/pom.xml index 89c0a1b78f..318e38a082 100644 --- a/pmd-java8/pom.xml +++ b/pmd-java8/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml index 4c59c9125d..417de06881 100644 --- a/pmd-javascript/pom.xml +++ b/pmd-javascript/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml index 0fa2cdfbaa..4580722684 100644 --- a/pmd-jsp/pom.xml +++ b/pmd-jsp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-kotlin/pom.xml b/pmd-kotlin/pom.xml index 2aaf5dfbd3..384e31e80b 100644 --- a/pmd-kotlin/pom.xml +++ b/pmd-kotlin/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index f228d2e7c3..d138311451 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -12,7 +12,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-lua/pom.xml b/pmd-lua/pom.xml index dad08e6495..aa86e5adab 100644 --- a/pmd-lua/pom.xml +++ b/pmd-lua/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-matlab/pom.xml b/pmd-matlab/pom.xml index 99e2f44a0b..b6e09e11d1 100644 --- a/pmd-matlab/pom.xml +++ b/pmd-matlab/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-modelica/pom.xml b/pmd-modelica/pom.xml index 7ff224dbf7..d4cd60d9b0 100644 --- a/pmd-modelica/pom.xml +++ b/pmd-modelica/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-objectivec/pom.xml b/pmd-objectivec/pom.xml index a327ad8411..0371376c9f 100644 --- a/pmd-objectivec/pom.xml +++ b/pmd-objectivec/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-perl/pom.xml b/pmd-perl/pom.xml index 0cdffaa08c..e6fc6e13b9 100644 --- a/pmd-perl/pom.xml +++ b/pmd-perl/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-php/pom.xml b/pmd-php/pom.xml index 21d5314926..06a17a3508 100644 --- a/pmd-php/pom.xml +++ b/pmd-php/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml index e8080a421a..6874aceeab 100644 --- a/pmd-plsql/pom.xml +++ b/pmd-plsql/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-python/pom.xml b/pmd-python/pom.xml index 700ee6d797..7e7337c031 100644 --- a/pmd-python/pom.xml +++ b/pmd-python/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-ruby/pom.xml b/pmd-ruby/pom.xml index f6e0d8ac7a..683a2110fe 100644 --- a/pmd-ruby/pom.xml +++ b/pmd-ruby/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-scala-modules/pmd-scala-common/pom.xml b/pmd-scala-modules/pmd-scala-common/pom.xml index f74e8d8a32..edd18d9b0c 100644 --- a/pmd-scala-modules/pmd-scala-common/pom.xml +++ b/pmd-scala-modules/pmd-scala-common/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../.. diff --git a/pmd-scala-modules/pmd-scala_2.12/pom.xml b/pmd-scala-modules/pmd-scala_2.12/pom.xml index 5bdc8c3b42..f0371d6c2c 100644 --- a/pmd-scala-modules/pmd-scala_2.12/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.12/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 6.44.0 + 6.45.0-SNAPSHOT ../pmd-scala-common diff --git a/pmd-scala-modules/pmd-scala_2.13/pom.xml b/pmd-scala-modules/pmd-scala_2.13/pom.xml index ce16d894d0..cfc266253a 100644 --- a/pmd-scala-modules/pmd-scala_2.13/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.13/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 6.44.0 + 6.45.0-SNAPSHOT ../pmd-scala-common diff --git a/pmd-scala/pom.xml b/pmd-scala/pom.xml index 3b211f56c9..8be793a5d4 100644 --- a/pmd-scala/pom.xml +++ b/pmd-scala/pom.xml @@ -9,7 +9,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-swift/pom.xml b/pmd-swift/pom.xml index 0006dc0c83..c714ee6a67 100644 --- a/pmd-swift/pom.xml +++ b/pmd-swift/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml index efce5e15d5..f6e41ef144 100644 --- a/pmd-test/pom.xml +++ b/pmd-test/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml index 710821dbc9..3e2bd2cfac 100644 --- a/pmd-visualforce/pom.xml +++ b/pmd-visualforce/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-vm/pom.xml b/pmd-vm/pom.xml index 944340b89e..dfbecb3abc 100644 --- a/pmd-vm/pom.xml +++ b/pmd-vm/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml index 8000b4e297..c52f923011 100644 --- a/pmd-xml/pom.xml +++ b/pmd-xml/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT ../ diff --git a/pom.xml b/pom.xml index 9e2f329b3b..42669441d9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 net.sourceforge.pmd pmd - 6.44.0 + 6.45.0-SNAPSHOT pom PMD @@ -55,7 +55,7 @@ scm:git:git://github.com/pmd/pmd.git scm:git:ssh://git@github.com/pmd/pmd.git https://github.com/pmd/pmd - pmd_releases/6.44.0 + HEAD @@ -76,7 +76,7 @@ - 2022-03-27T14:51:59Z + 2022-03-27T15:01:59Z 7 From 820a17d6bda47203bb18d6a931972e9fb513d590 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 27 Mar 2022 17:03:24 +0200 Subject: [PATCH 89/89] Prepare next development version [skip ci] --- docs/_config.yml | 6 +- docs/pages/release_notes.md | 156 --------------------------- docs/pages/release_notes_old.md | 184 ++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+), 159 deletions(-) diff --git a/docs/_config.yml b/docs/_config.yml index 206dec5716..68b6947986 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,9 +1,9 @@ repository: pmd/pmd pmd: - version: 6.44.0 - previous_version: 6.43.0 - date: 27-March-2022 + version: 6.45.0-SNAPSHOT + previous_version: 6.44.0 + date: 30-April-2022 release_type: minor # release types: major, minor, bugfix diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index c5bfae59d1..b8f8783555 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -14,167 +14,11 @@ This is a {{ site.pmd.release_type }} release. ### New and noteworthy -#### Java 18 Support - -This release of PMD brings support for Java 18. There are no new standard language features. - -PMD also supports [JEP 420: Pattern Matching for switch (Second Preview)](https://openjdk.java.net/jeps/420) as a -preview language feature. In order to analyze a project with PMD that uses these language features, -you'll need to enable it via the environment variable `PMD_JAVA_OPTS` and select the new language -version `18-preview`: - - export PMD_JAVA_OPTS=--enable-preview - ./run.sh pmd -language java -version 18-preview ... - -Note: Support for Java 16 preview language features have been removed. The version "16-preview" is no longer available. - -#### Better XML XPath support - -The new rule class {% jdoc xml::lang.xml.rule.DomXPathRule %} is intended to replace -usage of the `XPathRule` for XML rules. This rule executes the XPath query in a different -way, which sticks to the XPath specification. This means the expression is interpreted -the same way in PMD as in all other XPath development tools that stick to the standard. -You can for instance test the expression in an online XPath editor. - -Prefer using this class to define XPath rules: replace the value of the `class` -attribute with `net.sourceforge.pmd.lang.xml.rule.DomXPathRule` like so: -```xml - - - - - - - - - -``` - -The rule is more powerful than `XPathRule`, as it can now handle XML namespaces, -comments and processing instructions. Please refer to the Javadoc of {% jdoc xml::lang.xml.rule.DomXPathRule %} -for information about the differences with `XPathRule` and examples. - -`XPathRule` is still perfectly supported for all other languages, including Apex and Java. - -#### New XPath functions - -The new XPath functions `pmd:startLine`, `pmd:endLine`, `pmd:startColumn`, -and `pmd:endColumn` are now available in XPath rules for all languages. They -replace the node attributes `@BeginLine`, `@EndLine` and such. These attributes -will be deprecated in a future release. - -Please refer to [the documentation](https://pmd.github.io/latest/pmd_userdocs_extending_writing_xpath_rules.html#pmd-extension-functions) of these functions for more information, including usage samples. - -Note that the function `pmd:endColumn` returns an exclusive index, while the -attribute `@EndColumn` is inclusive. This is for forward compatibility with PMD 7, -which uses exclusive end indices. - -#### New programmatic API - -This release introduces a new programmatic API to replace the inflexible {% jdoc core::PMD %} class. -Programmatic execution of PMD should now be done with a {% jdoc core::PMDConfiguration %} -and a {% jdoc core::PmdAnalysis %}, for instance: - -```java -PMDConfiguration config = new PMDConfiguration(); -config.setDefaultLanguageVersion(LanguageRegistry.findLanguageByTerseName("java").getVersion("11")); -config.setInputPaths("src/main/java"); -config.prependAuxClasspath("target/classes"); -config.setMinimumPriority(RulePriority.HIGH); -config.addRuleSet("rulesets/java/quickstart.xml"); -config.setReportFormat("xml"); -config.setReportFile("target/pmd-report.xml"); - -try (PmdAnalysis pmd = PmdAnalysis.create(config)) { - // note: don't use `config` once a PmdAnalysis has been created. - // optional: add more rulesets - pmd.addRuleSet(pmd.newRuleSetLoader().loadFromResource("custom-ruleset.xml")); - // optional: add more files - pmd.files().addFile(Paths.get("src", "main", "more-java", "ExtraSource.java")); - // optional: add more renderers - pmd.addRenderer(renderer); - - // or just call PMD - pmd.performAnalysis(); -} -``` - -The `PMD` class still supports methods related to CLI execution: `runPmd` and `main`. -All other members are now deprecated for removal. -The CLI itself remains compatible, if you run PMD via command-line, no action is required on your part. - ### Fixed Issues -* apex - * [#3817](https://github.com/pmd/pmd/pull/3817): \[apex] Add designer bindings to display main attributes -* apex-performance - * [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() -* core - * [#2693](https://github.com/pmd/pmd/issues/2693): \[ci] Add integration tests with real open-source projects - * [#3299](https://github.com/pmd/pmd/issues/3299): \[core] Deprecate system properties of PMDCommandLineInterface -* java - * [#3809](https://github.com/pmd/pmd/issues/3809): \[java] Support JDK 18 -* doc - * [#2504](https://github.com/pmd/pmd/issues/2504): \[doc] Improve "Edit me on github" button - * [#3812](https://github.com/pmd/pmd/issues/3812): \[doc] Documentation website table of contents broken on pages with many subheadings -* java-design - * [#3850](https://github.com/pmd/pmd/issues/3850): \[java] ImmutableField - false negative when field assigned in constructor conditionally - * [#3851](https://github.com/pmd/pmd/issues/3851): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal - false negative when a compilation unit contains two class declarations -* xml - * [#2766](https://github.com/pmd/pmd/issues/2766): \[xml] XMLNS prefix is not pre-declared in xpath query - * [#3863](https://github.com/pmd/pmd/issues/3863): \[xml] Make XPath rules work exactly as in the XPath spec - ### API Changes -#### Deprecated API - -* Several members of {% jdoc core::PMD %} have been newly deprecated, including: - - `PMD#EOL`: use `System#lineSeparator()` - - `PMD#SUPPRESS_MARKER`: use {% jdoc core::PMDConfiguration#DEFAULT_SUPPRESS_MARKER %} - - `PMD#processFiles`: use the [new programmatic API](#new-programmatic-api) - - `PMD#getApplicableFiles`: is internal -* {% jdoc !!core::PMDConfiguration#prependClasspath(java.lang.String) %} is deprecated - in favour of {% jdoc core::PMDConfiguration#prependAuxClasspath(java.lang.String) %}. -* {% jdoc !!core::PMDConfiguration#setRuleSets(java.lang.String) %} and - {% jdoc core::PMDConfiguration#getRuleSets() %} are deprecated. Use instead - {% jdoc core::PMDConfiguration#setRuleSets(java.util.List) %}, - {% jdoc core::PMDConfiguration#addRuleSet(java.lang.String) %}, - and {% jdoc core::PMDConfiguration#getRuleSetPaths() %}. -* Several members of {% jdoc test::cli.BaseCLITest %} have been deprecated with replacements. -* Several members of {% jdoc core::cli.PMDCommandLineInterface %} have been explicitly deprecated. - The whole class however was deprecated long ago already with 6.30.0. It is internal API and should - not be used. - -* In modelica, the rule classes {% jdoc modelica::lang.modelica.rule.AmbiguousResolutionRule %} - and {% jdoc modelica::lang.modelica.rule.ConnectUsingNonConnector %} have been deprecated, - since they didn't comply to the usual rule class naming conventions yet. - The replacements are in the subpackage `bestpractices`. - -#### Experimental APIs - -* Together with the [new programmatic API](#new-programmatic-api) the interface - {% jdoc core::lang.document.TextFile %} has been added as *experimental*. It intends - to replace {% jdoc core::util.datasource.DataSource %} and {% jdoc core::cpd.SourceCode %} in the long term. - - This interface will change in PMD 7 to support read/write operations - and other things. You don't need to use it in PMD 6, as {% jdoc core::lang.document.FileCollector %} - decouples you from this. A file collector is available through {% jdoc !!core::PmdAnalysis#files() %}. - ### External Contributions -* [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() - [@filiprafalowicz](https://github.com/filiprafalowicz) -* [#3811](https://github.com/pmd/pmd/pull/3811): \[doc] Improve "Edit me on github" button - [@btjiong](https://github.com/btjiong) -* [#3836](https://github.com/pmd/pmd/pull/3836): \[doc] Make TOC scrollable when too many subheadings - [@JerritEic](https://github.com/JerritEic) - -### Stats -* 124 commits -* 23 closed tickets & PRs -* Days since last release: 29 - {% endtocmaker %} diff --git a/docs/pages/release_notes_old.md b/docs/pages/release_notes_old.md index e08efdc8c0..22658ab447 100644 --- a/docs/pages/release_notes_old.md +++ b/docs/pages/release_notes_old.md @@ -5,6 +5,190 @@ permalink: pmd_release_notes_old.html Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases +## 27-March-2022 - 6.44.0 + +The PMD team is pleased to announce PMD 6.44.0. + +This is a minor release. + +### Table Of Contents + +* [New and noteworthy](#new-and-noteworthy) + * [Java 18 Support](#java-18-support) + * [Better XML XPath support](#better-xml-xpath-support) + * [New XPath functions](#new-xpath-functions) + * [New programmatic API](#new-programmatic-api) +* [Fixed Issues](#fixed-issues) +* [API Changes](#api-changes) + * [Deprecated API](#deprecated-api) + * [Experimental APIs](#experimental-apis) +* [External Contributions](#external-contributions) +* [Stats](#stats) + +### New and noteworthy + +#### Java 18 Support + +This release of PMD brings support for Java 18. There are no new standard language features. + +PMD also supports [JEP 420: Pattern Matching for switch (Second Preview)](https://openjdk.java.net/jeps/420) as a +preview language feature. In order to analyze a project with PMD that uses these language features, +you'll need to enable it via the environment variable `PMD_JAVA_OPTS` and select the new language +version `18-preview`: + + export PMD_JAVA_OPTS=--enable-preview + ./run.sh pmd -language java -version 18-preview ... + +Note: Support for Java 16 preview language features have been removed. The version "16-preview" is no longer available. + +#### Better XML XPath support + +The new rule class DomXPathRule is intended to replace +usage of the `XPathRule` for XML rules. This rule executes the XPath query in a different +way, which sticks to the XPath specification. This means the expression is interpreted +the same way in PMD as in all other XPath development tools that stick to the standard. +You can for instance test the expression in an online XPath editor. + +Prefer using this class to define XPath rules: replace the value of the `class` +attribute with `net.sourceforge.pmd.lang.xml.rule.DomXPathRule` like so: +```xml + + + + + + + + + +``` + +The rule is more powerful than `XPathRule`, as it can now handle XML namespaces, +comments and processing instructions. Please refer to the Javadoc of DomXPathRule +for information about the differences with `XPathRule` and examples. + +`XPathRule` is still perfectly supported for all other languages, including Apex and Java. + +#### New XPath functions + +The new XPath functions `pmd:startLine`, `pmd:endLine`, `pmd:startColumn`, +and `pmd:endColumn` are now available in XPath rules for all languages. They +replace the node attributes `@BeginLine`, `@EndLine` and such. These attributes +will be deprecated in a future release. + +Please refer to [the documentation](https://pmd.github.io/latest/pmd_userdocs_extending_writing_xpath_rules.html#pmd-extension-functions) of these functions for more information, including usage samples. + +Note that the function `pmd:endColumn` returns an exclusive index, while the +attribute `@EndColumn` is inclusive. This is for forward compatibility with PMD 7, +which uses exclusive end indices. + +#### New programmatic API + +This release introduces a new programmatic API to replace the inflexible PMD class. +Programmatic execution of PMD should now be done with a PMDConfiguration +and a PmdAnalysis, for instance: + +```java +PMDConfiguration config = new PMDConfiguration(); +config.setDefaultLanguageVersion(LanguageRegistry.findLanguageByTerseName("java").getVersion("11")); +config.setInputPaths("src/main/java"); +config.prependAuxClasspath("target/classes"); +config.setMinimumPriority(RulePriority.HIGH); +config.addRuleSet("rulesets/java/quickstart.xml"); +config.setReportFormat("xml"); +config.setReportFile("target/pmd-report.xml"); + +try (PmdAnalysis pmd = PmdAnalysis.create(config)) { + // note: don't use `config` once a PmdAnalysis has been created. + // optional: add more rulesets + pmd.addRuleSet(pmd.newRuleSetLoader().loadFromResource("custom-ruleset.xml")); + // optional: add more files + pmd.files().addFile(Paths.get("src", "main", "more-java", "ExtraSource.java")); + // optional: add more renderers + pmd.addRenderer(renderer); + + // or just call PMD + pmd.performAnalysis(); +} +``` + +The `PMD` class still supports methods related to CLI execution: `runPmd` and `main`. +All other members are now deprecated for removal. +The CLI itself remains compatible, if you run PMD via command-line, no action is required on your part. + +### Fixed Issues + +* apex + * [#3817](https://github.com/pmd/pmd/pull/3817): \[apex] Add designer bindings to display main attributes +* apex-performance + * [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() +* core + * [#2693](https://github.com/pmd/pmd/issues/2693): \[ci] Add integration tests with real open-source projects + * [#3299](https://github.com/pmd/pmd/issues/3299): \[core] Deprecate system properties of PMDCommandLineInterface +* java + * [#3809](https://github.com/pmd/pmd/issues/3809): \[java] Support JDK 18 +* doc + * [#2504](https://github.com/pmd/pmd/issues/2504): \[doc] Improve "Edit me on github" button + * [#3812](https://github.com/pmd/pmd/issues/3812): \[doc] Documentation website table of contents broken on pages with many subheadings +* java-design + * [#3850](https://github.com/pmd/pmd/issues/3850): \[java] ImmutableField - false negative when field assigned in constructor conditionally + * [#3851](https://github.com/pmd/pmd/issues/3851): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal - false negative when a compilation unit contains two class declarations +* xml + * [#2766](https://github.com/pmd/pmd/issues/2766): \[xml] XMLNS prefix is not pre-declared in xpath query + * [#3863](https://github.com/pmd/pmd/issues/3863): \[xml] Make XPath rules work exactly as in the XPath spec + +### API Changes + +#### Deprecated API + +* Several members of PMD have been newly deprecated, including: + - `PMD#EOL`: use `System#lineSeparator()` + - `PMD#SUPPRESS_MARKER`: use DEFAULT_SUPPRESS_MARKER + - `PMD#processFiles`: use the [new programmatic API](#new-programmatic-api) + - `PMD#getApplicableFiles`: is internal +* PMDConfiguration#prependClasspath is deprecated + in favour of prependAuxClasspath. +* PMDConfiguration#setRuleSets and + getRuleSets are deprecated. Use instead + setRuleSets, + addRuleSet, + and getRuleSetPaths. +* Several members of BaseCLITest have been deprecated with replacements. +* Several members of PMDCommandLineInterface have been explicitly deprecated. + The whole class however was deprecated long ago already with 6.30.0. It is internal API and should + not be used. + +* In modelica, the rule classes AmbiguousResolutionRule + and ConnectUsingNonConnector have been deprecated, + since they didn't comply to the usual rule class naming conventions yet. + The replacements are in the subpackage `bestpractices`. + +#### Experimental APIs + +* Together with the [new programmatic API](#new-programmatic-api) the interface + TextFile has been added as *experimental*. It intends + to replace DataSource and SourceCode in the long term. + + This interface will change in PMD 7 to support read/write operations + and other things. You don't need to use it in PMD 6, as FileCollector + decouples you from this. A file collector is available through PmdAnalysis#files. + +### External Contributions + +* [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() - [@filiprafalowicz](https://github.com/filiprafalowicz) +* [#3811](https://github.com/pmd/pmd/pull/3811): \[doc] Improve "Edit me on github" button - [@btjiong](https://github.com/btjiong) +* [#3836](https://github.com/pmd/pmd/pull/3836): \[doc] Make TOC scrollable when too many subheadings - [@JerritEic](https://github.com/JerritEic) + +### Stats +* 124 commits +* 23 closed tickets & PRs +* Days since last release: 29 + ## 26-February-2022 - 6.43.0 The PMD team is pleased to announce PMD 6.43.0.

    Austin Tice

    🐛

    Ayoub Kaanich

    🐛

    BBG

    💻 📖 🐛

    Bailey Tjiong

    💻

    Barthélemy L.

    🐛

    Basavaraj K N

    🐛

    Basil Peace

    🐛

    Basil Peace

    🐛

    Belle

    🐛

    Ben Lerner

    🐛

    Ben Manes

    🐛

    Ben McCann

    🐛

    Bendegúz Nagy

    🐛

    Bennet S Yee

    🐛

    Benoit Lacelle

    🐛

    Benoit Lacelle

    🐛

    Bernardo Macêdo

    🐛

    Bernd Farka

    🐛

    Betina Cynthia Mamani

    🐛

    Bhanu Prakash Pamidi

    💻 🐛

    Bhargav Thanki

    🐛

    Binu R J

    🐛

    Björn Kautler

    💻 🐛

    Björn Kautler

    💻 🐛

    Blightbuster

    🐛

    Bo Zhang

    🐛

    Bob "Wombat" Hogg

    🐛

    Bobby Wertman

    🐛

    Bolarinwa Saheed Olayemi

    💻 🐛

    Boris Petrov

    🐛

    Brad Kent

    🐛

    Brad Kent

    🐛

    Brandon Mikeska

    🐛

    Brian Batronis

    🐛

    Brian Johnson

    🐛

    Brice Dutheil

    💻 🐛

    Bruno Ferreira

    🐛

    Bruno Ritz

    🐛

    Cameron Donaldson

    🐛

    Cameron Donaldson

    🐛

    Carlos Macasaet

    🐛

    Carsten Otto

    🐛

    Charlie Housh

    🐛

    Charlie Jonas

    🐛

    Chas Honton

    🐛

    Chen Yang

    🐛

    Chotu

    🐛

    Chotu

    🐛

    Chris Smith

    🐛

    Christian Hujer

    🐛

    Christian Pontesegger

    🐛

    ChristianWulf

    🐛

    Christofer Dutz

    💻

    Christoffer Anselm

    🐛

    Christophe Vidal

    🐛

    Christophe Vidal

    🐛

    Christopher Dancy

    🐛

    Clemens Prill

    🐛

    Clint Chester

    💻 🐛

    Clément Fournier

    💻 📖 🐛 🚧

    Codacy Badger

    🐛

    Code-Nil

    🐛

    ColColonCleaner

    🐛

    ColColonCleaner

    🐛

    Colin Ingarfield

    🐛

    Craig Andrews

    🐛

    Craig Muchinsky

    🐛

    Cyril

    💻 🐛

    Dale

    💻

    Damien Jiang

    🐛

    Dan Berindei

    🐛

    Dan Berindei

    🐛

    Dan Rollo

    🐛

    Dan Ziemba

    🐛

    Daniel Gredler

    💻

    Daniel Jipa

    🐛

    Daniel Paul Searles

    💻

    Daniel Reigada

    🐛

    Danilo Pianini

    🐛

    Danilo Pianini

    🐛

    Darko

    🐛

    David

    🐛

    David Atkinson

    🐛

    David Burström

    💻 🐛

    David Goaté

    🐛

    David Golpira

    🐛

    David Kovařík

    🐛

    David Kovařík

    🐛

    David M. Karr (fullname at gmail.com)

    🐛

    David Renz

    💻 🐛

    David Renz

    🐛

    Deleted user

    🐛

    Dell Green

    🐛

    Dem Pilafian

    🐛

    Den

    🐛

    Den

    🐛

    Denis Borovikov

    💻 🐛

    Dennie Reniers

    💻 🐛

    Dennis Kieselhorst

    🐛

    Derek P. Moore

    🐛

    Dichotomia

    🐛

    Dionisio Cortés Fernández

    💻 🐛

    Dmitri Bourlatchkov

    🐛

    Dmitri Bourlatchkov

    🐛

    Dmitriy Kuzmin

    🐛

    Dmytro Dashenkov

    🐛

    Drew Hall

    🐛

    Dumitru Postoronca

    🐛

    Dylan Adams

    🐛

    Eden Hao

    🐛

    Egor Bredikhin

    🐛

    Egor Bredikhin

    🐛

    Elan P. Kugelmass

    🐛

    Elder S.

    🐛

    Emile

    🐛

    Eric

    🐛

    Eric Kintzer

    🐛

    Eric Perret

    🐛

    Eric Squires

    🐛

    Eric Squires

    🐛

    Erich L Foster

    🐛

    Erik Bleske

    🐛

    Ernst Reissner

    🐛

    F.W. Dekker

    🐛

    Facundo

    🐛

    Federico Giust

    🐛

    Fedor Sherstobitov

    🐛

    Fedor Sherstobitov

    🐛

    Felix Lampe

    🐛

    Filip Golonka

    🐛

    Filipe Esperandio

    💻 🐛

    Francesco la Torre

    🐛

    Francisco Duarte

    🐛

    Frieder Bluemle

    🐛

    Frits Jalvingh

    💻 🐛

    Frits Jalvingh

    💻 🐛

    G. Bazior

    🐛

    Gabe Henkes

    🐛

    Genoud Magloire

    🐛

    Geoffrey555

    🐛

    Georg Romstorfer

    🐛

    Gio

    🐛

    Gol

    🐛

    Gol

    🐛

    Gonzalo Exequiel Ibars Ingman

    💻 🐛

    GooDer

    🐛

    Gregor Riegler

    🐛

    Grzegorz Olszewski

    🐛

    Gunther Schrijvers

    💻 🐛

    Gustavo Krieger

    🐛

    Guy Elsmore-Paddock

    🐛

    Guy Elsmore-Paddock

    🐛

    Görkem Mülayim

    🐛

    Hanzel Godinez

    🐛

    Harsh Kukreja

    🐛

    Heber

    🐛

    Henning Schmiedehausen

    💻 🐛

    Henning von Bargen

    💻

    Hervé Boutemy

    🐛

    Hervé Boutemy

    🐛

    Himanshu Pandey

    🐛

    Hokwang Lee

    🐛

    Hooperbloob

    💻

    Hung PHAN

    🐛

    IDoCodingStuffs

    💻 🐛

    Iccen Gan

    🐛

    Ignacio Mariano Tirabasso

    🐛

    Ignacio Mariano Tirabasso

    🐛

    Igor Melnichenko

    🐛

    Igor Moreno

    🐛

    Intelesis-MS

    🐛

    Iroha_

    🐛

    Ishan Srivastava

    🐛

    Ivano Guerini

    🐛

    Ivar Andreas Bonsaksen

    🐛

    Ivar Andreas Bonsaksen

    🐛

    Ivo Šmíd

    🐛

    JJengility

    🐛

    Jake Hemmerle

    🐛

    James Harrison

    🐛

    Jan

    🐛

    Jan Aertgeerts

    💻 🐛

    Jan Brümmer

    🐛

    Jan Brümmer

    🐛

    Jan Tříska

    🐛

    Jan-Lukas Else

    🐛

    Jason Williams

    🐛

    Jean-Paul Mayer

    🐛

    Jean-Simon Larochelle

    🐛

    Jeff Bartolotta

    💻 🐛

    Jeff Hube

    💻 🐛

    Jeff Hube

    💻 🐛

    Jeff Jensen

    🐛

    Jeff May

    🐛

    Jens Gerdes

    🐛

    Jeroen Borgers

    🐛

    Jerome Russ

    🐛

    JerritEic

    💻 📖

    Jiri Pejchal

    🐛

    Jiri Pejchal

    🐛

    Jithin Sunny

    🐛

    Jiří Škorpil

    🐛

    Joao Machado

    🐛

    Jochen Krauss

    🐛

    Johan Hammar

    🐛

    John Karp

    🐛

    John Zhang

    🐛

    John Zhang

    🐛

    John-Teng

    💻 🐛

    Jon Moroney

    💻 🐛

    Jonas Geiregat

    🐛

    Jonathan Wiesel

    💻 🐛

    Jordan

    🐛

    Jordi Llach

    🐛

    Jorge Solórzano

    🐛

    Jorge Solórzano

    🐛

    JorneVL

    🐛

    Jose Palafox

    🐛

    Jose Stovall

    🐛

    Joseph

    💻

    Joseph Heenan

    🐛

    Josh Feingold

    💻 🐛

    Josh Holthaus

    🐛

    Josh Holthaus

    🐛

    Joshua S Arquilevich

    🐛

    João Ferreira

    💻 🐛

    João Pedro Schmitt

    🐛

    Juan Martín Sotuyo Dodero

    💻 📖 🐛 🚧

    Juan Pablo Civile

    🐛

    Julian Voronetsky

    🐛

    Julien

    🐛

    Julien

    🐛

    Julius

    🐛

    JustPRV

    🐛

    Jörn Huxhorn

    🐛

    KThompso

    🐛

    Kai Amundsen

    🐛

    Karel Vervaeke

    🐛

    Karl-Andero Mere

    🐛

    Karl-Andero Mere

    🐛

    Karl-Philipp Richter

    🐛

    Karsten Silz

    🐛

    Kazuma Watanabe

    🐛

    Kev

    🐛

    Keve Müller

    🐛

    Kevin Guerra

    💻

    Kevin Jones

    🐛

    Kevin Jones

    🐛

    Kevin Wayne

    🐛

    Kieran Black

    🐛

    Kirill Zubov

    🐛

    Kirk Clemens

    💻 🐛

    Klaus Hartl

    🐛

    Koen Van Looveren

    🐛

    Kris Scheibe

    💻 🐛

    Kris Scheibe

    💻 🐛

    Kunal Thanki

    🐛

    Larry Diamond

    💻 🐛

    Lars Knickrehm

    🐛

    Leo Gutierrez

    🐛

    Lintsi

    🐛

    Linus Fernandes

    🐛

    Lixon Lookose

    🐛

    Lixon Lookose

    🐛

    Logesh

    🐛

    Lorenzo Gabriele

    🐛

    Loïc Ledoyen

    🐛

    Lucas Silva

    🐛

    Lucas Soncini

    💻 🐛

    Lukasz Slonina

    🐛

    Lukebray

    🐛

    Lukebray

    🐛

    Lyor Goldstein

    🐛

    MCMicS

    🐛

    Macarse

    🐛

    Machine account for PMD

    💻

    Maciek Siemczyk

    🐛

    Maikel Steneker

    💻 🐛

    Maksim Moiseikin

    🐛

    Maksim Moiseikin

    🐛

    Manfred Koch

    🐛

    Manuel Moya Ferrer

    💻 🐛

    Manuel Ryan

    🐛

    Marat Vyshegorodtsev

    🐛

    Marcel Härle

    🐛

    Marcello Fialho

    🐛

    Marcin Rataj

    🐛

    Marcin Rataj

    🐛

    Mark Adamcin

    🐛

    Mark Hall

    💻 🐛

    Mark Kolich

    🐛

    Mark Pritchard

    🐛

    Markus Rathgeb

    🐛

    Marquis Wang

    🐛

    Martin Feldsztejn

    🐛

    Martin Feldsztejn

    🐛

    Martin Lehmann

    🐛

    Martin Spamer

    🐛

    Martin Tarjányi

    🐛

    MatFl

    🐛

    Mateusz Stefanski

    🐛

    Mathieu Gouin

    🐛

    MatiasComercio

    💻 🐛

    MatiasComercio

    💻 🐛

    Matt Benson

    🐛

    Matt De Poorter

    🐛

    Matt Harrah

    🐛

    Matt Nelson

    🐛

    Matthew Amos

    🐛

    Matthew Duggan

    🐛

    Matthew Hall

    🐛

    Matthew Hall

    🐛

    Matías Fraga

    💻 🐛

    Maxime Robert

    💻 🐛

    Michael

    🐛

    Michael Bell

    🐛

    Michael Bernstein

    🐛

    Michael Clay

    🐛

    Michael Dombrowski

    🐛

    Michael Dombrowski

    🐛

    Michael Hausegger

    🐛

    Michael Hoefer

    🐛

    Michael Möbius

    🐛

    Michael N. Lipp

    🐛

    Michael Pellegrini

    🐛

    Michal Kordas

    🐛

    Michał Borek

    🐛

    Michał Borek

    🐛

    Michał Kuliński

    🐛

    Miguel Núñez Díaz-Montes

    🐛

    Mihai Ionut

    🐛

    Mirek Hankus

    🐛

    Mladjan Gadzic

    🐛

    MrAngry52

    🐛

    Muminur Choudhury

    🐛

    Muminur Choudhury

    🐛

    Mykhailo Palahuta

    💻 🐛

    Nagendra Kumar Singh

    🐛

    Nahuel Barrios

    🐛

    Nathan Braun

    🐛

    Nathan Reynolds

    🐛

    Nathan Reynolds

    🐛

    Nathanaël

    🐛

    Nathanaël

    🐛

    Nazdravi

    🐛

    Neha-Dhonde

    🐛

    Nicholas Doyle

    🐛

    Nick Butcher

    🐛

    Nico Gallinal

    🐛

    Nicola Dal Maso

    🐛

    Nicolas Filotto

    💻

    Nicolas Filotto

    💻

    Nikita Chursin

    🐛

    Niklas Baudy

    🐛

    Nikolas Havrikov

    🐛

    Nilesh Virkar

    🐛

    Nimit Patel

    🐛

    Niranjan Harpale

    🐛

    Noah Sussman

    🐛

    Noah Sussman

    🐛

    Noah0120

    🐛

    Noam Tamim

    🐛

    Noel Grandin

    🐛

    Olaf Haalstra

    🐛

    Oleg Pavlenko

    🐛

    Oleksii Dykov

    💻

    Oliver Eikemeier

    🐛

    Oliver Eikemeier

    🐛

    Olivier Parent

    💻 🐛

    Ollie Abbey

    💻 🐛

    OverDrone

    🐛

    Ozan Gulle

    💻 🐛

    PUNEET JAIN

    🐛

    Parbati Bose

    🐛

    Paul Berg

    🐛

    Paul Berg

    🐛

    Pavel Bludov

    🐛

    Pavel Mička

    🐛

    Pedro Nuno Santos

    🐛

    Pedro Rijo

    🐛

    Pelisse Romain

    💻 📖 🐛

    Pete Davids

    🐛

    Peter Bruin

    🐛

    Peter Bruin

    🐛

    Peter Chittum

    💻 🐛

    Peter Cudmore

    🐛

    Peter Kasson

    🐛

    Peter Kofler

    🐛

    Pham Hai Trung

    🐛

    Philip Graf

    💻 🐛

    Philip Hachey

    🐛

    Philip Hachey

    🐛

    Philippe Ozil

    🐛

    Phinehas Artemix

    🐛

    Phokham Nonava

    🐛

    Piotr Szymański

    🐛

    Piotrek Żygieło

    💻 🐛

    Pranay Jaiswal

    🐛

    Prasad Kamath

    🐛

    Prasad Kamath

    🐛

    Prasanna

    🐛

    Presh-AR

    🐛

    Puneet1726

    🐛

    Rafael Cortês

    🐛

    RaheemShaik999

    🐛

    RajeshR

    💻 🐛

    Ramachandra Mohan

    🐛

    Ramachandra Mohan

    🐛

    Raquel Pau

    🐛

    Ravikiran Janardhana

    🐛

    Reda Benhemmouche

    🐛

    Renato Oliveira

    💻 🐛

    Rich DiCroce

    🐛

    Riot R1cket

    🐛

    Rishabh Jain

    🐛

    Rishabh Jain

    🐛

    RishabhDeep Singh

    🐛

    Robbie Martinus

    💻 🐛

    Robert Henry

    🐛

    Robert Painsi

    🐛

    Robert Russell

    🐛

    Robert Sösemann

    💻 📖 📢 🐛

    Robert Whitebit

    🐛

    Robert Whitebit

    🐛

    Robin Richtsfeld

    🐛

    Robin Stocker

    💻 🐛

    Robin Wils

    🐛

    RochusOest

    🐛

    Rodolfo Noviski

    🐛

    Rodrigo Casara

    🐛

    Rodrigo Fernandes

    🐛

    Rodrigo Fernandes

    🐛

    Roman Salvador

    💻 🐛

    Ronald Blaschke

    🐛

    Róbert Papp

    🐛

    Saikat Sengupta

    🐛

    Saksham Handu

    🐛

    Saladoc

    🐛

    Salesforce Bob Lightning

    🐛

    Salesforce Bob Lightning

    🐛

    Sam Carlberg

    🐛

    Satoshi Kubo

    🐛

    Scott Kennedy

    🐛

    Scott Wells

    🐛 💻

    Sebastian Bögl

    🐛

    Sebastian Schuberth

    🐛

    Sebastian Schwarz

    🐛

    Sebastian Schwarz

    🐛

    Sergey Gorbaty

    🐛

    Sergey Kozlov

    🐛

    Sergey Yanzin

    💻 🐛

    Shubham

    💻 🐛

    Simon Xiao

    🐛

    Srinivasan Venkatachalam

    🐛

    Stanislav Gromov

    🐛

    Stanislav Gromov

    🐛

    Stanislav Myachenkov

    💻

    Stefan Birkner

    🐛

    Stefan Bohn

    🐛

    Stefan Endrullis

    🐛

    Stefan Klöss-Schuster

    🐛

    Stefan Wolf

    🐛

    Stephan H. Wissel

    🐛

    Stephan H. Wissel

    🐛

    Stephen

    🐛

    Stephen Friedrich

    🐛

    Steve Babula

    💻

    Stexxe

    🐛

    Stian Lågstad

    🐛

    StuartClayton5

    🐛

    Supun Arunoda

    🐛

    Supun Arunoda

    🐛

    Suren Abrahamyan

    🐛

    SwatiBGupta1110

    🐛

    SyedThoufich

    🐛

    Szymon Sasin

    🐛

    T-chuangxin

    🐛

    TERAI Atsuhiro

    🐛

    TIOBE Software

    💻 🐛

    TIOBE Software

    💻 🐛

    Taylor Smock

    🐛

    Techeira Damián

    💻 🐛

    Ted Husted

    🐛

    TehBakker

    🐛

    The Gitter Badger

    🐛

    Theodoor

    🐛

    Thiago Henrique Hüpner

    🐛

    Thiago Henrique Hüpner

    🐛

    Thibault Meyer

    🐛

    Thomas Güttler

    🐛

    Thomas Jones-Low

    🐛

    Thomas Smith

    💻 🐛

    ThrawnCA

    🐛

    Thunderforge

    💻 🐛

    Tim van der Lippe

    🐛

    Tim van der Lippe

    🐛

    Tobias Weimer

    💻 🐛

    Tom Daly

    🐛

    Tomer Figenblat

    🐛

    Tomi De Lucca

    💻 🐛

    Torsten Kleiber

    🐛

    TrackerSB

    🐛

    Ullrich Hafner

    🐛

    Ullrich Hafner

    🐛

    Utku Cuhadaroglu

    💻 🐛

    Valentin Brandl

    🐛

    Valeria

    🐛

    Vasily Anisimov

    🐛

    Vickenty Fesunov

    🐛

    Victor Noël

    🐛

    Vincent Galloy

    💻

    Vincent Galloy

    💻

    Vincent HUYNH

    🐛

    Vincent Maurin

    🐛

    Vincent Privat

    🐛

    Vishhwas

    🐛

    Vitaly

    🐛

    Vitaly Polonetsky

    🐛

    Vojtech Polivka

    🐛

    Vojtech Polivka

    🐛

    Vsevolod Zholobov

    🐛

    Vyom Yadav

    💻

    Wang Shidong

    🐛

    Waqas Ahmed

    🐛

    Wayne J. Earl

    🐛

    Wchenghui

    🐛

    Will Winder

    🐛

    Will Winder

    🐛

    William Brockhus

    💻 🐛

    Wilson Kurniawan

    🐛

    Wim Deblauwe

    🐛

    Woongsik Choi

    🐛

    XenoAmess

    💻 🐛

    Yang

    💻

    YaroslavTER

    🐛

    YaroslavTER

    🐛

    Young Chan

    💻 🐛

    YuJin Kim

    🐛

    Yuri Dolzhenko

    🐛

    Yurii Dubinka

    🐛

    Zoltan Farkas

    🐛

    Zustin

    🐛

    aaronhurst-google

    🐛

    aaronhurst-google

    🐛

    alexmodis

    🐛

    andreoss

    🐛

    andrey81inmd

    💻 🐛

    anicoara

    🐛

    arunprasathav

    🐛

    asiercamara

    🐛

    astillich-igniti

    💻

    astillich-igniti

    💻

    avesolovksyy

    🐛

    avishvat

    🐛

    avivmu

    🐛

    axelbarfod1

    🐛

    b-3-n

    🐛

    balbhadra9

    🐛

    base23de

    🐛

    base23de

    🐛

    bergander

    🐛

    berkam

    💻 🐛

    breizh31

    🐛

    caesarkim

    🐛

    carolyujing

    🐛

    cesares-basilico

    🐛

    chrite

    🐛

    chrite

    🐛

    cobratbq

    🐛

    coladict

    🐛

    cosmoJFH

    🐛

    cristalp

    🐛

    crunsk

    🐛

    cwholmes

    🐛

    cyberjj999

    🐛

    cyberjj999

    🐛

    cyw3

    🐛

    d1ss0nanz

    🐛

    danbrycefairsailcom

    🐛

    dariansanity

    🐛

    darrenmiliband

    🐛

    davidburstrom

    🐛

    dbirkman-paloalto

    🐛

    dbirkman-paloalto

    🐛

    deepak-patra

    🐛

    dependabot[bot]

    💻 🐛

    dinesh150

    🐛

    diziaq

    🐛

    dreaminpast123

    🐛

    duanyanan

    🐛

    dutt-sanjay

    🐛

    dutt-sanjay

    🐛

    dylanleung

    🐛

    dzeigler

    🐛

    ekkirala

    🐛

    emersonmoura

    🐛

    fairy

    🐛

    filiprafalowicz

    💻

    foxmason

    🐛

    foxmason

    🐛

    frankegabor

    🐛

    frankl

    🐛

    freafrea

    🐛

    fsapatin

    🐛

    gracia19

    🐛

    guo fei

    🐛

    gurmsc5

    🐛

    gurmsc5

    🐛

    gwilymatgearset

    💻 🐛

    haigsn

    🐛

    hemanshu070

    🐛

    henrik242

    🐛

    hongpuwu

    🐛

    hvbtup

    💻 🐛

    igniti GmbH

    🐛

    igniti GmbH

    🐛

    ilovezfs

    🐛

    itaigilo

    🐛

    jakivey32

    🐛

    jbennett2091

    🐛

    jcamerin

    🐛

    jkeener1

    🐛

    jmetertea

    🐛

    jmetertea

    🐛

    johnra2

    💻

    josemanuelrolon

    💻 🐛

    kabroxiko

    💻 🐛

    karwer

    🐛

    kaulonline

    🐛

    kdaemonv

    🐛

    kenji21

    💻 🐛

    kenji21

    💻 🐛

    kfranic

    🐛

    khalidkh

    🐛

    krzyk

    🐛

    lasselindqvist

    🐛

    lihuaib

    🐛

    lonelyma1021

    🐛

    lpeddy

    🐛

    lpeddy

    🐛

    lujiefsi

    💻

    lyriccoder

    🐛

    marcelmore

    🐛

    matchbox

    🐛

    matthiaskraaz

    🐛

    meandonlyme

    🐛

    mikesive

    🐛

    mikesive

    🐛

    milossesic

    🐛

    mriddell95

    🐛

    mrlzh

    🐛

    msloan

    🐛

    mucharlaravalika

    🐛

    mvenneman

    🐛

    nareshl119

    🐛

    nareshl119

    🐛

    nicolas-harraudeau-sonarsource

    🐛

    noerremark

    🐛

    novsirion

    🐛

    oggboy

    🐛

    oinume

    🐛

    orimarko

    💻 🐛

    pallavi agarwal

    🐛

    pallavi agarwal

    🐛

    parksungrin

    🐛

    patpatpat123

    🐛

    patriksevallius

    🐛

    pbrajesh1

    🐛

    phoenix384

    🐛

    piotrszymanski-sc

    💻

    plan3d

    🐛

    plan3d

    🐛

    poojasix

    🐛

    prabhushrikant

    🐛

    pujitha8783

    🐛

    r-r-a-j

    🐛

    raghujayjunk

    🐛

    rajeshveera

    🐛

    rajeswarreddy88

    🐛

    rajeswarreddy88

    🐛

    recdevs

    🐛

    reudismam

    💻 🐛

    rijkt

    🐛

    rillig-tk

    🐛

    rmohan20

    💻 🐛

    rxmicro

    🐛

    ryan-gustafson

    💻 🐛

    ryan-gustafson

    💻 🐛

    sabi0

    🐛

    scais

    🐛

    sebbASF

    🐛

    sergeygorbaty

    💻

    shilko2013

    🐛

    simeonKondr

    🐛

    snajberk

    🐛

    snajberk

    🐛

    sniperrifle2004

    🐛

    snuyanzin

    🐛 💻

    sratz

    🐛

    stonio

    🐛

    sturton

    💻 🐛

    sudharmohan

    🐛

    suruchidawar

    🐛

    suruchidawar

    🐛

    svenfinitiv

    🐛

    tashiscool

    🐛

    test-git-hook

    🐛

    testation21

    💻 🐛

    thanosa

    🐛

    tiandiyixian

    🐛

    tobwoerk

    🐛

    tobwoerk

    🐛

    tprouvot

    🐛

    trentchilders

    🐛

    triandicAnt

    🐛

    trishul14

    🐛

    tsui

    🐛

    winhkey

    🐛

    witherspore

    🐛

    witherspore

    🐛

    wjljack

    🐛

    wuchiuwong

    🐛

    xingsong

    🐛

    xioayuge

    🐛

    xnYi9wRezm

    💻 🐛

    xuanuy

    🐛

    xyf0921

    🐛

    xyf0921

    🐛

    yalechen-cyw3

    🐛

    yasuharu-sato

    🐛

    zenglian

    🐛

    zgrzyt93

    💻 🐛

    zh3ng

    🐛

    zt_soft

    🐛

    ztt79

    🐛

    ztt79

    🐛

    zzzzfeng

    🐛

    Árpád Magosányi

    🐛

    任贵杰

    🐛

    Michael

    🐛

    Michael Bell

    🐛

    Michael Bernstein

    🐛

    Michael Clay

    🐛

    Michael Clay

    🐛

    Michael Dombrowski

    🐛

    Michael Hausegger

    🐛

    Michael Hoefer

    🐛

    Michael Möbius

    🐛

    Michael N. Lipp

    🐛

    Michael Pellegrini

    🐛

    Michal Kordas

    🐛

    Michal Kordas

    🐛

    Michał Borek

    🐛

    Michał Kuliński

    🐛

    Miguel Núñez Díaz-Montes

    🐛

    Mihai Ionut

    🐛

    Mirek Hankus

    🐛

    Mladjan Gadzic

    🐛

    MrAngry52

    🐛

    MrAngry52

    🐛

    Muminur Choudhury

    🐛

    Mykhailo Palahuta

    💻 🐛

    Nagendra Kumar Singh

    🐛

    Nahuel Barrios

    🐛

    Nathan Braun

    🐛

    Nathan Reynolds

    🐛

    Nathan Reynolds

    🐛

    Nathan Reynolds

    🐛

    Nathanaël

    🐛

    Nazdravi

    🐛

    Neha-Dhonde

    🐛

    Nicholas Doyle

    🐛

    Nick Butcher

    🐛

    Nico Gallinal

    🐛

    Nicola Dal Maso

    🐛

    Nicola Dal Maso

    🐛

    Nicolas Filotto

    💻

    Nikita Chursin

    🐛

    Niklas Baudy

    🐛

    Nikolas Havrikov

    🐛

    Nilesh Virkar

    🐛

    Nimit Patel

    🐛

    Niranjan Harpale

    🐛

    Niranjan Harpale

    🐛

    Noah Sussman

    🐛

    Noah0120

    🐛

    Noam Tamim

    🐛

    Noel Grandin

    🐛

    Olaf Haalstra

    🐛

    Oleg Pavlenko

    🐛

    Oleksii Dykov

    💻

    Oleksii Dykov

    💻

    Oliver Eikemeier

    🐛

    Olivier Parent

    💻 🐛

    Ollie Abbey

    💻 🐛

    OverDrone

    🐛

    Ozan Gulle

    💻 🐛

    PUNEET JAIN

    🐛

    Parbati Bose

    🐛

    Parbati Bose

    🐛

    Paul Berg

    🐛

    Pavel Bludov

    🐛

    Pavel Mička

    🐛

    Pedro Nuno Santos

    🐛

    Pedro Rijo

    🐛

    Pelisse Romain

    💻 📖 🐛

    Pete Davids

    🐛

    Pete Davids

    🐛

    Peter Bruin

    🐛

    Peter Chittum

    💻 🐛

    Peter Cudmore

    🐛

    Peter Kasson

    🐛

    Peter Kofler

    🐛

    Pham Hai Trung

    🐛

    Philip Graf

    💻 🐛

    Philip Graf

    💻 🐛

    Philip Hachey

    🐛

    Philippe Ozil

    🐛

    Phinehas Artemix

    🐛

    Phokham Nonava

    🐛

    Piotr Szymański

    🐛

    Piotrek Żygieło

    💻 🐛

    Pranay Jaiswal

    🐛

    Pranay Jaiswal

    🐛

    Prasad Kamath

    🐛

    Prasanna

    🐛

    Presh-AR

    🐛

    Puneet1726

    🐛

    Rafael Cortês

    🐛

    RaheemShaik999

    🐛

    RajeshR

    💻 🐛

    RajeshR

    💻 🐛

    Ramachandra Mohan

    🐛

    Raquel Pau

    🐛

    Ravikiran Janardhana

    🐛

    Reda Benhemmouche

    🐛

    Renato Oliveira

    💻 🐛

    Rich DiCroce

    🐛

    Riot R1cket

    🐛

    Riot R1cket

    🐛

    Rishabh Jain

    🐛

    RishabhDeep Singh

    🐛

    Robbie Martinus

    💻 🐛

    Robert Henry

    🐛

    Robert Painsi

    🐛

    Robert Russell

    🐛

    Robert Sösemann

    💻 📖 📢 🐛

    Robert Sösemann

    💻 📖 📢 🐛

    Robert Whitebit

    🐛

    Robin Richtsfeld

    🐛

    Robin Stocker

    💻 🐛

    Robin Wils

    🐛

    RochusOest

    🐛

    Rodolfo Noviski

    🐛

    Rodrigo Casara

    🐛

    Rodrigo Casara

    🐛

    Rodrigo Fernandes

    🐛

    Roman Salvador

    💻 🐛

    Ronald Blaschke

    🐛

    Róbert Papp

    🐛

    Saikat Sengupta

    🐛

    Saksham Handu

    🐛

    Saladoc

    🐛

    Saladoc

    🐛

    Salesforce Bob Lightning

    🐛

    Sam Carlberg

    🐛

    Satoshi Kubo

    🐛

    Scott Kennedy

    🐛

    Scott Wells

    🐛 💻

    Sebastian Bögl

    🐛

    Sebastian Schuberth

    🐛

    Sebastian Schuberth

    🐛

    Sebastian Schwarz

    🐛

    Sergey Gorbaty

    🐛

    Sergey Kozlov

    🐛

    Sergey Yanzin

    💻 🐛

    Shubham

    💻 🐛

    Simon Xiao

    🐛

    Srinivasan Venkatachalam

    🐛

    Srinivasan Venkatachalam

    🐛

    Stanislav Gromov

    🐛

    Stanislav Myachenkov

    💻

    Stefan Birkner

    🐛

    Stefan Bohn

    🐛

    Stefan Endrullis

    🐛

    Stefan Klöss-Schuster

    🐛

    Stefan Wolf

    🐛

    Stefan Wolf

    🐛

    Stephan H. Wissel

    🐛

    Stephen

    🐛

    Stephen Friedrich

    🐛

    Steve Babula

    💻

    Stexxe

    🐛

    Stian Lågstad

    🐛

    StuartClayton5

    🐛

    StuartClayton5

    🐛

    Supun Arunoda

    🐛

    Suren Abrahamyan

    🐛

    SwatiBGupta1110

    🐛

    SyedThoufich

    🐛

    Szymon Sasin

    🐛

    T-chuangxin

    🐛

    TERAI Atsuhiro

    🐛

    TERAI Atsuhiro

    🐛

    TIOBE Software

    💻 🐛

    Taylor Smock

    🐛

    Techeira Damián

    💻 🐛

    Ted Husted

    🐛

    TehBakker

    🐛

    The Gitter Badger

    🐛

    Theodoor

    🐛

    Theodoor

    🐛

    Thiago Henrique Hüpner

    🐛

    Thibault Meyer

    🐛

    Thomas Güttler

    🐛

    Thomas Jones-Low

    🐛

    Thomas Smith

    💻 🐛

    ThrawnCA

    🐛

    Thunderforge

    💻 🐛

    Thunderforge

    💻 🐛

    Tim van der Lippe

    🐛

    Tobias Weimer

    💻 🐛

    Tom Daly

    🐛

    Tomer Figenblat

    🐛

    Tomi De Lucca

    💻 🐛

    Torsten Kleiber

    🐛

    TrackerSB

    🐛

    TrackerSB

    🐛

    Ullrich Hafner

    🐛

    Utku Cuhadaroglu

    💻 🐛

    Valentin Brandl

    🐛

    Valeria

    🐛

    Vasily Anisimov

    🐛

    Vickenty Fesunov

    🐛

    Victor Noël

    🐛

    Victor Noël

    🐛

    Vincent Galloy

    💻

    Vincent HUYNH

    🐛

    Vincent Maurin

    🐛

    Vincent Privat

    🐛

    Vishhwas

    🐛

    Vitaly

    🐛

    Vitaly Polonetsky

    🐛

    Vitaly Polonetsky

    🐛

    Vojtech Polivka

    🐛

    Vsevolod Zholobov

    🐛

    Vyom Yadav

    💻

    Wang Shidong

    🐛

    Waqas Ahmed

    🐛

    Wayne J. Earl

    🐛

    Wchenghui

    🐛

    Wchenghui

    🐛

    Will Winder

    🐛

    William Brockhus

    💻 🐛

    Wilson Kurniawan

    🐛

    Wim Deblauwe

    🐛

    Woongsik Choi

    🐛

    XenoAmess

    💻 🐛

    Yang

    💻

    Yang

    💻

    YaroslavTER

    🐛

    Young Chan

    💻 🐛

    YuJin Kim

    🐛

    Yuri Dolzhenko

    🐛

    Yurii Dubinka

    🐛

    Zoltan Farkas

    🐛

    Zustin

    🐛

    Zustin

    🐛

    aaronhurst-google

    🐛

    alexmodis

    🐛

    andreoss

    🐛

    andrey81inmd

    💻 🐛

    anicoara

    🐛

    arunprasathav

    🐛

    asiercamara

    🐛

    asiercamara

    🐛

    astillich-igniti

    💻

    avesolovksyy

    🐛

    avishvat

    🐛

    avivmu

    🐛

    axelbarfod1

    🐛

    b-3-n

    🐛

    balbhadra9

    🐛

    balbhadra9

    🐛

    base23de

    🐛

    bergander

    🐛

    berkam

    💻 🐛

    breizh31

    🐛

    caesarkim

    🐛

    carolyujing

    🐛

    cesares-basilico

    🐛

    cesares-basilico

    🐛

    chrite

    🐛

    cobratbq

    🐛

    coladict

    🐛

    cosmoJFH

    🐛

    cristalp

    🐛

    crunsk

    🐛

    cwholmes

    🐛

    cwholmes

    🐛

    cyberjj999

    🐛

    cyw3

    🐛

    d1ss0nanz

    🐛

    danbrycefairsailcom

    🐛

    dariansanity

    🐛

    darrenmiliband

    🐛

    davidburstrom

    🐛

    davidburstrom

    🐛

    dbirkman-paloalto

    🐛

    deepak-patra

    🐛

    dependabot[bot]

    💻 🐛

    dinesh150

    🐛

    diziaq

    🐛

    dreaminpast123

    🐛

    duanyanan

    🐛

    duanyanan

    🐛

    dutt-sanjay

    🐛

    dylanleung

    🐛

    dzeigler

    🐛

    ekkirala

    🐛

    emersonmoura

    🐛

    fairy

    🐛

    filiprafalowicz

    💻

    filiprafalowicz

    💻

    foxmason

    🐛

    frankegabor

    🐛

    frankl

    🐛

    freafrea

    🐛

    fsapatin

    🐛

    gracia19

    🐛

    guo fei

    🐛

    guo fei

    🐛

    gurmsc5

    🐛

    gwilymatgearset

    💻 🐛

    haigsn

    🐛

    hemanshu070

    🐛

    henrik242

    🐛

    hongpuwu

    🐛

    hvbtup

    💻 🐛

    hvbtup

    💻 🐛

    igniti GmbH

    🐛

    ilovezfs

    🐛

    itaigilo

    🐛

    jakivey32

    🐛

    jbennett2091

    🐛

    jcamerin

    🐛

    jkeener1

    🐛

    jkeener1

    🐛

    jmetertea

    🐛

    johnra2

    💻

    josemanuelrolon

    💻 🐛

    kabroxiko

    💻 🐛

    karwer

    🐛

    kaulonline

    🐛

    kdaemonv

    🐛

    kdaemonv

    🐛

    kenji21

    💻 🐛

    kfranic

    🐛

    khalidkh

    🐛

    krzyk

    🐛

    lasselindqvist

    🐛

    lihuaib

    🐛

    lonelyma1021

    🐛

    lonelyma1021

    🐛

    lpeddy

    🐛

    lujiefsi

    💻

    lyriccoder

    🐛

    marcelmore

    🐛

    matchbox

    🐛

    matthiaskraaz

    🐛

    meandonlyme

    🐛

    meandonlyme

    🐛

    mikesive

    🐛

    milossesic

    🐛

    mriddell95

    🐛

    mrlzh

    🐛

    msloan

    🐛

    mucharlaravalika

    🐛

    mvenneman

    🐛

    mvenneman

    🐛

    nareshl119

    🐛

    nicolas-harraudeau-sonarsource

    🐛

    noerremark

    🐛

    novsirion

    🐛

    oggboy

    🐛

    oinume

    🐛

    orimarko

    💻 🐛

    orimarko

    💻 🐛

    pallavi agarwal

    🐛

    parksungrin

    🐛

    patpatpat123

    🐛

    patriksevallius

    🐛

    pbrajesh1

    🐛

    phoenix384

    🐛

    piotrszymanski-sc

    💻

    piotrszymanski-sc

    💻

    plan3d

    🐛

    poojasix

    🐛

    prabhushrikant

    🐛

    pujitha8783

    🐛

    r-r-a-j

    🐛

    raghujayjunk

    🐛

    rajeshveera

    🐛

    rajeshveera

    🐛

    rajeswarreddy88

    🐛

    recdevs

    🐛

    reudismam

    💻 🐛

    rijkt

    🐛

    rillig-tk

    🐛

    rmohan20

    💻 🐛

    rxmicro

    🐛

    rxmicro

    🐛

    ryan-gustafson

    💻 🐛

    sabi0

    🐛

    scais

    🐛

    sebbASF

    🐛

    sergeygorbaty

    💻

    shilko2013

    🐛

    simeonKondr

    🐛

    simeonKondr

    🐛

    snajberk

    🐛

    sniperrifle2004

    🐛

    snuyanzin

    🐛 💻

    sratz

    🐛

    stonio

    🐛

    sturton

    💻 🐛

    sudharmohan

    🐛

    sudharmohan

    🐛

    suruchidawar

    🐛

    svenfinitiv

    🐛

    tashiscool

    🐛

    test-git-hook

    🐛

    testation21

    💻 🐛

    thanosa

    🐛

    tiandiyixian

    🐛

    tiandiyixian

    🐛

    tobwoerk

    🐛

    tprouvot

    🐛

    trentchilders

    🐛

    triandicAnt

    🐛

    trishul14

    🐛

    tsui

    🐛

    winhkey

    🐛

    winhkey

    🐛

    witherspore

    🐛

    wjljack

    🐛

    wuchiuwong

    🐛

    xingsong

    🐛

    xioayuge

    🐛

    xnYi9wRezm

    💻 🐛

    xuanuy

    🐛

    xuanuy

    🐛

    xyf0921

    🐛

    yalechen-cyw3

    🐛

    yasuharu-sato

    🐛

    zenglian

    🐛

    zgrzyt93

    💻 🐛

    zh3ng

    🐛

    zt_soft

    🐛

    zt_soft

    🐛

    ztt79

    🐛

    zzzzfeng

    🐛

    Árpád Magosányi

    🐛