diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index f867d26eb8..ad91264de5 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -619,7 +619,7 @@ public class JavaParser { return false; } - private boolean classModifierLookahead() { + private boolean classModifierForLocalTypesLookahead() { Token next = getToken(1); return next.kind == AT || next.kind == PUBLIC @@ -628,9 +628,7 @@ public class JavaParser { || next.kind == ABSTRACT || next.kind == STATIC || next.kind == FINAL - || next.kind == STRICTFP - || isSealedClassSupported() && isKeyword("sealed") - || isSealedClassSupported() && isNonSealedModifier(); + || next.kind == STRICTFP; } private boolean localTypeDeclLookahead() { @@ -2144,7 +2142,7 @@ void BlockStatement(): } ";" ) -| LOOKAHEAD({classModifierLookahead() || localTypeDeclLookahead()}) +| LOOKAHEAD({classModifierForLocalTypesLookahead() || localTypeDeclLookahead()}) mods=Modifiers() LocalTypeDecl(mods) | LOOKAHEAD(Type() ) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java index ca03798026..6dd38772ac 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java17TreeDumpTest.java @@ -72,4 +72,8 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest { java17p.parseResource("expression/Expr.java"); // make sure we can parse it with preview as well } + @Test + public void localVars() { + doTest("LocalVars"); + } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/LocalVars.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/LocalVars.java new file mode 100644 index 0000000000..2e109cd022 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/LocalVars.java @@ -0,0 +1,15 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +public class LocalVars { + + public void aMethod() { + String sealed = null; + + sealed = this.getClass().getName(); + + // error: sealed or non-sealed local classes are not allowed + // sealed class LocalSealedClass {} + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/LocalVars.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/LocalVars.txt new file mode 100644 index 0000000000..706743fd71 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/LocalVars.txt @@ -0,0 +1,39 @@ ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true] + +- TypeDeclaration[] + +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "LocalVars", @Default = false, @Final = false, @Image = "LocalVars", @Interface = false, @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "LocalVars", @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 = 0, @Default = false, @Final = false, @InterfaceMember = false, @Kind = MethodLikeKind.METHOD, @MethodName = "aMethod", @Modifiers = 1, @Name = "aMethod", @Native = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Static = false, @Strictfp = false, @Synchronized = false, @SyntacticallyAbstract = false, @SyntacticallyPublic = true, @Transient = false, @Void = true, @Volatile = false] + +- ResultType[@Void = true, @returnsArray = false] + +- MethodDeclarator[@Image = "aMethod", @ParameterCount = 0] + | +- FormalParameters[@ParameterCount = 0, @Size = 0] + +- Block[@containsComment = true] + +- 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 = "String"] + | | +- ReferenceType[@Array = false, @ArrayDepth = 0] + | | +- ClassOrInterfaceType[@AnonymousClass = false, @Array = false, @ArrayDepth = 0, @Image = "String", @ReferenceToClassSameCompilationUnit = false] + | +- VariableDeclarator[@Initializer = true, @Name = "sealed"] + | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = false, @Image = "sealed", @LambdaParameter = false, @LocalVariable = true, @Name = "sealed", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "sealed"] + | +- VariableInitializer[] + | +- Expression[@StandAlonePrimitive = false] + | +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Literal[@CharLiteral = false, @DoubleLiteral = false, @EscapedStringLiteral = null, @FloatLiteral = false, @IntLiteral = false, @LongLiteral = false, @SingleCharacterStringLiteral = false, @StringLiteral = false, @TextBlock = false, @TextBlockContent = null, @ValueAsDouble = NaN, @ValueAsFloat = NaN, @ValueAsInt = 0, @ValueAsLong = 0] + | +- NullLiteral[] + +- BlockStatement[@Allocation = false] + +- Statement[] + +- StatementExpression[] + +- PrimaryExpression[] + | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false] + | +- Name[@Image = "sealed"] + +- AssignmentOperator[@Compound = false, @Image = "="] + +- Expression[@StandAlonePrimitive = false] + +- PrimaryExpression[] + +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = true] + +- PrimarySuffix[@ArgumentCount = -1, @Arguments = false, @ArrayDereference = false, @Image = "getClass"] + +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + | +- Arguments[@ArgumentCount = 0, @Size = 0] + +- PrimarySuffix[@ArgumentCount = -1, @Arguments = false, @ArrayDereference = false, @Image = "getName"] + +- PrimarySuffix[@ArgumentCount = 0, @Arguments = true, @ArrayDereference = false] + +- Arguments[@ArgumentCount = 0, @Size = 0]