Simplify some jjtree aspects

This commit is contained in:
Clément Fournier
2020-01-25 02:40:35 +01:00
parent 1c5c80a516
commit 69ad3a7087
3 changed files with 27 additions and 27 deletions

View File

@ -57,24 +57,6 @@ public final class JjtreeBuilder<N extends AbstractJjtreeNode<?>> {
return nodes.get(0);
}
/***
* Extend the number of children of the current node of one to the left.
* If the node is closed, one additional node from the stack will be popped
* and added to its children. This allows mimicking "left-recursive" nodes,
* while keeping the parsing iterative.
*
* <p>Note that when the total number of children is definitely known, you
* can use "definite nodes", ie write the expected number of children (including
* the ones to the left) in the JJTree annotation (eg {@code #AdditiveExpression(2)}).
* So this is only useful when the number of children of the current node is not certain.
*
* <p>This method does not affect the stack unless the current jjtThis is
* closed in the future.
*/
public void extendLeft() {
mk--;
}
/***
* Peek the nth node from the top of the stack.
* peekNode(0) == peekNode()

View File

@ -1285,13 +1285,13 @@ void ClassOrInterfaceType() #void:
{ forceTypeContext(); }
}
private void ClassTypeSegment() #ClassOrInterfaceType:
private void ClassTypeSegment() #ClassOrInterfaceType(jjtree.nodeArity() + 1):
{}
{
TypeAnnotListNoInject()
<IDENTIFIER>
// We'll enclose the previous segment
{ setLastTokenImage(jjtThis); jjtree.extendLeft();}
{ setLastTokenImage(jjtThis); }
[ TypeArguments() ]
}
@ -1345,7 +1345,7 @@ void PrimitiveType() :
| "float"
| "double"
)
{jjtThis.setImage(getToken(0).getImage());}
{setLastTokenImage(jjtThis);}
}
@ -1628,7 +1628,8 @@ void PrimaryPrefix() #void :
("." MemberSelector() | MethodReference())
| UnqualifiedAllocationExpr()
| ("void" "." "class") #ClassLiteral
| (PrimitiveType() [ Dims() ] ) #ArrayType(>1)
| LOOKAHEAD(1) // suppress the warning here.
(PrimitiveType() [ Dims() ] ) #ArrayType(>1)
(
MethodReference()
| "." "class" #ClassLiteral(1)
@ -1636,7 +1637,7 @@ void PrimaryPrefix() #void :
// If annotations start the expression, it's necessarily a method or ctor reference
// This is because types in class literals or in qualified super/this may not be annotated
| LOOKAHEAD({getToken(1).kind == AT}) AnnotatedRefType() MethodReference()
| LOOKAHEAD("@") AnnotatedRefType() MethodReference()
| LOOKAHEAD(LambdaLahead()) LambdaExpression()
@ -1738,10 +1739,10 @@ void MemberSelector() #void :
| (<IDENTIFIER> {setLastTokenImage(jjtThis);}) #FieldAccess(1)
}
void MethodReference(): // LHS is injected
void MethodReference() #MethodReference(jjtree.nodeArity() + 1): // LHS is injected
{}
{
"::" {jjtree.extendLeft();}
"::"
[TypeArguments()]
( "new" | <IDENTIFIER> ) {setLastTokenImage(jjtThis);}
{/* empty, to set the image before jjtClose */}
@ -1847,11 +1848,10 @@ void ArgumentList() :
// more straightforward because can't be an array creation expr
void QualifiedAllocationExpr() #ConstructorCall:
void QualifiedAllocationExpr() #ConstructorCall(jjtree.nodeArity() + 1):
{}
{
"new"
{jjtree.extendLeft();}
[ TypeArguments() ]
AnnotatedClassOrInterfaceType()
ArgumentList()

View File

@ -1,6 +1,7 @@
package net.sourceforge.pmd.lang.java.ast
import net.sourceforge.pmd.lang.ast.test.shouldBe
import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType.PrimitiveType.BOOLEAN
import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType.PrimitiveType.INT
/**
@ -157,6 +158,23 @@ class ASTMethodReferenceTest : ParserTestSpec({
}
}
"boolean @A []::new" should parseAs {
constructorRef {
it::getTypeArguments shouldBe null
typeExpr {
arrayType {
primitiveType(BOOLEAN)
it::getDimensions shouldBe child {
arrayDim {
annotation("A")
}
}
}
}
}
}
"Class<?>[]::new" should parseAs {
constructorRef {
it::getTypeArguments shouldBe null