From 6e4daadc434974294e71eb7cec7f54c919168fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 8 Feb 2020 20:22:59 +0100 Subject: [PATCH 1/4] Add java version 14 --- .../java/net/sourceforge/pmd/lang/BaseLanguageModule.java | 2 ++ .../net/sourceforge/pmd/lang/java/JavaLanguageModule.java | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/BaseLanguageModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/BaseLanguageModule.java index 696fcbe974..05cfba2c9f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/BaseLanguageModule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/BaseLanguageModule.java @@ -51,6 +51,8 @@ public abstract class BaseLanguageModule implements Language { } if (isDefault) { + assert defaultVersion == null + : "Default version already set to " + defaultVersion + ", cannot set it to " + languageVersion; defaultVersion = languageVersion; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java index a8052f8f32..c92acd6ea0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java @@ -28,8 +28,10 @@ public class JavaLanguageModule extends BaseLanguageModule { addVersion("11", new JavaLanguageHandler(11), false); addVersion("12", new JavaLanguageHandler(12), false); addVersion("12-preview", new JavaLanguageHandler(12, true), false); - addVersion("13", new JavaLanguageHandler(13), true); + addVersion("13", new JavaLanguageHandler(13), false); addVersion("13-preview", new JavaLanguageHandler(13, true), false); + addVersion("14", new JavaLanguageHandler(14), true); + addVersion("14-preview", new JavaLanguageHandler(14, true), false); } } From ad023e8fa63392d814a9c91148b37275dbde83d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 8 Feb 2020 20:35:47 +0100 Subject: [PATCH 2/4] Support type test patterns --- .../pmd/lang/BaseLanguageModule.java | 1 + pmd-java/etc/grammar/Java.jjt | 44 ++++++++++------- .../pmd/lang/java/JavaLanguageModule.java | 4 +- .../pmd/lang/java/ast/ASTPattern.java | 26 ++++++++++ .../pmd/lang/java/ast/ASTTypeTestPattern.java | 47 +++++++++++++++++++ .../java/ast/ASTVariableDeclaratorId.java | 10 ++++ .../java/ast/JavaParserDecoratedVisitor.java | 6 +++ .../java/ast/JavaParserVisitorAdapter.java | 5 ++ .../java/ast/JavaParserVisitorDecorator.java | 5 ++ .../pmd/lang/java/rule/AbstractJavaRule.java | 6 +++ .../pmd/lang/java/ast/ASTPatternTest.kt | 34 ++++++++++++++ .../pmd/lang/java/ast/KotlinTestingDsl.kt | 14 +++++- .../pmd/lang/ast/test/BaseParsingHelper.kt | 3 +- 13 files changed, 184 insertions(+), 21 deletions(-) create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java create mode 100644 pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/BaseLanguageModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/BaseLanguageModule.java index 05cfba2c9f..93c64111c6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/BaseLanguageModule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/BaseLanguageModule.java @@ -111,6 +111,7 @@ public abstract class BaseLanguageModule implements Language { @Override public LanguageVersion getDefaultVersion() { + assert defaultVersion != null : "Null default version for language " + this; return defaultVersion; } diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 727a1d6f06..002b1009e3 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -205,7 +205,7 @@ options { STATIC = false; USER_CHAR_STREAM = true; JDK_VERSION = "1.5"; - + MULTI = true; VISITOR = true; NODE_USES_PARSER = true; @@ -294,25 +294,25 @@ public class JavaParser { throwParseException("Can't use hexadecimal floating point literals in pre-JDK 1.5 target"); } } - + private void checkForBadNumericalLiteralslUsage(Token token) { if (jdkVersion < 7) { if (token.image.contains("_")) { throwParseException("Can't use underscores in numerical literals when running in JDK inferior to 1.7 mode!"); } - + if (token.image.startsWith("0b") || token.image.startsWith("0B")) { - throwParseException("Can't use binary numerical literals when running in JDK inferior to 1.7 mode!"); + throwParseException("Can't use binary numerical literals when running in JDK inferior to 1.7 mode!"); } } } - + private void checkForBadDiamondUsage() { if (jdkVersion < 7) { throwParseException("Cannot use the diamond generic notation when running in JDK inferior to 1.7 mode!"); } } - + private void checkForBadTryWithResourcesUsage() { if (jdkVersion < 7) { throwParseException("Cannot use the try-with-resources notation when running in JDK inferior to 1.7 mode!"); @@ -355,6 +355,13 @@ public class JavaParser { throwParseException("Cannot use explicit receiver parameters when running in JDK inferior to 1.8 mode!"); } } + + private void checkforBadInstanceOfPattern() { + if (jdkVersion != 14 || !preview) { + throwParseException("Cannot use type test patterns in instanceof when running in JDK other than 14-preview"); + } + } + private void checkForBadAnonymousDiamondUsage() { if (jdkVersion < 9) { ASTAllocationExpression node = (ASTAllocationExpression)jjtree.peekNode(); @@ -397,7 +404,7 @@ public class JavaParser { } } private void checkForMultipleCaseLabels() { - if ((jdkVersion != 12 && jdkVersion != 13) || !preview) { + if (!switchExprAllowed()) { throwParseException("Multiple case labels in switch statements are only supported with Java 12 or 13 Preview"); } } @@ -410,14 +417,19 @@ public class JavaParser { * See also comment at #Expression(). */ private boolean inSwitchLabel = false; + + private boolean switchExprAllowed() { + return jdkVersion >= 14 || jdkVersion >= 12 && preview; + } + private void checkForSwitchRules() { - if ((jdkVersion != 12 && jdkVersion != 13) || !preview) { - throwParseException("Switch rules in switch statements are only supported with Java 12 or 13 Preview"); + if (!switchExprAllowed()) { + throwParseException("Switch rules in switch statements are only supported with Java 12 or 13 Preview, or Java >= 14"); } } private void checkForSwitchExpression() { - if ((jdkVersion != 12 && jdkVersion != 13) || !preview) { - throwParseException("Switch expressions are only supported with Java 12 or 13 Preview"); + if (!switchExprAllowed()) { + throwParseException("Switch expressions are only supported with Java 12 or 13 Preview, or Java >= 14"); } } @@ -447,7 +459,7 @@ public class JavaParser { if (jdkVersion <= 3) { return false; } - + return getToken(1).image.equals("assert"); } @@ -1429,7 +1441,7 @@ void EqualityExpression() #EqualityExpression(>1): void InstanceOfExpression() #InstanceOfExpression(>1): {} { - RelationalExpression() [ LOOKAHEAD(2) "instanceof" Type() ] + RelationalExpression() [ LOOKAHEAD(2) "instanceof" Type() [ {checkforBadInstanceOfPattern();} VariableDeclaratorId() #TypeTestPattern(2) ] ] } void RelationalExpression() #RelationalExpression(>1): @@ -1447,7 +1459,7 @@ void RelationalExpression() #RelationalExpression(>1): void ShiftExpression() #ShiftExpression(>1): {} { - AdditiveExpression() + AdditiveExpression() ( LOOKAHEAD(2) ( "<<" { jjtThis.setImage("<<");} | RSIGNEDSHIFT() { jjtThis.setImage(">>"); } @@ -1717,7 +1729,7 @@ void Block() : {Token t;} { "{" - + ( BlockStatement() )* t = "}" { if (isPrecededByComment(t)) { jjtThis.setContainsComment(); } } } @@ -1971,7 +1983,7 @@ void ResourceSpecification() : "(" Resources() (LOOKAHEAD(2) ";")? - ")" + ")" } void Resources() : diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java index c92acd6ea0..4deafd44e9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java @@ -28,9 +28,9 @@ public class JavaLanguageModule extends BaseLanguageModule { addVersion("11", new JavaLanguageHandler(11), false); addVersion("12", new JavaLanguageHandler(12), false); addVersion("12-preview", new JavaLanguageHandler(12, true), false); - addVersion("13", new JavaLanguageHandler(13), false); + addVersion("13", new JavaLanguageHandler(13), true); // 13 is the default addVersion("13-preview", new JavaLanguageHandler(13, true), false); - addVersion("14", new JavaLanguageHandler(14), true); + addVersion("14", new JavaLanguageHandler(14), false); addVersion("14-preview", new JavaLanguageHandler(14, true), false); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java new file mode 100644 index 0000000000..ee1c507354 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java @@ -0,0 +1,26 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +/** + * A pattern (for pattern matching constructs like {@link ASTInstanceOfExpression InstanceOfExpression}). + * This is a JDK 14 preview feature and is subject to change. + * + *

This interface will be implemented by all forms of patterns. For + * now, only type test patterns are supported. Record deconstruction + * patterns are in the works for JDK 15 preview. + * + *

See https://openjdk.java.net/jeps/305, https://openjdk.java.net/jeps/8235186 + * + *

+ *
+ * Pattern ::= {@link ASTTypeTestPattern TypeTestPattern}
+ *
+ * 
+ */ +public interface ASTPattern extends JavaNode { + + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java new file mode 100644 index 0000000000..86b0546525 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java @@ -0,0 +1,47 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +/** + * A type test pattern (JDK 14 preview feature). This can be found on + * the right-hand side of an {@link ASTInstanceOfExpression InstanceOfExpression}. + * + *
+ *
+ * TypeTestPattern ::= {@linkplain ASTType Type} {@link ASTVariableDeclaratorId VariableDeclaratorId}
+ *
+ * 
+ */ +public final class ASTTypeTestPattern extends AbstractJavaNode implements ASTPattern { + + + ASTTypeTestPattern(int id) { + super(id); + } + + ASTTypeTestPattern(JavaParser p, int id) { + super(p, id); + } + + + @Override + public Object jjtAccept(JavaParserVisitor visitor, Object data) { + return visitor.visit(this, data); + } + + + /** + * Gets the type against which the expression is tested. + */ + public ASTType getTypeNode() { + return (ASTType) getChild(0); + } + + /** Returns the declared variable. */ + public ASTVariableDeclaratorId getVarId() { + return (ASTVariableDeclaratorId) getChild(1); + } + +} 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 7ec951b2c3..70732e0c3b 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 @@ -239,6 +239,14 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim return isLambdaParamWithNoType() || isLocalVariableTypeInferred() || isLambdaTypeInferred(); } + /** + * Returns true if this is a binding variable in a + * {@linkplain ASTPattern pattern}. + */ + public boolean isPatternBinding() { + return getParent() instanceof ASTPattern; + } + private boolean isLocalVariableTypeInferred() { if (isResourceDeclaration()) { @@ -288,6 +296,8 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim } else if (isTypeInferred()) { // lambda expression with lax types. The type is inferred... return null; + } else if (getParent() instanceof ASTTypeTestPattern) { + return ((ASTTypeTestPattern) getParent()).getTypeNode(); } else { Node n = getParent().getParent(); if (n instanceof ASTLocalVariableDeclaration || n instanceof ASTFieldDeclaration) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java index e290b50ddc..fe79a473d0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java @@ -898,4 +898,10 @@ public class JavaParserDecoratedVisitor implements JavaParserVisitor { visitor.visit(node, data); return visit((JavaNode) node, data); } + + @Override + public Object visit(ASTTypeTestPattern node, Object data) { + visitor.visit(node, data); + return visit((JavaNode) node, data); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java index 4f8b181003..10a6c0c735 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java @@ -625,4 +625,9 @@ public class JavaParserVisitorAdapter implements JavaParserVisitor { public Object visit(ASTYieldStatement node, Object data) { return visit((JavaNode) node, data); } + + @Override + public Object visit(ASTTypeTestPattern node, Object data) { + return visit((JavaNode) node, data); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java index a94d67a3d9..aa8f4f46c9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java @@ -758,4 +758,9 @@ public class JavaParserVisitorDecorator implements JavaParserControllessVisitor public Object visit(ASTYieldStatement node, Object data) { return visitor.visit(node, data); } + + @Override + public Object visit(ASTTypeTestPattern node, Object data) { + return visitor.visit(node, data); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java index 219c6981b1..f21ab51b2f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java @@ -123,6 +123,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTTypeBound; import net.sourceforge.pmd.lang.java.ast.ASTTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTTypeParameter; import net.sourceforge.pmd.lang.java.ast.ASTTypeParameters; +import net.sourceforge.pmd.lang.java.ast.ASTTypeTestPattern; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpressionNotPlusMinus; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; @@ -834,4 +835,9 @@ public abstract class AbstractJavaRule extends AbstractRule implements JavaParse public Object visit(ASTYieldStatement node, Object data) { return visit((JavaNode) node, data); } + + @Override + public Object visit(ASTTypeTestPattern node, Object data) { + return visit((JavaNode) node, data); + } } 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 new file mode 100644 index 0000000000..64dc9dd6c1 --- /dev/null +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTPatternTest.kt @@ -0,0 +1,34 @@ +package net.sourceforge.pmd.lang.java.ast + +import net.sourceforge.pmd.lang.ast.test.shouldBe +import net.sourceforge.pmd.lang.java.ast.JavaVersion.J14__PREVIEW +import java.io.IOException + +class ASTPatternTest : ParserTestSpec({ + + parserTest("Test patterns only available on JDK 14 (preview)", javaVersions = !J14__PREVIEW) { + + expectParseException("Cannot use type test patterns in instanceof when running in JDK other than 14-preview") { + parseAstExpression("obj instanceof Class c") + } + + } + + parserTest("Test simple patterns", javaVersion = J14__PREVIEW) { + + importedTypes += IOException::class.java + + "obj instanceof Class c" should matchExpr { + unspecifiedChild() + child { + it::getTypeNode shouldBe child(ignoreChildren = true) {} + + it::getVarId shouldBe child { + it::getVariableName shouldBe "c" + } + } + } + } + + +}) 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 71756d18f8..cbc9ed4da2 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 @@ -3,18 +3,28 @@ package net.sourceforge.pmd.lang.java.ast import io.kotlintest.matchers.string.shouldContain import io.kotlintest.shouldThrow import net.sourceforge.pmd.lang.ast.Node -import net.sourceforge.pmd.lang.ast.test.* +import net.sourceforge.pmd.lang.ast.test.Assertions +import net.sourceforge.pmd.lang.ast.test.NodeSpec +import net.sourceforge.pmd.lang.ast.test.matchNode +import net.sourceforge.pmd.lang.ast.test.shouldMatchNode import net.sourceforge.pmd.lang.java.JavaParsingHelper /** * Represents the different Java language versions. */ enum class JavaVersion : Comparable { - J1_3, J1_4, J1_5, J1_6, J1_7, J1_8, J9, J10, J11, J12, J12__PREVIEW, J13, J13__PREVIEW; + J1_3, J1_4, J1_5, J1_6, J1_7, J1_8, J9, J10, J11, + J12, J12__PREVIEW, + J13, J13__PREVIEW, + J14, J14__PREVIEW; /** Name suitable for use with e.g. [JavaParsingHelper.parse] */ val pmdName: String = name.removePrefix("J").replaceFirst("__", "-").replace('_', '.').toLowerCase() + val parser: JavaParsingHelper = JavaParsingHelper.WITH_PROCESSING.withDefaultVersion(pmdName) + + operator fun not(): List = values().toList() - this + /** * Overloads the range operator, e.g. (`J9..J11`). * If both operands are the same, a singleton list is returned. diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt index c9e21e4a19..4a486a397c 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt @@ -49,7 +49,8 @@ abstract class BaseParsingHelper, T : RootNode */ fun getVersion(version: String?): LanguageVersion { val language = LanguageRegistry.getLanguage(langName) - return if (version == null) language.defaultVersion else language.getVersion(version) + return if (version == null) language.defaultVersion + else language.getVersion(version) ?: throw AssertionError("Unsupported version $version for language $language") } val defaultVersion: LanguageVersion From 5a6d332579a975d3d2e19078a3b31303fa75045b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 9 Feb 2020 00:11:06 +0100 Subject: [PATCH 3/4] Make sure symbol table doesn't cry on duplicate name --- .../pmd/lang/java/symboltable/AbstractJavaScope.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java index d93cf75f01..39dc26a5d7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java @@ -24,9 +24,13 @@ public abstract class AbstractJavaScope extends AbstractScope { } protected void checkForDuplicatedNameDeclaration(NameDeclaration declaration) { - if (declaration instanceof VariableNameDeclaration && getDeclarations().keySet().contains(declaration)) { - throw new RuntimeException(declaration + " is already in the symbol table"); - } + // Don't throw an exception, type tests patterns are tricky to implement + // and given it's a preview feature, and the sym table will be replaced + // for 7.0, it's not useful to support them. + + // if (declaration instanceof VariableNameDeclaration && getDeclarations().keySet().contains(declaration)) { + // throw new RuntimeException(declaration + " is already in the symbol table"); + // } } @Override From 97a43945531457d933057706f4c3b5e00d5ebe71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 9 Feb 2020 00:48:01 +0100 Subject: [PATCH 4/4] Mark new API as experimental --- .../pmd/lang/java/ast/ASTInstanceOfExpression.java | 6 ++++-- .../java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java | 3 +++ .../sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java | 3 +++ .../pmd/lang/java/ast/ASTVariableDeclaratorId.java | 2 ++ .../pmd/lang/java/ast/JavaParserDecoratedVisitor.java | 3 +++ .../sourceforge/pmd/lang/java/rule/AbstractJavaRule.java | 2 ++ .../pmd/lang/java/symboltable/AbstractJavaScope.java | 1 + 7 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTInstanceOfExpression.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTInstanceOfExpression.java index 9cfb458436..091810cbd2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTInstanceOfExpression.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTInstanceOfExpression.java @@ -16,7 +16,7 @@ import net.sourceforge.pmd.annotation.InternalApi; * *
  *
- * InstanceOfExpression ::=  {@linkplain ASTShiftExpression ShiftExpression} "instanceof" {@linkplain ASTType Type}
+ * InstanceOfExpression ::= {@linkplain ASTShiftExpression ShiftExpression} "instanceof" ({@linkplain ASTType Type} | {@link ASTPattern Pattern})
  *
  * 
*/ @@ -46,7 +46,9 @@ public class ASTInstanceOfExpression extends AbstractJavaTypeNode { * Gets the type against which the expression is tested. */ public ASTType getTypeNode() { - return (ASTType) getChild(1); + JavaNode child = getChild(1); + return child instanceof ASTType ? (ASTType) child + : ((ASTTypeTestPattern) child).getTypeNode(); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java index ee1c507354..db9f2b0e8c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPattern.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.ast; +import net.sourceforge.pmd.annotation.Experimental; + /** * A pattern (for pattern matching constructs like {@link ASTInstanceOfExpression InstanceOfExpression}). * This is a JDK 14 preview feature and is subject to change. @@ -20,6 +22,7 @@ package net.sourceforge.pmd.lang.java.ast; * * */ +@Experimental public interface ASTPattern extends JavaNode { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java index 86b0546525..c126b89198 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTTypeTestPattern.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.ast; +import net.sourceforge.pmd.annotation.Experimental; + /** * A type test pattern (JDK 14 preview feature). This can be found on * the right-hand side of an {@link ASTInstanceOfExpression InstanceOfExpression}. @@ -14,6 +16,7 @@ package net.sourceforge.pmd.lang.java.ast; * * */ +@Experimental public final class ASTTypeTestPattern extends AbstractJavaNode implements ASTPattern { 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 70732e0c3b..c5383b7c19 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 @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.ast; import java.util.List; +import net.sourceforge.pmd.annotation.Experimental; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; @@ -243,6 +244,7 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim * Returns true if this is a binding variable in a * {@linkplain ASTPattern pattern}. */ + @Experimental public boolean isPatternBinding() { return getParent() instanceof ASTPattern; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java index fe79a473d0..1512a3084c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.ast; +import net.sourceforge.pmd.annotation.Experimental; + /** * External wrapper for a visitor decorator. This one drives the AST visit, delegating to the base controlless visitor * given in the constructor. Add decorators using the {@link #decorateWith(JavaParserVisitorDecorator)}. @@ -900,6 +902,7 @@ public class JavaParserDecoratedVisitor implements JavaParserVisitor { } @Override + @Experimental public Object visit(ASTTypeTestPattern node, Object data) { visitor.visit(node, data); return visit((JavaNode) node, data); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java index f21ab51b2f..80c9c6fd52 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.rule; import java.util.List; import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.annotation.Experimental; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.JavaLanguageModule; @@ -837,6 +838,7 @@ public abstract class AbstractJavaRule extends AbstractRule implements JavaParse } @Override + @Experimental public Object visit(ASTTypeTestPattern node, Object data) { return visit((JavaNode) node, data); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java index 39dc26a5d7..3e7eb4fa51 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java @@ -27,6 +27,7 @@ public abstract class AbstractJavaScope extends AbstractScope { // Don't throw an exception, type tests patterns are tricky to implement // and given it's a preview feature, and the sym table will be replaced // for 7.0, it's not useful to support them. + // See https://cr.openjdk.java.net/~briangoetz/amber/pattern-semantics.html#scoping-of-pattern-variables // if (declaration instanceof VariableNameDeclaration && getDeclarations().keySet().contains(declaration)) { // throw new RuntimeException(declaration + " is already in the symbol table");