--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Sun Jun 09 15:48:57 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Jun 10 05:09:52 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -182,6 +182,8 @@
this.keepLineMap = keepLineMap;
this.errorTree = F.Erroneous();
endPosTable = newEndPosTable(keepEndPositions);
+ this.allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
+ Feature.SWITCH_EXPRESSION.allowedInSource(source);
}
protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
@@ -211,6 +213,10 @@
*/
boolean allowThisIdent;
+ /** Switch: is yield statement allowed in this source level?
+ */
+ boolean allowYieldStatement;
+
/** The type of the method receiver, as specified by a first "this" parameter.
*/
JCVariableDecl receiverParam;
@@ -769,9 +775,10 @@
public JCExpression unannotatedType(boolean allowVar) {
JCExpression result = term(TYPE);
-
- if (!allowVar && isRestrictedLocalVarTypeName(result, true)) {
- syntaxError(result.pos, Errors.VarNotAllowedHere);
+ Name restrictedTypeName;
+
+ if (!allowVar && (restrictedTypeName = restrictedTypeName(result, true)) != null) {
+ syntaxError(result.pos, Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
}
return result;
@@ -1377,6 +1384,7 @@
break;
case SWITCH:
checkSourceLevel(Feature.SWITCH_EXPRESSION);
+ allowYieldStatement = true;
int switchPos = token.pos;
nextToken();
JCExpression selector = parExpression();
@@ -1436,7 +1444,7 @@
kind = JCCase.RULE;
} else {
JCExpression value = parseExpression();
- stats = List.of(to(F.at(value).Break(value)));
+ stats = List.of(to(F.at(value).Yield(value)));
body = value;
kind = JCCase.RULE;
accept(SEMI);
@@ -1607,7 +1615,7 @@
int depth = 0;
boolean type = false;
ParensResult defaultResult = ParensResult.PARENS;
- outer: for (int lookahead = 0 ; ; lookahead++) {
+ outer: for (int lookahead = 0; ; lookahead++) {
TokenKind tk = S.token(lookahead).kind;
switch (tk) {
case COMMA:
@@ -1782,12 +1790,13 @@
if (explicitParams) {
LambdaClassifier lambdaClassifier = new LambdaClassifier();
for (JCVariableDecl param: params) {
+ Name restrictedTypeName;
if (param.vartype != null &&
- isRestrictedLocalVarTypeName(param.vartype, false) &&
+ (restrictedTypeName = restrictedTypeName(param.vartype, false)) != null &&
param.vartype.hasTag(TYPEARRAY)) {
log.error(DiagnosticFlag.SYNTAX, param.pos,
Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS.allowedInSource(source)
- ? Errors.VarNotAllowedArray : Errors.VarNotAllowedHere);
+ ? Errors.RestrictedTypeNotAllowedArray(restrictedTypeName) : Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
}
lambdaClassifier.addParameter(param);
if (lambdaClassifier.result() == LambdaParameterKind.ERROR) {
@@ -1799,7 +1808,7 @@
}
for (JCVariableDecl param: params) {
if (param.vartype != null
- && isRestrictedLocalVarTypeName(param.vartype, true)) {
+ && restrictedTypeName(param.vartype, true) != null) {
checkSourceLevel(param.pos, Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS);
param.startPos = TreeInfo.getStartPos(param.vartype);
param.vartype = null;
@@ -1837,7 +1846,7 @@
void addParameter(JCVariableDecl param) {
if (param.vartype != null && param.name != names.empty) {
- if (isRestrictedLocalVarTypeName(param.vartype, false)) {
+ if (restrictedTypeName(param.vartype, false) != null) {
reduce(LambdaParameterKind.VAR);
} else {
reduce(LambdaParameterKind.EXPLICIT);
@@ -1944,10 +1953,27 @@
return args.toList();
}
- JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
+ JCExpression arguments(List<JCExpression> typeArgs, JCExpression t) {
int pos = token.pos;
List<JCExpression> args = arguments();
- return toP(F.at(pos).Apply(typeArgs, t, args));
+ JCExpression mi = F.at(pos).Apply(typeArgs, t, args);
+ if (t.hasTag(IDENT) && isInvalidUnqualifiedMethodIdentifier(((JCIdent) t).pos,
+ ((JCIdent) t).name)) {
+ log.error(DiagnosticFlag.SYNTAX, t, Errors.InvalidYield);
+ mi = F.Erroneous(List.of(mi));
+ }
+ return toP(mi);
+ }
+
+ boolean isInvalidUnqualifiedMethodIdentifier(int pos, Name name) {
+ if (name == names.yield) {
+ if (allowYieldStatement) {
+ return true;
+ } else {
+ log.warning(pos, Warnings.InvalidYield);
+ }
+ }
+ return false;
}
/** TypeArgumentsOpt = [ TypeArguments ]
@@ -2506,6 +2532,7 @@
/**This method parses a statement appearing inside a block.
*/
+ @SuppressWarnings("fallthrough")
List<JCStatement> blockStatement() {
//todo: skip to anchor on error(?)
int pos = token.pos;
@@ -2543,6 +2570,52 @@
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum);
dc = token.comment(CommentStyle.JAVADOC);
return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
+ case IDENTIFIER:
+ if (token.name() == names.yield && allowYieldStatement) {
+ Token next = S.token(1);
+ boolean isYieldStatement;
+ switch (next.kind) {
+ case PLUS: case SUB: case STRINGLITERAL: case CHARLITERAL:
+ case INTLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
+ case NULL: case IDENTIFIER: case TRUE: case FALSE:
+ case NEW: case SWITCH: case THIS: case SUPER:
+ isYieldStatement = true;
+ break;
+ case PLUSPLUS: case SUBSUB:
+ isYieldStatement = S.token(2).kind != SEMI;
+ break;
+ case LPAREN:
+ int lookahead = 2;
+ int balance = 1;
+ boolean hasComma = false;
+ Token l;
+ while ((l = S.token(lookahead)).kind != EOF && balance != 0) {
+ switch (l.kind) {
+ case LPAREN: balance++; break;
+ case RPAREN: balance--; break;
+ case COMMA: if (balance == 1) hasComma = true; break;
+ }
+ lookahead++;
+ }
+ isYieldStatement = (!hasComma && lookahead != 3) || l.kind == ARROW;
+ break;
+ case SEMI: //error recovery - this is not a valid statement:
+ isYieldStatement = true;
+ break;
+ default:
+ isYieldStatement = false;
+ break;
+ }
+
+ if (isYieldStatement) {
+ nextToken();
+ JCExpression t = term(EXPR);
+ accept(SEMI);
+ return List.of(toP(F.at(pos).Yield(t)));
+ }
+
+ //else intentional fall-through
+ }
default:
Token prevToken = token;
JCExpression t = term(EXPR | TYPE);
@@ -2702,9 +2775,9 @@
}
case BREAK: {
nextToken();
- JCExpression value = token.kind == SEMI ? null : parseExpression();
+ Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
accept(SEMI);
- JCBreak t = toP(F.at(pos).Break(value));
+ JCBreak t = toP(F.at(pos).Break(label));
return t;
}
case CONTINUE: {
@@ -3181,14 +3254,14 @@
int startPos = Position.NOPOS;
if (elemType.hasTag(IDENT)) {
Name typeName = ((JCIdent)elemType).name;
- if (isRestrictedLocalVarTypeName(typeName, pos, !compound && localDecl)) {
+ if (isRestrictedTypeName(typeName, pos, !compound && localDecl)) {
if (type.hasTag(TYPEARRAY) && !compound) {
//error - 'var' and arrays
- reportSyntaxError(pos, Errors.VarNotAllowedArray);
+ reportSyntaxError(pos, Errors.RestrictedTypeNotAllowedArray(typeName));
} else {
if(compound)
//error - 'var' in compound local var decl
- reportSyntaxError(pos, Errors.VarNotAllowedCompound);
+ reportSyntaxError(pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
startPos = TreeInfo.getStartPos(mods);
if (startPos == Position.NOPOS)
startPos = TreeInfo.getStartPos(type);
@@ -3204,23 +3277,30 @@
return result;
}
- boolean isRestrictedLocalVarTypeName(JCExpression e, boolean shouldWarn) {
+ Name restrictedTypeName(JCExpression e, boolean shouldWarn) {
switch (e.getTag()) {
case IDENT:
- return isRestrictedLocalVarTypeName(((JCIdent)e).name, e.pos, shouldWarn);
+ return isRestrictedTypeName(((JCIdent)e).name, e.pos, shouldWarn) ? ((JCIdent)e).name : null;
case TYPEARRAY:
- return isRestrictedLocalVarTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
+ return restrictedTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
default:
- return false;
+ return null;
}
}
- boolean isRestrictedLocalVarTypeName(Name name, int pos, boolean shouldWarn) {
+ boolean isRestrictedTypeName(Name name, int pos, boolean shouldWarn) {
if (name == names.var) {
if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
return true;
} else if (shouldWarn) {
- log.warning(pos, Warnings.VarNotAllowed);
+ log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
+ }
+ }
+ if (name == names.yield) {
+ if (allowYieldStatement) {
+ return true;
+ } else if (shouldWarn) {
+ log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK13));
}
}
return false;
@@ -3614,8 +3694,8 @@
Name typeName() {
int pos = token.pos;
Name name = ident();
- if (isRestrictedLocalVarTypeName(name, pos, true)) {
- reportSyntaxError(pos, Errors.VarNotAllowed);
+ if (isRestrictedTypeName(name, pos, true)) {
+ reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, name == names.var ? Source.JDK10 : Source.JDK13));
}
return name;
}