iterator() {
+ return new NodeChildrenIterator<>(this, ASTClassOrInterfaceType.class);
+ }
+}
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordBody.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordBody.java
index 9e236d9a2f..0a7fa9fc06 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordBody.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordBody.java
@@ -8,7 +8,7 @@ package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.annotation.Experimental;
/**
- * Defines the body of a {@linkplain ASTRecordDeclaration RecordDeclaration} (JDK 14 preview feature).
+ * Defines the body of a {@linkplain ASTRecordDeclaration RecordDeclaration} (JDK 14 and JDK 15 preview feature).
* This can contain additional methods and or constructors.
*
*
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordComponent.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordComponent.java
index f314c33351..d3a4d8b2ad 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordComponent.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordComponent.java
@@ -8,7 +8,7 @@ package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.annotation.Experimental;
/**
- * Defines a single component of a {@linkplain ASTRecordDeclaration RecordDeclaration} (JDK 14 preview feature).
+ * Defines a single component of a {@linkplain ASTRecordDeclaration RecordDeclaration} (JDK 14 and JDK 15 preview feature).
*
*
*
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordComponentList.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordComponentList.java
index 460d24ee42..e3a4b5c3aa 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordComponentList.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordComponentList.java
@@ -10,7 +10,7 @@ import java.util.Iterator;
import net.sourceforge.pmd.annotation.Experimental;
/**
- * Defines the state description of a {@linkplain ASTRecordDeclaration RecordDeclaration} (JDK 14 preview feature).
+ * Defines the state description of a {@linkplain ASTRecordDeclaration RecordDeclaration} (JDK 14 and JDK 15 preview feature).
*
*
*
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordConstructorDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordConstructorDeclaration.java
index 755ee7508b..e36968d03b 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordConstructorDeclaration.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordConstructorDeclaration.java
@@ -8,7 +8,7 @@ package net.sourceforge.pmd.lang.java.ast;
import net.sourceforge.pmd.annotation.Experimental;
/**
- * This defines a compact constructor for a {@linkplain ASTRecordDeclaration RecordDeclaration} (JDK 14 preview feature).
+ * This defines a compact constructor for a {@linkplain ASTRecordDeclaration RecordDeclaration} (JDK 14 and JDK 15 preview feature).
*
*
*
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordDeclaration.java
index 74457295e4..d508938362 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordDeclaration.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTRecordDeclaration.java
@@ -12,7 +12,7 @@ import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.ast.NodeStream;
/**
- * A record declaration is a special data class type (JDK 14 preview feature).
+ * A record declaration is a special data class type (JDK 14 and JDK 15 preview feature).
* This is a {@linkplain Node#isFindBoundary() find boundary} for tree traversal methods.
*
*
@@ -26,7 +26,7 @@ import net.sourceforge.pmd.lang.ast.NodeStream;
*
*
*
- * @see JEP 359: Records (Preview)
+ * @see JEP 384: Records (Second Preview)
*/
@Experimental
public final class ASTRecordDeclaration extends AbstractAnyTypeDeclaration {
@@ -54,9 +54,20 @@ public final class ASTRecordDeclaration extends AbstractAnyTypeDeclaration {
return isNested();
}
- @NonNull
@Override
- public ASTRecordComponentList getRecordComponents() {
+ public boolean isFinal() {
+ // A record is implicitly final
+ return true;
+ }
+
+ @Override
+ public boolean isLocal() {
+ return getParent() instanceof ASTBlockStatement;
+ }
+
+
+ @Override
+ public @NonNull ASTRecordComponentList getRecordComponents() {
return getFirstChildOfType(ASTRecordComponentList.class);
}
}
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 a39a2d9fec..e401dc5dfe 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
@@ -197,6 +197,11 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim
return true;
}
+ if (getParent() instanceof ASTRecordComponent) {
+ // the field corresponding to this record component is declared final
+ return true;
+ }
+
if (getParent() instanceof ASTFormalParameter) {
// This accounts for exception parameters too for now
return ((ASTFormalParameter) getParent()).isFinal();
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AccessNode.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AccessNode.java
index 5186af4ae9..2deecf5d5c 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AccessNode.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AccessNode.java
@@ -23,6 +23,8 @@ public interface AccessNode extends JavaNode {
int VOLATILE = 0x0200;
int STRICTFP = 0x1000;
int DEFAULT = 0x2000;
+ int SEALED = 0x4000;
+ int NON_SEALED = 0x8000;
int getModifiers();
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java
index 3597ab88ca..e3fe30b2ac 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/visitors/PMDASMVisitor.java
@@ -40,7 +40,7 @@ public class PMDASMVisitor extends ClassVisitor {
public List innerClasses;
public PMDASMVisitor(String outerName) {
- super(Opcodes.ASM7);
+ super(Opcodes.ASM9);
this.outerName = outerName;
}
@@ -181,7 +181,7 @@ public class PMDASMVisitor extends ClassVisitor {
private PMDASMVisitor parent;
PMDFieldVisitor(PMDASMVisitor visitor) {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM9);
parent = visitor;
}
@@ -196,7 +196,7 @@ public class PMDASMVisitor extends ClassVisitor {
private PMDASMVisitor parent;
PMDAnnotationVisitor(PMDASMVisitor visitor) {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM9);
parent = visitor;
}
@@ -228,7 +228,7 @@ public class PMDASMVisitor extends ClassVisitor {
private PMDASMVisitor parent;
PMDSignatureVisitor(PMDASMVisitor visitor) {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM9);
this.parent = visitor;
}
@@ -292,7 +292,7 @@ public class PMDASMVisitor extends ClassVisitor {
private PMDASMVisitor parent;
PMDMethodVisitor(PMDASMVisitor visitor) {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM9);
parent = visitor;
}
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java
index 98c660c09e..1961e37dfd 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java
@@ -26,8 +26,8 @@ public class LanguageVersionDiscovererTest {
File javaFile = new File("/path/to/MyClass.java");
LanguageVersion languageVersion = discoverer.getDefaultLanguageVersionForFile(javaFile);
- assertEquals("LanguageVersion must be Java 14 !",
- LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("14"), languageVersion);
+ assertEquals("LanguageVersion must be Java 15 !",
+ LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("15"), languageVersion);
}
/**
@@ -48,7 +48,7 @@ public class LanguageVersionDiscovererTest {
public void testLanguageVersionDiscoverer() {
PMDConfiguration configuration = new PMDConfiguration();
LanguageVersionDiscoverer languageVersionDiscoverer = configuration.getLanguageVersionDiscoverer();
- assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("14"),
+ assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("15"),
languageVersionDiscoverer
.getDefaultLanguageVersion(LanguageRegistry.getLanguage(JavaLanguageModule.NAME)));
configuration
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java
index e8a2bb5506..9197fe2f7c 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionTest.java
@@ -52,6 +52,10 @@ public class LanguageVersionTest extends AbstractLanguageVersionTest {
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("14"), },
{ JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "14-preview",
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("14-preview"), },
+ { JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "15",
+ LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("15"), },
+ { JavaLanguageModule.NAME, JavaLanguageModule.TERSE_NAME, "15-preview",
+ LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("15-preview"), },
// this one won't be found: case sensitive!
{ "JAVA", "JAVA", "1.7", null, },
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java13Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java13Test.java
deleted file mode 100644
index 781b0281db..0000000000
--- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java13Test.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.java.JavaParsingHelper;
-
-public class Java13Test {
-
-
- private final JavaParsingHelper java12 =
- JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("12")
- .withResourceContext(Java13Test.class, "jdkversiontests/java13/");
-
- private final JavaParsingHelper java13p = java12.withDefaultVersion("13-preview");
-
-
- @Test
- public void testSwitchExpressions() {
- ASTCompilationUnit compilationUnit = java13p.parseResource("SwitchExpressions.java");
-
- ASTSwitchExpression switchExpression = compilationUnit.getFirstDescendantOfType(ASTSwitchExpression.class);
- Assert.assertEquals(4, switchExpression.getNumChildren());
- Assert.assertTrue(switchExpression.getChild(0) instanceof ASTExpression);
- Assert.assertEquals(3, switchExpression.findChildrenOfType(ASTSwitchLabeledRule.class).size());
- Assert.assertEquals(1, switchExpression.findChildrenOfType(ASTSwitchLabeledBlock.class).size());
- Assert.assertEquals(1, switchExpression.findDescendantsOfType(ASTYieldStatement.class).size());
- ASTYieldStatement yieldStatement = switchExpression.getFirstDescendantOfType(ASTYieldStatement.class);
- Assert.assertEquals(Integer.TYPE, yieldStatement.getType());
- }
-
- @Test
- public void testSwitchExpressionsYield() {
- ASTCompilationUnit compilationUnit = java13p.parseResource("SwitchExpressionsYield.java");
-
- ASTSwitchExpression switchExpression = compilationUnit.getFirstDescendantOfType(ASTSwitchExpression.class);
- Assert.assertEquals(11, switchExpression.getNumChildren());
- Assert.assertTrue(switchExpression.getChild(0) instanceof ASTExpression);
- Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabel.class).size());
-
- ASTYieldStatement yieldStatement = switchExpression.getFirstDescendantOfType(ASTYieldStatement.class);
- Assert.assertEquals("SwitchExpressionsBreak.SIX", yieldStatement.getImage());
- Assert.assertTrue(yieldStatement.getChild(0) instanceof ASTExpression);
-
- ASTLocalVariableDeclaration localVar = compilationUnit.findDescendantsOfType(ASTLocalVariableDeclaration.class)
- .get(1);
- ASTVariableDeclarator localVarDecl = localVar.getFirstChildOfType(ASTVariableDeclarator.class);
- Assert.assertEquals(Integer.TYPE, localVarDecl.getType());
- Assert.assertEquals(Integer.TYPE, switchExpression.getType());
- }
-
-
- @Test(expected = ParseException.class)
- public void testSwitchExpressionsBeforeJava13() {
- java12.parseResource("SwitchExpressions.java");
- }
-
- @Test
- public void testTextBlocks() {
- ASTCompilationUnit compilationUnit = java13p.parseResource("TextBlocks.java");
- List literals = compilationUnit.findDescendantsOfType(ASTLiteral.class);
- Assert.assertEquals(10, literals.size());
- for (int i = 0; i < 8; i++) {
- ASTLiteral literal = literals.get(i);
- Assert.assertTrue(literal.isTextBlock());
- }
- Assert.assertEquals("\"\"\"\n"
- + " \n"
- + " \n"
- + " Hello, world
\n"
- + " \n"
- + " \n"
- + " \"\"\"",
- literals.get(0).getImage());
- Assert.assertFalse(literals.get(8).isTextBlock());
- Assert.assertTrue(literals.get(9).isTextBlock());
- }
-
- @Test(expected = ParseException.class)
- public void testTextBlocksBeforeJava13() {
- java12.parseResource("TextBlocks.java");
- }
-
-}
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14Test.java
index f48295bb54..32925c4249 100644
--- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14Test.java
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14Test.java
@@ -27,15 +27,12 @@ public class Java14Test {
private final JavaParsingHelper java14p = java14.withDefaultVersion("14-preview");
private final JavaParsingHelper java13 = java14.withDefaultVersion("13");
- private final JavaParsingHelper java13p = java14.withDefaultVersion("13-preview");
/**
* Tests switch expressions with yield.
- * The switch expressions have no changed between java 13-preview and 14, so behave exactly the same.
*/
@Test
public void switchExpressions() {
- parseAndCheckSwitchExpression(java13p);
parseAndCheckSwitchExpression(java14);
parseAndCheckSwitchExpression(java14p);
}
@@ -85,11 +82,6 @@ public class Java14Test {
@Test
public void checkYieldConditionalBehaviour() {
- checkYieldStatements(java13p);
- }
-
- @Test
- public void checkYieldConditionalBehaviourJ14() {
checkYieldStatements(java14);
}
@@ -140,7 +132,6 @@ public class Java14Test {
@Test
public void multipleCaseLabels() {
- multipleCaseLabels(java13p);
multipleCaseLabels(java14);
multipleCaseLabels(java14p);
}
@@ -156,7 +147,6 @@ public class Java14Test {
@Test
public void switchRules() {
- switchRules(java13p);
switchRules(java14);
switchRules(java14p);
}
@@ -184,7 +174,6 @@ public class Java14Test {
@Test
public void simpleSwitchExpressions() {
- simpleSwitchExpressions(java13p);
simpleSwitchExpressions(java14);
simpleSwitchExpressions(java14p);
}
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15PreviewTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15PreviewTreeDumpTest.java
new file mode 100644
index 0000000000..739aedf86e
--- /dev/null
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15PreviewTreeDumpTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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 Java15PreviewTreeDumpTest extends BaseTreeDumpTest {
+ private final JavaParsingHelper java15p =
+ JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("15-preview")
+ .withResourceContext(Java15PreviewTreeDumpTest.class, "jdkversiontests/java15p/");
+ private final JavaParsingHelper java15 = java15p.withDefaultVersion("15");
+
+ public Java15PreviewTreeDumpTest() {
+ super(new RelevantAttributePrinter(), ".java");
+ }
+
+ @Override
+ public BaseParsingHelper, ?> getParser() {
+ return java15p;
+ }
+
+ @Test
+ public void patternMatchingInstanceof() {
+ doTest("PatternMatchingInstanceof");
+
+ // extended tests for type resolution etc.
+ ASTCompilationUnit compilationUnit = java15p.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 patternMatchingInstanceofBeforeJava15PreviewShouldFail() {
+ java15.parseResource("PatternMatchingInstanceof.java");
+ }
+
+ @Test
+ public void recordPoint() {
+ doTest("Point");
+
+ // extended tests for type resolution etc.
+ ASTCompilationUnit compilationUnit = java15p.parseResource("Point.java");
+ ASTRecordDeclaration recordDecl = compilationUnit.getFirstDescendantOfType(ASTRecordDeclaration.class);
+ List components = recordDecl.getFirstChildOfType(ASTRecordComponentList.class)
+ .findChildrenOfType(ASTRecordComponent.class);
+ Assert.assertNull(components.get(0).getVarId().getNameDeclaration().getAccessNodeParent());
+ Assert.assertEquals(Integer.TYPE, components.get(0).getVarId().getNameDeclaration().getType());
+ Assert.assertEquals("int", components.get(0).getVarId().getNameDeclaration().getTypeImage());
+ }
+
+ @Test(expected = ParseException.class)
+ public void recordPointBeforeJava15PreviewShouldFail() {
+ java15.parseResource("Point.java");
+ }
+
+ @Test(expected = ParseException.class)
+ public void recordCtorWithThrowsShouldFail() {
+ java15p.parse(" record R {"
+ + " R throws IOException {}"
+ + " }");
+ }
+
+ @Test(expected = ParseException.class)
+ public void recordMustNotExtend() {
+ java15p.parse("record RecordEx(int x) extends Number { }");
+ }
+
+ @Test
+ public void innerRecords() {
+ doTest("Records");
+ }
+
+ @Test(expected = ParseException.class)
+ public void recordIsARestrictedIdentifier() {
+ java15p.parse("public class record {}");
+ }
+
+ @Test
+ public void localRecords() {
+ doTest("LocalRecords");
+ }
+
+ @Test(expected = ParseException.class)
+ public void sealedClassBeforeJava15Preview() {
+ java15.parseResource("geometry/Shape.java");
+ }
+
+ @Test
+ public void sealedClass() {
+ doTest("geometry/Shape");
+ }
+
+ @Test
+ public void nonSealedClass() {
+ doTest("geometry/Square");
+ }
+
+ @Test(expected = ParseException.class)
+ public void sealedInterfaceBeforeJava15Preview() {
+ java15.parseResource("expression/Expr.java");
+ }
+
+ @Test
+ public void sealedInterface() {
+ doTest("expression/Expr");
+ }
+
+ @Test
+ public void localInterfaceAndEnums() {
+ doTest("LocalInterfacesAndEnums");
+ }
+
+ @Test(expected = ParseException.class)
+ public void localInterfacesAndEnumsBeforeJava15PreviewShouldFail() {
+ java15.parseResource("LocalInterfacesAndEnums.java");
+ }
+}
diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15TreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15TreeDumpTest.java
new file mode 100644
index 0000000000..bed127076d
--- /dev/null
+++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15TreeDumpTest.java
@@ -0,0 +1,52 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.java.ast;
+
+import org.junit.Test;
+
+import net.sourceforge.pmd.lang.ast.ParseException;
+import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper;
+import net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest;
+import net.sourceforge.pmd.lang.ast.test.RelevantAttributePrinter;
+import net.sourceforge.pmd.lang.java.JavaParsingHelper;
+
+public class Java15TreeDumpTest extends BaseTreeDumpTest {
+ private final JavaParsingHelper java15 =
+ JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("15")
+ .withResourceContext(Java15TreeDumpTest.class, "jdkversiontests/java15/");
+ private final JavaParsingHelper java15p = java15.withDefaultVersion("15-preview");
+ private final JavaParsingHelper java14 = java15.withDefaultVersion("14");
+
+ public Java15TreeDumpTest() {
+ super(new RelevantAttributePrinter(), ".java");
+ }
+
+ @Override
+ public BaseParsingHelper, ?> getParser() {
+ return java15;
+ }
+
+ @Test
+ public void textBlocks() {
+ doTest("TextBlocks");
+ java15p.parseResource("TextBlocks.java"); // make sure we can parse it with preview as well
+ }
+
+ @Test(expected = net.sourceforge.pmd.lang.ast.ParseException.class)
+ public void textBlocksBeforeJava15ShouldFail() {
+ java14.parseResource("TextBlocks.java");
+ }
+
+ @Test(expected = ParseException.class)
+ public void stringEscapeSequenceShouldFail() {
+ java14.parse("class Foo { String s =\"a\\sb\"; }");
+ }
+
+ @Test
+ public void sealedAndNonSealedIdentifiers() {
+ doTest("NonSealedIdentifier");
+ java15p.parseResource("NonSealedIdentifier.java"); // make sure we can parse it with preview as well
+ }
+}
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 892e8501bd..803dbf4d02 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
@@ -6,22 +6,24 @@ package net.sourceforge.pmd.lang.java.ast
import io.kotest.matchers.string.shouldContain
import net.sourceforge.pmd.lang.ast.test.shouldBe
+import net.sourceforge.pmd.lang.java.ast.JavaVersion
import net.sourceforge.pmd.lang.java.ast.JavaVersion.J14__PREVIEW
+import net.sourceforge.pmd.lang.java.ast.JavaVersion.J15__PREVIEW
import java.io.IOException
class ASTPatternTest : ParserTestSpec({
- parserTest("Test patterns only available on JDK 14 (preview)", javaVersions = !J14__PREVIEW) {
+ parserTest("Test patterns only available on JDK 14+15 (preview)", javaVersions = JavaVersion.values().asList().minus(J14__PREVIEW).minus(J15__PREVIEW)) {
+
inContext(ExpressionParsingCtx) {
"obj instanceof Class c" should throwParseException {
- it.message.shouldContain("Type test patterns in instanceof is a preview feature of JDK 14, you should select your language version accordingly")
+ it.message.shouldContain("Pattern Matching for instanceof is only supported with Java 14 Preview and Java 15 Preview")
}
}
-
}
- parserTest("Test simple patterns", javaVersion = J14__PREVIEW) {
+ parserTest("Test simple patterns", javaVersions = listOf(J14__PREVIEW, J15__PREVIEW)) {
importedTypes += IOException::class.java
diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/Java15KotlinTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/Java15KotlinTest.kt
new file mode 100644
index 0000000000..ea3a79771e
--- /dev/null
+++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/Java15KotlinTest.kt
@@ -0,0 +1,45 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.java.ast
+
+import io.kotest.matchers.shouldBe
+import net.sourceforge.pmd.lang.ast.test.matchNode
+
+class Java15KotlinTest: ParserTestSpec( {
+
+ // Note: More tests are in ASTLiteralTest.
+ parserTest("textBlocks", javaVersions = JavaVersion.J15..JavaVersion.Latest) {
+ ("\"\"\"\n" +
+ " \n" +
+ " \n" +
+ " Hello, world
\n" +
+ " \n" +
+ " \n" +
+ " \"\"\"") should matchExpr {
+ child {
+ child {
+ child {
+ it.isTextBlock shouldBe true
+ it.escapedStringLiteral shouldBe
+ "\"\"\"\n" +
+ " \n" +
+ " \n" +
+ " Hello, world
\n" +
+ " \n" +
+ " \n" +
+ " \"\"\""
+ it.textBlockContent shouldBe
+ "\n" +
+ " \n" +
+ " Hello, world
\n" +
+ " \n" +
+ "\n"
+ }
+ }
+ }
+ }
+ }
+
+})
diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt
index df3fa2af9d..8483594d66 100644
--- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt
+++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt
@@ -23,8 +23,9 @@ import java.beans.PropertyDescriptor
enum class JavaVersion : Comparable {
J1_3, J1_4, J1_5, J1_6, J1_7, J1_8, J9, J10, J11,
J12,
- J13, J13__PREVIEW,
- J14, J14__PREVIEW;
+ J13,
+ J14, J14__PREVIEW,
+ J15, J15__PREVIEW;
/** Name suitable for use with e.g. [JavaParsingHelper.parse] */
val pmdName: String = name.removePrefix("J").replaceFirst("__", "-").replace('_', '.').toLowerCase()
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java13/SwitchExpressions.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java13/SwitchExpressions.java
deleted file mode 100644
index 04379b4dd6..0000000000
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java13/SwitchExpressions.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- *
- *
- * @see JEP 354: Switch Expressions (Preview)
- */
-public class SwitchExpressions {
- private enum Day {
- MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
- }
-
- public static void main(String[] args) {
- Day day = Day.FRIDAY;
-
- int j = switch (day) {
- case MONDAY -> 0;
- case TUESDAY -> 1;
- default -> {
- int k = day.toString().length();
- int result = f(k);
- yield result;
- }
- };
- System.out.printf("j = %d%n", j);
-
- String s = "Bar";
- int result = switch (s) {
- case "Foo":
- yield 1;
- case "Bar":
- yield 2;
- default:
- System.out.println("Neither Foo nor Bar, hmmm...");
- yield 0;
- };
- System.out.printf("result = %d%n", result);
- }
-
- private static int f(int k) {
- return k+1;
- }
-}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java13/SwitchExpressionsYield.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java13/SwitchExpressionsYield.java
deleted file mode 100644
index a00183c805..0000000000
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java13/SwitchExpressionsYield.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- *
- * @see JEP 325: Switch Expressions (Preview)
- */
-public class SwitchExpressionsYield {
- private static final int MONDAY = 1;
- private static final int TUESDAY = 2;
- private static final int WEDNESDAY = 3;
- private static final int THURSDAY = 4;
- private static final int FRIDAY = 5;
- private static final int SATURDAY = 6;
- private static final int SUNDAY = 7;
-
- private static final int SIX = 6;
-
- public static void main(String[] args) {
- int day = FRIDAY;
-
- var numLetters = switch (day) {
- case MONDAY, FRIDAY, SUNDAY: yield SwitchExpressionsBreak.SIX;
- case TUESDAY : yield 7;
- case THURSDAY, SATURDAY : yield 8;
- case WEDNESDAY : yield 9;
- default : {
- int k = day * 2;
- int result = f(k);
- yield result;
- }
- };
- System.out.printf("NumLetters: %d%n", numLetters);
- }
-
- private static int f(int k) {
- return k*3;
- }
-}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java13/TextBlocks.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java13/TextBlocks.java
deleted file mode 100644
index 78a6d111c3..0000000000
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java13/TextBlocks.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * @see JEP 355: Text Blocks (Preview)
- */
-public class TextBlocks {
-
- public static void main(String[] args) {
- String html = """
-
-
- Hello, world
-
-
- """;
-
- System.out.println(html);
-
- String season = """
- winter"""; // the six characters w i n t e r
-
- String period = """
- winter
- """; // the seven characters w i n t e r LF
-
- String greeting =
- """
- Hi, "Bob"
- """; // the ten characters H i , SP " B o b " LF
-
- String salutation =
- """
- Hi,
- "Bob"
- """; // the eleven characters H i , LF SP " B o b " LF
-
- String empty = """
- """; // the empty string (zero length)
-
- String quote = """
- "
- """; // the two characters " LF
-
- String backslash = """
- \\
- """; // the two characters \ LF
-
- String normalStringLiteral = "test";
-
- String code =
- """
- String text = \"""
- A text block inside a text block
- \""";
- """;
- }
-}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.java
new file mode 100644
index 0000000000..dbeebe9403
--- /dev/null
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.java
@@ -0,0 +1,15 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+public class NonSealedIdentifier {
+ public static void main(String[] args) {
+ int result = 0;
+ int non = 1;
+ // sealed is a valid identifier name in both Java15 and Java15 Preview
+ int sealed = 2;
+ // non-sealed is a valid subtraction expression in both Java15 and Java15 Preview
+ result = non-sealed;
+ System.out.println(result);
+ }
+}
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.txt
new file mode 100644
index 0000000000..bcd2128440
--- /dev/null
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/NonSealedIdentifier.txt
@@ -0,0 +1,76 @@
++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true]
+ +- TypeDeclaration[]
+ +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "NonSealedIdentifier", @Default = false, @Final = false, @Image = "NonSealedIdentifier", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "NonSealedIdentifier", @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, @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 = "result", @Volatile = false]
+ | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"]
+ | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"]
+ | +- VariableDeclarator[@Initializer = true, @Name = "result"]
+ | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @FormalParameter = false, @Image = "result", @LambdaParameter = false, @LocalVariable = true, @Name = "result", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "result"]
+ | +- VariableInitializer[]
+ | +- Expression[@StandAlonePrimitive = true]
+ | +- PrimaryExpression[]
+ | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "0", @FloatLiteral = false, @Image = "0", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "0", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0]
+ +- 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 = "non", @Volatile = false]
+ | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"]
+ | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"]
+ | +- VariableDeclarator[@Initializer = true, @Name = "non"]
+ | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @FormalParameter = false, @Image = "non", @LambdaParameter = false, @LocalVariable = true, @Name = "non", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "non"]
+ | +- VariableInitializer[]
+ | +- Expression[@StandAlonePrimitive = true]
+ | +- PrimaryExpression[]
+ | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "1", @FloatLiteral = false, @Image = "1", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "1", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 1, @ValueAsLong = 1]
+ +- BlockStatement[@Allocation = false]
+ | +- 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 = "sealed", @Volatile = false]
+ | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"]
+ | | +- PrimitiveType[@Array = false, @ArrayDepth = 0, @Boolean = false, @Image = "int"]
+ | +- VariableDeclarator[@Initializer = true, @Name = "sealed"]
+ | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @FormalParameter = false, @Image = "sealed", @LambdaParameter = false, @LocalVariable = true, @Name = "sealed", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "sealed"]
+ | +- VariableInitializer[]
+ | +- Expression[@StandAlonePrimitive = true]
+ | +- PrimaryExpression[]
+ | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = "2", @FloatLiteral = false, @Image = "2", @IntLiteral = true, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = "2", @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 2, @ValueAsLong = 2]
+ +- BlockStatement[@Allocation = false]
+ | +- Statement[]
+ | +- StatementExpression[]
+ | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "result"]
+ | +- AssignmentOperator[@Compound = false, @Image = "="]
+ | +- Expression[@StandAlonePrimitive = false]
+ | +- AdditiveExpression[@Image = "-", @Operator = "-"]
+ | +- PrimaryExpression[]
+ | | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | | +- Name[@Image = "non"]
+ | +- PrimaryExpression[]
+ | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
+ | +- Name[@Image = "sealed"]
+ +- 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 = "result"]
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.java
new file mode 100644
index 0000000000..0876748bb0
--- /dev/null
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.java
@@ -0,0 +1,119 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+/**
+ * Text Blocks are a permanent language feature with JDK 15.
+ *
+ * @see
+
+ Hello, world
+
+