Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorssankaran2013-11-28 08:43:40 +0000
committerssankaran2013-11-28 16:25:31 +0000
commit227e3d5fec0001fbc06115e3f3e6f09f357952e2 (patch)
tree7b0193069d74cf7ceae6e28cc930885049b8cd6c
parent4f833be4365ac5abb1ac0cf3973cd75cbb0d7487 (diff)
downloadeclipse.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
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java98
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java91
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnArgumentName.java5
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java49
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java14
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java90
-rw-r--r--org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java6
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java4
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:

Back to the top