iterator() {
+ return children(ASTClassOrInterfaceType.class).iterator();
+ }
+}
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 e34163411f..63b2da1d0f 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 a296ecb8ef..59f60996b5 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
@@ -11,7 +11,7 @@ import net.sourceforge.pmd.lang.java.symbols.JClassSymbol;
import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol;
/**
- * 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).
*
* The varargs ellipsis {@code "..."} is parsed as an {@linkplain ASTArrayTypeDim array dimension}
* in the type node.
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 82cf139908..06b0ed909d 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
@@ -11,7 +11,7 @@ import net.sourceforge.pmd.lang.java.ast.InternalInterfaces.AllChildrenAreOfType
import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol;
/**
- * 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 3bffa597f2..d8039119ea 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
@@ -10,7 +10,7 @@ import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol;
/**
* This defines a compact constructor for a {@link ASTRecordDeclaration RecordDeclaration}
- * (JDK 14 preview feature). Compact constructors implicitly declares formal
+ * (JDK 14 and JDK 15 preview feature). Compact constructors implicitly declares formal
* parameters corresponding to the record component list. These can be
* fetched from {@link #getSymbol()}.
*
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 71c421b23b..66f2eb700d 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.
*
*
@@ -27,7 +27,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 {
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java
index 33fb67dc53..57534f8674 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java
@@ -50,6 +50,11 @@ abstract class AbstractJavaNode extends AbstractJjtreeNode {
SWITCH_EXPRESSIONS(12, 13, true),
SWITCH_RULES(12, 13, true),
- TEXT_BLOCK_LITERALS(13, 14, false),
+ TEXT_BLOCK_LITERALS(13, 14, true),
YIELD_STATEMENTS(13, 13, true),
/** \s */
- SPACE_STRING_ESCAPES(14, 14, false),
- RECORD_DECLARATIONS(14, 14, false),
- TYPE_TEST_PATTERNS_IN_INSTANCEOF(14, 14, false);
+ SPACE_STRING_ESCAPES(14, 14, true),
+ RECORD_DECLARATIONS(14, 15, false),
+ TYPE_TEST_PATTERNS_IN_INSTANCEOF(14, 15, false),
+ SEALED_CLASSES(15, 15, false),
+
+ ; // SUPPRESS CHECKSTYLE enum trailing semi is awesome
private final int minPreviewVersion;
@@ -473,6 +478,12 @@ public class LanguageLevelChecker {
@Override
public Void visit(ASTAnyTypeDeclaration node, T data) {
+ if ((node.getModifiers() & (AccessNode.SEALED | AccessNode.NON_SEALED)) != 0) {
+ check(node, PreviewFeature.SEALED_CLASSES, data);
+ } else if (node.isLocal() && node.getTypeKind() != TypeKind.CLASS) {
+ check(node, PreviewFeature.SEALED_CLASSES, data);
+ }
+
String simpleName = node.getSimpleName();
if ("var".equals(simpleName)) {
check(node, ReservedIdentifiers.VAR_AS_A_TYPE_NAME, data);
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 fec0c374a4..0000000000
--- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java13Test.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
- */
-
-package net.sourceforge.pmd.lang.java.ast;
-
-import java.util.List;
-
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import net.sourceforge.pmd.lang.ast.ParseException;
-import net.sourceforge.pmd.lang.java.JavaParsingHelper;
-
-@Ignore("those tests depend on type resolution")
-public class Java13Test {
-
-
- private final JavaParsingHelper java12 =
- JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("12")
- .withResourceContext(getClass(), "jdkversiontests/java13/");
-
- private final JavaParsingHelper java13p = java12.withDefaultVersion("13-preview");
-
- @Test
- public void testTextBlocks() {
- ASTCompilationUnit compilationUnit = java13p.parseResource("TextBlocks.java");
- List literals = compilationUnit.findDescendantsOfType(ASTStringLiteral.class);
- Assert.assertEquals(10, literals.size());
- for (int i = 0; i < 8; i++) {
- ASTStringLiteral 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 dd08f3011c..4d171feed2 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
@@ -29,15 +29,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);
}
@@ -87,11 +84,6 @@ public class Java14Test {
@Test
public void checkYieldConditionalBehaviour() {
- checkYieldStatements(java13p);
- }
-
- @Test
- public void checkYieldConditionalBehaviourJ14() {
checkYieldStatements(java14);
}
@@ -142,7 +134,6 @@ public class Java14Test {
@Test
public void multipleCaseLabels() {
- multipleCaseLabels(java13p);
multipleCaseLabels(java14);
multipleCaseLabels(java14p);
}
@@ -158,7 +149,6 @@ public class Java14Test {
@Test
public void switchRules() {
- switchRules(java13p);
switchRules(java14);
switchRules(java14p);
}
@@ -186,7 +176,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 91f570b0d6..71c359541a 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
@@ -7,22 +7,24 @@ package net.sourceforge.pmd.lang.java.ast
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.shouldBe
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.except(J14__PREVIEW, 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("Type test patterns in instanceof is a preview feature of JDK")
}
}
-
}
- parserTest("Test simple patterns", javaVersion = J14__PREVIEW) {
+ parserTest("Test simple patterns", javaVersions = listOf(J14__PREVIEW, J15__PREVIEW)) {
importedTypes += IOException::class.java
inContext(ExpressionParsingCtx) {
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..6bc3facde9
--- /dev/null
+++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/Java15KotlinTest.kt
@@ -0,0 +1,44 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.java.ast
+
+import net.sourceforge.pmd.lang.ast.test.shouldBe
+
+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::getEscapedStringLiteral shouldBe
+ "\"\"\"\n" +
+ " \n" +
+ " \n" +
+ " Hello, world
\n" +
+ " \n" +
+ " \n" +
+ " \"\"\""
+ it::getTextBlockContent 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 43e53a893b..0c889e864b 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
@@ -28,8 +28,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()
@@ -55,9 +56,10 @@ enum class JavaVersion : Comparable {
val Latest = values().last()
val Earliest = values().first()
- fun except(vararg versions: JavaVersion) = values().toList() - versions
- fun except(versions: List) = values().toList() - versions
+ fun except(v1: JavaVersion, vararg versions: JavaVersion) =
+ values().toList() - v1 - versions
+ fun except(versions: List) = values().toList() - versions
}
}
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
+
+