From e017def280d7a853a7d27b25fa02dfef7d0d62b6 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 28 Feb 2020 17:35:44 +0100 Subject: [PATCH] [java] Support vararg/array in RecordComponent and empty components --- pmd-java/etc/grammar/Java.jjt | 7 +++-- .../pmd/lang/java/ast/ASTRecordComponent.java | 23 ++++++++++++++-- .../lang/java/ast/ASTRecordComponentList.java | 3 +-- .../lang/java/ast/ASTRecordDeclaration.java | 4 +++ .../java/ast/ASTVariableDeclaratorId.java | 2 ++ .../pmd/lang/java/ast/Java14PreviewTest.java | 27 ++++++++++++++++--- .../ast/jdkversiontests/java14/Records.java | 6 +++++ 7 files changed, 63 insertions(+), 9 deletions(-) diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 1082fe3cc8..6d9dfc4125 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -1139,13 +1139,16 @@ void RecordDeclaration(int modifiers): void RecordComponentList() : {} { - "(" RecordComponent() ("," RecordComponent())* ")" + "(" [ RecordComponent() ("," RecordComponent())* ] ")" } void RecordComponent(): {} { - (TypeAnnotation())* Type() { jjtThis.setImage(token.image); } + (Annotation())* + Type() + [ (Annotation())* "..." {jjtThis.setVarargs();} ] + VariableDeclaratorId() } void RecordBody(): 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 fea7905177..3b3e474a43 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 @@ -12,14 +12,17 @@ import net.sourceforge.pmd.annotation.Experimental; * *
  *
- * RecordComponent ::= ({@linkplain ASTTypeAnnotation TypeAnnotation})*
+ * RecordComponent ::= ({@linkplain ASTAnnotation Annotation})*
  *                     {@linkplain ASTType Type}
- *                     <IDENTIFIER>
+ *                     ( ({@linkplain ASTAnnotation Annotation})* "..." )?
+ *                     {@linkplain ASTVariableDeclaratorId VariableDeclaratorId}
  *
  * 
*/ @Experimental public class ASTRecordComponent extends AbstractJavaNode { + private boolean varargs; + ASTRecordComponent(int id) { super(id); } @@ -32,4 +35,20 @@ public class ASTRecordComponent extends AbstractJavaNode { public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); } + + public boolean isVarargs() { + return varargs; + } + + void setVarargs() { + varargs = true; + } + + public ASTType getTypeNode() { + return getFirstChildOfType(ASTType.class); + } + + public ASTVariableDeclaratorId getVariableDeclaratorId() { + return getFirstChildOfType(ASTVariableDeclaratorId.class); + } } 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 ca3108235c..dbf7367601 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 @@ -12,8 +12,7 @@ import net.sourceforge.pmd.annotation.Experimental; * *
  *
- * RecordComponentList ::= "("       {@linkplain ASTRecordComponent RecordComponent}
- *                             ( "," {@linkplain ASTRecordComponent RecordComponent} )* ")"
+ * RecordComponentList ::= "(" ( {@linkplain ASTRecordComponent RecordComponent} ( "," {@linkplain ASTRecordComponent RecordComponent} )* )? ")"
  *
  * 
*/ 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 ddc805d601..8eebc3450b 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 @@ -57,4 +57,8 @@ public class ASTRecordDeclaration extends AbstractAnyTypeDeclaration { public boolean isFindBoundary() { return isNested(); } + + public List getRecordComponents() { + return getFirstChildOfType(ASTRecordComponentList.class).findChildrenOfType(ASTRecordComponent.class); + } } 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 331d91edc9..a96c120041 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 @@ -303,6 +303,8 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim return null; } else if (getParent() instanceof ASTTypeTestPattern) { return ((ASTTypeTestPattern) getParent()).getTypeNode(); + } else if (getParent() instanceof ASTRecordComponent) { + return ((ASTRecordComponent) getParent()).getTypeNode(); } else { Node n = getParent().getParent(); if (n instanceof ASTLocalVariableDeclaration || n instanceof ASTFieldDeclaration) { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14PreviewTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14PreviewTest.java index 163cfee673..3c428197c1 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14PreviewTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java14PreviewTest.java @@ -99,8 +99,8 @@ public class Java14PreviewTest { List components = recordDecl.getFirstChildOfType(ASTRecordComponentList.class) .findChildrenOfType(ASTRecordComponent.class); Assert.assertEquals(2, components.size()); - Assert.assertEquals("x", components.get(0).getImage()); - Assert.assertEquals("y", components.get(1).getImage()); + Assert.assertEquals("x", components.get(0).getVariableDeclaratorId().getImage()); + Assert.assertEquals("y", components.get(1).getVariableDeclaratorId().getImage()); } @Test(expected = ParseException.class) @@ -112,7 +112,28 @@ public class Java14PreviewTest { public void innerRecords() { ASTCompilationUnit compilationUnit = java14p.parseResource("Records.java"); List recordDecls = compilationUnit.findDescendantsOfType(ASTRecordDeclaration.class); - Assert.assertEquals(2, recordDecls.size()); + Assert.assertEquals(5, recordDecls.size()); + + ASTRecordDeclaration range = recordDecls.get(1); + Assert.assertEquals("Range", range.getImage()); + Assert.assertEquals(2, range.getRecordComponents().size()); + List rangeConstructors = range.findDescendantsOfType(ASTRecordConstructorDeclaration.class); + Assert.assertEquals(1, rangeConstructors.size()); + Assert.assertEquals("Range", rangeConstructors.get(0).getImage()); + + ASTRecordDeclaration varRec = recordDecls.get(2); + Assert.assertEquals("VarRec", varRec.getImage()); + Assert.assertEquals("x", varRec.getRecordComponents().get(0).getVariableDeclaratorId().getImage()); + Assert.assertTrue(varRec.getRecordComponents().get(0).isVarargs()); + + ASTRecordDeclaration arrayRec = recordDecls.get(3); + Assert.assertEquals("ArrayRec", arrayRec.getImage()); + Assert.assertEquals("x", arrayRec.getRecordComponents().get(0).getVariableDeclaratorId().getImage()); + Assert.assertTrue(arrayRec.getRecordComponents().get(0).getVariableDeclaratorId().hasArrayType()); + + ASTRecordDeclaration emptyRec = recordDecls.get(4); + Assert.assertEquals("EmptyRec", emptyRec.getImage()); + Assert.assertEquals(0, emptyRec.getRecordComponents().size()); } @Test(expected = ParseException.class) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/Records.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/Records.java index 32c95eb6ec..5f12b5a159 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/Records.java +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java14/Records.java @@ -15,4 +15,10 @@ public class Records { throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi)); } } + + public record VarRec(int ... x) {}; + + public record ArrayRec(int x[]) {}; + + public record EmptyRec() {}; }