diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index c2a67da487..8f27be423c 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -1079,8 +1079,8 @@ void PermittedSubclasses() #PermitsList: throw new ParseException("ERROR: expecting permits"); } } - TypeName() - ( "," TypeName() )* + ClassOrInterfaceType() + ( "," ClassOrInterfaceType() )* } void EnumDeclaration(): @@ -1355,20 +1355,6 @@ void Initializer() : [ "static" {jjtThis.setStatic();} ] Block() } -void TypeName() #ClassOrInterfaceType: -{ - StringBuilder s = new StringBuilder(); - Token t; -} -{ - t= {s.append(t.image);} - ( "." t= {s.append('.').append(t.image);} )* - {jjtThis.setImage(s.toString());} -} - - - - /* JLS: https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.3 ReferenceType: 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 5b1b36b4f5..96c4390e0f 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 @@ -54,6 +54,12 @@ public class Java17TreeDumpTest extends BaseTreeDumpTest { java17p.parseResource("geometry/Square.java"); // make sure we can parse it with preview as well } + @Test + public void sealedQualifiedPermitClass() { + doTest("SealedInnerClasses"); + java17p.parseResource("SealedInnerClasses.java"); // make sure we can parse it with preview as well + } + @Test public void sealedInterfaceBeforeJava17() { ParseException thrown = Assert.assertThrows(ParseException.class, new ThrowingRunnable() { diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/SealedInnerClasses.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/SealedInnerClasses.java new file mode 100644 index 0000000000..46d5f975e6 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/SealedInnerClasses.java @@ -0,0 +1,12 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +public class SealedInnerClasses { + sealed class Square implements Squircle { + non-sealed private class OtherSquare extends Square {} + static non-sealed class StaticClass implements Squircle {} + } + + sealed interface Squircle permits Square, Square.StaticClass {} +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/SealedInnerClasses.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/SealedInnerClasses.txt new file mode 100644 index 0000000000..7a0146f1f3 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java17/SealedInnerClasses.txt @@ -0,0 +1,26 @@ ++- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = "true"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "SealedInnerClasses", @CanonicalName = "SealedInnerClasses", @EffectiveVisibility = "public", @Enum = "false", @Final = "false", @Image = "SealedInnerClasses", @Interface = "false", @Local = "false", @Native = "false", @Nested = "false", @PackageName = "", @PackagePrivate = "false", @Private = "false", @Protected = "false", @Public = "true", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "SealedInnerClasses", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "true", @SyntacticallyStatic = "false", @TopLevel = "true", @Transient = "false", @Visibility = "public", @Volatile = "false"] + +- ModifierList[] + +- ClassOrInterfaceBody[@Size = "2"] + +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "SealedInnerClasses$Square", @CanonicalName = "SealedInnerClasses.Square", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Image = "Square", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "Square", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- ImplementsList[@Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Squircle", @TypeImage = "Squircle"] + | +- ClassOrInterfaceBody[@Size = "2"] + | +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "SealedInnerClasses$Square$OtherSquare", @CanonicalName = "SealedInnerClasses.Square.OtherSquare", @EffectiveVisibility = "private", @Enum = "false", @Final = "false", @Image = "OtherSquare", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "false", @Private = "true", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "OtherSquare", @Static = "false", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "private", @Volatile = "false"] + | | +- ModifierList[] + | | +- ExtendsList[@Size = "1"] + | | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Square", @TypeImage = "Square"] + | | +- ClassOrInterfaceBody[@Size = "0"] + | +- ClassOrInterfaceDeclaration[@Abstract = "false", @Annotation = "false", @Anonymous = "false", @BinaryName = "SealedInnerClasses$Square$StaticClass", @CanonicalName = "SealedInnerClasses.Square.StaticClass", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Image = "StaticClass", @Interface = "false", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "true", @RegularInterface = "false", @SimpleName = "StaticClass", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "true", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + | +- ModifierList[] + | +- ImplementsList[@Size = "1"] + | | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Squircle", @TypeImage = "Squircle"] + | +- ClassOrInterfaceBody[@Size = "0"] + +- ClassOrInterfaceDeclaration[@Abstract = "true", @Annotation = "false", @Anonymous = "false", @BinaryName = "SealedInnerClasses$Squircle", @CanonicalName = "SealedInnerClasses.Squircle", @EffectiveVisibility = "package", @Enum = "false", @Final = "false", @Image = "Squircle", @Interface = "true", @Local = "false", @Native = "false", @Nested = "true", @PackageName = "", @PackagePrivate = "true", @Private = "false", @Protected = "false", @Public = "false", @Record = "false", @RegularClass = "false", @RegularInterface = "true", @SimpleName = "Squircle", @Static = "true", @Strictfp = "false", @Synchronized = "false", @SyntacticallyAbstract = "false", @SyntacticallyFinal = "false", @SyntacticallyPublic = "false", @SyntacticallyStatic = "false", @TopLevel = "false", @Transient = "false", @Visibility = "package", @Volatile = "false"] + +- ModifierList[] + +- PermitsList[@Size = "2"] + | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Square", @TypeImage = "Square"] + | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "StaticClass", @TypeImage = "StaticClass"] + | +- ClassOrInterfaceType[@ArrayDepth = "0", @ArrayType = "false", @ClassOrInterfaceType = "true", @FullyQualified = "false", @PrimitiveType = "false", @ReferenceToClassSameCompilationUnit = "false", @SimpleName = "Square", @TypeImage = "Square"] + +- ClassOrInterfaceBody[@Size = "0"]