In java compiler JCTree.java
the JCVariableDecl
is defined as the following:
public static class JCVariableDecl extends JCStatement implements VariableTree { /** variable modifiers */ public JCModifiers mods; /** variable name */ public Name name; /** variable name expression */ public JCExpression nameexpr; /** type of the variable */ public JCExpression vartype; /** variable's initial value */ public JCExpression init; /** symbol */ public VarSymbol sym; ... }
However, I am not sure how nameexpr
can be useful here. In what situation nameexpr
field is not null? I have read the BNF of Java 8 and JavacParser.java
JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) { int pos = token.pos; Name name; if (lambdaParameter && token.kind == UNDERSCORE) { log.error(pos, "underscore.as.identifier.in.lambda"); name = token.name(); nextToken(); } else { if (allowThisIdent) { JCExpression pn = qualident(false); if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) { name = ((JCIdent)pn).name; } else { if ((mods.flags & Flags.VARARGS) != 0) { log.error(token.pos, "varargs.and.receiver"); } if (token.kind == LBRACKET) { log.error(token.pos, "array.and.receiver"); } return toP(F.at(pos).ReceiverVarDef(mods, pn, type)); } } else { name = ident(); } } if ((mods.flags & Flags.VARARGS) != 0 && token.kind == LBRACKET) { log.error(token.pos, "varargs.and.old.array.syntax"); } type = bracketsOpt(type); return toP(F.at(pos).VarDef(mods, name, type, null)); }
it seems that we need to construct a case to make
pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this
to be false.
Advertisement
Answer
The code is checking for a receiver parameter, which looks like this:
public class SomeClass { public void foo(SomeClass this) { // ^^^^^^^^^^^^^^ } }
In the grammar production rules of the spec, it is listed as:
FormalParameterList: ReceiverParameter FormalParameters , LastFormalParameter LastFormalParameter FormalParameters: FormalParameter {, FormalParameter} ReceiverParameter {, FormalParameter} ReceiverParameter: {Annotation} UnannType [Identifier .] this
It’s a parameter that has the name of “this”, or NameOfOuterClass.this
if in an inner class constructor. this
is not an identifier, so this is why it is checking for pn.hasTag(Tag.IDENT)
.
If you have not heard of receiver parameters before, it’s basically a “an optional syntactic device that exists solely to allow the type of the represented object to be denoted in source code, so that the type may be annotated,” and “it is never bound to any value passed as an argument in a method invocation expression or qualified class instance creation expression, and it has no effect whatsoever at run time” as the language spec puts it.
Since it has almost the same structure as a variable declarator, I guess they decided to also use JCVariableDecl
to represent it.