diff options
| author | ssankaran | 2013-11-28 08:43:40 +0000 |
|---|---|---|
| committer | ssankaran | 2013-11-28 16:25:31 +0000 |
| commit | 227e3d5fec0001fbc06115e3f3e6f09f357952e2 (patch) | |
| tree | 7b0193069d74cf7ceae6e28cc930885049b8cd6c | |
| parent | 4f833be4365ac5abb1ac0cf3973cd75cbb0d7487 (diff) | |
| download | eclipse.jdt.core-227e3d5fec0001fbc06115e3f3e6f09f357952e2.tar.gz eclipse.jdt.core-227e3d5fec0001fbc06115e3f3e6f09f357952e2.tar.xz eclipse.jdt.core-227e3d5fec0001fbc06115e3f3e6f09f357952e2.zip | |
Part I of fix for Bug 422468 - [1.8][assist] Code assist issues with
type elided lambda parameters
8 files changed, 275 insertions, 82 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java index e9301c8b2a..e12991fa44 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java @@ -1433,4 +1433,102 @@ public void testFieldInit() throws JavaModelException { elements ); } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=422468, [1.8][assist] Code assist issues with type elided lambda parameters +public void test422468() throws JavaModelException { + this.wc = getWorkingCopy( + "/Resolve/src/X.java", + "interface I {\n" + + " void foo(X x, Object y);\n" + + "}\n" + + "public class X {\n" + + " I i = (first, second) -> { System.out.println(); };\n" + + "}\n"); + + String str = this.wc.getSource(); + String selection = "first"; + int start = str.lastIndexOf(selection); + int length = selection.length(); + + IJavaElement[] elements = this.wc.codeSelect(start, length); + assertElementsEqual( + "Unexpected elements", + "first [in i [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]]", + elements + ); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=422468, [1.8][assist] Code assist issues with type elided lambda parameters +public void test422468a() throws JavaModelException { + this.wc = getWorkingCopy( + "/Resolve/src/X.java", + "interface I {\n" + + " void foo(X x, Object y);\n" + + "}\n" + + "public class X {\n" + + " I i = (first, second) -> { System.out.println(); };\n" + + "}\n"); + + String str = this.wc.getSource(); + String selection = "second"; + int start = str.lastIndexOf(selection); + int length = selection.length(); + + IJavaElement[] elements = this.wc.codeSelect(start, length); + assertElementsEqual( + "Unexpected elements", + "second [in i [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]]", + elements + ); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=422468, [1.8][assist] Code assist issues with type elided lambda parameters +public void test422468b() throws JavaModelException { + this.wc = getWorkingCopy( + "/Resolve/src/X.java", + "interface I {\n" + + " I foo (I x);\n" + + "}\n" + + "public class X {\n" + + " static void goo(I i) {}\n" + + " public static void main(String[] args) {\n" + + " goo((x) -> (y) -> (z) -> z.foo((p) -> p));\n" + + " }\n" + + "} \n"); + + String str = this.wc.getSource(); + String selection = "y"; + int start = str.lastIndexOf(selection); + int length = selection.length(); + + IJavaElement[] elements = this.wc.codeSelect(start, length); + assertElementsEqual( + "Unexpected elements", + "y [in main(String[]) [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]]", + elements + ); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=422468, [1.8][assist] Code assist issues with type elided lambda parameters +public void test422468c() throws JavaModelException { + this.wc = getWorkingCopy( + "/Resolve/src/X.java", + "interface I {\n" + + " I foo (I x);\n" + + "}\n" + + "public class X {\n" + + " static void goo(I i) {}\n" + + " public static void main(String[] args) {\n" + + " goo( x -> y -> z -> z.foo(p -> p));\n" + + " }\n" + + "} \n"); + + String str = this.wc.getSource(); + String selection = "y"; + int start = str.lastIndexOf(selection); + int length = selection.length(); + + IJavaElement[] elements = this.wc.codeSelect(start, length); + assertElementsEqual( + "Unexpected elements", + "y [in main(String[]) [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]]", + elements + ); +} } diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java index 29b1ddc3cd..5a08e9a53d 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java @@ -19,7 +19,28 @@ package org.eclipse.jdt.internal.codeassist.impl; * */ -import org.eclipse.jdt.internal.compiler.ast.*; +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; +import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.Block; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; +import org.eclipse.jdt.internal.compiler.ast.Expression; +import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; +import org.eclipse.jdt.internal.compiler.ast.ImportReference; +import org.eclipse.jdt.internal.compiler.ast.Initializer; +import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; +import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; +import org.eclipse.jdt.internal.compiler.ast.MessageSend; +import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.NameReference; +import org.eclipse.jdt.internal.compiler.ast.Statement; +import org.eclipse.jdt.internal.compiler.ast.SuperReference; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; @@ -82,6 +103,7 @@ public abstract class AssistParser extends Parser { protected static final int WITH_BODY = 1; protected boolean isFirst = false; + protected boolean lambdaNeedsClosure = false; // :) public AssistParser(ProblemReporter problemReporter) { super(problemReporter, true); @@ -261,6 +283,17 @@ public RecoveredElement buildInitialRecoveryState(){ this.lastCheckPoint = lambda.sourceEnd + 1; continue; } + if (this.assistNode != null && node instanceof Statement) { + Statement stmt = (Statement) node; + if (!(stmt instanceof Expression) || ((Expression) stmt).statementExpression()) { + if (this.assistNode.sourceStart >= stmt.sourceStart && this.assistNode.sourceEnd <= stmt.sourceEnd) { + element.add(stmt, 0); + this.lastCheckPoint = stmt.sourceEnd + 1; + this.isOrphanCompletionNode = false; + } + } + continue; + } if (node instanceof ImportReference){ ImportReference importRef = (ImportReference) node; element = element.add(importRef, 0); @@ -364,10 +397,31 @@ protected void consumeExitMemberValue() { super.consumeExitMemberValue(); popElement(K_ATTRIBUTE_VALUE_DELIMITER); } + protected void consumeExplicitConstructorInvocation(int flag, int recFlag) { super.consumeExplicitConstructorInvocation(flag, recFlag); popElement(K_SELECTOR); + triggerRecoveryUponLambdaClosure(); +} +protected void triggerRecoveryUponLambdaClosure() { + if (this.assistNode == null || !this.lambdaNeedsClosure) + return; + ASTNode node = this.astStack[this.astPtr]; + if (this.assistNode.sourceStart >= node.sourceStart && this.assistNode.sourceEnd <= node.sourceEnd) { + for (int i = 0; i <= this.astPtr; i++) { + if (this.astStack[i] instanceof LambdaExpression) + return; + } + this.restartRecovery = true; + this.isOrphanCompletionNode = false; + this.lambdaNeedsClosure = false; + } +} +protected void consumeExplicitConstructorInvocationWithTypeArguments(int flag, int recFlag) { + super.consumeExplicitConstructorInvocationWithTypeArguments(flag, recFlag); + triggerRecoveryUponLambdaClosure(); } + protected void consumeForceNoDiet() { super.consumeForceNoDiet(); // if we are not in a method (i.e. we are not in a local variable initializer) @@ -390,37 +444,9 @@ protected void consumeInterfaceHeader() { super.consumeInterfaceHeader(); pushOnElementStack(K_TYPE_DELIMITER); } - -protected void consumeLambdaExpression() { - // LambdaExpression ::= LambdaHeader LambdaBody // Synthetic/fake production with a synthetic non-terminal. - this.astLengthPtr--; // pop length for LambdaBody (always 1) - Statement body = (Statement) this.astStack[this.astPtr--]; - if (body instanceof Block) { - this.nestedType--; // matching NestedType in "LambdaBody ::= NestedType NestedMethod '{' BlockStatementsopt '}'" - this.intPtr--; // position after '{' pushed during consumeNestedMethod() - if (this.options.ignoreMethodBodies) { - body = new Block(0); - } - } - - LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr--]; - this.astLengthPtr--; - lexp.body = body; - lexp.sourceEnd = body.sourceEnd; - - if (body instanceof Expression) { - Expression expression = (Expression) body; - expression.statementEnd = body.sourceEnd; - } - if (this.currentElement != null) { - if (this.currentElement.parseTree() == lexp && this.currentElement.parent != null) { - this.currentElement = this.currentElement.parent; - } - this.restartRecovery = true; - } - if (!this.parsingJava8Plus) { - problemReporter().lambdaExpressionsNotBelow18(lexp); - } +protected void consumeExpressionStatement() { + super.consumeExpressionStatement(); + triggerRecoveryUponLambdaClosure(); } protected void consumeMethodBody() { super.consumeMethodBody(); @@ -431,6 +457,7 @@ protected void consumeMethodDeclaration(boolean isNotAbstract, boolean isDefault popElement(K_METHOD_DELIMITER); } super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod); + triggerRecoveryUponLambdaClosure(); } protected void consumeMethodHeader() { super.consumeMethodHeader(); diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnArgumentName.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnArgumentName.java index 98d8147578..0484ed9ac5 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnArgumentName.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnArgumentName.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -29,6 +29,9 @@ public class SelectionOnArgumentName extends Argument { super(name, posNom, tr, modifiers); } + public SelectionOnArgumentName(char[] name , long posNom , TypeReference tr , int modifiers, boolean typeElided){ + super(name, posNom, tr, modifiers, typeElided); + } public TypeBinding bind(MethodScope scope, TypeBinding typeBinding, boolean used) { super.bind(scope, typeBinding, used); diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java index 69f6f84038..357ab583ab 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java @@ -40,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.ImportReference; +import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; @@ -82,7 +83,6 @@ public class SelectionParser extends AssistParser { /* public fields */ public int selectionStart, selectionEnd; - public static final char[] SUPER = "super".toCharArray(); //$NON-NLS-1$ public static final char[] THIS = "this".toCharArray(); //$NON-NLS-1$ @@ -586,7 +586,7 @@ protected void consumeExitVariableWithInitialization() { int end = variable.initialization.sourceEnd; if ((this.selectionStart < start) && (this.selectionEnd < start) || (this.selectionStart > end) && (this.selectionEnd > end)) { - variable.initialization = null; + variable.initialization = null; } } @@ -1412,6 +1412,29 @@ public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, Compilation selectionScanner.selectionEnd = end; return super.parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/); } + +protected int resumeOnSyntaxError() { + + if (this.referenceContext instanceof CompilationUnitDeclaration) + return super.resumeOnSyntaxError(); + + // Defer initial *triggered* recovery if we see a type elided lambda expression on the stack. + if (this.assistNode != null && this.restartRecovery) { + this.lambdaNeedsClosure = false; + for (int i = this.astPtr; i >= 0; i--) { + if (this.astStack[i] instanceof LambdaExpression) { + LambdaExpression expression = (LambdaExpression) this.astStack[i]; + if (expression.argumentsTypeElided()) { + this.restartRecovery = false; // will be restarted in when the containing expression statement or explicit constructor call is reduced. + this.lambdaNeedsClosure = true; + return RESUME; + } + } + } + } + return super.resumeOnSyntaxError(); +} + /* * Reset context so as to resume to regular parse loop * If unable to reset for resuming, answers false. @@ -1430,7 +1453,7 @@ protected boolean resumeAfterRecovery() { if(!(this.currentElement instanceof RecoveredType)) { resetStacks(); return false; - } + } RecoveredType recoveredType = (RecoveredType)this.currentElement; if(recoveredType.typeDeclaration != null && recoveredType.typeDeclaration.allocation == this.assistNode){ @@ -1472,7 +1495,25 @@ protected void updateRecoveryState() { */ recoveryTokenCheck(); } - +protected Argument typeElidedArgument() { + char[] selector = this.identifierStack[this.identifierPtr]; + if (selector != assistIdentifier()){ + return super.typeElidedArgument(); + } + this.identifierLengthPtr--; + char[] identifierName = this.identifierStack[this.identifierPtr]; + long namePositions = this.identifierPositionStack[this.identifierPtr--]; + + Argument arg = + new SelectionOnArgumentName( + identifierName, + namePositions, + null, // elided type + ClassFileConstants.AccDefault, + true); + arg.declarationSourceStart = (int) (namePositions >>> 32); + return arg; +} public String toString() { String s = Util.EMPTY_STRING; s = s + "elementKindStack : int[] = {"; //$NON-NLS-1$ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java index b2cb8eefd1..ed2ae35527 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java @@ -83,12 +83,18 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC private boolean hasIgnoredMandatoryErrors = false; private static final SyntheticArgumentBinding [] NO_SYNTHETIC_ARGUMENTS = new SyntheticArgumentBinding[0]; - public LambdaExpression(CompilationResult compilationResult, Argument [] arguments, Statement body, boolean shouldUnelideTypes) { + public LambdaExpression(CompilationResult compilationResult, boolean shouldUnelideTypes) { super(compilationResult); + this.shouldUnelideTypes = shouldUnelideTypes; + } + + public void setArguments(Argument [] arguments) { this.arguments = arguments != null ? arguments : ASTNode.NO_ARGUMENTS; + this.argumentTypes = new TypeBinding[arguments != null ? arguments.length : 0]; + } + + public void setBody(Statement body) { this.body = body; - this.shouldUnelideTypes = shouldUnelideTypes; - this.argumentTypes = new TypeBinding[arguments != null ? arguments.length : 0]; } protected FunctionalExpression original() { @@ -303,7 +309,7 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC return this.resolvedType; } - private boolean argumentsTypeElided() { + public boolean argumentsTypeElided() { return this.arguments.length > 0 && this.arguments[0].hasElidedType(); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java index 48ccff18f1..6d9f45bfd6 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java @@ -1004,7 +1004,6 @@ public JavadocParser javadocParser; // used for recovery protected int lastJavadocEnd; public org.eclipse.jdt.internal.compiler.ReadManager readManager; -private boolean shouldDeferRecovery = false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291040 private int valueLambdaNestDepth = -1; private int stateStackLengthStack[] = new int[0]; protected boolean parsingJava8Plus; @@ -1014,6 +1013,13 @@ private boolean tolerateDefaultClassMethods = false; private boolean processingLambdaParameterList = false; private boolean expectTypeAnnotation = false; +// resumeOnSyntaxError codes: + +protected static final int HALT = 0; // halt and throw up hands. +protected static final int RESTART = 1; // stacks reset, alternate goal from check point. +protected static final int RESUME = 2; // stacks untouched, just continue from where left off. + + protected Parser () { // Caveat Emptor: For inheritance purposes and then only in very special needs. Only minimal state is initialized ! } @@ -2553,7 +2559,6 @@ protected void consumeClassBodyopt() { // ClassBodyopt ::= $empty pushOnAstStack(null); this.endPosition = this.rParenPos; - this.shouldDeferRecovery = false; } protected void consumeClassDeclaration() { // ClassDeclaration ::= ClassHeader ClassBody @@ -3413,7 +3418,6 @@ protected void consumeEnhancedForStatementHeaderInit(boolean hasModifiers) { iteratorForStatement.sourceEnd = localDeclaration.declarationSourceEnd; } protected void consumeEnterAnonymousClassBody(boolean qualified) { - this.shouldDeferRecovery = false; // EnterAnonymousClassBody ::= $empty TypeReference typeReference = getTypeReference(0); @@ -7866,11 +7870,11 @@ protected void consumeLambdaHeader() { if (argument.name.length == 1 && argument.name[0] == '_') problemReporter().illegalUseOfUnderscoreAsAnIdentifier(argument.sourceStart, argument.sourceEnd, true); // true == lambdaParameter } - LambdaExpression lexp = new LambdaExpression(this.compilationUnit.compilationResult, arguments, null, this instanceof AssistParser /* synthesize elided types as needed */); + LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr]; + lexp.setArguments(arguments); lexp.sourceEnd = this.intStack[this.intPtr--]; // ')' position or identifier position. lexp.sourceStart = this.intStack[this.intPtr--]; // '(' position or identifier position. lexp.hasParentheses = (this.scanner.getSource()[lexp.sourceStart] == '('); - pushOnAstStack(lexp); pushOnExpressionStack(lexp); this.listLength = 0; // reset this.listLength after having read all parameters } @@ -7890,7 +7894,7 @@ protected void consumeLambdaExpression() { LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr--]; this.astLengthPtr--; - lexp.body = body; + lexp.setBody(body); lexp.sourceEnd = body.sourceEnd; if (body instanceof Expression) { @@ -7902,6 +7906,22 @@ protected void consumeLambdaExpression() { } } +protected Argument typeElidedArgument() { + this.identifierLengthPtr--; + char[] identifierName = this.identifierStack[this.identifierPtr]; + long namePositions = this.identifierPositionStack[this.identifierPtr--]; + + Argument arg = + new Argument( + identifierName, + namePositions, + null, // elided type + ClassFileConstants.AccDefault, + true); + arg.declarationSourceStart = (int) (namePositions >>> 32); + return arg; +} + protected void consumeTypeElidedLambdaParameter(boolean parenthesized) { // LambdaParameters ::= Identifier @@ -7917,28 +7937,20 @@ protected void consumeTypeElidedLambdaParameter(boolean parenthesized) { annotationLength = this.expressionLengthStack[this.expressionLengthPtr--]; this.expressionPtr -= annotationLength; } - - this.identifierLengthPtr--; - char[] identifierName = this.identifierStack[this.identifierPtr]; - long namePositions = this.identifierPositionStack[this.identifierPtr--]; - Argument arg = - new Argument( - identifierName, - namePositions, - null, // elided type - ClassFileConstants.AccDefault, - true); - arg.declarationSourceStart = (int) (namePositions >>> 32); + Argument arg = typeElidedArgument(); if (modifier != ClassFileConstants.AccDefault || annotationLength != 0) { problemReporter().illegalModifiersForElidedType(arg); arg.declarationSourceStart = modifiersStart; } - pushOnAstStack(arg); if (!parenthesized) { // in the absence of '(' and ')', record positions. + LambdaExpression lambda; + pushOnAstStack(lambda = new LambdaExpression(this.compilationUnit.compilationResult, this instanceof AssistParser)); pushOnIntStack(arg.declarationSourceStart); pushOnIntStack(arg.declarationSourceEnd); + lambda.sourceStart = arg.declarationSourceStart; } + pushOnAstStack(arg); /* if incomplete method header, this.listLength counter will not have been reset, indicating that some arguments are available on the stack */ this.listLength++; @@ -8136,7 +8148,7 @@ protected void consumeReferenceExpressionGenericTypeForm() { } } protected void consumeEnterInstanceCreationArgumentList() { - this.shouldDeferRecovery = false; // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=417935#c2 + return; } protected void consumeSimpleAssertStatement() { // AssertStatement ::= 'assert' Expression ';' @@ -8717,6 +8729,7 @@ protected void consumeToken(int type) { //System.out.println(this.scanner.toStringAction(type)); switch (type) { case TokenNameBeginLambda: + pushOnAstStack(new LambdaExpression(this.compilationUnit.compilationResult, this instanceof AssistParser)); this.processingLambdaParameterList = true; break; case TokenNameARROW: @@ -10827,8 +10840,7 @@ try { this.stack[this.stateStackTop] = act; act = tAction(act, this.currentToken); - if (act == ERROR_ACTION || (this.restartRecovery && !this.shouldDeferRecovery)) { - this.shouldDeferRecovery = false; + if (act == ERROR_ACTION || this.restartRecovery) { if (DEBUG_AUTOMATON) { if (this.restartRecovery) { System.out.println("Restart - "); //$NON-NLS-1$ @@ -10839,18 +10851,24 @@ try { int errorPos = this.scanner.currentPosition - 1; if (!this.hasReportedError) { - this.hasError = true; + this.hasError = true; // looks incorrect for recovery case ? } int previousToken = this.currentToken; - if (resumeOnSyntaxError()) { - if (act == ERROR_ACTION && previousToken != 0) this.lastErrorEndPosition = errorPos; - act = START_STATE; - this.stateStackTop = -1; - this.currentToken = getFirstToken(); - continue ProcessTerminals; + switch (resumeOnSyntaxError()) { + case HALT: + act = ERROR_ACTION; + break ProcessTerminals; + case RESTART: + if (act == ERROR_ACTION && previousToken != 0) this.lastErrorEndPosition = errorPos; + act = START_STATE; + this.stateStackTop = -1; + this.currentToken = getFirstToken(); + continue ProcessTerminals; + case RESUME: + break; // We presume the world is virgin so we can continue exactly from where we left off. + default: + throw new IllegalStateException(); } - act = ERROR_ACTION; - break ProcessTerminals; } if (act <= NUM_RULES) { this.stateStackTop--; @@ -12177,22 +12195,22 @@ protected boolean resumeAfterRecovery() { return false; } } -protected boolean resumeOnSyntaxError() { +protected int resumeOnSyntaxError() { if (this.haltOnSyntaxError) - return false; + return HALT; /* request recovery initialization */ if (this.currentElement == null){ // Reset javadoc before restart parsing after recovery this.javadoc = null; // do not investigate deeper in statement recovery - if (this.statementRecoveryActivated) return false; + if (this.statementRecoveryActivated) return HALT; // build some recovered elements this.currentElement = buildInitialRecoveryState(); } /* do not investigate deeper in recovery when no recovered element */ - if (this.currentElement == null) return false; + if (this.currentElement == null) return HALT; /* manual forced recovery restart - after headers */ if (this.restartRecovery){ @@ -12214,7 +12232,7 @@ protected boolean resumeOnSyntaxError() { } /* attempt to reset state in order to resume to parse loop */ - return resumeAfterRecovery(); + return resumeAfterRecovery() ? RESTART : HALT; } public void setMethodsFullRecovery(boolean enabled) { this.options.performMethodsFullRecovery = enabled; diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java index 56c2c5dd78..800a69ca35 100644 --- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java +++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java @@ -790,9 +790,9 @@ protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) { * A syntax error was detected. If a method is being parsed, records the number of errors and * attempts to restart from the last statement by going for an expression. */ -protected boolean resumeOnSyntaxError() { +protected int resumeOnSyntaxError() { if (this.diet || this.hasRecoveredOnExpression) { // no reentering inside expression recovery - return false; + return HALT; } // record previous error, in case more accurate than potential one in expression recovery @@ -821,6 +821,6 @@ protected boolean resumeOnSyntaxError() { this.hasRecoveredOnExpression = true; this.hasReportedError = false; this.hasError = false; - return true; + return RESTART; } } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java index 7f83fff177..c05ba9722d 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java @@ -1511,8 +1511,8 @@ protected void resetModifiers() { * Syntax error was detected. Will attempt to perform some recovery action in order * to resume to the regular parse loop. */ -protected boolean resumeOnSyntaxError() { - return false; +protected int resumeOnSyntaxError() { + return HALT; } /* * Answer a char array representation of the type name formatted like: |
