mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8194892: add compiler support for local-variable syntax for lambda parameters
Reviewed-by: mcimadamore
This commit is contained in:
parent
c37e80c84f
commit
2591c21c01
15 changed files with 418 additions and 76 deletions
|
@ -43,11 +43,10 @@ import com.sun.tools.javac.tree.*;
|
||||||
import com.sun.tools.javac.tree.JCTree.*;
|
import com.sun.tools.javac.tree.JCTree.*;
|
||||||
import com.sun.tools.javac.util.*;
|
import com.sun.tools.javac.util.*;
|
||||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
|
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
|
||||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
|
||||||
import com.sun.tools.javac.util.JCDiagnostic.Error;
|
import com.sun.tools.javac.util.JCDiagnostic.Error;
|
||||||
import com.sun.tools.javac.util.JCDiagnostic.Warning;
|
import com.sun.tools.javac.util.JCDiagnostic.Warning;
|
||||||
import com.sun.tools.javac.util.JCDiagnostic.Fragment;
|
|
||||||
import com.sun.tools.javac.util.List;
|
import com.sun.tools.javac.util.List;
|
||||||
|
import com.sun.tools.javac.util.JCDiagnostic.Fragment;
|
||||||
|
|
||||||
import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
|
import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
|
||||||
import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
|
import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
|
||||||
|
@ -290,9 +289,31 @@ public class JavacParser implements Parser {
|
||||||
|
|
||||||
/** Skip forward until a suitable stop token is found.
|
/** Skip forward until a suitable stop token is found.
|
||||||
*/
|
*/
|
||||||
protected void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
|
protected void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement, boolean stopAtLambdaBody) {
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (token.kind) {
|
switch (token.kind) {
|
||||||
|
case ARROW:
|
||||||
|
if (stopAtLambdaBody) {
|
||||||
|
//find end of lambda expression; this could be either a comma or an rparen (if in method context),
|
||||||
|
//or a semi colon (if in assignment context).
|
||||||
|
int depth = 0;
|
||||||
|
while (true) {
|
||||||
|
switch (token.kind) {
|
||||||
|
case EOF:
|
||||||
|
case LBRACE: depth++; break;
|
||||||
|
case RBRACE: depth--; break;
|
||||||
|
case COMMA:
|
||||||
|
case RPAREN:
|
||||||
|
case SEMI:
|
||||||
|
if (depth == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nextToken();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SEMI:
|
case SEMI:
|
||||||
nextToken();
|
nextToken();
|
||||||
return;
|
return;
|
||||||
|
@ -1076,7 +1097,8 @@ public class JavacParser implements Parser {
|
||||||
break;
|
break;
|
||||||
case LPAREN:
|
case LPAREN:
|
||||||
if (typeArgs == null && (mode & EXPR) != 0) {
|
if (typeArgs == null && (mode & EXPR) != 0) {
|
||||||
ParensResult pres = analyzeParens();
|
LambdaClassfier lambdaClassifier = new LambdaClassfier();
|
||||||
|
ParensResult pres = analyzeParens(lambdaClassifier);
|
||||||
switch (pres) {
|
switch (pres) {
|
||||||
case CAST:
|
case CAST:
|
||||||
accept(LPAREN);
|
accept(LPAREN);
|
||||||
|
@ -1095,9 +1117,15 @@ public class JavacParser implements Parser {
|
||||||
mode = EXPR;
|
mode = EXPR;
|
||||||
JCExpression t1 = term3();
|
JCExpression t1 = term3();
|
||||||
return F.at(pos).TypeCast(t, t1);
|
return F.at(pos).TypeCast(t, t1);
|
||||||
|
case BAD_LAMBDA:
|
||||||
|
Assert.checkNonNull(lambdaClassifier.diagFragment);
|
||||||
|
t = syntaxError(pos, List.nil(), Errors.InvalidLambdaParameterDeclaration(lambdaClassifier.diagFragment));
|
||||||
|
skip(false, false, false, false, true);
|
||||||
|
break;
|
||||||
case IMPLICIT_LAMBDA:
|
case IMPLICIT_LAMBDA:
|
||||||
case EXPLICIT_LAMBDA:
|
case EXPLICIT_LAMBDA:
|
||||||
t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
|
case IMPLICIT_LAMBDA_ALL_VAR:
|
||||||
|
t = lambdaExpressionOrStatement(true, pres != ParensResult.IMPLICIT_LAMBDA, pos);
|
||||||
break;
|
break;
|
||||||
default: //PARENS
|
default: //PARENS
|
||||||
accept(LPAREN);
|
accept(LPAREN);
|
||||||
|
@ -1509,15 +1537,17 @@ public class JavacParser implements Parser {
|
||||||
* matching '>' and see if the subsequent terminal is either '.' or '::'.
|
* matching '>' and see if the subsequent terminal is either '.' or '::'.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("fallthrough")
|
@SuppressWarnings("fallthrough")
|
||||||
ParensResult analyzeParens() {
|
ParensResult analyzeParens(LambdaClassfier lambdaClassifier) {
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
boolean type = false;
|
boolean type = false;
|
||||||
outer: for (int lookahead = 0 ; ; lookahead++) {
|
outer: for (int lookahead = 0 ; ; lookahead++) {
|
||||||
TokenKind tk = S.token(lookahead).kind;
|
Token lookaheadToken = S.token(lookahead);
|
||||||
|
TokenKind tk = lookaheadToken.kind;
|
||||||
switch (tk) {
|
switch (tk) {
|
||||||
case COMMA:
|
case COMMA:
|
||||||
type = true;
|
type = true;
|
||||||
case EXTENDS: case SUPER: case DOT: case AMP:
|
break;
|
||||||
|
case FINAL: case EXTENDS: case SUPER: case DOT: case AMP:
|
||||||
//skip
|
//skip
|
||||||
break;
|
break;
|
||||||
case QUES:
|
case QUES:
|
||||||
|
@ -1534,7 +1564,8 @@ public class JavacParser implements Parser {
|
||||||
return ParensResult.CAST;
|
return ParensResult.CAST;
|
||||||
} else if (peekToken(lookahead, LAX_IDENTIFIER)) {
|
} else if (peekToken(lookahead, LAX_IDENTIFIER)) {
|
||||||
//Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
|
//Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
|
||||||
return ParensResult.EXPLICIT_LAMBDA;
|
lambdaClassifier.addExplicitParameter();
|
||||||
|
lookahead++; //skip Identifier
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LPAREN:
|
case LPAREN:
|
||||||
|
@ -1547,24 +1578,29 @@ public class JavacParser implements Parser {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RPAREN:
|
case RPAREN:
|
||||||
// if we have seen something that looks like a type,
|
if (peekToken(lookahead, ARROW)) {
|
||||||
// then it's a cast expression
|
//this is a lambda
|
||||||
if (type) return ParensResult.CAST;
|
return lambdaClassifier.result();
|
||||||
// otherwise, disambiguate cast vs. parenthesized expression
|
} else {
|
||||||
// based on subsequent token.
|
// if we have seen something that looks like a type,
|
||||||
switch (S.token(lookahead + 1).kind) {
|
// then it's a cast expression
|
||||||
/*case PLUSPLUS: case SUBSUB: */
|
if (type) return ParensResult.CAST;
|
||||||
case BANG: case TILDE:
|
// otherwise, disambiguate cast vs. parenthesized expression
|
||||||
case LPAREN: case THIS: case SUPER:
|
// based on subsequent token.
|
||||||
case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
|
switch (S.token(lookahead + 1).kind) {
|
||||||
case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
|
/*case PLUSPLUS: case SUBSUB: */
|
||||||
case TRUE: case FALSE: case NULL:
|
case BANG: case TILDE:
|
||||||
case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
|
case LPAREN: case THIS: case SUPER:
|
||||||
case BYTE: case SHORT: case CHAR: case INT:
|
case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
|
||||||
case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
|
case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
|
||||||
return ParensResult.CAST;
|
case TRUE: case FALSE: case NULL:
|
||||||
default:
|
case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
|
||||||
return ParensResult.PARENS;
|
case BYTE: case SHORT: case CHAR: case INT:
|
||||||
|
case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
|
||||||
|
return ParensResult.CAST;
|
||||||
|
default:
|
||||||
|
return ParensResult.PARENS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case UNDERSCORE:
|
case UNDERSCORE:
|
||||||
case ASSERT:
|
case ASSERT:
|
||||||
|
@ -1572,17 +1608,23 @@ public class JavacParser implements Parser {
|
||||||
case IDENTIFIER:
|
case IDENTIFIER:
|
||||||
if (peekToken(lookahead, LAX_IDENTIFIER)) {
|
if (peekToken(lookahead, LAX_IDENTIFIER)) {
|
||||||
// Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
|
// Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
|
||||||
return ParensResult.EXPLICIT_LAMBDA;
|
if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) &&
|
||||||
} else if (peekToken(lookahead, RPAREN, ARROW)) {
|
lookaheadToken.name() == names.var) {
|
||||||
// Identifier, ')' '->' -> implicit lambda
|
lambdaClassifier.addImplicitVarParameter();
|
||||||
return ParensResult.IMPLICIT_LAMBDA;
|
} else {
|
||||||
|
lambdaClassifier.addExplicitParameter();
|
||||||
|
}
|
||||||
|
lookahead++; //skip Identifier
|
||||||
|
} else if ((!type && peekToken(lookahead, COMMA)) || peekToken(lookahead, RPAREN)) {
|
||||||
|
lambdaClassifier.addImplicitParameter();
|
||||||
}
|
}
|
||||||
type = false;
|
type = false;
|
||||||
break;
|
break;
|
||||||
case FINAL:
|
|
||||||
case ELLIPSIS:
|
case ELLIPSIS:
|
||||||
//those can only appear in explicit lambdas
|
//those can only appear in explicit, non-var, lambdas
|
||||||
return ParensResult.EXPLICIT_LAMBDA;
|
lambdaClassifier.addExplicitParameter();
|
||||||
|
lookahead++; //skip Identifier
|
||||||
|
break;
|
||||||
case MONKEYS_AT:
|
case MONKEYS_AT:
|
||||||
type = true;
|
type = true;
|
||||||
lookahead += 1; //skip '@'
|
lookahead += 1; //skip '@'
|
||||||
|
@ -1614,7 +1656,9 @@ public class JavacParser implements Parser {
|
||||||
case LBRACKET:
|
case LBRACKET:
|
||||||
if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
|
if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
|
||||||
// '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
|
// '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
|
||||||
return ParensResult.EXPLICIT_LAMBDA;
|
lambdaClassifier.addExplicitParameter();
|
||||||
|
lookahead += 2; //skip ']' Identifier
|
||||||
|
break;
|
||||||
} else if (peekToken(lookahead, RBRACKET, RPAREN) ||
|
} else if (peekToken(lookahead, RBRACKET, RPAREN) ||
|
||||||
peekToken(lookahead, RBRACKET, AMP)) {
|
peekToken(lookahead, RBRACKET, AMP)) {
|
||||||
// '[', ']', ')' -> cast
|
// '[', ']', ')' -> cast
|
||||||
|
@ -1643,12 +1687,15 @@ public class JavacParser implements Parser {
|
||||||
// '>', '&' -> cast
|
// '>', '&' -> cast
|
||||||
return ParensResult.CAST;
|
return ParensResult.CAST;
|
||||||
} else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
|
} else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
|
||||||
peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
|
peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW)) {
|
||||||
peekToken(lookahead, ELLIPSIS)) {
|
|
||||||
// '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
|
// '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
|
||||||
// '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
|
// '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
|
||||||
|
lambdaClassifier.addExplicitParameter();
|
||||||
|
lookahead++; //skip Identifier
|
||||||
|
break;
|
||||||
|
} else if (peekToken(lookahead, ELLIPSIS)) {
|
||||||
// '>', '...' -> explicit lambda
|
// '>', '...' -> explicit lambda
|
||||||
return ParensResult.EXPLICIT_LAMBDA;
|
break; //this is handled in the outer switch
|
||||||
}
|
}
|
||||||
//it looks a type, but could still be (i) a cast to generic type,
|
//it looks a type, but could still be (i) a cast to generic type,
|
||||||
//(ii) an unbound method reference or (iii) an explicit lambda
|
//(ii) an unbound method reference or (iii) an explicit lambda
|
||||||
|
@ -1666,6 +1713,61 @@ public class JavacParser implements Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LambdaClassfier {
|
||||||
|
ParensResult kind;
|
||||||
|
Fragment diagFragment;
|
||||||
|
|
||||||
|
void addExplicitParameter() {
|
||||||
|
reduce(ParensResult.EXPLICIT_LAMBDA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addImplicitVarParameter() {
|
||||||
|
reduce(ParensResult.IMPLICIT_LAMBDA_ALL_VAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addImplicitParameter() {
|
||||||
|
reduce(ParensResult.IMPLICIT_LAMBDA);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reduce(ParensResult newKind) {
|
||||||
|
if (kind == null) {
|
||||||
|
kind = newKind;
|
||||||
|
} else if (kind != newKind && kind != ParensResult.BAD_LAMBDA) {
|
||||||
|
ParensResult currentKind = kind;
|
||||||
|
kind = ParensResult.BAD_LAMBDA;
|
||||||
|
switch (currentKind) {
|
||||||
|
case EXPLICIT_LAMBDA:
|
||||||
|
if (newKind == ParensResult.IMPLICIT_LAMBDA) {
|
||||||
|
diagFragment = Fragments.ImplicitAndExplicitNotAllowed;
|
||||||
|
} else if (newKind == ParensResult.IMPLICIT_LAMBDA_ALL_VAR) {
|
||||||
|
diagFragment = Fragments.VarAndExplicitNotAllowed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IMPLICIT_LAMBDA:
|
||||||
|
if (newKind == ParensResult.EXPLICIT_LAMBDA) {
|
||||||
|
diagFragment = Fragments.ImplicitAndExplicitNotAllowed;
|
||||||
|
} else if (newKind == ParensResult.IMPLICIT_LAMBDA_ALL_VAR) {
|
||||||
|
diagFragment = Fragments.VarAndImplicitNotAllowed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IMPLICIT_LAMBDA_ALL_VAR:
|
||||||
|
if (newKind == ParensResult.EXPLICIT_LAMBDA) {
|
||||||
|
diagFragment = Fragments.VarAndExplicitNotAllowed;
|
||||||
|
} else if (newKind == ParensResult.IMPLICIT_LAMBDA) {
|
||||||
|
diagFragment = Fragments.VarAndImplicitNotAllowed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AssertionError("unexpected option for field kind");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParensResult result() {
|
||||||
|
return kind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Accepts all identifier-like tokens */
|
/** Accepts all identifier-like tokens */
|
||||||
protected Filter<TokenKind> LAX_IDENTIFIER = t -> t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
|
protected Filter<TokenKind> LAX_IDENTIFIER = t -> t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
|
||||||
|
|
||||||
|
@ -1673,7 +1775,15 @@ public class JavacParser implements Parser {
|
||||||
CAST,
|
CAST,
|
||||||
EXPLICIT_LAMBDA,
|
EXPLICIT_LAMBDA,
|
||||||
IMPLICIT_LAMBDA,
|
IMPLICIT_LAMBDA,
|
||||||
PARENS
|
IMPLICIT_LAMBDA_ALL_VAR,
|
||||||
|
BAD_LAMBDA,
|
||||||
|
PARENS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BAD_LAMBDA_KIND {
|
||||||
|
EXPLICIT_AND_VAR,
|
||||||
|
IMPLICIT_AND_VAR,
|
||||||
|
EXPLICIT_AND_IMPLICIT,
|
||||||
}
|
}
|
||||||
|
|
||||||
JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
|
JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
|
||||||
|
@ -1896,6 +2006,9 @@ public class JavacParser implements Parser {
|
||||||
List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
|
List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
|
||||||
|
|
||||||
if (token.kind == LBRACKET) {
|
if (token.kind == LBRACKET) {
|
||||||
|
if (t == null) {
|
||||||
|
log.error(token.pos, Errors.VarNotAllowedArray);
|
||||||
|
}
|
||||||
int pos = token.pos;
|
int pos = token.pos;
|
||||||
nextToken();
|
nextToken();
|
||||||
t = bracketsOptCont(t, pos, nextLevelAnnotations);
|
t = bracketsOptCont(t, pos, nextLevelAnnotations);
|
||||||
|
@ -2294,7 +2407,7 @@ public class JavacParser implements Parser {
|
||||||
if (token.pos == lastErrPos)
|
if (token.pos == lastErrPos)
|
||||||
return stats.toList();
|
return stats.toList();
|
||||||
if (token.pos <= endPosTable.errorEndPos) {
|
if (token.pos <= endPosTable.errorEndPos) {
|
||||||
skip(false, true, true, true);
|
skip(false, true, true, true, false);
|
||||||
lastErrPos = token.pos;
|
lastErrPos = token.pos;
|
||||||
}
|
}
|
||||||
stats.addAll(stat);
|
stats.addAll(stat);
|
||||||
|
@ -3133,7 +3246,7 @@ public class JavacParser implements Parser {
|
||||||
while (token.kind != EOF) {
|
while (token.kind != EOF) {
|
||||||
if (token.pos <= endPosTable.errorEndPos) {
|
if (token.pos <= endPosTable.errorEndPos) {
|
||||||
// error recovery
|
// error recovery
|
||||||
skip(checkForImports, false, false, false);
|
skip(checkForImports, false, false, false, false);
|
||||||
if (token.kind == EOF)
|
if (token.kind == EOF)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3270,7 +3383,7 @@ public class JavacParser implements Parser {
|
||||||
defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
|
defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
|
||||||
} else {
|
} else {
|
||||||
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ExpectedStr("'" + names.with + "'"));
|
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ExpectedStr("'" + names.with + "'"));
|
||||||
skip(false, false, false, false);
|
skip(false, false, false, false, false);
|
||||||
}
|
}
|
||||||
} else if (token.name() == names.uses) {
|
} else if (token.name() == names.uses) {
|
||||||
nextToken();
|
nextToken();
|
||||||
|
@ -3475,7 +3588,7 @@ public class JavacParser implements Parser {
|
||||||
false));
|
false));
|
||||||
if (token.pos <= endPosTable.errorEndPos) {
|
if (token.pos <= endPosTable.errorEndPos) {
|
||||||
// error recovery
|
// error recovery
|
||||||
skip(false, true, true, false);
|
skip(false, true, true, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3537,7 +3650,7 @@ public class JavacParser implements Parser {
|
||||||
accept(LBRACE);
|
accept(LBRACE);
|
||||||
if (token.pos <= endPosTable.errorEndPos) {
|
if (token.pos <= endPosTable.errorEndPos) {
|
||||||
// error recovery
|
// error recovery
|
||||||
skip(false, true, false, false);
|
skip(false, true, false, false, false);
|
||||||
if (token.kind == LBRACE)
|
if (token.kind == LBRACE)
|
||||||
nextToken();
|
nextToken();
|
||||||
}
|
}
|
||||||
|
@ -3546,7 +3659,7 @@ public class JavacParser implements Parser {
|
||||||
defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
|
defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
|
||||||
if (token.pos <= endPosTable.errorEndPos) {
|
if (token.pos <= endPosTable.errorEndPos) {
|
||||||
// error recovery
|
// error recovery
|
||||||
skip(false, true, true, false);
|
skip(false, true, true, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accept(RBRACE);
|
accept(RBRACE);
|
||||||
|
@ -3713,7 +3826,7 @@ public class JavacParser implements Parser {
|
||||||
accept(SEMI);
|
accept(SEMI);
|
||||||
if (token.pos <= endPosTable.errorEndPos) {
|
if (token.pos <= endPosTable.errorEndPos) {
|
||||||
// error recovery
|
// error recovery
|
||||||
skip(false, true, false, false);
|
skip(false, true, false, false, false);
|
||||||
if (token.kind == LBRACE) {
|
if (token.kind == LBRACE) {
|
||||||
body = block();
|
body = block();
|
||||||
}
|
}
|
||||||
|
@ -3947,7 +4060,7 @@ public class JavacParser implements Parser {
|
||||||
// need to distinguish between vararg annos and array annos
|
// need to distinguish between vararg annos and array annos
|
||||||
// look at typeAnnotationsPushedBack comment
|
// look at typeAnnotationsPushedBack comment
|
||||||
this.permitTypeAnnotationsPushBack = true;
|
this.permitTypeAnnotationsPushBack = true;
|
||||||
JCExpression type = parseType();
|
JCExpression type = parseType(lambdaParameter);
|
||||||
this.permitTypeAnnotationsPushBack = false;
|
this.permitTypeAnnotationsPushBack = false;
|
||||||
|
|
||||||
if (token.kind == ELLIPSIS) {
|
if (token.kind == ELLIPSIS) {
|
||||||
|
@ -3964,6 +4077,10 @@ public class JavacParser implements Parser {
|
||||||
}
|
}
|
||||||
typeAnnotationsPushedBack = List.nil();
|
typeAnnotationsPushedBack = List.nil();
|
||||||
}
|
}
|
||||||
|
if (lambdaParameter && isRestrictedLocalVarTypeName(type)) {
|
||||||
|
//implicit lambda parameter type (with 'var')
|
||||||
|
type = null;
|
||||||
|
}
|
||||||
return variableDeclaratorId(mods, type, lambdaParameter);
|
return variableDeclaratorId(mods, type, lambdaParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1229,6 +1229,20 @@ compiler.err.var.not.allowed.array=\
|
||||||
compiler.err.var.not.allowed.compound=\
|
compiler.err.var.not.allowed.compound=\
|
||||||
''var'' is not allowed in a compound declaration
|
''var'' is not allowed in a compound declaration
|
||||||
|
|
||||||
|
# 0: fragment
|
||||||
|
compiler.err.invalid.lambda.parameter.declaration=\
|
||||||
|
invalid lambda parameter declaration\n\
|
||||||
|
({0})
|
||||||
|
|
||||||
|
compiler.misc.implicit.and.explicit.not.allowed=\
|
||||||
|
cannot mix implicitly-typed and explicitly-typed parameters
|
||||||
|
|
||||||
|
compiler.misc.var.and.explicit.not.allowed=\
|
||||||
|
cannot mix ''var'' and explicitly-typed parameters
|
||||||
|
|
||||||
|
compiler.misc.var.and.implicit.not.allowed=\
|
||||||
|
cannot mix ''var'' and implicitly-typed parameters
|
||||||
|
|
||||||
compiler.misc.local.cant.infer.null=\
|
compiler.misc.local.cant.infer.null=\
|
||||||
variable initializer is ''null''
|
variable initializer is ''null''
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ class ReplParser extends JavacParser {
|
||||||
while (token.kind != EOF) {
|
while (token.kind != EOF) {
|
||||||
if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
|
if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
|
||||||
// error recovery
|
// error recovery
|
||||||
skip(true, false, false, false);
|
skip(true, false, false, false, false);
|
||||||
if (token.kind == EOF) {
|
if (token.kind == EOF) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.var.not.allowed.array
|
||||||
|
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
class BracketsNotAllowedImplicitLambda {
|
||||||
|
BiFunction<String[], String, String> f = (var s1[], var s2) -> s2;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.invalid.lambda.parameter.declaration
|
||||||
|
// key: compiler.misc.implicit.and.explicit.not.allowed
|
||||||
|
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
class ExplicitImplicitLambda {
|
||||||
|
IntBinaryOperator f = (int x, y) -> x + y;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.invalid.lambda.parameter.declaration
|
||||||
|
// key: compiler.misc.var.and.implicit.not.allowed
|
||||||
|
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
class VarAllOrNothing {
|
||||||
|
IntBinaryOperator f = (x, var y) -> x + y;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.invalid.lambda.parameter.declaration
|
||||||
|
// key: compiler.misc.var.and.explicit.not.allowed
|
||||||
|
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
class VarExplicitLambda {
|
||||||
|
IntBinaryOperator f = (int x, var y) -> x + y;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 2018, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// key: compiler.err.invalid.lambda.parameter.declaration
|
||||||
|
// key: compiler.misc.var.and.explicit.not.allowed
|
||||||
|
|
||||||
|
class VarNotAllowedExplicitLambda {
|
||||||
|
F f = (String s, var v)->{};
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
T8131742.java:8:38: compiler.err.expected3: ',', ')', '['
|
T8131742.java:8:31: compiler.err.expected: ')'
|
||||||
T8131742.java:8:39: compiler.err.this.as.identifier
|
T8131742.java:8:39: compiler.err.this.as.identifier
|
||||||
T8131742.java:8:43: compiler.err.expected: ';'
|
T8131742.java:8:43: compiler.err.expected: token.identifier
|
||||||
3 errors
|
3 errors
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -40,6 +40,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import combo.ComboInstance;
|
import combo.ComboInstance;
|
||||||
import combo.ComboParameter;
|
import combo.ComboParameter;
|
||||||
|
@ -105,26 +106,44 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SourceKind {
|
||||||
|
SOURCE_9("9"),
|
||||||
|
SOURCE_10("10");
|
||||||
|
|
||||||
|
String sourceNumber;
|
||||||
|
|
||||||
|
SourceKind(String sourceNumber) {
|
||||||
|
this.sourceNumber = sourceNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum LambdaParameterKind implements ComboParameter {
|
enum LambdaParameterKind implements ComboParameter {
|
||||||
IMPLICIT(""),
|
|
||||||
EXPLIICT_SIMPLE("A"),
|
|
||||||
EXPLIICT_SIMPLE_ARR1("A[]"),
|
|
||||||
EXPLIICT_SIMPLE_ARR2("A[][]"),
|
|
||||||
EXPLICIT_VARARGS("A..."),
|
|
||||||
EXPLICIT_GENERIC1("A<X>"),
|
|
||||||
EXPLICIT_GENERIC2("A<? extends X, ? super Y>"),
|
|
||||||
EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>..."),
|
|
||||||
EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]"),
|
|
||||||
EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]");
|
|
||||||
|
|
||||||
String parameterType;
|
IMPLICIT_1("", ExplicitKind.IMPLICIT),
|
||||||
|
IMPLICIT_2("var", ExplicitKind.IMPLICIT_VAR),
|
||||||
|
EXPLIICT_SIMPLE("A", ExplicitKind.EXPLICIT),
|
||||||
|
EXPLIICT_SIMPLE_ARR1("A[]", ExplicitKind.EXPLICIT),
|
||||||
|
EXPLIICT_SIMPLE_ARR2("A[][]", ExplicitKind.EXPLICIT),
|
||||||
|
EXPLICIT_VARARGS("A...", ExplicitKind.EXPLICIT),
|
||||||
|
EXPLICIT_GENERIC1("A<X>", ExplicitKind.EXPLICIT),
|
||||||
|
EXPLICIT_GENERIC2("A<? extends X, ? super Y>", ExplicitKind.EXPLICIT),
|
||||||
|
EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>...", ExplicitKind.EXPLICIT),
|
||||||
|
EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]", ExplicitKind.EXPLICIT),
|
||||||
|
EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]", ExplicitKind.EXPLICIT);
|
||||||
|
|
||||||
LambdaParameterKind(String parameterType) {
|
enum ExplicitKind {
|
||||||
this.parameterType = parameterType;
|
IMPLICIT,
|
||||||
|
IMPLICIT_VAR,
|
||||||
|
EXPLICIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean explicit() {
|
String parameterType;
|
||||||
return this != IMPLICIT;
|
ExplicitKind explicitKind;
|
||||||
|
|
||||||
|
|
||||||
|
LambdaParameterKind(String parameterType, ExplicitKind ekind) {
|
||||||
|
this.parameterType = parameterType;
|
||||||
|
this.explicitKind = ekind;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isVarargs() {
|
boolean isVarargs() {
|
||||||
|
@ -136,12 +155,23 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
|
||||||
public String expand(String optParameter) {
|
public String expand(String optParameter) {
|
||||||
return parameterType;
|
return parameterType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExplicitKind explicitKind(SourceKind sk) {
|
||||||
|
switch (explicitKind) {
|
||||||
|
case IMPLICIT_VAR:
|
||||||
|
return (sk == SourceKind.SOURCE_9) ?
|
||||||
|
ExplicitKind.EXPLICIT : ExplicitKind.IMPLICIT_VAR;
|
||||||
|
default:
|
||||||
|
return explicitKind;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ModifierKind implements ComboParameter {
|
enum ModifierKind implements ComboParameter {
|
||||||
NONE(""),
|
NONE(""),
|
||||||
FINAL("final"),
|
FINAL("final"),
|
||||||
PUBLIC("public");
|
PUBLIC("public"),
|
||||||
|
ANNO("@A");
|
||||||
|
|
||||||
String modifier;
|
String modifier;
|
||||||
|
|
||||||
|
@ -152,7 +182,8 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
|
||||||
boolean compatibleWith(LambdaParameterKind pk) {
|
boolean compatibleWith(LambdaParameterKind pk) {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case PUBLIC: return false;
|
case PUBLIC: return false;
|
||||||
case FINAL: return pk != LambdaParameterKind.IMPLICIT;
|
case ANNO:
|
||||||
|
case FINAL: return pk != LambdaParameterKind.IMPLICIT_1;
|
||||||
case NONE: return true;
|
case NONE: return true;
|
||||||
default: throw new AssertionError("Invalid modifier kind " + this);
|
default: throw new AssertionError("Invalid modifier kind " + this);
|
||||||
}
|
}
|
||||||
|
@ -208,6 +239,7 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
|
||||||
new ComboTestHelper<LambdaParserTest>()
|
new ComboTestHelper<LambdaParserTest>()
|
||||||
.withFilter(LambdaParserTest::redundantTestFilter)
|
.withFilter(LambdaParserTest::redundantTestFilter)
|
||||||
.withFilter(LambdaParserTest::badImplicitFilter)
|
.withFilter(LambdaParserTest::badImplicitFilter)
|
||||||
|
.withDimension("SOURCE", (x, sk) -> x.sk = sk, SourceKind.values())
|
||||||
.withDimension("LAMBDA", (x, lk) -> x.lk = lk, LambdaKind.values())
|
.withDimension("LAMBDA", (x, lk) -> x.lk = lk, LambdaKind.values())
|
||||||
.withDimension("NAME", (x, name) -> x.pn = name, LambdaParameterName.values())
|
.withDimension("NAME", (x, name) -> x.pn = name, LambdaParameterName.values())
|
||||||
.withArrayDimension("TYPE", (x, type, idx) -> x.pks[idx] = type, 2, LambdaParameterKind.values())
|
.withArrayDimension("TYPE", (x, type, idx) -> x.pks[idx] = type, 2, LambdaParameterKind.values())
|
||||||
|
@ -221,6 +253,7 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
|
||||||
ModifierKind[] mks = new ModifierKind[2];
|
ModifierKind[] mks = new ModifierKind[2];
|
||||||
LambdaKind lk;
|
LambdaKind lk;
|
||||||
LambdaParameterName pn;
|
LambdaParameterName pn;
|
||||||
|
SourceKind sk;
|
||||||
|
|
||||||
boolean badImplicitFilter() {
|
boolean badImplicitFilter() {
|
||||||
return !(mks[0] != ModifierKind.NONE && lk.isShort());
|
return !(mks[0] != ModifierKind.NONE && lk.isShort());
|
||||||
|
@ -240,13 +273,15 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String template = "class Test {\n" +
|
String template = "@interface A { }\n" +
|
||||||
" SAM s = #{EXPR};\n" +
|
"class Test {\n" +
|
||||||
"}";
|
" SAM s = #{EXPR};\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doWork() throws IOException {
|
public void doWork() throws IOException {
|
||||||
newCompilationTask()
|
newCompilationTask()
|
||||||
|
.withOptions(Arrays.asList("-source", sk.sourceNumber))
|
||||||
.withSourceFromTemplate(template)
|
.withSourceFromTemplate(template)
|
||||||
.parse(this::check);
|
.parse(this::check);
|
||||||
}
|
}
|
||||||
|
@ -256,7 +291,7 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
|
||||||
(lk.arity() > 1 && !mks[1].compatibleWith(pks[1]));
|
(lk.arity() > 1 && !mks[1].compatibleWith(pks[1]));
|
||||||
|
|
||||||
if (lk.arity() == 2 &&
|
if (lk.arity() == 2 &&
|
||||||
(pks[0].explicit() != pks[1].explicit() ||
|
(pks[0].explicitKind(sk) != pks[1].explicitKind(sk) ||
|
||||||
pks[0].isVarargs())) {
|
pks[0].isVarargs())) {
|
||||||
errorExpected = true;
|
errorExpected = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ class ParserTest<var extends AutoCloseable> {
|
||||||
List<? extends var> l2; //error
|
List<? extends var> l2; //error
|
||||||
List<? super var> l3; //error
|
List<? super var> l3; //error
|
||||||
try {
|
try {
|
||||||
Function<var, String> f = (var x2) -> ""; //error
|
Function<var, String> f = (var x2) -> ""; //ok
|
||||||
} catch (var ex) { } //error
|
} catch (var ex) { } //error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,7 @@ ParserTest.java:59:14: compiler.err.var.not.allowed.here
|
||||||
ParserTest.java:60:24: compiler.err.var.not.allowed.here
|
ParserTest.java:60:24: compiler.err.var.not.allowed.here
|
||||||
ParserTest.java:61:22: compiler.err.var.not.allowed.here
|
ParserTest.java:61:22: compiler.err.var.not.allowed.here
|
||||||
ParserTest.java:63:22: compiler.err.var.not.allowed.here
|
ParserTest.java:63:22: compiler.err.var.not.allowed.here
|
||||||
ParserTest.java:63:40: compiler.err.var.not.allowed.here
|
|
||||||
ParserTest.java:64:18: compiler.err.var.not.allowed.here
|
ParserTest.java:64:18: compiler.err.var.not.allowed.here
|
||||||
ParserTest.java:68:35: compiler.err.var.not.allowed.here
|
ParserTest.java:68:35: compiler.err.var.not.allowed.here
|
||||||
ParserTest.java:69:22: compiler.err.var.not.allowed.here
|
ParserTest.java:69:22: compiler.err.var.not.allowed.here
|
||||||
24 errors
|
23 errors
|
||||||
|
|
|
@ -104,7 +104,7 @@ class TrialParser extends JavacParser {
|
||||||
while (token.kind != EOF) {
|
while (token.kind != EOF) {
|
||||||
if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
|
if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
|
||||||
// error recovery
|
// error recovery
|
||||||
skip(true, false, false, false);
|
skip(true, false, false, false, false);
|
||||||
if (token.kind == EOF) {
|
if (token.kind == EOF) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @bug 8194892
|
||||||
|
* @summary add compiler support for local-variable syntax for lambda parameters
|
||||||
|
* @compile/fail/ref=VarInImplicitLambdaNegTest01.out -XDrawDiagnostics VarInImplicitLambdaNegTest01.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
class VarInImplicitLambdaNegTest01 {
|
||||||
|
IntBinaryOperator f1 = (x, var y) -> x + y;
|
||||||
|
IntBinaryOperator f2 = (var x, y) -> x + y;
|
||||||
|
IntBinaryOperator f3 = (int x, var y) -> x + y;
|
||||||
|
IntBinaryOperator f4 = (int x, y) -> x + y;
|
||||||
|
|
||||||
|
BiFunction<String[], String, String> f5 = (var s1[], var s2) -> s2;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
VarInImplicitLambdaNegTest01.java:11:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.implicit.not.allowed)
|
||||||
|
VarInImplicitLambdaNegTest01.java:12:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.implicit.not.allowed)
|
||||||
|
VarInImplicitLambdaNegTest01.java:13:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.explicit.not.allowed)
|
||||||
|
VarInImplicitLambdaNegTest01.java:14:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
|
||||||
|
VarInImplicitLambdaNegTest01.java:16:54: compiler.err.var.not.allowed.array
|
||||||
|
5 errors
|
Loading…
Add table
Add a link
Reference in a new issue