diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 3d4765cd61..86bb21588a 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -1541,8 +1541,8 @@ void FormalParameter() : } { ( "final" {jjtThis.setFinal(true);} | Annotation() )* - Type() ("|" {checkForBadMultipleExceptionsCatching();} Type())* - [ "..." {checkForBadVariableArgumentsUsage();} {jjtThis.setVarargs();} ] + Type() ("|" {checkForBadMultipleExceptionsCatching();} (AnnotationNoNode())* Type())* + [ (AnnotationNoNode())* "..." {checkForBadVariableArgumentsUsage();} {jjtThis.setVarargs();} ] VariableDeclaratorId() } @@ -1586,18 +1586,16 @@ void Type(): Token t; } { - LOOKAHEAD(2) ReferenceType() + LOOKAHEAD( | PrimitiveType() (AnnotationNoNode())* "[" "]" ) ReferenceType() | PrimitiveType() } void ReferenceType(): {} { - // The grammar here is mildly wrong, the annotations can be before each [] - // This will wait for #997 - PrimitiveType() (TypeAnnotation())* ( LOOKAHEAD(2) "[" "]" { jjtThis.bumpArrayDepth(); })+ + PrimitiveType() (LOOKAHEAD((AnnotationNoNode())* "[" "]") (AnnotationNoNode())* "[" "]" { jjtThis.bumpArrayDepth(); })+ | - ( ClassOrInterfaceType()) (TypeAnnotation())* ( LOOKAHEAD(2) "[" "]" { jjtThis.bumpArrayDepth(); })* + ClassOrInterfaceType() (LOOKAHEAD((AnnotationNoNode())* "[" "]") (AnnotationNoNode())* "[" "]" { jjtThis.bumpArrayDepth(); })* } void ClassOrInterfaceType(): @@ -1989,8 +1987,8 @@ void PrimaryPrefix() : | LOOKAHEAD(3) "(" Expression() ")" | AllocationExpression() | LOOKAHEAD( ResultType() "." "class" ) ResultType() "." "class" -| LOOKAHEAD( Name() "::" ) Name() -| LOOKAHEAD( ReferenceType() MethodReference() ) ReferenceType() MethodReference() +| LOOKAHEAD( Name() "::" ) Name() // followed by method reference in PrimarySuffix +| LOOKAHEAD( "@" | Type() "::" ) (AnnotationNoNode())* (LOOKAHEAD(2) ReferenceType()|PrimitiveType()) // followed by method reference in PrimarySuffix | Name() } @@ -2533,6 +2531,15 @@ void RSIGNEDSHIFT(): // TODO 7.0.0 make #void /* Annotation syntax follows. */ + +// Todo PMD7 remove this, this is transitional in the PMD6 branch. +void AnnotationNoNode() #void: +{checkForBadTypeAnnotations();} +{ + Annotation() + {jjtree.popNode();} +} + void Annotation(): {} { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java index 686e9f3c6c..ecdb31ef3c 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java @@ -148,10 +148,10 @@ public class ParserCornersTest { public void testParsersCases18() throws Exception { ASTCompilationUnit cu = java8.parseResource("ParserCornerCases18.java"); - Assert.assertEquals(21, cu.findChildNodesWithXPath("//FormalParameter").size()); - Assert.assertEquals(4, + Assert.assertEquals(24, cu.findChildNodesWithXPath("//FormalParameter").size()); + Assert.assertEquals(5, cu.findChildNodesWithXPath("//FormalParameter[@ExplicitReceiverParameter='true']").size()); - Assert.assertEquals(17, + Assert.assertEquals(19, cu.findChildNodesWithXPath("//FormalParameter[@ExplicitReceiverParameter='false']").size()); } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases18.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases18.java index d6564e90b8..8651c40fe5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases18.java +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/ParserCornerCases18.java @@ -189,6 +189,29 @@ public class ParserCornerCases18 { return new Object @NonNull[0]; } + // this comes from https://github.com/pmd/pmd/issues/4152 + public static T[][] check(T @Anno[] @Anno [] arr) { + if (arr == null) { + throw new NullPointerException(); + } + return arr; + } + + // this comes from https://github.com/pmd/pmd/issues/4152 + public Function func(Main this) { + return @A Main.Inner::new; // this line lead to the crash + } + + // this comes from https://github.com/pmd/pmd/issues/4152 + public static byte max(final byte @NotNull ... array) { return 0;} + + // this comes from https://github.com/pmd/pmd/issues/4152 + @Retention(RetentionPolicy.CLASS) + @Target({ TYPE_USE }) + @interface Anno { + } + + private static void testMultiDimArrayWithAnnotations() { // ever used a 3D-Array in java?? Object x = new Object @NonNull[2] @Nullable[1] @NonNull[3];