forked from phoedos/pmd
Remove LateInitNode
This commit is contained in:
Clément Fournier
committed by
Andreas Dangel
parent
089b7999d2
commit
3e36c1621b
@ -464,22 +464,6 @@ public class JavaParser {
|
||||
token_source.setSuppressMarker(marker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the two nodes at the top of the stack and inject the next-to-last as the first
|
||||
* child of the last. Basically it transforms eg [A][B] into [[A]B]. Can be used to e.g.
|
||||
* build a left-recursive expression or type subtree from an iterative parsing.
|
||||
*/
|
||||
private void wrapLeft() {
|
||||
AbstractJavaNode lastSegment = (AbstractJavaNode) jjtree.popNode();
|
||||
Node previousSegment = jjtree.popNode();
|
||||
|
||||
lastSegment.insertChild((AbstractJavaNode) previousSegment, 0);
|
||||
if (lastSegment instanceof AbstractLateInitNode) {
|
||||
((AbstractLateInitNode) lastSegment).onInjectFinished();
|
||||
}
|
||||
jjtree.pushNode(lastSegment);
|
||||
}
|
||||
|
||||
private void setLastTokenImage(JavaNode node) {
|
||||
node.setImage(getToken(0).getImage());
|
||||
}
|
||||
@ -1998,7 +1982,6 @@ void AnnotationList() #void:
|
||||
void TypeAnnotationList() #void:
|
||||
{}
|
||||
{
|
||||
// don't repeat the check
|
||||
(TypeAnnotation())*
|
||||
}
|
||||
|
||||
@ -2110,8 +2093,8 @@ void ClassOrInterfaceType() #void:
|
||||
}
|
||||
|
||||
/*
|
||||
Now if there are other segments, either the previous type specified type arguments,
|
||||
or the next has an annotation.
|
||||
Now if there are other segments, either the previous segment specified type
|
||||
arguments, or the next has an annotation.
|
||||
|
||||
Each of the following segments is its own ClassOrInterfaceType which encloses the
|
||||
previous one. The resulting structure appears left-recursive, but the parser just
|
||||
@ -2123,11 +2106,9 @@ void ClassOrInterfaceType() #void:
|
||||
"."
|
||||
(TypeAnnotation())*
|
||||
<IDENTIFIER> { jjtThis.setImage(getToken(0).getImage()); }
|
||||
{jjtree.extendLeft(1);}
|
||||
{jjtree.extendLeft(1);} // We'll enclose the previous segment
|
||||
[ LOOKAHEAD( "<" ) TypeArguments() ]
|
||||
) #ClassOrInterfaceType
|
||||
// inject the previous segment into the last one
|
||||
// { wrapLeft(); }
|
||||
)*
|
||||
{
|
||||
Node top = jjtree.peekNode();
|
||||
@ -2437,24 +2418,6 @@ void PrimaryExpression() #void :
|
||||
PrimaryPrefix() ( LOOKAHEAD(2) PrimarySuffix() )* {forceExprContext();}
|
||||
}
|
||||
|
||||
/**
|
||||
* A selector like a
|
||||
*/
|
||||
void MemberSelector() #void :
|
||||
{}
|
||||
{
|
||||
// if there are type arguments, this is a method call
|
||||
LOOKAHEAD(2) ("." {jjtree.extendLeft();} TypeArguments() <IDENTIFIER> {setLastTokenImage (jjtThis) ;} ArgumentsList()) #MethodCall // { wrapLeft (); }
|
||||
| LOOKAHEAD(3) ("." {jjtree.extendLeft();} <IDENTIFIER> {setLastTokenImage(jjtThis);} ArgumentsList()) #MethodCall // { wrapLeft (); }
|
||||
| ("." {jjtree.extendLeft();} <IDENTIFIER> {setLastTokenImage(jjtThis);}) #FieldAccess // { wrapLeft (); }
|
||||
}
|
||||
|
||||
void MethodReference(): // LHS is injected
|
||||
{checkForBadMethodReferenceUsage();}
|
||||
{
|
||||
"::" {jjtree.extendLeft();}
|
||||
[TypeArguments()] ( "new" | <IDENTIFIER>) {setLastTokenImage(jjtThis);}
|
||||
}
|
||||
/*
|
||||
Expressions that may be present at the start of a primary expression.
|
||||
|
||||
@ -2471,7 +2434,7 @@ void PrimaryPrefix() #void :
|
||||
| LOOKAHEAD( <IDENTIFIER> "->", {!inSwitchLabel} ) LambdaExpression()
|
||||
| LOOKAHEAD( "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->", {!inSwitchLabel} ) LambdaExpression()
|
||||
| LOOKAHEAD( FormalParameters() "->", {!inSwitchLabel} ) LambdaExpression()
|
||||
| ("(" Expression() ")") #ParenthesizedExpression
|
||||
| ("(" Expression() ")") #ParenthesizedExpression
|
||||
| UnqualifiedAllocationExpr()
|
||||
| LOOKAHEAD( TypeOrVoid() "." "class" )
|
||||
(TypeOrVoid() "." "class") #ClassLiteral
|
||||
@ -2499,15 +2462,32 @@ void PrimaryPrefix() #void :
|
||||
void PrimarySuffix() #void :
|
||||
{}
|
||||
{
|
||||
MethodReference() // { wrapLeft(); }
|
||||
| ArgumentsList() #MethodCall(2) // { wrapLeft(); }
|
||||
| ("[" Expression() "]") #ArrayAccess(2) // { wrapLeft(); }
|
||||
MethodReference()
|
||||
| ArgumentsList() #MethodCall(2)
|
||||
| ("[" Expression() "]") #ArrayAccess(2)
|
||||
// all the following start with a "."
|
||||
| LOOKAHEAD(2) ("." "this") #ThisExpression(1)
|
||||
| LOOKAHEAD(2) ("." "super") #SuperExpression(1) // { wrapLeft(); }
|
||||
| LOOKAHEAD(2) ("." "this") #ThisExpression(1)
|
||||
| LOOKAHEAD(2) ("." "super") #SuperExpression(1)
|
||||
// lookahead("." "new")
|
||||
| LOOKAHEAD(2) QualifiedAllocationExpr() //{ wrapLeft(); }
|
||||
| LOOKAHEAD(1) MemberSelector() // starts with "."
|
||||
| LOOKAHEAD(2) QualifiedAllocationExpr()
|
||||
| MemberSelector() // more complex method call patterns
|
||||
}
|
||||
|
||||
|
||||
void MemberSelector() #void :
|
||||
{}
|
||||
{
|
||||
// if there are type arguments, this is a method call
|
||||
LOOKAHEAD(2) ("." {jjtree.extendLeft();} TypeArguments() <IDENTIFIER> {setLastTokenImage (jjtThis) ;} ArgumentsList()) #MethodCall
|
||||
| LOOKAHEAD(3) ("." {jjtree.extendLeft();} <IDENTIFIER> {setLastTokenImage(jjtThis);} ArgumentsList()) #MethodCall
|
||||
| ("." {jjtree.extendLeft();} <IDENTIFIER> {setLastTokenImage(jjtThis);}) #FieldAccess
|
||||
}
|
||||
|
||||
void MethodReference(): // LHS is injected
|
||||
{checkForBadMethodReferenceUsage();}
|
||||
{
|
||||
"::" {jjtree.extendLeft();}
|
||||
[TypeArguments()] ( "new" | <IDENTIFIER>) {setLastTokenImage(jjtThis);}
|
||||
}
|
||||
|
||||
void LambdaExpression() :
|
||||
@ -2545,7 +2525,6 @@ void LambdaParameterType() #void :
|
||||
LOOKAHEAD( { jdkVersion >= 11 && isKeyword("var") } ) <IDENTIFIER>
|
||||
| Type()
|
||||
}
|
||||
// TODO compound expression abstraction
|
||||
|
||||
void Literal() #void :
|
||||
{ Token t;}
|
||||
@ -2563,9 +2542,9 @@ void NumericLiteral():
|
||||
Token t;
|
||||
}
|
||||
{
|
||||
( t=<INTEGER_LITERAL> { jjtThis.setIntLiteral();}
|
||||
| t=<FLOATING_POINT_LITERAL> { jjtThis.setFloatLiteral();}
|
||||
| t=<HEX_FLOATING_POINT_LITERAL> { checkForBadHexFloatingPointLiteral(); jjtThis.setFloatLiteral();}
|
||||
( t=<INTEGER_LITERAL> { jjtThis.setIntLiteral();}
|
||||
| t=<FLOATING_POINT_LITERAL> { jjtThis.setFloatLiteral();}
|
||||
| t=<HEX_FLOATING_POINT_LITERAL> { checkForBadHexFloatingPointLiteral(); jjtThis.setFloatLiteral();}
|
||||
)
|
||||
{
|
||||
checkForBadNumericalLiteralslUsage(t);
|
||||
@ -2687,10 +2666,9 @@ void ArrayDimsAndInits() :
|
||||
LOOKAHEAD(2)
|
||||
( LOOKAHEAD(2) (TypeAnnotation())* "[" Expression() "]" {jjtThis.bumpArrayDepth();})+ ( LOOKAHEAD(2) "[" "]" {jjtThis.bumpArrayDepth();} )*
|
||||
|
|
||||
( "[" "]" {jjtThis.bumpArrayDepth();})+ ArrayInitializer()
|
||||
Dims() ArrayInitializer()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Statement syntax follows.
|
||||
*/
|
||||
@ -3241,4 +3219,4 @@ void VariableReference():
|
||||
{}
|
||||
{
|
||||
<IDENTIFIER>
|
||||
}
|
||||
}
|
||||
|
@ -14,12 +14,12 @@ import net.sourceforge.pmd.lang.java.xpath.SemanticAmbiguityChecker;
|
||||
|
||||
|
||||
/**
|
||||
* An ambiguous name occurring in any context. Without a disambiguation pass that
|
||||
* taking care of obscuring rules and the current declarations in scope, this node could be
|
||||
* a type, package, or variable name -we can't know for sure. The node is a placeholder
|
||||
* for that unknown entity. It implements both {@link ASTType} and {@link ASTPrimaryExpression}
|
||||
* to be able to be inserted in their hierarchy. E.g. if the LHS of a method call is an ambiguous
|
||||
* name,
|
||||
* An ambiguous name occurring in any context. Without a disambiguation
|
||||
* pass that taking care of obscuring rules and the current declarations
|
||||
* in scope, this node could be a type, package, or variable name -we
|
||||
* can't know for sure. The node is a placeholder for that unknown entity.
|
||||
* It implements both {@link ASTType} and {@link ASTPrimaryExpression} to
|
||||
* be able to be inserted in their hierarchy.
|
||||
*
|
||||
* <p>This node corresponds simultaneously to the <a href="https://docs.oracle.com/javase/specs/jls/se9/html/jls-6.html#jls-AmbiguousName">AmbiguousName</a>
|
||||
* and PackageOrTypeName productions of the JLS.
|
||||
@ -32,9 +32,10 @@ import net.sourceforge.pmd.lang.java.xpath.SemanticAmbiguityChecker;
|
||||
*
|
||||
* @implNote <h3>Disambiguation</h3>
|
||||
*
|
||||
* <p>Some ambiguous names are pushed by the expression parser because we don't want to look too
|
||||
* far ahead (in primary prefix). But it can happen that the next segment (primary suffix) constrains
|
||||
* the name to be e.g. a type name or an expression name. E.g. From the JLS:
|
||||
* <p>Some ambiguous names are pushed by the expression parser because
|
||||
* we don't want to look too far ahead (in primary prefix). But it can
|
||||
* happen that the next segment (primary suffix) constrains the name to
|
||||
* be e.g. a type name or an expression name. E.g. From the JLS:
|
||||
*
|
||||
* <blockquote>
|
||||
* A name is syntactically classified as an ExpressionName in these contexts:
|
||||
@ -42,18 +43,22 @@ import net.sourceforge.pmd.lang.java.xpath.SemanticAmbiguityChecker;
|
||||
* - As the qualifying expression in a qualified class instance creation expression (§15.9)*
|
||||
* </blockquote>
|
||||
*
|
||||
* We don't know at the moment the name is parsed that it will be followed by "." "new" and a constructor
|
||||
* call. But as soon as the {@link ASTConstructorCall} is pushed, we know that the LHS must be an
|
||||
* expression. In that case, the name can be reclassified, and e.g. if it's a simple name be promoted
|
||||
* to {@link ASTVariableReference}. This type of immediate disambiguation is carried out by {@link AbstractLateInitNode#onInjectFinished()}.
|
||||
* We don't know at the moment the name is parsed that it will be
|
||||
* followed by "." "new" and a constructor call. But as soon as the
|
||||
* {@link ASTConstructorCall} is pushed, we know that the LHS must be an
|
||||
* expression. In that case, the name can be reclassified, and e.g. if
|
||||
* it's a simple name be promoted to {@link ASTVariableReference}. This
|
||||
* type of immediate disambiguation is carried out by the {@link AbstractJavaNode#jjtClose()}
|
||||
* method of those nodes that can be pushed.
|
||||
*
|
||||
* <p>Another mechanism is {@link #forceExprContext()} and {@link #forceTypeContext()}, which are
|
||||
* called by the parser to promote an ambiguous name to an expression or a type when it's sure they
|
||||
* must be one, but there's no {@link AbstractLateInitNode} that follows them.
|
||||
* <p>Another mechanism is {@link #forceExprContext()} and {@link #forceTypeContext()},
|
||||
* which are called by the parser to promote an ambiguous name to an
|
||||
* expression or a type when it's sure they must be one.
|
||||
*
|
||||
* <p>These two mechanisms perform the first classification step, the one that only depends on the
|
||||
* syntactic context and not on semantic information. A second pass on the AST after building the
|
||||
* symbol tables would allow us to remove all the remaining ambiguous names.
|
||||
* <p>These two mechanisms perform the first classification step, the
|
||||
* one that only depends on the syntactic context and not on semantic
|
||||
* information. A second pass on the AST after building the symbol tables
|
||||
* would allow us to remove all the remaining ambiguous names.
|
||||
*/
|
||||
public final class ASTAmbiguousName extends AbstractJavaTypeNode implements ASTReferenceType, ASTPrimaryExpression {
|
||||
|
||||
@ -109,13 +114,15 @@ public final class ASTAmbiguousName extends AbstractJavaTypeNode implements ASTR
|
||||
|
||||
/**
|
||||
* Called by the parser if this ambiguous name was a full expression.
|
||||
* Then, since the node was in an expression syntactic context,
|
||||
* we can do some preliminary reclassification:
|
||||
* * If the name is a single identifier, then this can be
|
||||
* reclassified as an {@link ASTVariableReference}
|
||||
* * If the name is a sequence of identifiers, then the last
|
||||
* segment can be reclassified as an {@link ASTFieldAccess},
|
||||
* and the rest of the sequence (to the left) is left ambiguous.
|
||||
* Then, since the node was in an expression syntactic context, we
|
||||
* can do some preliminary reclassification:
|
||||
* <ul>
|
||||
* <li>If the name is a single identifier, then this can be
|
||||
* reclassified as an {@link ASTVariableReference}
|
||||
* <li>If the name is a sequence of identifiers, then the last
|
||||
* segment can be reclassified as an {@link ASTFieldAccess},
|
||||
* and the rest of the sequence (to the left) is left ambiguous.
|
||||
* </ul>
|
||||
*
|
||||
* @return the node which will replace this node in the tree
|
||||
*/
|
||||
@ -127,9 +134,9 @@ public final class ASTAmbiguousName extends AbstractJavaTypeNode implements ASTR
|
||||
|
||||
|
||||
/**
|
||||
* Called by the parser if this ambiguous name was expected to be a type name.
|
||||
* Then we simply promote it to an {@link ASTClassOrInterfaceType} with the appropriate
|
||||
* {@link ASTClassOrInterfaceType#getAmbiguousLhs()}.
|
||||
* Called by the parser if this ambiguous name was expected to be
|
||||
* a type name. Then we simply promote it to an {@link ASTClassOrInterfaceType}
|
||||
* with the appropriate {@link ASTClassOrInterfaceType#getAmbiguousLhs()}.
|
||||
*
|
||||
* @return the node which will replace this node in the tree
|
||||
*/
|
||||
@ -140,16 +147,20 @@ public final class ASTAmbiguousName extends AbstractJavaTypeNode implements ASTR
|
||||
|
||||
|
||||
/**
|
||||
* Low level method to reclassify this ambiguous name. Basically the name is split
|
||||
* in two: the part before the last dot, and the part after it.
|
||||
* Low level method to reclassify this ambiguous name. Basically
|
||||
* the name is split in two: the part before the last dot, and the
|
||||
* part after it.
|
||||
*
|
||||
* @param simpleNameHandler Called with this name as parameter if this ambiguous name
|
||||
* is a simple name. No resizing of the node is performed.
|
||||
* @param splitNameConsumer Called with this node as first parameter, and the last name
|
||||
* segment as second parameter. After the handler is executed,
|
||||
* the text bounds of this node are shrunk to fit to only the
|
||||
* left part. The handler may e.g. move the node to another
|
||||
* parent.
|
||||
* @param simpleNameHandler Called with this name as parameter if
|
||||
* this ambiguous name is a simple name.
|
||||
* No resizing of the node is performed.
|
||||
*
|
||||
* @param splitNameConsumer Called with this node as first parameter,
|
||||
* and the last name segment as second
|
||||
* parameter. After the handler is executed,
|
||||
* the text bounds of this node are shrunk
|
||||
* to fit to only the left part. The handler
|
||||
* may e.g. move the node to another parent.
|
||||
* @param <T> Result type
|
||||
*
|
||||
* @return The node that will replace this one.
|
||||
@ -185,17 +196,15 @@ public final class ASTAmbiguousName extends AbstractJavaTypeNode implements ASTR
|
||||
|
||||
|
||||
/**
|
||||
* A specialized version of {@link #shrinkOneSegment(Function, BiFunction)} for nodes
|
||||
* that carry the unambiguous part as their own image. E.g. when the parser sees an ambiguous
|
||||
* name as primary prefix, then method arguments immediately after, it pushes an {@link ASTMethodCall},
|
||||
* calls wrapLeft(), which calls {@link AbstractLateInitNode#onInjectFinished()}, which calls this method
|
||||
* to shrink the ambiguous name because it's necessarily the method's name. The last part is set
|
||||
* on the parent.
|
||||
* A specialized version of {@link #shrinkOneSegment(Function, BiFunction)}
|
||||
* for nodes that carry the unambiguous part as their own image.
|
||||
* Basically the last segment is set as the image of the parent
|
||||
* node, and no node corresponds to it.
|
||||
*/
|
||||
void shrinkOrDeleteInParentSetImage() {
|
||||
// the params of the lambdas here are this object,
|
||||
// but if we use them instead of this, we avoid capturing the this reference
|
||||
// and the lambdas can be optimised to a singleton
|
||||
// but if we use them instead of this, we avoid capturing the
|
||||
// this reference and the lambdas can be optimised to a singleton
|
||||
shrinkOneSegment(
|
||||
simpleName -> {
|
||||
simpleName.jjtGetParent().setImage(simpleName.getImage());
|
||||
|
@ -36,13 +36,14 @@ public class ASTMethodReference extends AbstractJavaTypeNode implements ASTPrima
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void jjtOpen() {
|
||||
super.jjtOpen();
|
||||
AbstractJavaNode node = (AbstractJavaNode) parser.jjtree.peekNode();
|
||||
enlargeLeft(node);
|
||||
public void jjtClose() {
|
||||
super.jjtClose();
|
||||
enlargeLeft();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if this is a constructor reference,
|
||||
* e.g. {@code ArrayList::new}.
|
||||
|
@ -2,13 +2,11 @@
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/* Generated By:JavaCC: Do not edit this line. JJTJavaParserState.java Version 5.0 */
|
||||
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
|
||||
public class JJTJavaParserState {
|
||||
class JJTJavaParserState {
|
||||
|
||||
private java.util.List<Node> nodes;
|
||||
private java.util.List<Integer> marks;
|
||||
@ -24,15 +22,19 @@ public class JJTJavaParserState {
|
||||
mk = 0;
|
||||
}
|
||||
|
||||
/* Determines whether the current node was actually closed and
|
||||
pushed. This should only be called in the final user action of a
|
||||
node scope. */
|
||||
/**
|
||||
* Determines whether the current node was actually closed and
|
||||
* pushed. This should only be called in the final user action of a
|
||||
* node scope.
|
||||
*/
|
||||
public boolean nodeCreated() {
|
||||
return node_created;
|
||||
}
|
||||
|
||||
/* Call this to reinitialize the node stack. It is called
|
||||
automatically by the parser's ReInit() method. */
|
||||
/**
|
||||
* Call this to reinitialize the node stack. It is called
|
||||
* automatically by the parser's ReInit() method.
|
||||
*/
|
||||
public void reset() {
|
||||
nodes.clear();
|
||||
marks.clear();
|
||||
@ -40,8 +42,10 @@ public class JJTJavaParserState {
|
||||
mk = 0;
|
||||
}
|
||||
|
||||
/* Returns the root node of the AST. It only makes sense to call
|
||||
this after a successful parse. */
|
||||
/**
|
||||
* Returns the root node of the AST. It only makes sense to call
|
||||
* this after a successful parse.
|
||||
*/
|
||||
public Node rootNode() {
|
||||
return nodes.get(0);
|
||||
}
|
||||
@ -57,14 +61,16 @@ public class JJTJavaParserState {
|
||||
}
|
||||
|
||||
|
||||
/* Pushes a node on to the stack. */
|
||||
/** Pushes a node on to the stack. */
|
||||
public void pushNode(Node n) {
|
||||
nodes.add(n);
|
||||
++sp;
|
||||
}
|
||||
|
||||
/* Returns the node on the top of the stack, and remove it from the
|
||||
stack. */
|
||||
/**
|
||||
* Returns the node on the top of the stack, and remove it from the
|
||||
* stack.
|
||||
*/
|
||||
public Node popNode() {
|
||||
if (--sp < mk) {
|
||||
mk = marks.remove(marks.size() - 1);
|
||||
@ -72,13 +78,15 @@ public class JJTJavaParserState {
|
||||
return nodes.remove(nodes.size() - 1);
|
||||
}
|
||||
|
||||
/* Returns the node currently on the top of the stack. */
|
||||
/** Returns the node currently on the top of the stack. */
|
||||
public Node peekNode() {
|
||||
return nodes.get(nodes.size() - 1);
|
||||
}
|
||||
|
||||
/* Returns the number of children on the stack in the current node
|
||||
scope. */
|
||||
/**
|
||||
* Returns the number of children on the stack in the current node
|
||||
* scope.
|
||||
*/
|
||||
public int nodeArity() {
|
||||
return sp - mk;
|
||||
}
|
||||
@ -99,10 +107,12 @@ public class JJTJavaParserState {
|
||||
}
|
||||
|
||||
|
||||
/* A definite node is constructed from a specified number of
|
||||
children. That number of nodes are popped from the stack and
|
||||
made the children of the definite node. Then the definite node
|
||||
is pushed on to the stack. */
|
||||
/**
|
||||
* A definite node is constructed from a specified number of
|
||||
* children. That number of nodes are popped from the stack and
|
||||
* made the children of the definite node. Then the definite node
|
||||
* is pushed on to the stack.
|
||||
*/
|
||||
public void closeNodeScope(Node n, int num) {
|
||||
mk = marks.remove(marks.size() - 1);
|
||||
while (num-- > 0) {
|
||||
@ -116,11 +126,13 @@ public class JJTJavaParserState {
|
||||
}
|
||||
|
||||
|
||||
/* A conditional node is constructed if its condition is true. All
|
||||
the nodes that have been pushed since the node was opened are
|
||||
made children of the conditional node, which is then pushed
|
||||
on to the stack. If the condition is false the node is not
|
||||
constructed and they are left on the stack. */
|
||||
/**
|
||||
* A conditional node is constructed if its condition is true. All
|
||||
* the nodes that have been pushed since the node was opened are
|
||||
* made children of the conditional node, which is then pushed
|
||||
* on to the stack. If the condition is false the node is not
|
||||
* constructed and they are left on the stack.
|
||||
*/
|
||||
public void closeNodeScope(Node n, boolean condition) {
|
||||
if (condition) {
|
||||
int a = nodeArity();
|
||||
@ -139,4 +151,3 @@ public class JJTJavaParserState {
|
||||
}
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=cfc84c2e5756b80b513365816808f071 (do not edit this line) */
|
||||
|
@ -192,4 +192,4 @@ class ASTMethodReferenceTest : ParserTestSpec({
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user