diff -r 3390b463d7a2 -r 03ae177c26b0 src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java --- 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 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 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) {