diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt
index 7fc17b1edf..132280c698 100644
--- a/pmd-java/etc/grammar/Java.jjt
+++ b/pmd-java/etc/grammar/Java.jjt
@@ -1,4 +1,7 @@
/**
+ * JEP 394: Pattern Matching for instanceof for Java16
+ * Andreas Dangel 02/2021
+ *====================================================================
* Remove support for Java 13 preview language features.
* Promote text blocks as a permanent language features with Java 15.
* Support Pattern Matching for instanceof with Java 15 Preview.
@@ -378,8 +381,8 @@ public class JavaParser {
}
private void checkforBadInstanceOfPattern() {
- if (jdkVersion != 14 && jdkVersion != 15 || !preview) {
- throwParseException("Pattern Matching for instanceof is only supported with Java 14 Preview and Java 15 Preview");
+ if (!(jdkVersion == 14 && preview || jdkVersion == 15 && preview || jdkVersion == 16)) {
+ throwParseException("Pattern Matching for instanceof is only supported with Java 14 Preview and Java 15 Preview and Java 16");
}
}
@@ -1682,10 +1685,26 @@ void EqualityExpression() #EqualityExpression(>1):
InstanceOfExpression() ( LOOKAHEAD(2) ( "==" {jjtThis.setImage("==");} | "!=" {jjtThis.setImage("!=");} ) InstanceOfExpression() )*
}
+void TypePattern() #TypeTestPattern:
+{}
+{
+ ( "final" {jjtThis.setFinal(true);} | Annotation() )*
+ Type()
+ VariableDeclaratorId()
+}
+
void InstanceOfExpression() #InstanceOfExpression(>1):
{}
{
- RelationalExpression() [ LOOKAHEAD(2) "instanceof" Type() [ {checkforBadInstanceOfPattern();} VariableDeclaratorId() #TypeTestPattern(2) ] ]
+ RelationalExpression()
+ [ "instanceof"
+ (
+ LOOKAHEAD("final" | "@") {checkforBadInstanceOfPattern();} TypePattern()
+ |
+ Type()
+ [ {checkforBadInstanceOfPattern();} VariableDeclaratorId() #TypeTestPattern(2) ]
+ )
+ ]
}
void RelationalExpression() #RelationalExpression(>1):
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java
index 707be4e0cd..ef957a26c5 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java
@@ -1,4 +1,4 @@
-/**
+/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
@@ -8,22 +8,21 @@ import net.sourceforge.pmd.annotation.Experimental;
/**
* A pattern (for pattern matching constructs like {@link ASTInstanceOfExpression InstanceOfExpression}).
- * This is a JDK 14 and JDK 15 preview feature and is subject to change.
+ * This is a JDK 16 feature.
*
*
This interface will be implemented by all forms of patterns. For
* now, only type test patterns are supported. Record deconstruction
- * patterns are in the works for JDK 15 preview.
- *
- *
See https://openjdk.java.net/jeps/305, https://openjdk.java.net/jeps/8235186
+ * patterns is planned for a future JDK version.
*
*
*
* Pattern ::= {@link ASTTypeTestPattern TypeTestPattern}
*
*
+ *
+ * @see JEP 394: Pattern Matching for instanceof
*/
@Experimental
public interface ASTPattern extends JavaNode {
-
}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java
index c126b89198..40c59ff9b4 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java
@@ -1,24 +1,29 @@
-/**
+/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
+import java.util.List;
+
import net.sourceforge.pmd.annotation.Experimental;
/**
- * A type test pattern (JDK 14 preview feature). This can be found on
+ * A type pattern (JDK16). This can be found on
* the right-hand side of an {@link ASTInstanceOfExpression InstanceOfExpression}.
*
*
*
- * TypeTestPattern ::= {@linkplain ASTType Type} {@link ASTVariableDeclaratorId VariableDeclaratorId}
+ * TypeTestPattern ::= ( "final" | {@linkplain ASTAnnotation Annotation} )* {@linkplain ASTType Type} {@link ASTVariableDeclaratorId VariableDeclaratorId}
*
*
- */
+ *
+ * @see JEP 394: Pattern Matching for instanceof
+*/
@Experimental
-public final class ASTTypeTestPattern extends AbstractJavaNode implements ASTPattern {
+public final class ASTTypeTestPattern extends AbstractJavaAnnotatableNode implements ASTPattern {
+ private boolean isFinal;
ASTTypeTestPattern(int id) {
super(id);
@@ -34,17 +39,28 @@ public final class ASTTypeTestPattern extends AbstractJavaNode implements ASTPat
return visitor.visit(this, data);
}
+ @Override
+ public List getDeclaredAnnotations() {
+ return this.findChildrenOfType(ASTAnnotation.class);
+ }
/**
* Gets the type against which the expression is tested.
*/
public ASTType getTypeNode() {
- return (ASTType) getChild(0);
+ return getFirstChildOfType(ASTType.class);
}
/** Returns the declared variable. */
public ASTVariableDeclaratorId getVarId() {
- return (ASTVariableDeclaratorId) getChild(1);
+ return getFirstChildOfType(ASTVariableDeclaratorId.class);
}
+ void setFinal(boolean isFinal) {
+ this.isFinal = isFinal;
+ }
+
+ boolean isFinal() {
+ return isFinal;
+ }
}
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 a8703fa98d..c1c213f000 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
@@ -199,9 +199,10 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim
return true;
} else if (isLambdaParamWithNoType()) {
return false;
- } else if (isPatternBinding()) {
- // implicitly like final, assignment of a pattern binding is not allowed
- return true;
+ }
+
+ if (getParent() instanceof ASTTypeTestPattern) {
+ return ((ASTTypeTestPattern) getParent()).isFinal();
}
if (getParent() instanceof ASTRecordComponent) {
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14PreviewTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14PreviewTest.java
index b487c35267..ac22623748 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14PreviewTest.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14PreviewTest.java
@@ -83,7 +83,7 @@ public class Java14PreviewTest {
Assert.assertEquals(String.class, variable.getType());
Assert.assertEquals("s", variable.getVariableName());
Assert.assertTrue(variable.isPatternBinding());
- Assert.assertTrue(variable.isFinal());
+ Assert.assertFalse(variable.isFinal());
// Note: these variables are not part of the symbol table
// See ScopeAndDeclarationFinder#visit(ASTVariableDeclaratorId, Object)
Assert.assertNull(variable.getNameDeclaration());
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
new file mode 100644
index 0000000000..8afcc25eee
--- /dev/null
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java16TreeDumpTest.java
@@ -0,0 +1,55 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.java.ast;
+
+import java.util.List;
+
+import org.junit.Assert;
+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 Java16TreeDumpTest extends BaseTreeDumpTest {
+ private final JavaParsingHelper java16 =
+ JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("16")
+ .withResourceContext(Java15TreeDumpTest.class, "jdkversiontests/java16/");
+ private final JavaParsingHelper java16p = java16.withDefaultVersion("16-preview");
+ private final JavaParsingHelper java15 = java16.withDefaultVersion("15");
+
+ public Java16TreeDumpTest() {
+ super(new RelevantAttributePrinter(), ".java");
+ }
+
+ @Override
+ public BaseParsingHelper, ?> getParser() {
+ return java16;
+ }
+
+ @Test
+ public void patternMatchingInstanceof() {
+ 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());
+ }
+ }
+
+ @Test(expected = ParseException.class)
+ public void patternMatchingInstanceofBeforeJava16ShouldFail() {
+ java15.parseResource("PatternMatchingInstanceof.java");
+ }
+
+}
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 f513429d89..806588b2eb 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
@@ -4,32 +4,67 @@
package net.sourceforge.pmd.lang.java.ast
-import net.sourceforge.pmd.lang.ast.test.shouldBe
+import io.kotest.matchers.shouldBe
+import net.sourceforge.pmd.lang.ast.test.shouldBe as typeShouldBe
import net.sourceforge.pmd.lang.java.ast.JavaVersion
import net.sourceforge.pmd.lang.java.ast.JavaVersion.*
import java.io.IOException
class ASTPatternTest : ParserTestSpec({
- parserTest("Test patterns only available on JDK 14+15 (preview)", javaVersions = JavaVersion.values().asList().minus(J14__PREVIEW).minus(J15__PREVIEW)) {
+ parserTest("Test patterns only available on JDK 14+15 (preview) and JDK16 and JDK16 (preview)",
+ javaVersions = JavaVersion.values().asList().minus(J14__PREVIEW).minus(J15__PREVIEW).minus(J16).minus(J16__PREVIEW)) {
- expectParseException("Pattern Matching for instanceof is only supported with Java 14 Preview and Java 15 Preview") {
+ expectParseException("Pattern Matching for instanceof is only supported with Java 14 Preview and Java 15 Preview and Java 16") {
parseAstExpression("obj instanceof Class c")
}
}
- parserTest("Test simple patterns", javaVersions = listOf(J14__PREVIEW, J15__PREVIEW)) {
+ parserTest("Test simple patterns", javaVersions = listOf(J14__PREVIEW, J15__PREVIEW, J16)) {
importedTypes += IOException::class.java
"obj instanceof Class c" should matchExpr {
unspecifiedChild()
child {
- it::getTypeNode shouldBe child(ignoreChildren = true) {}
+ it.isAnnotationPresent("java.lang.Deprecated") shouldBe false
+ it::getTypeNode typeShouldBe child(ignoreChildren = true) {}
- it::getVarId shouldBe child {
- it::getVariableName shouldBe "c"
+ it::getVarId typeShouldBe child {
+ it.name shouldBe "c"
+ it.isFinal shouldBe false
+ }
+ }
+ }
+
+ "obj instanceof final Class c" should matchExpr {
+ unspecifiedChild()
+ child {
+ it.isAnnotationPresent("java.lang.Deprecated") shouldBe false
+ it::getTypeNode typeShouldBe child(ignoreChildren = true) {}
+
+ it::getVarId typeShouldBe child {
+ it.name shouldBe "c"
+ it.isFinal shouldBe true
+ }
+ }
+ }
+
+ "obj instanceof @Deprecated Class c" should matchExpr {
+ unspecifiedChild()
+ child {
+ child(ignoreChildren = true) {
+ it.annotationName shouldBe "Deprecated"
+ }
+
+ it.isAnnotationPresent("java.lang.Deprecated") shouldBe true
+
+ it::getTypeNode typeShouldBe child(ignoreChildren = true) {}
+
+ it::getVarId typeShouldBe child {
+ it.name shouldBe "c"
+ it.isFinal shouldBe false
}
}
}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/PatternMatchingInstanceof.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/PatternMatchingInstanceof.txt
index e69073e1e7..00481b37e4 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/PatternMatchingInstanceof.txt
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15p/PatternMatchingInstanceof.txt
@@ -44,7 +44,7 @@
| | | +- 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 = true, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
| | +- Statement[]
| | | +- Block[@containsComment = true]
| | | +- BlockStatement[@Allocation = false]
@@ -113,7 +113,7 @@
| | | +- 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 = true, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
| | +- Statement[]
| | | +- Block[@containsComment = true]
| | | +- BlockStatement[@Allocation = false]
@@ -179,7 +179,7 @@
| | | | +- 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 = true, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = 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]
@@ -228,7 +228,7 @@
| | | +- 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 = true, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = 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]
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.java
new file mode 100644
index 0000000000..c4e6e46e5a
--- /dev/null
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.java
@@ -0,0 +1,55 @@
+/**
+ *
+ * @see JEP 394: Pattern Matching for instanceof
+ */
+public class PatternMatchingInstanceof {
+ private String s = "other string";
+
+ public void test() {
+ Object obj = "abc";
+ //obj = 1;
+ if (obj instanceof String s) {
+ System.out.println("a) obj == s: " + (obj == s)); // true
+ s = "other value"; // not a compile error - s is only effectively final
+ System.out.println("changed s to " + s + ": obj == s: " + (obj == s));
+ } else {
+ System.out.println("b) obj == s: " + (obj == s)); // false
+ }
+
+ if (!(obj instanceof String s)) {
+ System.out.println("c) obj == s: " + (obj == s)); // false
+ } else {
+ System.out.println("d) obj == s: " + (obj == s)); // true
+ }
+
+ if (obj instanceof String s && s.length() > 2) {
+ System.out.println("e) obj == s: " + (obj == s)); // true
+ }
+ if (obj instanceof String s || s.length() > 5) {
+ System.out.println("f) obj == s: " + (obj == s)); // false
+ }
+
+ // With Java16 there can be final and annotations
+ if (obj instanceof final String s) {
+ System.out.println("g) obj == s: " + (obj == s)); // true
+ //s = "another value"; // compile error: error: cannot assign a value to final variable s
+ } else {
+ System.out.println("h) obj == s: " + (obj == s)); // false
+ }
+ if (obj instanceof @Deprecated String s) {
+ System.out.println("i) obj == s: " + (obj == s)); // true
+ } else {
+ System.out.println("j) obj == s: " + (obj == s)); // false
+ }
+ if (obj instanceof final @Deprecated String s) {
+ System.out.println("k) obj == s: " + (obj == s)); // true
+ //s = "another value"; // compile error: error: cannot assign a value to final variable s
+ } else {
+ System.out.println("l) obj == s: " + (obj == s)); // false
+ }
+ }
+
+ public static void main(String[] args) {
+ new PatternMatchingInstanceof().test();
+ }
+}
\ No newline at end of file
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.txt
new file mode 100644
index 0000000000..dca5fe68c6
--- /dev/null
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java16/PatternMatchingInstanceof.txt
@@ -0,0 +1,530 @@
++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true]
+ +- TypeDeclaration[]
+ +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "PatternMatchingInstanceof", @Default = false, @Final = false, @Image = "PatternMatchingInstanceof", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "PatternMatchingInstanceof", @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.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 = "s", @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 = "s"]
+ | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = true, @Final = false, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | +- VariableInitializer[]
+ | +- Expression[@StandAlonePrimitive = false]
+ | +- PrimaryExpression[]
+ | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""other string"", @FloatLiteral = false, @Image = ""other string"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""other string"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.METHOD]
+ | +- MethodDeclaration[@Abstract = false, @Arity = 0, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "test", @Modifiers = 1, @Name = "test", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false]
+ | +- ResultType[@Void = true, @returnsArray = false]
+ | +- MethodDeclarator[@Image = "test", @ParameterCount = 0]
+ | | +- FormalParameters[@ParameterCount = 0, @Size = 0]
+ | +- 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 = "obj", @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 = "obj"]
+ | | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @FormalParameter = false, @Image = "obj", @LambdaParameter = false, @LocalVariable = true, @Name = "obj", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "obj"]
+ | | +- VariableInitializer[]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""abc"", @FloatLiteral = false, @Image = ""abc"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""abc"", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | +- BlockStatement[@Allocation = false]
+ | | +- Statement[]
+ | | +- IfStatement[@Else = true]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- InstanceOfExpression[]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "obj"]
+ | | | +- TypeTestPattern[]
+ | | | +- 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, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | | +- 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]
+ | | | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | | | +- PrimaryExpression[]
+ | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""a) obj == s: "", @FloatLiteral = false, @Image = ""a) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""a) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Expression[@StandAlonePrimitive = false]
+ | | | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | | | +- PrimaryExpression[]
+ | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | | +- Name[@Image = "obj"]
+ | | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "s"]
+ | | | +- BlockStatement[@Allocation = false]
+ | | | | +- Statement[]
+ | | | | +- StatementExpression[]
+ | | | | +- PrimaryExpression[]
+ | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | | +- Name[@Image = "s"]
+ | | | | +- AssignmentOperator[@Compound = false, @Image = "="]
+ | | | | +- Expression[@StandAlonePrimitive = false]
+ | | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""other value"", @FloatLiteral = false, @Image = ""other value"", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""other value"", @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]
+ | | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""changed s to "", @FloatLiteral = false, @Image = ""changed s to "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""changed s to "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "s"]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "": obj == s: "", @FloatLiteral = false, @Image = "": obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = "": obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "obj"]
+ | | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "s"]
+ | | +- Statement[]
+ | | +- Block[@containsComment = 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]
+ | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""b) obj == s: "", @FloatLiteral = false, @Image = ""b) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""b) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "obj"]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "s"]
+ | +- BlockStatement[@Allocation = false]
+ | | +- Statement[]
+ | | +- IfStatement[@Else = true]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- UnaryExpressionNotPlusMinus[@Image = "!", @Operator = "!"]
+ | | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- InstanceOfExpression[]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "obj"]
+ | | | +- TypeTestPattern[]
+ | | | +- 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, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | | +- Statement[]
+ | | | +- Block[@containsComment = 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]
+ | | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""c) obj == s: "", @FloatLiteral = false, @Image = ""c) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""c) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "obj"]
+ | | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "s"]
+ | | +- Statement[]
+ | | +- Block[@containsComment = 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]
+ | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""d) obj == s: "", @FloatLiteral = false, @Image = ""d) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""d) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "obj"]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "s"]
+ | +- BlockStatement[@Allocation = false]
+ | | +- Statement[]
+ | | +- IfStatement[@Else = false]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- ConditionalAndExpression[]
+ | | | +- InstanceOfExpression[]
+ | | | | +- PrimaryExpression[]
+ | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | | +- Name[@Image = "obj"]
+ | | | | +- TypeTestPattern[]
+ | | | | +- 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, @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 = 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]
+ | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""e) obj == s: "", @FloatLiteral = false, @Image = ""e) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""e) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "obj"]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "s"]
+ | +- BlockStatement[@Allocation = false]
+ | | +- Statement[]
+ | | +- IfStatement[@Else = false]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- ConditionalOrExpression[]
+ | | | +- InstanceOfExpression[]
+ | | | | +- PrimaryExpression[]
+ | | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | | +- Name[@Image = "obj"]
+ | | | | +- TypeTestPattern[]
+ | | | | +- 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, @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 = "5", @FloatLiteral = false, @Image = "5", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "5", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 5, @ValueAsLong = 5]
+ | | +- Statement[]
+ | | +- Block[@containsComment = 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]
+ | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""f) obj == s: "", @FloatLiteral = false, @Image = ""f) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""f) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "obj"]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "s"]
+ | +- BlockStatement[@Allocation = false]
+ | | +- Statement[]
+ | | +- IfStatement[@Else = true]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- InstanceOfExpression[]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "obj"]
+ | | | +- TypeTestPattern[]
+ | | | +- 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 = true, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | | +- Statement[]
+ | | | +- Block[@containsComment = 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]
+ | | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""g) obj == s: "", @FloatLiteral = false, @Image = ""g) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""g) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "obj"]
+ | | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "s"]
+ | | +- Statement[]
+ | | +- Block[@containsComment = 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]
+ | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""h) obj == s: "", @FloatLiteral = false, @Image = ""h) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""h) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "obj"]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "s"]
+ | +- BlockStatement[@Allocation = false]
+ | | +- Statement[]
+ | | +- IfStatement[@Else = true]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- InstanceOfExpression[]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "obj"]
+ | | | +- TypeTestPattern[]
+ | | | +- Annotation[@AnnotationName = "Deprecated"]
+ | | | | +- MarkerAnnotation[@AnnotationName = "Deprecated"]
+ | | | | +- Name[@Image = "Deprecated"]
+ | | | +- 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, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | | +- Statement[]
+ | | | +- Block[@containsComment = 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]
+ | | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""i) obj == s: "", @FloatLiteral = false, @Image = ""i) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""i) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Expression[@StandAlonePrimitive = false]
+ | | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | | +- PrimaryExpression[]
+ | | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | | +- Name[@Image = "obj"]
+ | | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "s"]
+ | | +- Statement[]
+ | | +- Block[@containsComment = 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]
+ | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""j) obj == s: "", @FloatLiteral = false, @Image = ""j) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""j) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "obj"]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "s"]
+ | +- BlockStatement[@Allocation = false]
+ | +- Statement[]
+ | +- IfStatement[@Else = true]
+ | +- Expression[@StandAlonePrimitive = false]
+ | | +- InstanceOfExpression[]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "obj"]
+ | | +- TypeTestPattern[]
+ | | +- Annotation[@AnnotationName = "Deprecated"]
+ | | | +- MarkerAnnotation[@AnnotationName = "Deprecated"]
+ | | | +- Name[@Image = "Deprecated"]
+ | | +- 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 = true, @FormalParameter = false, @Image = "s", @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "s"]
+ | +- Statement[]
+ | | +- Block[@containsComment = 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]
+ | | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""k) obj == s: "", @FloatLiteral = false, @Image = ""k) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""k) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Expression[@StandAlonePrimitive = false]
+ | | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | | +- PrimaryExpression[]
+ | | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | | +- Name[@Image = "obj"]
+ | | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "s"]
+ | +- Statement[]
+ | +- Block[@containsComment = 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]
+ | +- AdditiveExpression[@Image = "+", @Operator = "+"]
+ | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = ""l) obj == s: "", @FloatLiteral = false, @Image = ""l) obj == s: "", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = true, @TextBlock = false, @TextBlockContent = ""l) obj == s: "", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ | +- PrimaryExpression[]
+ | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | +- Expression[@StandAlonePrimitive = false]
+ | +- EqualityExpression[@Image = "==", @Operator = "=="]
+ | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "obj"]
+ | +- PrimaryExpression[]
+ | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | +- Name[@Image = "s"]
+ +- 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, @FormalParameter = true, @Image = "args", @LambdaParameter = false, @LocalVariable = false, @Name = "args", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "args"]
+ +- Block[@containsComment = false]
+ +- BlockStatement[@Allocation = true]
+ +- Statement[]
+ +- StatementExpression[]
+ +- PrimaryExpression[]
+ +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | +- AllocationExpression[@AnonymousClass = false]
+ | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "PatternMatchingInstanceof", @ReferenceToClassSameCompilationUnit = true]
+ | +- Arguments[@ArgumentCount = 0, @Size = 0]
+ +- PrimarySuffix[@ArgumentCount = -1, @Arguments = false, @ArrayDereference = false, @Image = "test"]
+ +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false]
+ +- Arguments[@ArgumentCount = 0, @Size = 0]