--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Feb 22 12:26:01 2018 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Feb 22 15:49:32 2018 -0500
@@ -1673,6 +1673,8 @@
CAST,
EXPLICIT_LAMBDA,
IMPLICIT_LAMBDA,
+ IMPLICIT_LAMBDA_ALL_VAR,
+ BAD_LAMBDA,
PARENS
}
@@ -1681,9 +1683,92 @@
formalParameters(true) :
implicitParameters(hasParens);
+ if (explicitParams) {
+ LambdaClassfier lambdaClassfier = new LambdaClassfier();
+ for (JCVariableDecl param: params) {
+ if (param.vartype != null &&
+ isRestrictedLocalVarTypeName(param.vartype) &&
+ param.vartype.hasTag(TYPEARRAY)) {
+ log.error(DiagnosticFlag.SYNTAX, param.pos, Errors.VarNotAllowedArray);
+ }
+ if (param.vartype != null && param.name != names.empty) {
+ if (isRestrictedLocalVarTypeName(param.vartype)) {
+ lambdaClassfier.addImplicitVarParameter();
+ } else {
+ lambdaClassfier.addExplicitParameter();
+ }
+ }
+ if (param.vartype == null && param.name != names.empty ||
+ param.vartype != null && param.name == names.empty) {
+ lambdaClassfier.addImplicitParameter();
+ }
+ if (lambdaClassfier.result() == ParensResult.BAD_LAMBDA) {
+ break;
+ }
+ }
+ if (lambdaClassfier.diagFragment != null) {
+ log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidLambdaParameterDeclaration(lambdaClassfier.diagFragment));
+ }
+ }
return lambdaExpressionOrStatementRest(params, pos);
}
+ class LambdaClassfier {
+ ParensResult kind; //ParensResult.EXPLICIT_LAMBDA;
+ Fragment diagFragment;
+ List<JCVariableDecl> params;
+
+ 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;
+ }
+ }
+
JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
checkSourceLevel(Feature.LAMBDA);
accept(ARROW);
@@ -3044,7 +3129,21 @@
return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
}
} else {
- name = ident();
+ if (!lambdaParameter ||
+ LAX_IDENTIFIER.accepts(token.kind) ||
+ mods.flags != Flags.PARAMETER ||
+ mods.annotations.nonEmpty()) {
+ name = ident();
+ } else {
+ /** if it is a lambda parameter and the token kind is not an identifier,
+ * and there are no modifiers or annotations, then this means that the compiler
+ * supposed the lambda to be explicit but it can contain a mix of implicit,
+ * var or explicit parameters. So we assign the error name to the parameter name
+ * instead of issuing an error and analyze the lambda parameters as a whole at
+ * a higher level.
+ */
+ name = names.empty;
+ }
}
}
if ((mods.flags & Flags.VARARGS) != 0 &&
@@ -3947,7 +4046,7 @@
// need to distinguish between vararg annos and array annos
// look at typeAnnotationsPushedBack comment
this.permitTypeAnnotationsPushBack = true;
- JCExpression type = parseType();
+ JCExpression type = parseType(lambdaParameter);
this.permitTypeAnnotationsPushBack = false;
if (token.kind == ELLIPSIS) {