提交 8ac35cfc 编写于 作者: M mcimadamore

8005852: Treatment of '_' as identifier

Summary: warn when '_' is found in an identifier position
Reviewed-by: jjg
上级 f59adebe
...@@ -245,40 +245,42 @@ public class JavacParser implements Parser { ...@@ -245,40 +245,42 @@ public class JavacParser implements Parser {
token = S.token(); token = S.token();
} }
protected boolean peekToken(TokenKind tk) { protected boolean peekToken(Filter<TokenKind> tk) {
return peekToken(0, tk); return peekToken(0, tk);
} }
protected boolean peekToken(int lookahead, TokenKind tk) { protected boolean peekToken(int lookahead, Filter<TokenKind> tk) {
return S.token(lookahead + 1).kind == tk; return tk.accepts(S.token(lookahead + 1).kind);
} }
protected boolean peekToken(TokenKind tk1, TokenKind tk2) { protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
return peekToken(0, tk1, tk2); return peekToken(0, tk1, tk2);
} }
protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2) { protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
return S.token(lookahead + 1).kind == tk1 && return tk1.accepts(S.token(lookahead + 1).kind) &&
S.token(lookahead + 2).kind == tk2; tk2.accepts(S.token(lookahead + 2).kind);
} }
protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) { protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
return peekToken(0, tk1, tk2, tk3); return peekToken(0, tk1, tk2, tk3);
} }
protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2, TokenKind tk3) { protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
return S.token(lookahead + 1).kind == tk1 && return tk1.accepts(S.token(lookahead + 1).kind) &&
S.token(lookahead + 2).kind == tk2 && tk2.accepts(S.token(lookahead + 2).kind) &&
S.token(lookahead + 3).kind == tk3; tk3.accepts(S.token(lookahead + 3).kind);
} }
protected boolean peekToken(TokenKind... kinds) { @SuppressWarnings("unchecked")
protected boolean peekToken(Filter<TokenKind>... kinds) {
return peekToken(0, kinds); return peekToken(0, kinds);
} }
protected boolean peekToken(int lookahead, TokenKind... kinds) { @SuppressWarnings("unchecked")
protected boolean peekToken(int lookahead, Filter<TokenKind>... kinds) {
for (; lookahead < kinds.length ; lookahead++) { for (; lookahead < kinds.length ; lookahead++) {
if (S.token(lookahead + 1).kind != kinds[lookahead]) { if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) {
return false; return false;
} }
} }
...@@ -333,6 +335,7 @@ public class JavacParser implements Parser { ...@@ -333,6 +335,7 @@ public class JavacParser implements Parser {
if (stopAtMemberDecl) if (stopAtMemberDecl)
return; return;
break; break;
case UNDERSCORE:
case IDENTIFIER: case IDENTIFIER:
if (stopAtIdentifier) if (stopAtIdentifier)
return; return;
...@@ -552,11 +555,16 @@ public class JavacParser implements Parser { ...@@ -552,11 +555,16 @@ public class JavacParser implements Parser {
nextToken(); nextToken();
return name; return name;
} }
} else if (token.kind == UNDERSCORE) {
warning(token.pos, "underscore.as.identifier");
Name name = token.name();
nextToken();
return name;
} else { } else {
accept(IDENTIFIER); accept(IDENTIFIER);
return names.error; return names.error;
} }
} }
/** /**
* Qualident = Ident { DOT Ident } * Qualident = Ident { DOT Ident }
...@@ -1056,7 +1064,7 @@ public class JavacParser implements Parser { ...@@ -1056,7 +1064,7 @@ public class JavacParser implements Parser {
typeArgs = null; typeArgs = null;
} else return illegal(); } else return illegal();
break; break;
case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
if (typeArgs != null) return illegal(); if (typeArgs != null) return illegal();
if ((mode & EXPR) != 0 && peekToken(ARROW)) { if ((mode & EXPR) != 0 && peekToken(ARROW)) {
t = lambdaExpressionOrStatement(false, false, pos); t = lambdaExpressionOrStatement(false, false, pos);
...@@ -1274,7 +1282,7 @@ public class JavacParser implements Parser { ...@@ -1274,7 +1282,7 @@ public class JavacParser implements Parser {
int pos = 0, depth = 0; int pos = 0, depth = 0;
for (Token t = S.token(pos) ; ; t = S.token(++pos)) { for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
switch (t.kind) { switch (t.kind) {
case IDENTIFIER: case QUES: case EXTENDS: case SUPER: case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
case DOT: case RBRACKET: case LBRACKET: case COMMA: case DOT: case RBRACKET: case LBRACKET: case COMMA:
case BYTE: case SHORT: case INT: case LONG: case FLOAT: case BYTE: case SHORT: case INT: case LONG: case FLOAT:
case DOUBLE: case BOOLEAN: case CHAR: case DOUBLE: case BOOLEAN: case CHAR:
...@@ -1323,8 +1331,8 @@ public class JavacParser implements Parser { ...@@ -1323,8 +1331,8 @@ public class JavacParser implements Parser {
if (peekToken(lookahead, RPAREN)) { if (peekToken(lookahead, RPAREN)) {
//Type, ')' -> cast //Type, ')' -> cast
return ParensResult.CAST; return ParensResult.CAST;
} else if (peekToken(lookahead, IDENTIFIER)) { } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
//Type, 'Identifier -> explicit lambda //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA; return ParensResult.EXPLICIT_LAMBDA;
} }
break; break;
...@@ -1350,16 +1358,19 @@ public class JavacParser implements Parser { ...@@ -1350,16 +1358,19 @@ public class JavacParser implements Parser {
case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
case TRUE: case FALSE: case NULL: case TRUE: case FALSE: case NULL:
case NEW: case IDENTIFIER: case ASSERT: case ENUM: case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
case BYTE: case SHORT: case CHAR: case INT: case BYTE: case SHORT: case CHAR: case INT:
case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
return ParensResult.CAST; return ParensResult.CAST;
default: default:
return ParensResult.PARENS; return ParensResult.PARENS;
} }
case UNDERSCORE:
case ASSERT:
case ENUM:
case IDENTIFIER: case IDENTIFIER:
if (peekToken(lookahead, IDENTIFIER)) { if (peekToken(lookahead, LAX_IDENTIFIER)) {
// Identifier, Identifier -> explicit lambda // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA; return ParensResult.EXPLICIT_LAMBDA;
} else if (peekToken(lookahead, RPAREN, ARROW)) { } else if (peekToken(lookahead, RPAREN, ARROW)) {
// Identifier, ')' '->' -> implicit lambda // Identifier, ')' '->' -> implicit lambda
...@@ -1372,8 +1383,8 @@ public class JavacParser implements Parser { ...@@ -1372,8 +1383,8 @@ public class JavacParser implements Parser {
//those can only appear in explicit lambdas //those can only appear in explicit lambdas
return ParensResult.EXPLICIT_LAMBDA; return ParensResult.EXPLICIT_LAMBDA;
case LBRACKET: case LBRACKET:
if (peekToken(lookahead, RBRACKET, IDENTIFIER)) { if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
// '[', ']', Identifier -> explicit lambda // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA; return ParensResult.EXPLICIT_LAMBDA;
} else if (peekToken(lookahead, RBRACKET, RPAREN) || } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
peekToken(lookahead, RBRACKET, AMP)) { peekToken(lookahead, RBRACKET, AMP)) {
...@@ -1402,11 +1413,11 @@ public class JavacParser implements Parser { ...@@ -1402,11 +1413,11 @@ public class JavacParser implements Parser {
// '>', ')' -> cast // '>', ')' -> cast
// '>', '&' -> cast // '>', '&' -> cast
return ParensResult.CAST; return ParensResult.CAST;
} else if (peekToken(lookahead, IDENTIFIER, COMMA) || } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
peekToken(lookahead, IDENTIFIER, RPAREN, ARROW) || peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
peekToken(lookahead, ELLIPSIS)) { peekToken(lookahead, ELLIPSIS)) {
// '>', Identifier, ',' -> explicit lambda // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
// '>', Identifier, ')', '->' -> explicit lambda // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
// '>', '...' -> explicit lambda // '>', '...' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA; return ParensResult.EXPLICIT_LAMBDA;
} }
...@@ -1426,6 +1437,13 @@ public class JavacParser implements Parser { ...@@ -1426,6 +1437,13 @@ public class JavacParser implements Parser {
} }
} }
/** Accepts all identifier-like tokens */
Filter<TokenKind> LAX_IDENTIFIER = new Filter<TokenKind>() {
public boolean accepts(TokenKind t) {
return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
}
};
enum ParensResult { enum ParensResult {
CAST, CAST,
EXPLICIT_LAMBDA, EXPLICIT_LAMBDA,
...@@ -1433,21 +1451,9 @@ public class JavacParser implements Parser { ...@@ -1433,21 +1451,9 @@ public class JavacParser implements Parser {
PARENS; PARENS;
} }
JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) {
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
params.append(firstParam);
JCVariableDecl lastParam = firstParam;
while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
nextToken();
params.append(lastParam = formalParameter());
}
accept(RPAREN);
return lambdaExpressionOrStatementRest(params.toList(), pos);
}
JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) { JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
List<JCVariableDecl> params = explicitParams ? List<JCVariableDecl> params = explicitParams ?
formalParameters() : formalParameters(true) :
implicitParameters(hasParens); implicitParameters(hasParens);
return lambdaExpressionOrStatementRest(params, pos); return lambdaExpressionOrStatementRest(params, pos);
...@@ -1628,7 +1634,7 @@ public class JavacParser implements Parser { ...@@ -1628,7 +1634,7 @@ public class JavacParser implements Parser {
nextToken(); nextToken();
JCExpression bound = parseType(); JCExpression bound = parseType();
return F.at(pos).Wildcard(t, bound); return F.at(pos).Wildcard(t, bound);
} else if (token.kind == IDENTIFIER) { } else if (LAX_IDENTIFIER.accepts(token.kind)) {
//error recovery //error recovery
TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
JCExpression wc = toP(F.at(pos).Wildcard(t, null)); JCExpression wc = toP(F.at(pos).Wildcard(t, null));
...@@ -1678,7 +1684,7 @@ public class JavacParser implements Parser { ...@@ -1678,7 +1684,7 @@ public class JavacParser implements Parser {
if (token.pos == endPosTable.errorEndPos) { if (token.pos == endPosTable.errorEndPos) {
// error recovery // error recovery
Name name = null; Name name = null;
if (token.kind == IDENTIFIER) { if (LAX_IDENTIFIER.accepts(token.kind)) {
name = token.name(); name = token.name();
nextToken(); nextToken();
} else { } else {
...@@ -2026,10 +2032,7 @@ public class JavacParser implements Parser { ...@@ -2026,10 +2032,7 @@ public class JavacParser implements Parser {
nextToken(); nextToken();
JCStatement stat = parseStatement(); JCStatement stat = parseStatement();
return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat)); return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
} else if ((lastmode & TYPE) != 0 && } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
(token.kind == IDENTIFIER ||
token.kind == ASSERT ||
token.kind == ENUM)) {
pos = token.pos; pos = token.pos;
JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
F.at(pos); F.at(pos);
...@@ -2183,14 +2186,14 @@ public class JavacParser implements Parser { ...@@ -2183,14 +2186,14 @@ public class JavacParser implements Parser {
} }
case BREAK: { case BREAK: {
nextToken(); nextToken();
Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
JCBreak t = to(F.at(pos).Break(label)); JCBreak t = to(F.at(pos).Break(label));
accept(SEMI); accept(SEMI);
return t; return t;
} }
case CONTINUE: { case CONTINUE: {
nextToken(); nextToken();
Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
JCContinue t = to(F.at(pos).Continue(label)); JCContinue t = to(F.at(pos).Continue(label));
accept(SEMI); accept(SEMI);
return t; return t;
...@@ -2351,9 +2354,7 @@ public class JavacParser implements Parser { ...@@ -2351,9 +2354,7 @@ public class JavacParser implements Parser {
return variableDeclarators(optFinal(0), parseType(), stats).toList(); return variableDeclarators(optFinal(0), parseType(), stats).toList();
} else { } else {
JCExpression t = term(EXPR | TYPE); JCExpression t = term(EXPR | TYPE);
if ((lastmode & TYPE) != 0 && if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
(token.kind == IDENTIFIER || token.kind == ASSERT ||
token.kind == ENUM)) {
return variableDeclarators(modifiersOpt(), t, stats).toList(); return variableDeclarators(modifiersOpt(), t, stats).toList();
} else if ((lastmode & TYPE) != 0 && token.kind == COLON) { } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
error(pos, "bad.initializer", "for-loop"); error(pos, "bad.initializer", "for-loop");
...@@ -2609,8 +2610,18 @@ public class JavacParser implements Parser { ...@@ -2609,8 +2610,18 @@ public class JavacParser implements Parser {
/** VariableDeclaratorId = Ident BracketsOpt /** VariableDeclaratorId = Ident BracketsOpt
*/ */
JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
return variableDeclaratorId(mods, type, false);
}
//where
JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
int pos = token.pos; int pos = token.pos;
Name name = ident(); Name name;
if (lambdaParameter && token.kind == UNDERSCORE) {
syntaxError(pos, "expected", IDENTIFIER);
name = token.name();
} else {
name = ident();
}
if ((mods.flags & Flags.VARARGS) != 0 && if ((mods.flags & Flags.VARARGS) != 0 &&
token.kind == LBRACKET) { token.kind == LBRACKET) {
log.error(token.pos, "varargs.and.old.array.syntax"); log.error(token.pos, "varargs.and.old.array.syntax");
...@@ -2770,7 +2781,7 @@ public class JavacParser implements Parser { ...@@ -2770,7 +2781,7 @@ public class JavacParser implements Parser {
} else { } else {
int pos = token.pos; int pos = token.pos;
List<JCTree> errs; List<JCTree> errs;
if (token.kind == IDENTIFIER) { if (LAX_IDENTIFIER.accepts(token.kind)) {
errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
setErrorEndPos(token.pos); setErrorEndPos(token.pos);
} else { } else {
...@@ -2787,7 +2798,7 @@ public class JavacParser implements Parser { ...@@ -2787,7 +2798,7 @@ public class JavacParser implements Parser {
} }
int pos = token.pos; int pos = token.pos;
List<JCTree> errs; List<JCTree> errs;
if (token.kind == IDENTIFIER) { if (LAX_IDENTIFIER.accepts(token.kind)) {
errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
setErrorEndPos(token.pos); setErrorEndPos(token.pos);
} else { } else {
...@@ -3182,14 +3193,17 @@ public class JavacParser implements Parser { ...@@ -3182,14 +3193,17 @@ public class JavacParser implements Parser {
* FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
*/ */
List<JCVariableDecl> formalParameters() { List<JCVariableDecl> formalParameters() {
return formalParameters(false);
}
List<JCVariableDecl> formalParameters(boolean lambdaParameters) {
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
JCVariableDecl lastParam = null; JCVariableDecl lastParam = null;
accept(LPAREN); accept(LPAREN);
if (token.kind != RPAREN) { if (token.kind != RPAREN) {
params.append(lastParam = formalParameter()); params.append(lastParam = formalParameter(lambdaParameters));
while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
nextToken(); nextToken();
params.append(lastParam = formalParameter()); params.append(lastParam = formalParameter(lambdaParameters));
} }
} }
accept(RPAREN); accept(RPAREN);
...@@ -3225,6 +3239,9 @@ public class JavacParser implements Parser { ...@@ -3225,6 +3239,9 @@ public class JavacParser implements Parser {
* LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
*/ */
protected JCVariableDecl formalParameter() { protected JCVariableDecl formalParameter() {
return formalParameter(false);
}
protected JCVariableDecl formalParameter(boolean lambdaParameter) {
JCModifiers mods = optFinal(Flags.PARAMETER); JCModifiers mods = optFinal(Flags.PARAMETER);
JCExpression type = parseType(); JCExpression type = parseType();
if (token.kind == ELLIPSIS) { if (token.kind == ELLIPSIS) {
...@@ -3233,12 +3250,12 @@ public class JavacParser implements Parser { ...@@ -3233,12 +3250,12 @@ public class JavacParser implements Parser {
type = to(F.at(token.pos).TypeArray(type)); type = to(F.at(token.pos).TypeArray(type));
nextToken(); nextToken();
} }
return variableDeclaratorId(mods, type); return variableDeclaratorId(mods, type, lambdaParameter);
} }
protected JCVariableDecl implicitParameter() { protected JCVariableDecl implicitParameter() {
JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
return variableDeclaratorId(mods, null); return variableDeclaratorId(mods, null, true);
} }
/* ---------- auxiliary methods -------------- */ /* ---------- auxiliary methods -------------- */
......
...@@ -33,6 +33,7 @@ import com.sun.tools.javac.parser.Tokens.Token.Tag; ...@@ -33,6 +33,7 @@ import com.sun.tools.javac.parser.Tokens.Token.Tag;
import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Filter;
import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Names;
...@@ -74,7 +75,6 @@ public class Tokens { ...@@ -74,7 +75,6 @@ public class Tokens {
protected Tokens(Context context) { protected Tokens(Context context) {
context.put(tokensKey, this); context.put(tokensKey, this);
names = Names.instance(context); names = Names.instance(context);
for (TokenKind t : TokenKind.values()) { for (TokenKind t : TokenKind.values()) {
if (t.name != null) if (t.name != null)
enterKeyword(t.name, t); enterKeyword(t.name, t);
...@@ -113,7 +113,7 @@ public class Tokens { ...@@ -113,7 +113,7 @@ public class Tokens {
* This enum defines all tokens used by the javac scanner. A token is * This enum defines all tokens used by the javac scanner. A token is
* optionally associated with a name. * optionally associated with a name.
*/ */
public enum TokenKind implements Formattable { public enum TokenKind implements Formattable, Filter<TokenKind> {
EOF(), EOF(),
ERROR(), ERROR(),
IDENTIFIER(Tag.NAMED), IDENTIFIER(Tag.NAMED),
...@@ -176,6 +176,7 @@ public class Tokens { ...@@ -176,6 +176,7 @@ public class Tokens {
TRUE("true", Tag.NAMED), TRUE("true", Tag.NAMED),
FALSE("false", Tag.NAMED), FALSE("false", Tag.NAMED),
NULL("null", Tag.NAMED), NULL("null", Tag.NAMED),
UNDERSCORE("_", Tag.NAMED),
ARROW("->"), ARROW("->"),
COLCOL("::"), COLCOL("::"),
LPAREN("("), LPAREN("("),
...@@ -283,6 +284,11 @@ public class Tokens { ...@@ -283,6 +284,11 @@ public class Tokens {
public String toString(Locale locale, Messages messages) { public String toString(Locale locale, Messages messages) {
return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString()); return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString());
} }
@Override
public boolean accepts(TokenKind that) {
return this == that;
}
} }
public interface Comment { public interface Comment {
......
...@@ -2132,6 +2132,10 @@ compiler.warn.assert.as.identifier=\ ...@@ -2132,6 +2132,10 @@ compiler.warn.assert.as.identifier=\
as of release 1.4, ''assert'' is a keyword, and may not be used as an identifier\n\ as of release 1.4, ''assert'' is a keyword, and may not be used as an identifier\n\
(use -source 1.4 or higher to use ''assert'' as a keyword) (use -source 1.4 or higher to use ''assert'' as a keyword)
compiler.warn.underscore.as.identifier=\
''_'' used as an identifier\n\
(use of ''_'' as an identifier might not be supported in future releases)
compiler.err.enum.as.identifier=\ compiler.err.enum.as.identifier=\
as of release 5, ''enum'' is a keyword, and may not be used as an identifier\n\ as of release 5, ''enum'' is a keyword, and may not be used as an identifier\n\
(use -source 1.4 or lower to use ''enum'' as an identifier) (use -source 1.4 or lower to use ''enum'' as an identifier)
......
...@@ -23,8 +23,7 @@ ...@@ -23,8 +23,7 @@
/* /*
* @test * @test
* @bug 7115050 * @bug 7115050 8003280 8005852
* @bug 8003280
* @summary Add lambda tests * @summary Add lambda tests
* Add parser support for lambda expressions * Add parser support for lambda expressions
* @library ../lib * @library ../lib
...@@ -46,12 +45,12 @@ public class LambdaParserTest ...@@ -46,12 +45,12 @@ public class LambdaParserTest
enum LambdaKind { enum LambdaKind {
NILARY_EXPR("()->x"), NILARY_EXPR("()->x"),
NILARY_STMT("()->{ return x; }"), NILARY_STMT("()->{ return x; }"),
ONEARY_SHORT_EXPR("x->x"), ONEARY_SHORT_EXPR("#PN->x"),
ONEARY_SHORT_STMT("x->{ return x; }"), ONEARY_SHORT_STMT("#PN->{ return x; }"),
ONEARY_EXPR("(#M1 #T1 x)->x"), ONEARY_EXPR("(#M1 #T1 #PN)->x"),
ONEARY_STMT("(#M1 #T1 x)->{ return x; }"), ONEARY_STMT("(#M1 #T1 #PN)->{ return x; }"),
TWOARY_EXPR("(#M1 #T1 x, #M2 #T2 y)->x"), TWOARY_EXPR("(#M1 #T1 #PN, #M2 #T2 y)->x"),
TWOARY_STMT("(#M1 #T1 x, #M2 #T2 y)->{ return x; }"); TWOARY_STMT("(#M1 #T1 #PN, #M2 #T2 y)->{ return x; }");
String lambdaTemplate; String lambdaTemplate;
...@@ -60,11 +59,12 @@ public class LambdaParserTest ...@@ -60,11 +59,12 @@ public class LambdaParserTest
} }
String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2, String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2,
ModifierKind mk1, ModifierKind mk2) { ModifierKind mk1, ModifierKind mk2, LambdaParameterName pn) {
return lambdaTemplate.replaceAll("#M1", mk1.modifier) return lambdaTemplate.replaceAll("#M1", mk1.modifier)
.replaceAll("#M2", mk2.modifier) .replaceAll("#M2", mk2.modifier)
.replaceAll("#T1", pk1.parameterType) .replaceAll("#T1", pk1.parameterType)
.replaceAll("#T2", pk2.parameterType); .replaceAll("#T2", pk2.parameterType)
.replaceAll("#PN", pn.nameStr);
} }
int arity() { int arity() {
...@@ -87,6 +87,17 @@ public class LambdaParserTest ...@@ -87,6 +87,17 @@ public class LambdaParserTest
} }
} }
enum LambdaParameterName {
IDENT("x"),
UNDERSCORE("_");
String nameStr;
LambdaParameterName(String nameStr) {
this.nameStr = nameStr;
}
}
enum LambdaParameterKind { enum LambdaParameterKind {
IMPLICIT(""), IMPLICIT(""),
EXPLIICT_SIMPLE("A"), EXPLIICT_SIMPLE("A"),
...@@ -151,8 +162,8 @@ public class LambdaParserTest ...@@ -151,8 +162,8 @@ public class LambdaParserTest
} }
String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2, String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2,
ModifierKind mk1, ModifierKind mk2, LambdaKind lk, SubExprKind sk) { ModifierKind mk1, ModifierKind mk2, LambdaKind lk, LambdaParameterName pn, SubExprKind sk) {
return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2)) return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2, pn))
.replaceAll("#S", sk.subExpression); .replaceAll("#S", sk.subExpression);
} }
} }
...@@ -174,25 +185,27 @@ public class LambdaParserTest ...@@ -174,25 +185,27 @@ public class LambdaParserTest
public static void main(String... args) throws Exception { public static void main(String... args) throws Exception {
for (LambdaKind lk : LambdaKind.values()) { for (LambdaKind lk : LambdaKind.values()) {
for (LambdaParameterKind pk1 : LambdaParameterKind.values()) { for (LambdaParameterName pn : LambdaParameterName.values()) {
if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT) for (LambdaParameterKind pk1 : LambdaParameterKind.values()) {
continue; if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT)
for (LambdaParameterKind pk2 : LambdaParameterKind.values()) {
if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT)
continue; continue;
for (ModifierKind mk1 : ModifierKind.values()) { for (LambdaParameterKind pk2 : LambdaParameterKind.values()) {
if (mk1 != ModifierKind.NONE && lk.isShort()) if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT)
continue;
if (lk.arity() < 1 && mk1 != ModifierKind.NONE)
continue; continue;
for (ModifierKind mk2 : ModifierKind.values()) { for (ModifierKind mk1 : ModifierKind.values()) {
if (lk.arity() < 2 && mk2 != ModifierKind.NONE) if (mk1 != ModifierKind.NONE && lk.isShort())
continue; continue;
for (SubExprKind sk : SubExprKind.values()) { if (lk.arity() < 1 && mk1 != ModifierKind.NONE)
for (ExprKind ek : ExprKind.values()) { continue;
pool.execute( for (ModifierKind mk2 : ModifierKind.values()) {
new LambdaParserTest(pk1, pk2, mk1, if (lk.arity() < 2 && mk2 != ModifierKind.NONE)
mk2, lk, sk, ek)); continue;
for (SubExprKind sk : SubExprKind.values()) {
for (ExprKind ek : ExprKind.values()) {
pool.execute(
new LambdaParserTest(pk1, pk2, mk1,
mk2, lk, sk, ek, pn));
}
} }
} }
} }
...@@ -209,6 +222,7 @@ public class LambdaParserTest ...@@ -209,6 +222,7 @@ public class LambdaParserTest
ModifierKind mk1; ModifierKind mk1;
ModifierKind mk2; ModifierKind mk2;
LambdaKind lk; LambdaKind lk;
LambdaParameterName pn;
SubExprKind sk; SubExprKind sk;
ExprKind ek; ExprKind ek;
JavaSource source; JavaSource source;
...@@ -216,12 +230,13 @@ public class LambdaParserTest ...@@ -216,12 +230,13 @@ public class LambdaParserTest
LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2, LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2,
ModifierKind mk1, ModifierKind mk2, LambdaKind lk, ModifierKind mk1, ModifierKind mk2, LambdaKind lk,
SubExprKind sk, ExprKind ek) { SubExprKind sk, ExprKind ek, LambdaParameterName pn) {
this.pk1 = pk1; this.pk1 = pk1;
this.pk2 = pk2; this.pk2 = pk2;
this.mk1 = mk1; this.mk1 = mk1;
this.mk2 = mk2; this.mk2 = mk2;
this.lk = lk; this.lk = lk;
this.pn = pn;
this.sk = sk; this.sk = sk;
this.ek = ek; this.ek = ek;
this.source = new JavaSource(); this.source = new JavaSource();
...@@ -239,7 +254,7 @@ public class LambdaParserTest ...@@ -239,7 +254,7 @@ public class LambdaParserTest
public JavaSource() { public JavaSource() {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
source = template.replaceAll("#E", source = template.replaceAll("#E",
ek.expressionString(pk1, pk2, mk1, mk2, lk, sk)); ek.expressionString(pk1, pk2, mk1, mk2, lk, pn, sk));
} }
@Override @Override
...@@ -272,6 +287,9 @@ public class LambdaParserTest ...@@ -272,6 +287,9 @@ public class LambdaParserTest
errorExpected = true; errorExpected = true;
} }
errorExpected |= pn == LambdaParameterName.UNDERSCORE &&
lk.arity() > 0;
if (errorExpected != diagChecker.errorFound) { if (errorExpected != diagChecker.errorFound) {
throw new Error("invalid diagnostics for source:\n" + throw new Error("invalid diagnostics for source:\n" +
source.getCharContent(true) + source.getCharContent(true) +
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册