[java] Add new language versions 20 and 20-preview
This commit is contained in:
@ -9,8 +9,10 @@ Usually the latest non-preview Java Version is the default version.
|
||||
|
||||
| Java Version | Alias | Supported by PMD since |
|
||||
|--------------|-------|------------------------|
|
||||
| 20-preview | | 6.55.0 |
|
||||
| 20 (default) | | 6.55.0 |
|
||||
| 19-preview | | 6.48.0 |
|
||||
| 19 (default) | | 6.48.0 |
|
||||
| 19 | | 6.48.0 |
|
||||
| 18-preview | | 6.44.0 |
|
||||
| 18 | | 6.44.0 |
|
||||
| 17 | | 6.37.0 |
|
||||
@ -32,13 +34,14 @@ Usually the latest non-preview Java Version is the default version.
|
||||
## 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. `19-preview`:
|
||||
it via the environment variable `PMD_JAVA_OPTS` and select the new language version, e.g. `20-preview`:
|
||||
|
||||
export PMD_JAVA_OPTS=--enable-preview
|
||||
./run.sh pmd --use-version java-19-preview ...
|
||||
./run.sh pmd --use-version java-20-preview ...
|
||||
|
||||
Note: we only support preview language features for the latest two java versions.
|
||||
|
||||
Note: `--use-version` is only supported since PMD 6.52.0. Older versions of PMD use two CLI options that have to be specified together: `-language java -version 19-preview`.
|
||||
Note: `--use-version` is only supported since PMD 6.52.0. Older versions of PMD use two CLI options that have to
|
||||
be specified together: `-language java -version 20-preview`.
|
||||
|
||||
|
||||
|
@ -248,8 +248,10 @@ nested element. Possible values are:
|
||||
<sourceLanguage name="java" version="17"/>
|
||||
<sourceLanguage name="java" version="18"/>
|
||||
<sourceLanguage name="java" version="18-preview"/>
|
||||
<sourceLanguage name="java" version="19"/> <!-- this is the default -->
|
||||
<sourceLanguage name="java" version="19"/>
|
||||
<sourceLanguage name="java" version="19-preview"/>
|
||||
<sourceLanguage name="java" version="20"/> <!-- this is the default -->
|
||||
<sourceLanguage name="java" version="20-preview"/>
|
||||
<sourceLanguage name="jsp" version=""/>
|
||||
<sourceLanguage name="modelica" version=""/>
|
||||
<sourceLanguage name="pom" version=""/>
|
||||
|
@ -542,24 +542,24 @@ public class JavaParser {
|
||||
}
|
||||
|
||||
private boolean isJEP406Supported() {
|
||||
return (jdkVersion == 18 || jdkVersion == 19) && preview;
|
||||
return (jdkVersion == 18 || jdkVersion == 19 || jdkVersion == 20) && preview;
|
||||
}
|
||||
|
||||
private void checkForPatternMatchingInSwitch() {
|
||||
if (!isJEP406Supported()) {
|
||||
throwParseException("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview.");
|
||||
throwParseException("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForNullCaseLabel() {
|
||||
if (!isJEP406Supported()) {
|
||||
throwParseException("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview.");
|
||||
throwParseException("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForDefaultCaseLabel() {
|
||||
if (!isJEP406Supported()) {
|
||||
throwParseException("Default case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview.");
|
||||
throwParseException("Default case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -576,14 +576,14 @@ public class JavaParser {
|
||||
}
|
||||
|
||||
private void checkForGuard() {
|
||||
if (!((jdkVersion == 19) && preview)) {
|
||||
throwParseException("Guards are only supported with JDK 19 Preview.");
|
||||
if (!((jdkVersion == 19 || jdkVersion == 20) && preview)) {
|
||||
throwParseException("Guards are only supported with JDK 19 Preview or JDK 20 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForRecordPatterns() {
|
||||
if (!((jdkVersion == 19) && preview)) {
|
||||
throwParseException("Record Patterns are only supported with JDK 19 Preview.");
|
||||
if (!((jdkVersion == 19 || jdkVersion == 20) && preview)) {
|
||||
throwParseException("Record Patterns are only supported with JDK 19 Preview or JDK 20 Preview.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,10 @@ public class JavaLanguageModule extends BaseLanguageModule {
|
||||
addVersion("17", new JavaLanguageHandler(17));
|
||||
addVersion("18", new JavaLanguageHandler(18));
|
||||
addVersion("18-preview", new JavaLanguageHandler(18, true));
|
||||
addDefaultVersion("19", new JavaLanguageHandler(19)); // 19 is the default
|
||||
addVersion("19", new JavaLanguageHandler(19));
|
||||
addVersion("19-preview", new JavaLanguageHandler(19, true));
|
||||
addDefaultVersion("20", new JavaLanguageHandler(20)); // 20 is the default
|
||||
addVersion("20-preview", new JavaLanguageHandler(20, true));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
}
|
||||
});
|
||||
Assert.assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
thrown.getMessage().contains("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -82,7 +82,7 @@ public class Java18PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
}
|
||||
});
|
||||
Assert.assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -40,7 +40,7 @@ public class Java19PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
thrown.getMessage().contains("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -67,7 +67,7 @@ public class Java19PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -84,7 +84,7 @@ public class Java19PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview."));
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -116,6 +116,6 @@ public class Java19PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Record Patterns are only supported with JDK 19 Preview."));
|
||||
thrown.getMessage().contains("Record Patterns are only supported with JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
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 Java20PreviewTreeDumpTest extends BaseTreeDumpTest {
|
||||
private final JavaParsingHelper java20p =
|
||||
JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("20-preview")
|
||||
.withResourceContext(Java20PreviewTreeDumpTest.class, "jdkversiontests/java20p/");
|
||||
private final JavaParsingHelper java20 = java20p.withDefaultVersion("19");
|
||||
|
||||
public Java20PreviewTreeDumpTest() {
|
||||
super(new RelevantAttributePrinter(), ".java");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseParsingHelper<?, ?> getParser() {
|
||||
return java20p;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dealingWithNullBeforeJava20Preview() {
|
||||
ParseException thrown = assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java20.parseResource("DealingWithNull.java");
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Null case labels in switch are only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dealingWithNull() {
|
||||
doTest("DealingWithNull");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enhancedTypeCheckingSwitch() {
|
||||
doTest("EnhancedTypeCheckingSwitch");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exhaustiveSwitch() {
|
||||
doTest("ExhaustiveSwitch");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guardedAndParenthesizedPatternsBeforeJava19Preview() {
|
||||
ParseException thrown = assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java20.parseResource("GuardedAndParenthesizedPatterns.java");
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void guardedAndParenthesizedPatterns() {
|
||||
doTest("GuardedAndParenthesizedPatterns");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patternsInSwitchLabelsBeforeJava19Preview() {
|
||||
ParseException thrown = assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java20.parseResource("PatternsInSwitchLabels.java");
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Pattern Matching in Switch is only supported with JDK 18 Preview or JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patternsInSwitchLabels() {
|
||||
doTest("PatternsInSwitchLabels");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refiningPatternsInSwitch() {
|
||||
doTest("RefiningPatternsInSwitch");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scopeOfPatternVariableDeclarations() {
|
||||
doTest("ScopeOfPatternVariableDeclarations");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recordPatterns() {
|
||||
doTest("RecordPatterns");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recordPatternsBeforeJava19Preview() {
|
||||
ParseException thrown = assertThrows(ParseException.class, new ThrowingRunnable() {
|
||||
@Override
|
||||
public void run() throws Throwable {
|
||||
java20.parseResource("RecordPatterns.java");
|
||||
}
|
||||
});
|
||||
assertTrue("Unexpected message: " + thrown.getMessage(),
|
||||
thrown.getMessage().contains("Record Patterns are only supported with JDK 19 Preview or JDK 20 Preview."));
|
||||
}
|
||||
}
|
@ -27,7 +27,8 @@ enum class JavaVersion : Comparable<JavaVersion> {
|
||||
J16,
|
||||
J17,
|
||||
J18, J18__PREVIEW,
|
||||
J19, J19__PREVIEW;
|
||||
J19, J19__PREVIEW,
|
||||
J20, J20__PREVIEW;
|
||||
|
||||
/** Name suitable for use with e.g. [JavaParsingHelper.parse] */
|
||||
val pmdName: String = name.removePrefix("J").replaceFirst("__", "-").replace('_', '.').lowercase()
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
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");
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
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; }
|
@ -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"]
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
public class ExhaustiveSwitch {
|
||||
|
||||
static int coverage(Object o) {
|
||||
return switch (o) {
|
||||
case String s -> s.length();
|
||||
case Integer i -> i;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
static int coverageDefaultCase(Object o) {
|
||||
return switch (o) {
|
||||
case String s -> s.length();
|
||||
case Integer i -> i;
|
||||
case 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<T> permits E, F {}
|
||||
final static class E<X> implements I<String> {}
|
||||
final static class F<Y> implements I<Y> {}
|
||||
|
||||
static int testGenericSealedExhaustive(I<Integer> i) {
|
||||
return switch (i) {
|
||||
// Exhaustive as no E case possible!
|
||||
case F<Integer> 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<Integer>()));
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
public class GuardedAndParenthesizedPatterns {
|
||||
|
||||
|
||||
static void test(Object o) {
|
||||
switch (o) {
|
||||
case String s when s.length() == 1 -> System.out.println("single char string");
|
||||
case String s -> System.out.println("string");
|
||||
case Integer i when i.intValue() == 1 -> System.out.println("integer 1");
|
||||
case (Long l) when 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");
|
||||
}
|
||||
}
|
||||
|
||||
// verify that "when" can still be used as an identifier
|
||||
void testIdentifierWhen(String when) {
|
||||
System.out.println(when);
|
||||
}
|
||||
|
||||
// verify that "when" can still be used as an identifier
|
||||
void testIdentifierWhen() {
|
||||
int when = 1;
|
||||
System.out.println(when);
|
||||
}
|
||||
|
||||
// verify that "when" can still be used as a type name
|
||||
private static class when {}
|
||||
|
||||
static void testWithNull(Object o) {
|
||||
switch (o) {
|
||||
case String s when (s.length() == 1) -> System.out.println("single char string");
|
||||
case String s -> System.out.println("string");
|
||||
case (Integer i) when i.intValue() == 1 -> System.out.println("integer 1");
|
||||
case ((Long l)) when ((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");
|
||||
}
|
||||
|
||||
// note: with this 3rd preview, the following is not allowed anymore:
|
||||
// if (o instanceof (String s && s.length() > 4)) {
|
||||
// > An alternative to guarded pattern labels is to support guarded patterns directly as a special pattern form,
|
||||
// > e.g. p && e. Having experimented with this in previous previews, the resulting ambiguity with boolean
|
||||
// > expressions have lead us to prefer when clauses in pattern switches.
|
||||
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);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
@ -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"]
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.org/jeps/405">JEP 405: Record Patterns (Preview)</a>
|
||||
*/
|
||||
public class RecordPatterns {
|
||||
|
||||
record Point(int x, int y) {}
|
||||
enum Color { RED, GREEN, BLUE }
|
||||
record ColoredPoint(Point p, Color c) {}
|
||||
record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}
|
||||
|
||||
void printSum1(Object o) {
|
||||
if (o instanceof Point p) {
|
||||
int x = p.x();
|
||||
int y = p.y();
|
||||
System.out.println(x+y);
|
||||
}
|
||||
}
|
||||
|
||||
// record pattern
|
||||
void printSum2(Object o) {
|
||||
if (o instanceof Point(int x, int y)) {
|
||||
System.out.println(x+y);
|
||||
}
|
||||
}
|
||||
|
||||
void printUpperLeftColoredPoint(Rectangle r) {
|
||||
if (r instanceof Rectangle(ColoredPoint ul, ColoredPoint lr)) {
|
||||
System.out.println(ul.c());
|
||||
}
|
||||
}
|
||||
|
||||
// nested record pattern
|
||||
void printColorOfUpperLeftPoint(Rectangle r) {
|
||||
if (r instanceof Rectangle(ColoredPoint(Point p, Color c),
|
||||
ColoredPoint lr)) {
|
||||
System.out.println(c);
|
||||
}
|
||||
}
|
||||
|
||||
// fully nested record pattern, also using "var"
|
||||
void printXCoordOfUpperLeftPointWithPatterns(Rectangle r) {
|
||||
if (r instanceof Rectangle(ColoredPoint(Point(var x, var y), var c),
|
||||
var lr)) {
|
||||
System.out.println("Upper-left corner: " + x);
|
||||
}
|
||||
}
|
||||
|
||||
// record patterns with generic types
|
||||
record Box<T>(T t) {}
|
||||
void test1(Box<Object> bo) {
|
||||
if (bo instanceof Box<Object>(String s)) {
|
||||
System.out.println("String " + s);
|
||||
}
|
||||
}
|
||||
void test2(Box<String> bo) {
|
||||
if (bo instanceof Box<String>(var s)) {
|
||||
System.out.println("String " + s);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
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 when 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 when 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);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see <a href="https://openjdk.org/jeps/427">JEP 427: Pattern Matching for switch (Third Preview)</a>
|
||||
*/
|
||||
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');
|
||||
}
|
||||
}
|
@ -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 = "\'\\t\'", @FloatLiteral = false, @Image = "\'\\t\'", @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "\'\\t\'", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
|
Reference in New Issue
Block a user