Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 422468 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest18.java (-5 / +108 lines)
Lines 15-26 Link Here
15
15
16
package org.eclipse.jdt.core.tests.compiler.parser;
16
package org.eclipse.jdt.core.tests.compiler.parser;
17
17
18
import org.eclipse.jdt.core.JavaModelException;
19
18
import junit.framework.Test;
20
import junit.framework.Test;
19
21
20
public class CompletionParserTest18 extends AbstractCompletionTest {
22
public class CompletionParserTest18 extends AbstractCompletionTest {
21
23
22
static {
24
static {
23
//	TESTS_NAMES = new String [] { "test0001" };
25
//	TESTS_NAMES = new String [] { "test0005" };
24
}
26
}
25
27
26
public CompletionParserTest18(String testName) {
28
public CompletionParserTest18(String testName) {
Lines 233-242 Link Here
233
			"  }\n" + 
235
			"  }\n" + 
234
			"  void go() {\n" + 
236
			"  void go() {\n" + 
235
			"    I i = (<no type> argument) ->     {\n" + 
237
			"    I i = (<no type> argument) ->     {\n" + 
236
			"      {\n" + 
238
			"      if (true)\n" + 
237
			"        if (true)\n" + 
239
			"          {\n" + 
238
			"            return <CompleteOnName:arg>;\n" + 
240
			"            return <CompleteOnName:arg>;\n" + 
239
			"      }\n" + 
241
			"          }\n" + 
240
			"    };\n" + 
242
			"    };\n" + 
241
			"  }\n" + 
243
			"  }\n" + 
242
			"}\n";
244
			"}\n";
Lines 251-257 Link Here
251
		expectedReplacedSource,
253
		expectedReplacedSource,
252
		"diet ast");
254
		"diet ast");
253
}
255
}
254
public void test0006() {
256
public void _test0006() {
255
	String string =
257
	String string =
256
			"interface I {\n" +
258
			"interface I {\n" +
257
			"	int foo(int x);\n" +
259
			"	int foo(int x);\n" +
Lines 345-348 Link Here
345
		expectedReplacedSource,
347
		expectedReplacedSource,
346
		"diet ast");
348
		"diet ast");
347
}
349
}
350
public void test0010() {
351
	String string =
352
			"interface I {\n" +
353
			"	void foo(String x);\n" +
354
			"}\n" +
355
			"public class X {\n" +
356
			"	String xField;\n" +
357
			"	static void goo(String s) {\n" +
358
			"	}\n" +
359
			"	static void goo(I i) {\n" +
360
			"	}\n" +
361
			"	public static void main(String[] args) {\n" +
362
			"		goo((xyz) -> {\n" +
363
			"			System.out.println(xyz.);\n" +
364
			"		});\n" +
365
			"	}\n" +
366
			"}\n";
367
368
	String completeBehind = "xyz.";
369
	int cursorLocation = string.lastIndexOf(completeBehind) + completeBehind.length() - 1;
370
371
	String expectedCompletionNodeToString = "<CompleteOnName:xyz.>";
372
	String expectedParentNodeToString = "System.out.println(<CompleteOnName:xyz.>)";
373
	String completionIdentifier = "";
374
	String expectedReplacedSource = "xyz.";
375
	String expectedUnitDisplayString =
376
			"interface I {\n" +
377
			"  void foo(String x);\n" +
378
			"}\n" +
379
			"public class X {\n" +
380
			"  String xField;\n" +
381
			"  public X() {\n" +
382
			"  }\n" +
383
			"  static void goo(String s) {\n" +
384
			"  }\n" +
385
			"  static void goo(I i) {\n" +
386
			"  }\n" +
387
			"  public static void main(String[] args) {\n" +
388
			"    goo((<no type> xyz) -> {\n" +
389
			"  System.out.println(<CompleteOnName:xyz.>);\n" +
390
			"});\n" +
391
			"  }\n" +
392
			"}\n";
393
394
	checkMethodParse(
395
		string.toCharArray(),
396
		cursorLocation,
397
		expectedCompletionNodeToString,
398
		expectedParentNodeToString,
399
		expectedUnitDisplayString,
400
		completionIdentifier,
401
		expectedReplacedSource,
402
		"diet ast");
403
}
404
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=417935, [1.8][code select] ICU#codeSelect doesn't work on reference to lambda parameter
405
public void test417935() throws JavaModelException {
406
	String string = 
407
			"import java.util.ArrayList;\n" +
408
			"import java.util.Arrays;\n" +
409
			"import java.util.Collections;\n" +
410
			"import java.util.Comparator;\n" +
411
			"public class X {\n" +
412
			"   int compareTo(X x) { return 0; }\n" +
413
			"	void foo() {\n" +
414
			"		Collections.sort(new ArrayList<X>(Arrays.asList(new X(), new X(), new X())),\n" +
415
			"				(X o1, X o2) -> o1.compareTo(o2)); //[2]\n" +
416
			"	}\n" +
417
			"}\n";
418
419
			String completeBehind = "compa";
420
			int cursorLocation = string.lastIndexOf(completeBehind) + completeBehind.length() - 1;
421
422
			String expectedCompletionNodeToString = "<CompleteOnName:o1.compa>";
423
			String expectedParentNodeToString = "<NONE>";
424
			String completionIdentifier = "compa";
425
			String expectedReplacedSource = "o1.compareTo";
426
			String expectedUnitDisplayString =
427
					"import java.util.ArrayList;\n" + 
428
					"import java.util.Arrays;\n" + 
429
					"import java.util.Collections;\n" + 
430
					"import java.util.Comparator;\n" + 
431
					"public class X {\n" + 
432
					"  public X() {\n" + 
433
					"  }\n" + 
434
					"  int compareTo(X x) {\n" + 
435
					"  }\n" + 
436
					"  void foo() {\n" + 
437
					"    (X o1, X o2) -> <CompleteOnName:o1.compa>;\n" + 
438
					"  }\n" + 
439
					"}\n";
440
441
			checkMethodParse(
442
				string.toCharArray(),
443
				cursorLocation,
444
				expectedCompletionNodeToString,
445
				expectedParentNodeToString,
446
				expectedUnitDisplayString,
447
				completionIdentifier,
448
				expectedReplacedSource,
449
				"diet ast");
450
}
348
}
451
}
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java (-1 / +95 lines)
Lines 570-576 Link Here
570
			"	public static void main(String[] args) {\n" +
570
			"	public static void main(String[] args) {\n" +
571
			"			I i = () -> {\n" +
571
			"			I i = () -> {\n" +
572
			"               xyz\n" +
572
			"               xyz\n" +
573
			"			}\n" +
573
			"	}\n" +
574
			"	}\n" +
574
			"	}\n" +
575
			"}\n");
575
			"}\n");
576
576
Lines 597-600 Link Here
597
			"	goo() {key=LX;.goo()LX;} [in X [in [Working copy] X.java [in <default> [in src [in Completion]]]]],\n" +
597
			"	goo() {key=LX;.goo()LX;} [in X [in [Working copy] X.java [in <default> [in src [in Completion]]]]],\n" +
598
			"}" , requestor.getContext());
598
			"}" , requestor.getContext());
599
}
599
}
600
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=422468, [1.8][assist] Code assist issues with type elided lambda parameters
601
public void _test018() throws JavaModelException { // ensure higher relevance for matching return type.
602
	this.workingCopies = new ICompilationUnit[1];
603
	this.workingCopies[0] = getWorkingCopy(
604
			"/Completion/src/X.java",
605
			"interface I {\n" +
606
			"	void foo(String x);\n" +
607
			"}\n" +
608
			"public class X {\n" +
609
			"	String xField;\n" +
610
			"	static void goo(String s) {\n" +
611
			"	}\n" +
612
			"	static void goo(I i) {\n" +
613
			"	}\n" +
614
			"	public static void main(String[] args) {\n" +
615
			"		goo((xyz) -> {\n" +
616
			"			System.out.println(xyz.);\n" +
617
			"		});\n" +
618
			"	}\n" +
619
			"}\n");
620
621
	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, false);
622
	requestor.allowAllRequiredProposals();
623
	requestor.setRequireExtendedContext(true);
624
	requestor.setComputeEnclosingElement(false);
625
	requestor.setComputeVisibleElements(true);
626
	requestor.setAssignableType("LX;");
627
	
628
	String str = this.workingCopies[0].getSource();
629
	String completeBehind = "xyz.";
630
	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
631
	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
632
	assertEquals("completion offset=192\n" +
633
			"completion range=[189, 191]\n" +
634
			"completion token=\"xyz\"\n" +
635
			"completion token kind=TOKEN_KIND_NAME\n" +
636
			"expectedTypesSignatures=null\n" +
637
			"expectedTypesKeys=null\n" +
638
			"completion token location={STATEMENT_START}\n" +
639
			"visibleElements={\n" +
640
			"	xField {key=LX;.xField)LX;} [in X [in [Working copy] X.java [in <default> [in src [in Completion]]]]],\n" +
641
			"	goo() {key=LX;.goo()LX;} [in X [in [Working copy] X.java [in <default> [in src [in Completion]]]]],\n" +
642
			"}" , requestor.getContext());
643
}
644
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=422468, [1.8][assist] Code assist issues with type elided lambda parameters
645
public void _test018a() throws JavaModelException { // ensure higher relevance for matching return type.
646
	this.workingCopies = new ICompilationUnit[1];
647
	this.workingCopies[0] = getWorkingCopy(
648
			"/Completion/src/X.java",
649
			"interface I {\n" +
650
			"	void foo(String x);\n" +
651
			"}\n" +
652
			"public class X {\n" +
653
			"	String xField;\n" +
654
			"	static void goo(String s) {\n" +
655
			"	}\n" +
656
			"	static void goo(I i) {\n" +
657
			"	}\n" +
658
			"	public static void main(String[] args) {\n" +
659
			"       args = null;\n" +
660
			"       if (args != null) {\n" +
661
			"           xField = null;\n" +
662
			"       else \n" +
663
			"           xField = null;\n" +
664
			"       while (true);\n" +
665
			"		goo((xyz) -> {\n" +
666
			"			System.out.println(xyz.)\n" +
667
			"		});\n" +
668
			"	}\n" +
669
			"}\n");
670
671
	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, false);
672
	requestor.allowAllRequiredProposals();
673
	requestor.setRequireExtendedContext(true);
674
	requestor.setComputeEnclosingElement(false);
675
	requestor.setComputeVisibleElements(true);
676
	requestor.setAssignableType("LX;");
677
	
678
	String str = this.workingCopies[0].getSource();
679
	String completeBehind = "xyz.";
680
	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
681
	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
682
	assertEquals("completion offset=192\n" +
683
			"completion range=[189, 191]\n" +
684
			"completion token=\"xyz\"\n" +
685
			"completion token kind=TOKEN_KIND_NAME\n" +
686
			"expectedTypesSignatures=null\n" +
687
			"expectedTypesKeys=null\n" +
688
			"completion token location={STATEMENT_START}\n" +
689
			"visibleElements={\n" +
690
			"	xField {key=LX;.xField)LX;} [in X [in [Working copy] X.java [in <default> [in src [in Completion]]]]],\n" +
691
			"	goo() {key=LX;.goo()LX;} [in X [in [Working copy] X.java [in <default> [in src [in Completion]]]]],\n" +
692
			"}" , requestor.getContext());
693
}
600
}
694
}
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java (-1 / +100 lines)
Lines 28-34 Link Here
28
	ICompilationUnit wc = null;
28
	ICompilationUnit wc = null;
29
29
30
static {
30
static {
31
	// TESTS_NAMES = new String[] { "test0023" };
31
//	 TESTS_NAMES = new String[] { "testParser" };
32
	// TESTS_NUMBERS = new int[] { 124 };
32
	// TESTS_NUMBERS = new int[] { 124 };
33
	// TESTS_RANGE = new int[] { 16, -1 };
33
	// TESTS_RANGE = new int[] { 16, -1 };
34
}
34
}
Lines 1531-1534 Link Here
1531
		elements
1531
		elements
1532
	);
1532
	);
1533
}
1533
}
1534
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=422468, [1.8][assist] Code assist issues with type elided lambda parameters
1535
public void test422468d() throws JavaModelException {
1536
	this.wc = getWorkingCopy(
1537
			"/Resolve/src/X.java",
1538
			"interface I {\n" +
1539
			"	J foo(String x, String y);\n" +
1540
			"}\n" +
1541
			"interface J {\n" +
1542
			"	K foo(String x, String y);\n" +
1543
			"}\n" +
1544
			"interface K {\n" +
1545
			"	int foo(String x, int y);\n" +
1546
			"}\n" +
1547
			"public class X {\n" +
1548
			"	static void goo(K i) {}\n" +
1549
			"	public static void main(String[] args) {\n" +
1550
			"		I i = (x, y) -> { return (a, b) -> (p, q) -> a.length(); };\n" +
1551
			"	}\n" +
1552
			"}\n");
1553
1554
	String str = this.wc.getSource();
1555
	String selection = "a.length";
1556
	int start = str.lastIndexOf(selection);
1557
	int length = selection.length();
1558
1559
	IJavaElement[] elements = this.wc.codeSelect(start, length);
1560
	assertElementsEqual(
1561
		"Unexpected elements",
1562
		"length() [in String [in String.class [in java.lang [in "+ getExternalPath() + "jclMin1.8.jar]]]]",
1563
		elements
1564
	);
1565
}
1566
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=422468, [1.8][assist] Code assist issues with type elided lambda parameters
1567
public void test422468e() throws JavaModelException {
1568
	this.wc = getWorkingCopy(
1569
			"/Resolve/src/X.java",
1570
			"interface I {\n" +
1571
			"	J foo(String x, String y);\n" +
1572
			"}\n" +
1573
			"interface J {\n" +
1574
			"	K foo(String x, String y);\n" +
1575
			"}\n" +
1576
			"interface K {\n" +
1577
			"	int foo(String x, int y);\n" +
1578
			"}\n" +
1579
			"public class X {\n" +
1580
			"	static void goo(K i) {}\n" +
1581
			"	public static void main(String[] args) {\n" +
1582
			"		I i = (x, y) -> { return (a, b) -> (p, q) -> a.length(); };\n" +
1583
			"	}\n" +
1584
			"}\n");
1585
1586
	String str = this.wc.getSource();
1587
	String selection = "q";
1588
	int start = str.lastIndexOf(selection);
1589
	int length = selection.length();
1590
1591
	IJavaElement[] elements = this.wc.codeSelect(start, length);
1592
	assertElementsEqual(
1593
		"Unexpected elements",
1594
		"q [in main(String[]) [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]]",
1595
		elements
1596
	);
1597
}
1598
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=422468, [1.8][assist] Code assist issues with type elided lambda parameters
1599
public void testParser() throws JavaModelException {
1600
	this.wc = getWorkingCopy(
1601
			"/Resolve/src/X.java",
1602
			"interface I {\n" +
1603
			"	int foo(String x, Integer y);\n" +
1604
			"}\n" +
1605
			"public class X {\n" +
1606
			"	public static void main(String[] args) {\n" +
1607
			"		I i = (x, y) -> {\n" +
1608
			"			x = \"Hello\"\n" +
1609
			"			y = 10;		\n" +
1610
			"			if (x.length() > y) {\n" +
1611
			"				System.out.println(\"if\");\n" +
1612
			"			} else {\n" +
1613
			"				System.out.println(\"else\");\n" +
1614
			"			}\n" +
1615
			"			return x.length();\n" +
1616
			"		};\n" +
1617
			"		// System.out.println((I) (p, q) -> { return q.\n" +
1618
			"	}\n" +
1619
			"}\n");
1620
1621
	String str = this.wc.getSource();
1622
	String selection = "x";
1623
	int start = str.lastIndexOf(selection);
1624
	int length = selection.length();
1625
1626
	IJavaElement[] elements = this.wc.codeSelect(start, length);
1627
	assertElementsEqual(
1628
		"Unexpected elements",
1629
		"x [in main(String[]) [in X [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]]",
1630
		elements
1631
	);
1632
}
1534
}
1633
}
(-)a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java (-2 / +2 lines)
Lines 37-43 Link Here
37
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
37
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
38
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
38
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
39
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
39
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
40
import org.eclipse.jdt.internal.compiler.parser.Parser;
40
import org.eclipse.jdt.internal.compiler.parser.CommitRollbackParser;
41
import org.eclipse.jdt.internal.core.AnnotatableInfo;
41
import org.eclipse.jdt.internal.core.AnnotatableInfo;
42
import org.eclipse.jdt.internal.core.Annotation;
42
import org.eclipse.jdt.internal.core.Annotation;
43
import org.eclipse.jdt.internal.core.CompilationUnit;
43
import org.eclipse.jdt.internal.core.CompilationUnit;
Lines 64-70 Link Here
64
	public CompletionUnitStructureRequestor(
64
	public CompletionUnitStructureRequestor(
65
			ICompilationUnit unit,
65
			ICompilationUnit unit,
66
			CompilationUnitElementInfo unitInfo,
66
			CompilationUnitElementInfo unitInfo,
67
			Parser parser,
67
			CommitRollbackParser parser,
68
			ASTNode assistNode,
68
			ASTNode assistNode,
69
			Map bindingCache,
69
			Map bindingCache,
70
			Map elementCache,
70
			Map elementCache,
(-)a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java (-7 / +35 lines)
Lines 31-37 Link Here
31
import org.eclipse.jdt.internal.compiler.*;
31
import org.eclipse.jdt.internal.compiler.*;
32
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
32
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
33
import org.eclipse.jdt.internal.compiler.env.*;
33
import org.eclipse.jdt.internal.compiler.env.*;
34
35
import org.eclipse.jdt.internal.compiler.ast.*;
34
import org.eclipse.jdt.internal.compiler.ast.*;
36
import org.eclipse.jdt.internal.compiler.parser.*;
35
import org.eclipse.jdt.internal.compiler.parser.*;
37
import org.eclipse.jdt.internal.compiler.problem.*;
36
import org.eclipse.jdt.internal.compiler.problem.*;
Lines 614-620 Link Here
614
public Object becomeSimpleParser() {
613
public Object becomeSimpleParser() {
615
	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
614
	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
616
	int[] parserState = new int[] {this.cursorLocation, completionScanner.cursorLocation};
615
	int[] parserState = new int[] {this.cursorLocation, completionScanner.cursorLocation};
617
	
616
	// ??
618
	this.cursorLocation = Integer.MAX_VALUE;
617
	this.cursorLocation = Integer.MAX_VALUE;
619
	completionScanner.cursorLocation = Integer.MAX_VALUE;
618
	completionScanner.cursorLocation = Integer.MAX_VALUE;
620
	
619
	
Lines 3470-3475 Link Here
3470
					case K_MEMBER_VALUE_ARRAY_INITIALIZER:
3469
					case K_MEMBER_VALUE_ARRAY_INITIALIZER:
3471
						popElement(K_MEMBER_VALUE_ARRAY_INITIALIZER);
3470
						popElement(K_MEMBER_VALUE_ARRAY_INITIALIZER);
3472
						break;
3471
						break;
3472
					case K_LAMBDA_EXPRESSION_DELIMITER:
3473
						break; // will be popped when the containing block statement is reduced.
3473
					default:
3474
					default:
3474
						popElement(K_ARRAY_INITIALIZER);
3475
						popElement(K_ARRAY_INITIALIZER);
3475
						break;
3476
						break;
Lines 3675-3680 Link Here
3675
								break;
3676
								break;
3676
							case TokenNamedo:
3677
							case TokenNamedo:
3677
								pushOnElementStack(K_BLOCK_DELIMITER, DO);
3678
								pushOnElementStack(K_BLOCK_DELIMITER, DO);
3679
								break;
3680
							case TokenNameARROW:
3678
								break;
3681
								break;
3679
							default :
3682
							default :
3680
								pushOnElementStack(K_BLOCK_DELIMITER);
3683
								pushOnElementStack(K_BLOCK_DELIMITER);
Lines 4609-4614 Link Here
4609
	this.labelPtr = -1;
4612
	this.labelPtr = -1;
4610
	initializeForBlockStatements();
4613
	initializeForBlockStatements();
4611
}
4614
}
4615
protected void copyState(CommitRollbackParser from) {
4616
4617
	super.copyState(from);
4618
	
4619
	CompletionParser parser = (CompletionParser) from;
4620
	
4621
	this.invocationType = parser.invocationType;
4622
	this.qualifier = parser.qualifier;
4623
	this.inReferenceExpression = parser.inReferenceExpression;
4624
	this.hasUnusedModifiers = parser.hasUnusedModifiers;
4625
	this.canBeExplicitConstructor = parser.canBeExplicitConstructor;
4626
}
4612
/*
4627
/*
4613
 * Initializes the state of the parser that is about to go for BlockStatements.
4628
 * Initializes the state of the parser that is about to go for BlockStatements.
4614
 */
4629
 */
Lines 4954-4959 Link Here
4954
			break;
4969
			break;
4955
	}
4970
	}
4956
}
4971
}
4972
4973
protected CommitRollbackParser createSnapShotParser() {
4974
	return new CompletionParser(this.problemReporter, this.storeSourceEnds);
4975
}
4957
/*
4976
/*
4958
 * Reset internal state after completion is over
4977
 * Reset internal state after completion is over
4959
 */
4978
 */
Lines 4977-4983 Link Here
4977
	int[] state = (int[]) parserState;
4996
	int[] state = (int[]) parserState;
4978
	
4997
	
4979
	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
4998
	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
4980
	
4999
	// ??
4981
	this.cursorLocation = state[0];
5000
	this.cursorLocation = state[0];
4982
	completionScanner.cursorLocation = state[1];
5001
	completionScanner.cursorLocation = state[1];
4983
}
5002
}
Lines 4988-5000 Link Here
4988
 * Move checkpoint location, reset internal stacks and
5007
 * Move checkpoint location, reset internal stacks and
4989
 * decide which grammar goal is activated.
5008
 * decide which grammar goal is activated.
4990
 */
5009
 */
4991
protected boolean resumeAfterRecovery() {
5010
protected int resumeAfterRecovery(boolean errorRecovery) {
4992
	this.hasUnusedModifiers = false;
5011
	this.hasUnusedModifiers = false;
4993
	if (this.assistNode != null) {
5012
	if (this.assistNode != null) {
5013
		
5014
		if (requireExtendedRecovery()) {
5015
			if (!errorRecovery) {
5016
				return RESUME;
5017
			}
5018
			return super.resumeAfterRecovery(errorRecovery);
5019
		}
5020
		
4994
		/* if reached [eof] inside method body, but still inside nested type,
5021
		/* if reached [eof] inside method body, but still inside nested type,
4995
			or inside a field initializer, should continue in diet mode until
5022
			or inside a field initializer, should continue in diet mode until
4996
			the end of the method body or compilation unit */
5023
			the end of the method body or compilation unit */
4997
		if ((this.scanner.eofPosition == this.cursorLocation+1)
5024
		if ((this.scanner.eofPosition >= this.cursorLocation+1)
4998
			&& (!(this.referenceContext instanceof CompilationUnitDeclaration)
5025
			&& (!(this.referenceContext instanceof CompilationUnitDeclaration)
4999
			|| isIndirectlyInsideFieldInitialization()
5026
			|| isIndirectlyInsideFieldInitialization()
5000
			|| this.assistNodeParent instanceof FieldDeclaration && !(this.assistNodeParent instanceof Initializer))) {
5027
			|| this.assistNodeParent instanceof FieldDeclaration && !(this.assistNodeParent instanceof Initializer))) {
Lines 5022-5027 Link Here
5022
				}
5049
				}
5023
			}
5050
			}
5024
			*/
5051
			*/
5052
5025
			/* restart in diet mode for finding sibling constructs */
5053
			/* restart in diet mode for finding sibling constructs */
5026
			if (this.currentElement instanceof RecoveredType
5054
			if (this.currentElement instanceof RecoveredType
5027
				|| this.currentElement.enclosingType() != null){
5055
				|| this.currentElement.enclosingType() != null){
Lines 5035-5045 Link Here
5035
				this.scanner.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
5063
				this.scanner.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
5036
			} else {
5064
			} else {
5037
				resetStacks();
5065
				resetStacks();
5038
				return false;
5066
				return HALT;
5039
			}
5067
			}
5040
		}
5068
		}
5041
	}
5069
	}
5042
	return super.resumeAfterRecovery();
5070
	return super.resumeAfterRecovery(errorRecovery);
5043
}
5071
}
5044
public void setAssistIdentifier(char[] assistIdent){
5072
public void setAssistIdentifier(char[] assistIdent){
5045
	((CompletionScanner)this.scanner).completionIdentifier = assistIdent;
5073
	((CompletionScanner)this.scanner).completionIdentifier = assistIdent;
(-)a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java (-41 / +160 lines)
Lines 23-28 Link Here
23
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
23
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
24
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
24
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
25
import org.eclipse.jdt.internal.compiler.ast.Annotation;
25
import org.eclipse.jdt.internal.compiler.ast.Annotation;
26
import org.eclipse.jdt.internal.compiler.ast.Argument;
26
import org.eclipse.jdt.internal.compiler.ast.Block;
27
import org.eclipse.jdt.internal.compiler.ast.Block;
27
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
28
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
28
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
29
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
Lines 44-49 Link Here
44
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
45
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
45
import org.eclipse.jdt.internal.compiler.lookup.Binding;
46
import org.eclipse.jdt.internal.compiler.lookup.Binding;
46
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
47
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
48
import org.eclipse.jdt.internal.compiler.parser.CommitRollbackParser;
47
import org.eclipse.jdt.internal.compiler.parser.Parser;
49
import org.eclipse.jdt.internal.compiler.parser.Parser;
48
import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock;
50
import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock;
49
import org.eclipse.jdt.internal.compiler.parser.RecoveredElement;
51
import org.eclipse.jdt.internal.compiler.parser.RecoveredElement;
Lines 93-99 Link Here
93
	protected static final int K_FIELD_INITIALIZER_DELIMITER = ASSIST_PARSER + 4; // whether we are inside a field initializer
95
	protected static final int K_FIELD_INITIALIZER_DELIMITER = ASSIST_PARSER + 4; // whether we are inside a field initializer
94
	protected static final int K_ATTRIBUTE_VALUE_DELIMITER = ASSIST_PARSER + 5; // whether we are inside a annotation attribute valuer
96
	protected static final int K_ATTRIBUTE_VALUE_DELIMITER = ASSIST_PARSER + 5; // whether we are inside a annotation attribute valuer
95
	protected static final int K_ENUM_CONSTANT_DELIMITER = ASSIST_PARSER + 6; // whether we are inside a field initializer
97
	protected static final int K_ENUM_CONSTANT_DELIMITER = ASSIST_PARSER + 6; // whether we are inside a field initializer
96
98
	protected static final int K_LAMBDA_EXPRESSION_DELIMITER = ASSIST_PARSER + 7; // whether we are inside a lambda expression
99
	
97
	// selector constants
100
	// selector constants
98
	protected static final int THIS_CONSTRUCTOR = -1;
101
	protected static final int THIS_CONSTRUCTOR = -1;
99
	protected static final int SUPER_CONSTRUCTOR = -2;
102
	protected static final int SUPER_CONSTRUCTOR = -2;
Lines 101-109 Link Here
101
	// enum constant constants
104
	// enum constant constants
102
	protected static final int NO_BODY = 0;
105
	protected static final int NO_BODY = 0;
103
	protected static final int WITH_BODY = 1;
106
	protected static final int WITH_BODY = 1;
107
	
108
	protected static final int EXPRESSION_BODY = 0;
109
	protected static final int BLOCK_BODY = 1;
110
	private static final boolean DEBUG_COMMIT_ROLLBACK = true;
104
111
105
	protected boolean isFirst = false;
112
	protected boolean isFirst = false;
106
	protected boolean lambdaNeedsClosure = false; // :)
113
107
114
108
public AssistParser(ProblemReporter problemReporter) {
115
public AssistParser(ProblemReporter problemReporter) {
109
	super(problemReporter, true);
116
	super(problemReporter, true);
Lines 112-119 Link Here
112
	setMethodsFullRecovery(false);
119
	setMethodsFullRecovery(false);
113
	setStatementsRecovery(false);
120
	setStatementsRecovery(false);
114
}
121
}
122
115
public abstract char[] assistIdentifier();
123
public abstract char[] assistIdentifier();
116
124
125
protected void copyState(CommitRollbackParser from) {
126
	
127
	super.copyState(from);
128
129
	AssistParser parser = (AssistParser) from;
130
	
131
	this.previousToken = parser.previousToken;
132
	this.previousIdentifierPtr = parser.previousIdentifierPtr;
133
	
134
	this.lastModifiers = parser.lastModifiers;
135
	this.lastModifiersStart = parser.lastModifiersStart;
136
	
137
	this.bracketDepth = parser.bracketDepth;
138
	this.elementPtr = parser.elementPtr;
139
	
140
	int length;
141
	System.arraycopy(parser.blockStarts, 0, this.blockStarts = new int [length = parser.blockStarts.length], 0, length);
142
	System.arraycopy(parser.elementKindStack, 0, this.elementKindStack = new int [length = parser.elementKindStack.length], 0, length);
143
	System.arraycopy(parser.elementInfoStack, 0, this.elementInfoStack = new int [length = parser.elementInfoStack.length], 0, length);
144
	System.arraycopy(parser.elementObjectInfoStack, 0, this.elementObjectInfoStack = new Object [length = parser.elementObjectInfoStack.length], 0, length);
145
	
146
	this.previousKind = parser.previousKind;
147
	this.previousInfo = parser.previousInfo;
148
	this.previousObjectInfo = parser.previousObjectInfo;
149
}
117
/**
150
/**
118
 * The parser become a simple parser which behave like a Parser
151
 * The parser become a simple parser which behave like a Parser
119
 * @return the state of the assist parser to be able to restore the assist parser state
152
 * @return the state of the assist parser to be able to restore the assist parser state
Lines 279-286 Link Here
279
		}
312
		}
280
		if (node instanceof LambdaExpression) {
313
		if (node instanceof LambdaExpression) {
281
			LambdaExpression lambda = (LambdaExpression) node;
314
			LambdaExpression lambda = (LambdaExpression) node;
282
			element = element.add(lambda, 0);
315
			if (!lambda.argumentsTypeElided()) {
283
			this.lastCheckPoint = lambda.sourceEnd + 1;
316
				Argument [] arguments = lambda.arguments();
317
				for (int j = 0, length = arguments.length; j < length; j++) {
318
					element = element.add(fakeLocalFromArgument(arguments[j]), 0);
319
				}
320
			}
284
			continue;
321
			continue;
285
		}
322
		}
286
		if (this.assistNode != null && node instanceof Statement) {
323
		if (this.assistNode != null && node instanceof Statement) {
Lines 401-427 Link Here
401
protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
438
protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
402
	super.consumeExplicitConstructorInvocation(flag, recFlag);
439
	super.consumeExplicitConstructorInvocation(flag, recFlag);
403
	popElement(K_SELECTOR);
440
	popElement(K_SELECTOR);
404
	triggerRecoveryUponLambdaClosure();
405
}
406
protected void triggerRecoveryUponLambdaClosure() {
407
	if (this.assistNode == null || !this.lambdaNeedsClosure)
408
		return;
409
	ASTNode node = this.astStack[this.astPtr];
410
	if (this.assistNode.sourceStart >= node.sourceStart && this.assistNode.sourceEnd <= node.sourceEnd) {
411
		for (int i = 0; i <= this.astPtr; i++) {
412
			if (this.astStack[i] instanceof LambdaExpression)
413
				return;
414
		}
415
		this.restartRecovery = true;
416
		this.isOrphanCompletionNode = false;
417
		this.lambdaNeedsClosure = false;
418
	}
419
}
420
protected void consumeExplicitConstructorInvocationWithTypeArguments(int flag, int recFlag) {
421
	super.consumeExplicitConstructorInvocationWithTypeArguments(flag, recFlag);
422
	triggerRecoveryUponLambdaClosure();
423
}
441
}
424
442
443
protected void consumeBlock() {
444
	super.consumeBlock();
445
	if (DEBUG_COMMIT_ROLLBACK) {
446
		System.out.println("----- }");//$NON-NLS-1$
447
	}
448
}
449
protected void consumeBlockStatement() {
450
	super.consumeBlockStatement();
451
	Statement statement = (Statement) this.astStack[this.astPtr];
452
	int statementStart, statementEnd;
453
	statementStart = statement.sourceStart;
454
	statementEnd = statement instanceof AbstractVariableDeclaration ? ((AbstractVariableDeclaration)statement).declarationSourceEnd : statement.sourceEnd;
455
	for (int i = this.elementPtr; i >= 0; --i) {
456
		if (this.elementKindStack[i] != K_LAMBDA_EXPRESSION_DELIMITER)
457
			continue;
458
		LambdaExpression expression = (LambdaExpression) this.elementObjectInfoStack[i];
459
		if (expression.sourceStart >= statementStart && expression.sourceEnd <= statementEnd) {
460
			this.elementPtr = i - 1;
461
			this.restartRecovery = true;
462
		} else {
463
			this.restartRecovery = false;  // lambda is still awaiting closure.
464
			return;
465
		}
466
	}
467
}
468
469
protected void consumeBlockStatements() {
470
	super.consumeBlockStatements();
471
	if (requireExtendedRecovery()) {
472
		this.commit = true;
473
		if (DEBUG_COMMIT_ROLLBACK) {
474
			System.out.println(this.astStack[this.astPtr]);
475
			System.out.println("---------------------------------------------------------");//$NON-NLS-1$
476
		}
477
	} else {
478
		this.restartRecovery = true;
479
	}
480
}
425
protected void consumeForceNoDiet() {
481
protected void consumeForceNoDiet() {
426
	super.consumeForceNoDiet();
482
	super.consumeForceNoDiet();
427
	// if we are not in a method (i.e. we are not in a local variable initializer)
483
	// if we are not in a method (i.e. we are not in a local variable initializer)
Lines 444-452 Link Here
444
	super.consumeInterfaceHeader();
500
	super.consumeInterfaceHeader();
445
	pushOnElementStack(K_TYPE_DELIMITER);
501
	pushOnElementStack(K_TYPE_DELIMITER);
446
}
502
}
447
protected void consumeExpressionStatement() {
503
448
	super.consumeExpressionStatement();
504
LocalDeclaration fakeLocalFromArgument(Argument argument) {
449
	triggerRecoveryUponLambdaClosure();
505
	LocalDeclaration local = new LocalDeclaration(argument.name, argument.sourceStart, argument.sourceEnd);
506
	local.declarationSourceStart = argument.declarationSourceStart;
507
	local.declarationSourceEnd = argument.declarationSourceEnd;
508
	local.modifiers = argument.modifiers;
509
	local.modifiersSourceStart = argument.modifiersSourceStart;
510
	local.annotations = argument.annotations;
511
	local.type = argument.type;
512
	return local;
513
}
514
protected void consumeLambdaHeader() {
515
	super.consumeLambdaHeader();
516
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr];
517
	pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, EXPRESSION_BODY, lexp);
518
519
//	if (this.currentElement != null) {
520
//		for (int i = 0, length = arguments.length; i < length; i++) {
521
//			this.currentElement = this.currentElement.add(fakeLocalFromArgument(arguments[i]), 0);
522
//		}
523
//	}
450
}
524
}
451
protected void consumeMethodBody() {
525
protected void consumeMethodBody() {
452
	super.consumeMethodBody();
526
	super.consumeMethodBody();
Lines 457-463 Link Here
457
		popElement(K_METHOD_DELIMITER);
531
		popElement(K_METHOD_DELIMITER);
458
	}
532
	}
459
	super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
533
	super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
460
	triggerRecoveryUponLambdaClosure();
461
}
534
}
462
protected void consumeMethodHeader() {
535
protected void consumeMethodHeader() {
463
	super.consumeMethodHeader();
536
	super.consumeMethodHeader();
Lines 519-532 Link Here
519
	// OpenBlock ::= $empty
592
	// OpenBlock ::= $empty
520
593
521
	super.consumeOpenBlock();
594
	super.consumeOpenBlock();
522
	int stackLength = this.blockStarts.length;
595
	// if (this.astPtr < 0 || !(this.astStack[this.astPtr] instanceof LambdaExpression && this.previousToken == TokenNameARROW)) {
523
	if (this.realBlockPtr >= stackLength) {
596
		int stackLength = this.blockStarts.length;
524
		System.arraycopy(
597
		if (this.realBlockPtr >= stackLength) {
525
			this.blockStarts, 0,
598
			System.arraycopy(
526
			this.blockStarts = new int[stackLength + StackIncrement], 0,
599
					this.blockStarts, 0,
527
			stackLength);
600
					this.blockStarts = new int[stackLength + StackIncrement], 0,
601
					stackLength);
602
		}
603
		this.blockStarts[this.realBlockPtr] = this.scanner.startPosition;
604
	// }
605
	if (requireExtendedRecovery()) {
606
		this.commit = true;
607
		if (DEBUG_COMMIT_ROLLBACK) {
608
			System.out.println(" ---  {"); //$NON-NLS-1$
609
		}
528
	}
610
	}
529
	this.blockStarts[this.realBlockPtr] = this.scanner.startPosition;
530
}
611
}
531
protected void consumeOpenFakeBlock() {
612
protected void consumeOpenFakeBlock() {
532
	// OpenBlock ::= $empty
613
	// OpenBlock ::= $empty
Lines 853-858 Link Here
853
				}
934
				}
854
				break;
935
				break;
855
			case TokenNameLBRACE:
936
			case TokenNameLBRACE:
937
				if (this.previousToken == TokenNameARROW) {
938
					popElement(K_LAMBDA_EXPRESSION_DELIMITER);
939
					pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, BLOCK_BODY, this.previousObjectInfo);
940
				}
856
				this.bracketDepth++;
941
				this.bracketDepth++;
857
				break;
942
				break;
858
			case TokenNameLBRACKET:
943
			case TokenNameLBRACKET:
Lines 1264-1269 Link Here
1264
	}
1349
	}
1265
	return false;
1350
	return false;
1266
}
1351
}
1352
protected boolean isIndirectlyInsideLambdaExpression(){
1353
	int i = this.elementPtr;
1354
	while (i > -1) {
1355
		if (this.elementKindStack[i] == K_LAMBDA_EXPRESSION_DELIMITER)
1356
			return true;
1357
		i--;
1358
	}
1359
	return false;
1360
}
1267
protected boolean isIndirectlyInsideType(){
1361
protected boolean isIndirectlyInsideType(){
1268
	int i = this.elementPtr;
1362
	int i = this.elementPtr;
1269
	while(i > -1) {
1363
	while(i > -1) {
Lines 1597-1602 Link Here
1597
		flushElementStack();
1691
		flushElementStack();
1598
	}
1692
	}
1599
}
1693
}
1694
1695
public boolean requireExtendedRecovery() {
1696
	if (this.assistNode instanceof TypeReference)
1697
		return false;
1698
	return lastIndexOfElement(K_LAMBDA_EXPRESSION_DELIMITER) >= 0;
1699
}
1700
1600
protected void pushOnElementStack(int kind){
1701
protected void pushOnElementStack(int kind){
1601
	this.pushOnElementStack(kind, 0, null);
1702
	this.pushOnElementStack(kind, 0, null);
1602
}
1703
}
Lines 1659-1665 Link Here
1659
			break;
1760
			break;
1660
		case TokenNameRBRACE :
1761
		case TokenNameRBRACE :
1661
			super.recoveryTokenCheck();
1762
			super.recoveryTokenCheck();
1662
			if(this.currentElement != oldElement && !isInsideAttributeValue()) {
1763
			if(this.currentElement != oldElement && !isInsideAttributeValue() && !isIndirectlyInsideLambdaExpression()) {
1663
				if(oldElement instanceof RecoveredInitializer
1764
				if(oldElement instanceof RecoveredInitializer
1664
					|| oldElement instanceof RecoveredMethod
1765
					|| oldElement instanceof RecoveredMethod
1665
					|| (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredInitializer)
1766
					|| (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredInitializer)
Lines 1691-1697 Link Here
1691
 * Move checkpoint location, reset internal stacks and
1792
 * Move checkpoint location, reset internal stacks and
1692
 * decide which grammar goal is activated.
1793
 * decide which grammar goal is activated.
1693
 */
1794
 */
1694
protected boolean resumeAfterRecovery() {
1795
protected int resumeAfterRecovery(boolean errorRecovery) {
1796
	
1797
	if (requireExtendedRecovery()) {
1798
		if (errorRecovery) {
1799
			int mode = fallBackToSpringForward((Statement) null);
1800
			if (mode == RESUME || mode == HALT)
1801
				return mode;
1802
			// else fall through and RESTART
1803
		} else {
1804
			return RESUME;
1805
		}
1806
	}
1695
1807
1696
	// reset internal stacks
1808
	// reset internal stacks
1697
	this.astPtr = -1;
1809
	this.astPtr = -1;
Lines 1700-1723 Link Here
1700
	this.expressionLengthPtr = -1;
1812
	this.expressionLengthPtr = -1;
1701
	this.typeAnnotationLengthPtr = -1;
1813
	this.typeAnnotationLengthPtr = -1;
1702
	this.typeAnnotationPtr = -1;
1814
	this.typeAnnotationPtr = -1;
1815
	
1703
	this.identifierPtr = -1;
1816
	this.identifierPtr = -1;
1704
	this.identifierLengthPtr	= -1;
1817
	this.identifierLengthPtr	= -1;
1705
	this.intPtr = -1;
1818
	this.intPtr = -1;
1819
	
1820
	
1706
	this.dimensions = 0 ;
1821
	this.dimensions = 0 ;
1707
	this.recoveredStaticInitializerStart = 0;
1822
	this.recoveredStaticInitializerStart = 0;
1708
1823
1709
	this.genericsIdentifiersLengthPtr = -1;
1824
	this.genericsIdentifiersLengthPtr = -1;
1710
	this.genericsLengthPtr = -1;
1825
	this.genericsLengthPtr = -1;
1711
	this.genericsPtr = -1;
1826
	this.genericsPtr = -1;
1827
	
1828
	this.valueLambdaNestDepth = -1;
1712
1829
1713
	this.modifiers = ClassFileConstants.AccDefault;
1830
	this.modifiers = ClassFileConstants.AccDefault;
1714
	this.modifiersSourceStart = -1;
1831
	this.modifiersSourceStart = -1;
1715
1832
1833
	// Assist state should require some rewinding too ???
1834
	
1716
	// if in diet mode, reset the diet counter because we're going to restart outside an initializer.
1835
	// if in diet mode, reset the diet counter because we're going to restart outside an initializer.
1717
	if (this.diet) this.dietInt = 0;
1836
	if (this.diet) this.dietInt = 0;
1718
1837
1719
	/* attempt to move checkpoint location */
1838
	/* attempt to move checkpoint location */
1720
	if (!moveRecoveryCheckpoint()) return false;
1839
	if (!moveRecoveryCheckpoint()) return HALT;
1721
1840
1722
	// only look for headers
1841
	// only look for headers
1723
	if (this.referenceContext instanceof CompilationUnitDeclaration
1842
	if (this.referenceContext instanceof CompilationUnitDeclaration
Lines 1738-1744 Link Here
1738
			goForHeaders();
1857
			goForHeaders();
1739
			this.diet = true; // passed this point, will not consider method bodies
1858
			this.diet = true; // passed this point, will not consider method bodies
1740
		}
1859
		}
1741
		return true;
1860
		return RESTART;
1742
	}
1861
	}
1743
	if (this.referenceContext instanceof AbstractMethodDeclaration
1862
	if (this.referenceContext instanceof AbstractMethodDeclaration
1744
		|| this.referenceContext instanceof TypeDeclaration){
1863
		|| this.referenceContext instanceof TypeDeclaration){
Lines 1750-1759 Link Here
1750
			prepareForBlockStatements();
1869
			prepareForBlockStatements();
1751
			goForBlockStatementsOrCatchHeader();
1870
			goForBlockStatementsOrCatchHeader();
1752
		}
1871
		}
1753
		return true;
1872
		return RESTART;
1754
	}
1873
	}
1755
	// does not know how to restart
1874
	// does not know how to restart
1756
	return false;
1875
	return HALT;
1757
}
1876
}
1758
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292087
1877
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292087
1759
// To be implemented in children viz. CompletionParser that are aware of array initializers
1878
// To be implemented in children viz. CompletionParser that are aware of array initializers
Lines 1826-1829 Link Here
1826
		return ast;
1945
		return ast;
1827
	}
1946
	}
1828
}
1947
}
1829
}
1948
}
(-)a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java (-34 / +22 lines)
Lines 40-46 Link Here
40
import org.eclipse.jdt.internal.compiler.ast.Expression;
40
import org.eclipse.jdt.internal.compiler.ast.Expression;
41
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
41
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
42
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
42
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
43
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
44
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
43
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
45
import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
44
import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
46
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
45
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
Lines 62-67 Link Here
62
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
61
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
63
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
62
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
64
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
63
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
64
import org.eclipse.jdt.internal.compiler.parser.CommitRollbackParser;
65
import org.eclipse.jdt.internal.compiler.parser.JavadocParser;
65
import org.eclipse.jdt.internal.compiler.parser.JavadocParser;
66
import org.eclipse.jdt.internal.compiler.parser.RecoveredType;
66
import org.eclipse.jdt.internal.compiler.parser.RecoveredType;
67
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
67
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
Lines 1184-1189 Link Here
1184
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
1184
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
1185
	}
1185
	}
1186
}
1186
}
1187
protected CommitRollbackParser createSnapShotParser() {
1188
	return new SelectionParser(this.problemReporter);
1189
}
1187
public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
1190
public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
1188
	return new SelectionOnImportReference(tokens, positions, mod);
1191
	return new SelectionOnImportReference(tokens, positions, mod);
1189
}
1192
}
Lines 1413-1440 Link Here
1413
	return super.parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
1416
	return super.parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
1414
}
1417
}
1415
1418
1416
protected int resumeOnSyntaxError() {
1417
	
1418
	if (this.referenceContext instanceof CompilationUnitDeclaration)
1419
		return super.resumeOnSyntaxError();
1420
	
1421
	// Defer initial *triggered* recovery if we see a type elided lambda expression on the stack. 
1422
	if (this.assistNode != null && this.restartRecovery) {
1423
		this.lambdaNeedsClosure = false;
1424
		for (int i = this.astPtr; i >= 0; i--) {
1425
			if (this.astStack[i] instanceof LambdaExpression) {
1426
				LambdaExpression expression = (LambdaExpression) this.astStack[i];
1427
				if (expression.argumentsTypeElided()) {
1428
					this.restartRecovery = false; // will be restarted in when the containing expression statement or explicit constructor call is reduced.
1429
					this.lambdaNeedsClosure = true;
1430
					return RESUME;
1431
				}
1432
			}
1433
		}
1434
	}
1435
	return super.resumeOnSyntaxError();
1436
}
1437
1438
/*
1419
/*
1439
 * Reset context so as to resume to regular parse loop
1420
 * Reset context so as to resume to regular parse loop
1440
 * If unable to reset for resuming, answers false.
1421
 * If unable to reset for resuming, answers false.
Lines 1442-1468 Link Here
1442
 * Move checkpoint location, reset internal stacks and
1423
 * Move checkpoint location, reset internal stacks and
1443
 * decide which grammar goal is activated.
1424
 * decide which grammar goal is activated.
1444
 */
1425
 */
1445
protected boolean resumeAfterRecovery() {
1426
protected int resumeAfterRecovery(boolean errorRecovery) {
1446
1427
1447
	/* if reached assist node inside method body, but still inside nested type,
1428
	/* if reached assist node inside method body, but still inside nested type,
1448
		should continue in diet mode until the end of the method body */
1429
		should continue in diet mode until the end of the method body */
1449
	if (this.assistNode != null
1430
	if (this.assistNode != null
1450
		&& !(this.referenceContext instanceof CompilationUnitDeclaration)){
1431
		&& !(this.referenceContext instanceof CompilationUnitDeclaration)){
1451
		this.currentElement.preserveEnclosingBlocks();
1432
		this.currentElement.preserveEnclosingBlocks();
1433
		if (requireExtendedRecovery()) {
1434
			if (!errorRecovery) {
1435
				return RESUME;
1436
			}
1437
			return super.resumeAfterRecovery(errorRecovery);
1438
		}
1452
		if (this.currentElement.enclosingType() == null) {
1439
		if (this.currentElement.enclosingType() == null) {
1453
			if(!(this.currentElement instanceof RecoveredType)) {
1440
			if (!(this.currentElement instanceof RecoveredType)) {
1454
				resetStacks();
1441
				resetStacks();
1455
				return false;
1442
				return HALT;
1456
	}
1443
			}
1457
1444
1458
			RecoveredType recoveredType = (RecoveredType)this.currentElement;
1445
			RecoveredType recoveredType = (RecoveredType) this.currentElement;
1459
			if(recoveredType.typeDeclaration != null && recoveredType.typeDeclaration.allocation == this.assistNode){
1446
			if (recoveredType.typeDeclaration != null && recoveredType.typeDeclaration.allocation == this.assistNode) {
1460
				resetStacks();
1447
				resetStacks();
1461
				return false;
1448
				return HALT;
1462
			}
1449
			}
1463
		}
1450
		}
1464
	}
1451
	}
1465
	return super.resumeAfterRecovery();
1452
	return super.resumeAfterRecovery(errorRecovery);
1466
}
1453
}
1467
1454
1468
public void selectionIdentifierCheck(){
1455
public void selectionIdentifierCheck(){
Lines 1504-1518 Link Here
1504
	char[] identifierName = this.identifierStack[this.identifierPtr];
1491
	char[] identifierName = this.identifierStack[this.identifierPtr];
1505
	long namePositions = this.identifierPositionStack[this.identifierPtr--];
1492
	long namePositions = this.identifierPositionStack[this.identifierPtr--];
1506
1493
1507
	Argument arg =
1494
	Argument argument =
1508
		new SelectionOnArgumentName(
1495
		new SelectionOnArgumentName(
1509
			identifierName,
1496
			identifierName,
1510
			namePositions,
1497
			namePositions,
1511
			null, // elided type
1498
			null, // elided type
1512
			ClassFileConstants.AccDefault,
1499
			ClassFileConstants.AccDefault,
1513
			true);
1500
			true);
1514
	arg.declarationSourceStart = (int) (namePositions >>> 32);
1501
	argument.declarationSourceStart = (int) (namePositions >>> 32);
1515
	return arg;
1502
	this.assistNode = argument;
1503
	return argument;
1516
}
1504
}
1517
public  String toString() {
1505
public  String toString() {
1518
	String s = Util.EMPTY_STRING;
1506
	String s = Util.EMPTY_STRING;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java (+2 lines)
Lines 307-312 Link Here
307
	public static final int IsSynthetic = ASTNode.Bit7;
307
	public static final int IsSynthetic = ASTNode.Bit7;
308
	
308
	
309
	public static final Argument [] NO_ARGUMENTS = new Argument [0];
309
	public static final Argument [] NO_ARGUMENTS = new Argument [0];
310
	
311
	public static final Block NO_BODY = new Block(0);
310
312
311
	public ASTNode() {
313
	public ASTNode() {
312
314
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java (-16 / +64 lines)
Lines 71-94 Link Here
71
	private Statement body;
71
	private Statement body;
72
	public boolean hasParentheses;
72
	public boolean hasParentheses;
73
	public MethodScope scope;
73
	public MethodScope scope;
74
	private boolean voidCompatible = true;
74
	boolean voidCompatible = true;
75
	private boolean valueCompatible = false;
75
	boolean valueCompatible = false;
76
	private boolean shapeAnalysisComplete = false;
76
	private boolean shapeAnalysisComplete = false;
77
	private boolean returnsValue;
77
	boolean returnsValue;
78
	private boolean returnsVoid;
78
	boolean returnsVoid;
79
	private LambdaExpression original = this;
79
	private LambdaExpression original = this;
80
	private SyntheticArgumentBinding[] outerLocalVariables = NO_SYNTHETIC_ARGUMENTS;
80
	private SyntheticArgumentBinding[] outerLocalVariables = NO_SYNTHETIC_ARGUMENTS;
81
	private int outerLocalVariablesSlotSize = 0;
81
	private int outerLocalVariablesSlotSize = 0;
82
	public boolean shouldCaptureInstance = false;
82
	public boolean shouldCaptureInstance = false;
83
	private boolean shouldUnelideTypes = false;
83
	private boolean assistNode = false;
84
	private boolean hasIgnoredMandatoryErrors = false;
84
	private boolean hasIgnoredMandatoryErrors = false;
85
	private static final SyntheticArgumentBinding [] NO_SYNTHETIC_ARGUMENTS = new SyntheticArgumentBinding[0];
85
	private static final SyntheticArgumentBinding [] NO_SYNTHETIC_ARGUMENTS = new SyntheticArgumentBinding[0];
86
	
86
	
87
	public LambdaExpression(CompilationResult compilationResult, boolean shouldUnelideTypes) {
87
	public LambdaExpression(CompilationResult compilationResult, boolean assistNode) {
88
		super(compilationResult);
88
		super(compilationResult);
89
		this.shouldUnelideTypes = shouldUnelideTypes;
89
		this.assistNode = assistNode;
90
		setArguments(NO_ARGUMENTS);
90
		setArguments(NO_ARGUMENTS);
91
		setBody(new Block(0));
91
		setBody(NO_BODY);
92
	}
92
	}
93
	
93
	
94
	public void setArguments(Argument [] arguments) {
94
	public void setArguments(Argument [] arguments) {
Lines 101-107 Link Here
101
	}
101
	}
102
102
103
	public void setBody(Statement body) {
103
	public void setBody(Statement body) {
104
		this.body = body == null ? new Block(0) : body;
104
		this.body = body == null ? NO_BODY : body;
105
	}
105
	}
106
	
106
	
107
	public Statement body() {
107
	public Statement body() {
Lines 110-115 Link Here
110
110
111
	public void setArrowPosition(int arrowPosition) {
111
	public void setArrowPosition(int arrowPosition) {
112
		this.arrowPosition = arrowPosition;
112
		this.arrowPosition = arrowPosition;
113
	}
114
	
115
	public int getArrowPosition() {
116
		return this.arrowPosition;
113
	}
117
	}
114
	
118
	
115
	protected FunctionalExpression original() {
119
	protected FunctionalExpression original() {
Lines 188-194 Link Here
188
		
192
		
189
		if (!haveDescriptor) {
193
		if (!haveDescriptor) {
190
			if (argumentsTypeElided) {
194
			if (argumentsTypeElided) {
191
				if (!this.shouldUnelideTypes)
195
				if (!this.assistNode)
192
					return null; // FUBAR, bail out...
196
					return null; // FUBAR, bail out...
193
				// for code assist ONLY, keep the sluice gate shut on bogus errors otherwise.
197
				// for code assist ONLY, keep the sluice gate shut on bogus errors otherwise.
194
				argumentsTypeElided = false;
198
				argumentsTypeElided = false;
Lines 524-529 Link Here
524
		return false;
528
		return false;
525
	}
529
	}
526
		
530
		
531
	private void analyzeShape() { // simple minded analysis for code assist.
532
		class ShapeComputer extends ASTVisitor {
533
			public boolean visit(TypeDeclaration type, BlockScope skope) {
534
				return false;
535
			}
536
			public boolean visit(TypeDeclaration type, ClassScope skope) {
537
				return false;
538
			}
539
			public boolean visit(LambdaExpression type, BlockScope skope) {
540
				return false;
541
			}
542
		    public boolean visit(ReturnStatement returnStatement, BlockScope skope) {
543
		    	if (returnStatement.expression != null) {
544
		    		LambdaExpression.this.valueCompatible = true;
545
		    		LambdaExpression.this.voidCompatible = false;
546
		    	} else {
547
		    		LambdaExpression.this.voidCompatible = true;
548
		    		LambdaExpression.this.valueCompatible = false;
549
		    	}
550
		    	return false;
551
		    }
552
		}
553
		if (this.body instanceof Expression) {
554
			this.voidCompatible = ((Expression) this.body).statementExpression();
555
			this.valueCompatible = true;
556
		} else {
557
			// We need to be a bit tolerant/fuzzy here: the code is being written "just now", if we are too pedantic, selection/completion will break;
558
			this.voidCompatible = true;
559
			this.valueCompatible = true;
560
			this.body.traverse(new ShapeComputer(), null);
561
		}
562
		this.shapeAnalysisComplete = true;
563
	}
564
	
527
	public boolean isCompatibleWith(final TypeBinding left, final Scope someScope) {
565
	public boolean isCompatibleWith(final TypeBinding left, final Scope someScope) {
528
		
566
		
529
		final MethodBinding sam = left.getSingleAbstractMethod(this.enclosingScope);
567
		final MethodBinding sam = left.getSingleAbstractMethod(this.enclosingScope);
Lines 540-547 Link Here
540
			compilerOptions.isAnnotationBasedNullAnalysisEnabled = false;
578
			compilerOptions.isAnnotationBasedNullAnalysisEnabled = false;
541
			try {
579
			try {
542
				final LambdaExpression copy = copy();
580
				final LambdaExpression copy = copy();
543
				if (copy == null)
581
				if (copy == null) {
544
					return false;
582
					if (this.assistNode) {
583
						analyzeShape(); // not on terra firma here !
584
						if (sam.returnType.id == TypeIds.T_void) {
585
							if (!this.voidCompatible)
586
								return false;
587
						} else {
588
							if (!this.valueCompatible)
589
								return false;
590
						}
591
					}
592
					return !isPertinentToApplicability(left);
593
				}
545
				copy.setExpressionContext(this.expressionContext);
594
				copy.setExpressionContext(this.expressionContext);
546
				copy.setExpectedType(left);
595
				copy.setExpectedType(left);
547
				this.hasIgnoredMandatoryErrors = false;
596
				this.hasIgnoredMandatoryErrors = false;
Lines 576-584 Link Here
576
			}
625
			}
577
		}
626
		}
578
627
579
		if (!isPertinentToApplicability(left))
628
		if (!isPertinentToApplicability(left))  // This check should happen after return type check below, but for buggy javac compatibility we have left it in.
580
			return true;
629
			return true;
581
	
630
582
		if (sam.returnType.id == TypeIds.T_void) {
631
		if (sam.returnType.id == TypeIds.T_void) {
583
			if (!this.voidCompatible)
632
			if (!this.voidCompatible)
584
				return false;
633
				return false;
Lines 586-593 Link Here
586
			if (!this.valueCompatible)
635
			if (!this.valueCompatible)
587
				return false;
636
				return false;
588
		}
637
		}
589
		
638
			Expression [] returnExpressions = this.resultExpressions;
590
		Expression [] returnExpressions = this.resultExpressions;
591
		for (int i = 0, length = returnExpressions.length; i < length; i++) {
639
		for (int i = 0, length = returnExpressions.length; i < length; i++) {
592
			if (returnExpressions[i] instanceof FunctionalExpression) { // don't want to use the resolvedType - polluted from some other overload resolution candidate
640
			if (returnExpressions[i] instanceof FunctionalExpression) { // don't want to use the resolvedType - polluted from some other overload resolution candidate
593
				if (!returnExpressions[i].isCompatibleWith(sam.returnType, this.enclosingScope))
641
				if (!returnExpressions[i].isCompatibleWith(sam.returnType, this.enclosingScope))
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/CommitRollbackParser.java (+308 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2013 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * This is an implementation of an early-draft specification developed under the Java
9
 * Community Process (JCP) and is made available for testing and evaluation purposes
10
 * only. The code is not compatible with any specification of the JCP.
11
 * 
12
 * Contributors:
13
 *     IBM Corporation - initial API and implementation
14
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.parser;
16
17
import org.eclipse.jdt.core.compiler.InvalidInputException;
18
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
19
import org.eclipse.jdt.internal.compiler.ast.Annotation;
20
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
21
import org.eclipse.jdt.internal.compiler.ast.Expression;
22
import org.eclipse.jdt.internal.compiler.ast.Statement;
23
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
24
25
public abstract class CommitRollbackParser implements TerminalTokens, ParserBasicInformation {
26
	
27
	// resumeOnSyntaxError codes:
28
	protected static final int HALT = 0;     // halt and throw up hands.
29
	protected static final int RESTART = 1;  // stacks adjusted, alternate goal from check point.
30
	protected static final int RESUME = 2;   // stacks untouched, just continue from where left off.
31
32
	public static byte rhs[] = null;
33
	public static char lhs[] =  null;
34
	public static char term_action[] = null;
35
	public static byte term_check[] = null;
36
	public static char base_action[] = null;
37
	
38
	public ReferenceContext referenceContext;
39
40
41
	// Constants.
42
	protected static final int AstStackIncrement = 100;
43
	protected static final int ExpressionStackIncrement = 100;
44
	protected static final int GenericsStackIncrement = 10;
45
	protected static final int StackIncrement = 255;
46
	protected static final int TypeAnnotationStackIncrement = 100;
47
	
48
	public Scanner scanner;
49
	public int currentToken;
50
	protected int kurrentToken; // copy of currentToken as it is trampled over all over the place :-(
51
	protected boolean commit = false;
52
	
53
	// -------------  Stack pointers ---------------
54
55
	protected int stateStackTop;
56
	protected int unstackedAct;
57
58
	protected int identifierPtr;
59
	protected int identifierLengthPtr;
60
	
61
	protected int astPtr;
62
	protected int astLengthPtr;
63
	
64
	protected int expressionPtr;
65
	protected int expressionLengthPtr;
66
	
67
	protected int genericsPtr;
68
	protected int genericsLengthPtr;
69
	protected int genericsIdentifiersLengthPtr;
70
	
71
	protected int typeAnnotationPtr;
72
	protected int typeAnnotationLengthPtr;
73
	
74
	protected int intPtr;
75
	protected int nestedType;
76
	protected int realBlockPtr;
77
	public int valueLambdaNestDepth = -1;
78
	
79
	// ---------------- Stacks ----------------
80
	
81
	protected int[] stack = new int[StackIncrement];
82
	
83
	protected char[][] identifierStack;
84
	protected int[] identifierLengthStack;
85
	protected long[] identifierPositionStack;
86
87
	protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
88
	protected int[] astLengthStack;
89
	
90
	protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
91
	protected int[] expressionLengthStack;
92
93
	protected ASTNode[] genericsStack = new ASTNode[GenericsStackIncrement];
94
	protected int[] genericsLengthStack = new int[GenericsStackIncrement];
95
	protected int[] genericsIdentifiersLengthStack = new int[GenericsStackIncrement];
96
	
97
	protected Annotation [] typeAnnotationStack = new Annotation[TypeAnnotationStackIncrement];
98
	protected int [] typeAnnotationLengthStack;
99
	
100
	protected int[] intStack;
101
	protected int[] nestedMethod;
102
	protected int[] realBlockStack;
103
	protected int stateStackLengthStack[] = new int[0];
104
	protected int[] variablesCounter;
105
	
106
	// Loose variables.
107
	
108
	protected int listLength;
109
	protected int listTypeParameterLength;
110
	protected int modifiers;
111
	protected int modifiersSourceStart;
112
	protected int dimensions;
113
	protected int recoveredStaticInitializerStart;
114
	
115
	CommitRollbackParser cryogenicallyFrozenParser;
116
	private static final int[] RECOVERY_TOKENS = new int [] { TokenNameSEMICOLON, TokenNameRPAREN,};
117
	
118
	protected void copyState(CommitRollbackParser parser) {
119
120
		// Stack pointers.
121
		
122
		this.stateStackTop = parser.stateStackTop;
123
		this.unstackedAct = parser.unstackedAct;
124
		this.identifierPtr = parser.identifierPtr;
125
		this.identifierLengthPtr = parser.identifierLengthPtr;
126
		this.astPtr = parser.astPtr;
127
		this.astLengthPtr = parser.astLengthPtr;
128
		this.expressionPtr = parser.expressionPtr;
129
		this.expressionLengthPtr = parser.expressionLengthPtr;
130
		this.genericsPtr = parser.genericsPtr;
131
		this.genericsLengthPtr = parser.genericsLengthPtr;
132
		this.genericsIdentifiersLengthPtr = parser.genericsIdentifiersLengthPtr;
133
		this.typeAnnotationPtr = parser.typeAnnotationPtr;
134
		this.typeAnnotationLengthPtr = parser.typeAnnotationLengthPtr;
135
		this.intPtr = parser.intPtr;
136
		this.nestedType = parser.nestedType;
137
		this.realBlockPtr = parser.realBlockPtr;
138
		this.valueLambdaNestDepth = parser.valueLambdaNestDepth;
139
		
140
		// Stacks.
141
		
142
		int length;
143
		System.arraycopy(parser.stack, 0, this.stack = new int [length = parser.stack.length], 0, length);
144
		System.arraycopy(parser.identifierStack, 0, this.identifierStack = new char [length = parser.identifierStack.length][], 0, length);
145
		System.arraycopy(parser.identifierLengthStack, 0, this.identifierLengthStack = new int [length = parser.identifierLengthStack.length], 0, length);
146
		System.arraycopy(parser.identifierPositionStack, 0, this.identifierPositionStack = new long[length = parser.identifierPositionStack.length], 0, length);
147
		System.arraycopy(parser.astStack, 0, this.astStack = new ASTNode [length = parser.astStack.length], 0, length);
148
		System.arraycopy(parser.astLengthStack, 0, this.astLengthStack = new int [length = parser.astLengthStack.length], 0, length);
149
		System.arraycopy(parser.expressionStack, 0, this.expressionStack = new Expression [length = parser.expressionStack.length], 0, length);
150
		System.arraycopy(parser.expressionLengthStack, 0, this.expressionLengthStack = new int [length = parser.expressionLengthStack.length], 0, length);
151
		System.arraycopy(parser.genericsStack, 0, this.genericsStack = new ASTNode [length = parser.genericsStack.length], 0, length);
152
		System.arraycopy(parser.genericsLengthStack, 0, this.genericsLengthStack = new int [length = parser.genericsLengthStack.length], 0, length);
153
		System.arraycopy(parser.genericsIdentifiersLengthStack, 0, this.genericsIdentifiersLengthStack = new int [length = parser.genericsIdentifiersLengthStack.length], 0, length);
154
		System.arraycopy(parser.typeAnnotationStack, 0, this.typeAnnotationStack = new Annotation [length = parser.typeAnnotationStack.length], 0, length);
155
		System.arraycopy(parser.typeAnnotationLengthStack, 0, this.typeAnnotationLengthStack = new int [length = parser.typeAnnotationLengthStack.length], 0, length);
156
		System.arraycopy(parser.intStack, 0, this.intStack = new int [length = parser.intStack.length], 0, length);
157
		System.arraycopy(parser.nestedMethod, 0, this.nestedMethod = new int [length = parser.nestedMethod.length], 0, length);
158
		System.arraycopy(parser.realBlockStack, 0, this.realBlockStack = new int [length = parser.realBlockStack.length], 0, length);
159
		System.arraycopy(parser.stateStackLengthStack, 0, this.stateStackLengthStack = new int [length = parser.stateStackLengthStack.length], 0, length);
160
		System.arraycopy(parser.variablesCounter, 0, this.variablesCounter = new int [length = parser.variablesCounter.length], 0, length);
161
		System.arraycopy(parser.stack, 0, this.stack = new int [length = parser.stack.length], 0, length);
162
		System.arraycopy(parser.stack, 0, this.stack = new int [length = parser.stack.length], 0, length);
163
		System.arraycopy(parser.stack, 0, this.stack = new int [length = parser.stack.length], 0, length);
164
165
		// Loose variables.
166
		
167
		this.listLength = parser.listLength;
168
		this.listTypeParameterLength = parser.listTypeParameterLength;
169
		this.dimensions = parser.dimensions;
170
		this.recoveredStaticInitializerStart = parser.recoveredStaticInitializerStart;
171
172
		// Parser.resetStacks is not clearing the modifiers, but AssistParser.resumeAfterRecovery is - why ? (the former doesn't)
173
		// this.modifiers = parser.modifiers;
174
		// this.modifiersSourceStart = parser.modifiersSourceStart;
175
	}
176
	
177
	protected CommitRollbackParser createSnapShotParser() {
178
		return new Parser();
179
	}
180
	
181
	/* Must be called from Parser.parse ONLY. Rule reduction routine must simply set the flag to request commit. 
182
	   This ensures the end state of chain rule reductions gets committed rather than some intermediate state.
183
	   See the reduce do-while loop.
184
	*/
185
	protected void commit() {
186
		if (this.cryogenicallyFrozenParser == null) {
187
			this.cryogenicallyFrozenParser = createSnapShotParser();
188
		}
189
		this.cryogenicallyFrozenParser.copyState(this);
190
		this.commit = false;
191
	}
192
	
193
	protected int getNextToken() {
194
		try {
195
			return this.scanner.getNextToken();
196
		} catch (InvalidInputException e) {
197
			return TokenNameEOF;
198
		}
199
	}
200
	
201
	// We get here on real syntax error or syntax error triggered by fake EOF at completion site, never due to triggered recovery.
202
	protected int fallBackToSpringForward(Statement unused) {
203
		int nextToken;
204
		int lastAction = this.stack[this.stateStackTop];
205
				
206
		// If triggered fake EOF at completion site, see if the real next token would have passed muster.
207
		if (this.kurrentToken == TokenNameEOF) {
208
			if (this.scanner.eofPosition < this.scanner.source.length) {
209
				this.scanner.eofPosition = this.scanner.source.length;
210
				nextToken = getNextToken();
211
				if (automatonWillShift(nextToken, lastAction)) {
212
					this.currentToken = this.kurrentToken = nextToken;
213
					this.unstackedAct = this.stack[this.stateStackTop--];
214
					return RESUME;
215
				}
216
			} else {
217
				nextToken = TokenNameEOF;
218
			}
219
		} else {
220
			nextToken = this.kurrentToken;
221
		}
222
		if (nextToken == TokenNameEOF)
223
			return HALT; // don't know how to proceed.
224
		this.scanner.ungetToken(nextToken); // spit out what has been bitten more than we can chew.
225
		// OK, next token is no good to resume "in place", attempt some local repair.
226
		for (int i = 0, length = RECOVERY_TOKENS.length; i < length; i++) {
227
			if (automatonWillShift(RECOVERY_TOKENS[i], lastAction)) {
228
				this.currentToken = this.kurrentToken = RECOVERY_TOKENS[i];
229
				this.unstackedAct = this.stack[this.stateStackTop--];
230
				return RESUME;
231
			}
232
		}
233
		// OK, no in place resumption, no local repair, fast forward to next statement.
234
		if (this.cryogenicallyFrozenParser == null || this.referenceContext instanceof CompilationUnitDeclaration) {
235
			return RESTART;
236
		}
237
		this.copyState(this.cryogenicallyFrozenParser);
238
		this.currentToken = this.scanner.fastForward(unused);
239
		return RESUME;
240
	}
241
242
	protected void resetStacks() {
243
	
244
		this.astPtr = -1;
245
		this.astLengthPtr = -1;
246
		this.expressionPtr = -1;
247
		this.expressionLengthPtr = -1;
248
		this.typeAnnotationLengthPtr = -1;
249
		this.typeAnnotationPtr = -1;
250
		this.identifierPtr = -1;
251
		this.identifierLengthPtr	= -1;
252
		this.intPtr = -1;
253
		
254
		this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse
255
		this.variablesCounter[this.nestedType] = 0;
256
		
257
		this.dimensions = 0 ;
258
		this.realBlockStack[this.realBlockPtr = 0] = 0;
259
		this.recoveredStaticInitializerStart = 0;
260
		this.listLength = 0;
261
		this.listTypeParameterLength = 0;
262
	
263
		this.genericsIdentifiersLengthPtr = -1;
264
		this.genericsLengthPtr = -1;
265
		this.genericsPtr = -1;
266
		this.valueLambdaNestDepth = -1;
267
	}
268
269
	protected boolean automatonWillShift(int token, int lastAction) {
270
		int stackTop = this.stateStackTop;        // local copy of stack pointer
271
		int stackTopState = this.stack[stackTop]; // single cell non write through "alternate stack" - the automaton's stack pointer either stays fixed during this manoeuvre or monotonically decreases.
272
		int highWaterMark = stackTop;
273
		// A rotated version of the automaton - cf. parse()'s for(;;)
274
		for (;;) {  
275
			if (lastAction > ERROR_ACTION) {  
276
				lastAction -= ERROR_ACTION;    /* shift-reduce on loop entry from above, reduce on loop back */
277
				do { /* reduce */
278
					stackTop -= rhs[lastAction] - 1;
279
					if (stackTop < highWaterMark) {
280
						stackTopState = this.stack[highWaterMark = stackTop];
281
					} // else stackTopState is upto date already.
282
					lastAction = ntAction(stackTopState, lhs[lastAction]);
283
				} while (lastAction <= NUM_RULES);
284
			}
285
			highWaterMark = ++stackTop;
286
			stackTopState = lastAction; // "push"
287
			lastAction = tAction(lastAction, token); // can be looked up from a precomputed cache.
288
			if (lastAction <= NUM_RULES) {
289
				stackTop --; 
290
			    lastAction += ERROR_ACTION;
291
				continue;
292
			}
293
			// Error => false, Shift, Shift/Reduce => true, Accept => impossible. 
294
			return lastAction != ERROR_ACTION;
295
		}
296
	}
297
298
public static int tAction(int state, int sym) {
299
	return term_action[term_check[base_action[state]+sym] == sym ? base_action[state] + sym : base_action[state]];
300
}
301
302
public static int ntAction(int state, int sym) {
303
	return base_action[state + sym];
304
}
305
306
307
}
308
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ConflictedParser.java (+4 lines)
Lines 22-25 Link Here
22
	   we treat the type annotation as a declarative annotation.
22
	   we treat the type annotation as a declarative annotation.
23
	*/
23
	*/
24
	boolean atConflictScenario(int token);
24
	boolean atConflictScenario(int token);
25
26
	void startRecovery();
27
28
	boolean requireExtendedRecovery();
25
}
29
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java (-234 / +56 lines)
Lines 159-165 Link Here
159
import org.eclipse.jdt.internal.compiler.util.Messages;
159
import org.eclipse.jdt.internal.compiler.util.Messages;
160
import org.eclipse.jdt.internal.compiler.util.Util;
160
import org.eclipse.jdt.internal.compiler.util.Util;
161
161
162
public class Parser implements ConflictedParser, ParserBasicInformation, TerminalTokens, OperatorIds, TypeIds {
162
public class Parser extends CommitRollbackParser implements ConflictedParser, OperatorIds, TypeIds {
163
	
163
	
164
	protected static final int THIS_CALL = ExplicitConstructorCall.This;
164
	protected static final int THIS_CALL = ExplicitConstructorCall.This;
165
	protected static final int SUPER_CALL = ExplicitConstructorCall.Super;
165
	protected static final int SUPER_CALL = ExplicitConstructorCall.Super;
Lines 168-193 Link Here
168
	
168
	
169
	public static char asb[] = null;
169
	public static char asb[] = null;
170
	public static char asr[] = null;
170
	public static char asr[] = null;
171
	//ast stack
172
	protected final static int AstStackIncrement = 100;
173
	public static char base_action[] = null;
174
	public static final int BracketKinds = 3;
171
	public static final int BracketKinds = 3;
175
172
176
	public static short check_table[] = null;
173
	public static short check_table[] = null;
177
	public static final int CurlyBracket = 2;
174
	public static final int CurlyBracket = 2;
178
	private static final boolean DEBUG = false;
175
	private static final boolean DEBUG = true;
179
	private static final boolean DEBUG_AUTOMATON = false;
176
	private static final boolean DEBUG_AUTOMATON = true;
180
	private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
177
	private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
181
	private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
178
	private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
182
	//expression stack
183
	protected final static int ExpressionStackIncrement = 100;
184
185
	protected final static int GenericsStackIncrement = 10;
186
187
	private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
179
	private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
188
    public static char in_symb[] = null;
180
    public static char in_symb[] = null;
189
	private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
181
	private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
190
	public static char lhs[] =  null;
191
182
192
	public static String name[] = null;
183
	public static String name[] = null;
193
	public static char nasb[] = null;
184
	public static char nasb[] = null;
Lines 197-203 Link Here
197
188
198
	public static String readableName[] = null;
189
	public static String readableName[] = null;
199
190
200
	public static byte rhs[] = null;
201
191
202
	public static int[] reverse_index = null;
192
	public static int[] reverse_index = null;
203
	public static char[] recovery_templates_index = null;
193
	public static char[] recovery_templates_index = null;
Lines 219-229 Link Here
219
    public static char scope_suffix[] = null;
209
    public static char scope_suffix[] = null;
220
	public static final int SquareBracket = 1;
210
	public static final int SquareBracket = 1;
221
211
222
	//internal data for the automat
223
	protected final static int StackIncrement = 255;
224
225
	public static char term_action[] = null;
226
	public static byte term_check[] = null;
227
212
228
	public static char terminal_index[] = null;
213
	public static char terminal_index[] = null;
229
214
Lines 737-745 Link Here
737
	public static int nasi(int state) {
722
	public static int nasi(int state) {
738
		return nasb[original_state(state)];
723
		return nasb[original_state(state)];
739
	}
724
	}
740
	public static int ntAction(int state, int sym) {
741
		return base_action[state + sym];
742
	}
743
	protected static int original_state(int state) {
725
	protected static int original_state(int state) {
744
		return -base_check(state);
726
		return -base_check(state);
745
	}
727
	}
Lines 885-949 Link Here
885
		}
867
		}
886
		return chars;
868
		return chars;
887
	}
869
	}
888
	public static int tAction(int state, int sym) {
889
		return term_action[term_check[base_action[state]+sym] == sym ? base_action[state] + sym : base_action[state]];
890
	}
891
	protected int astLengthPtr;
892
893
	protected int[] astLengthStack;
894
	protected int astPtr;
895
	protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
896
	public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
870
	public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
897
871
898
	protected RecoveredElement currentElement;
872
	protected RecoveredElement currentElement;
899
	public int currentToken;
873
	
900
	protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
874
	protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
901
	protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
875
	protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
902
	protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
876
	protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
903
	protected int endStatementPosition;
877
	protected int endStatementPosition;
904
	protected int expressionLengthPtr;
905
	protected int[] expressionLengthStack;
906
	protected int expressionPtr;
907
	protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
908
	public int firstToken ; // handle for multiple parsing goals
878
	public int firstToken ; // handle for multiple parsing goals
909
	
879
	
910
	/* jsr308 -- Type annotation management, we now maintain type annotations in a separate stack
911
	   as otherwise they get interspersed with other expressions and some of the code is not prepared
912
	   to handle such interleaving and will look ugly if changed. 
913
	   
914
	   See consumeArrayCreationExpressionWithoutInitializer for example. 
915
916
	   Where SE8 annotations occur in a place SE5 annotations are legal, the SE8 annotations end up in
917
	   the expression stack as we have no way of distinguishing between the two.
918
	*/  
919
	protected int typeAnnotationPtr;
920
	protected int typeAnnotationLengthPtr;
921
	protected Annotation [] typeAnnotationStack = new Annotation[TypeAnnotationStackIncrement];
922
	protected int [] typeAnnotationLengthStack;
923
	// annotation stack
924
	protected final static int TypeAnnotationStackIncrement = 100;
925
	
926
	// generics management
927
	protected int genericsIdentifiersLengthPtr;
928
	protected int[] genericsIdentifiersLengthStack = new int[GenericsStackIncrement];
929
	protected int genericsLengthPtr;
930
	protected int[] genericsLengthStack = new int[GenericsStackIncrement];
931
	protected int genericsPtr;
932
	protected ASTNode[] genericsStack = new ASTNode[GenericsStackIncrement];
933
	protected boolean hasError;
880
	protected boolean hasError;
934
	protected boolean hasReportedError;
881
	protected boolean hasReportedError;
935
	//identifiers stacks
936
	protected int identifierLengthPtr;
937
	protected int[] identifierLengthStack;
938
	protected long[] identifierPositionStack;
939
	protected int identifierPtr;
940
	protected char[][] identifierStack;
941
	protected boolean ignoreNextOpeningBrace;
882
	protected boolean ignoreNextOpeningBrace;
942
883
943
	//positions , dimensions , .... (int stacks)
944
	protected int intPtr;
945
946
	protected int[] intStack;
947
	public int lastAct ; //handle for multiple parsing goals
884
	public int lastAct ; //handle for multiple parsing goals
948
	//error recovery management
885
	//error recovery management
949
	protected int lastCheckPoint;
886
	protected int lastCheckPoint;
Lines 951-968 Link Here
951
	protected int lastErrorEndPositionBeforeRecovery = -1;
888
	protected int lastErrorEndPositionBeforeRecovery = -1;
952
	protected int lastIgnoredToken, nextIgnoredToken;
889
	protected int lastIgnoredToken, nextIgnoredToken;
953
890
954
	protected int listLength; // for recovering some incomplete list (interfaces, throws or parameters)
955
956
	protected int listTypeParameterLength; // for recovering some incomplete list (type parameters)
957
	protected int lParenPos,rParenPos; //accurate only when used !
891
	protected int lParenPos,rParenPos; //accurate only when used !
958
	protected int modifiers;
959
	protected int modifiersSourceStart;
960
	protected int[] nestedMethod; //the ptr is nestedType
961
962
	protected int nestedType, dimensions;
963
	ASTNode [] noAstNodes = new ASTNode[AstStackIncrement];
964
965
	Expression [] noExpressions = new Expression[ExpressionStackIncrement];
966
	//modifiers dimensions nestedType etc.......
892
	//modifiers dimensions nestedType etc.......
967
	protected boolean optimizeStringLiterals =true;
893
	protected boolean optimizeStringLiterals =true;
968
	protected CompilerOptions options;
894
	protected CompilerOptions options;
Lines 970-979 Link Here
970
	protected ProblemReporter problemReporter;
896
	protected ProblemReporter problemReporter;
971
897
972
	protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
898
	protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
973
protected int realBlockPtr;
974
protected int[] realBlockStack;
975
protected int recoveredStaticInitializerStart;
976
public ReferenceContext referenceContext;
977
public boolean reportOnlyOneSyntaxError = false;
899
public boolean reportOnlyOneSyntaxError = false;
978
public boolean reportSyntaxErrorIsRequired = true;
900
public boolean reportSyntaxErrorIsRequired = true;
979
protected boolean restartRecovery;
901
protected boolean restartRecovery;
Lines 988-999 Link Here
988
protected TypeDeclaration pendingRecoveredType;
910
protected TypeDeclaration pendingRecoveredType;
989
public RecoveryScanner recoveryScanner;
911
public RecoveryScanner recoveryScanner;
990
//scanner token
912
//scanner token
991
public Scanner scanner;
992
protected int[] stack = new int[StackIncrement];
993
protected int stateStackTop;
994
protected int synchronizedBlockSourceStart;
913
protected int synchronizedBlockSourceStart;
995
996
protected int[] variablesCounter;
997
914
998
protected boolean checkExternalizeStrings;
915
protected boolean checkExternalizeStrings;
999
916
Lines 1004-1024 Link Here
1004
// used for recovery
921
// used for recovery
1005
protected int lastJavadocEnd;
922
protected int lastJavadocEnd;
1006
public org.eclipse.jdt.internal.compiler.ReadManager readManager;
923
public org.eclipse.jdt.internal.compiler.ReadManager readManager;
1007
private int valueLambdaNestDepth = -1;
924
private boolean parsingJava8Plus;
1008
private int stateStackLengthStack[] = new int[0];
1009
protected boolean parsingJava8Plus;
1010
protected int unstackedAct = ERROR_ACTION;
1011
private boolean haltOnSyntaxError = false;
925
private boolean haltOnSyntaxError = false;
1012
private boolean tolerateDefaultClassMethods = false;
926
private boolean tolerateDefaultClassMethods = false;
1013
private boolean processingLambdaParameterList = false;
927
private boolean processingLambdaParameterList = false;
1014
private boolean expectTypeAnnotation = false;
928
private boolean expectTypeAnnotation = false;
1015
1016
// resumeOnSyntaxError codes:
1017
1018
protected static final int HALT = 0;     // halt and throw up hands.
1019
protected static final int RESTART = 1;  // stacks reset, alternate goal from check point.
1020
protected static final int RESUME = 2;   // stacks untouched, just continue from where left off.
1021
1022
929
1023
protected Parser () {
930
protected Parser () {
1024
	// Caveat Emptor: For inheritance purposes and then only in very special needs. Only minimal state is initialized !
931
	// Caveat Emptor: For inheritance purposes and then only in very special needs. Only minimal state is initialized !
Lines 2251-2257 Link Here
2251
	pushOnAstStack(block);
2158
	pushOnAstStack(block);
2252
}
2159
}
2253
protected void consumeBlockStatement() {
2160
protected void consumeBlockStatement() {
2254
	// todo.
2161
	// for assist parsers.
2255
}
2162
}
2256
protected void consumeBlockStatements() {
2163
protected void consumeBlockStatements() {
2257
	// BlockStatements ::= BlockStatements BlockStatement
2164
	// BlockStatements ::= BlockStatements BlockStatement
Lines 7861-7871 Link Here
7861
	this.nestedMethod[this.nestedType] ++;
7768
	this.nestedMethod[this.nestedType] ++;
7862
	LambdaExpression lambda = new LambdaExpression(this.compilationUnit.compilationResult, this instanceof AssistParser);
7769
	LambdaExpression lambda = new LambdaExpression(this.compilationUnit.compilationResult, this instanceof AssistParser);
7863
	pushOnAstStack(lambda);
7770
	pushOnAstStack(lambda);
7864
	if (this.currentElement != null) {
7865
		this.currentElement = this.currentElement.add(lambda, 0);
7866
		this.lastCheckPoint = this.scanner.currentPosition;
7867
		this.lastIgnoredToken = -1;
7868
	}
7869
	this.processingLambdaParameterList = true;	
7771
	this.processingLambdaParameterList = true;	
7870
}
7772
}
7871
7773
Lines 7896-7911 Link Here
7896
	}
7798
	}
7897
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr];
7799
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr];
7898
	lexp.setArguments(arguments);
7800
	lexp.setArguments(arguments);
7899
	lexp.setArrowPosition(arrowPosition); // '->' position
7801
	lexp.setArrowPosition(arrowPosition);
7900
	lexp.sourceEnd = this.intStack[this.intPtr--];   // ')' position or identifier position.
7802
	lexp.sourceEnd = this.intStack[this.intPtr--];   // ')' position or identifier position.
7901
	lexp.sourceStart = this.intStack[this.intPtr--]; // '(' position or identifier position.
7803
	lexp.sourceStart = this.intStack[this.intPtr--]; // '(' position or identifier position.
7902
	lexp.hasParentheses = (this.scanner.getSource()[lexp.sourceStart] == '(');
7804
	lexp.hasParentheses = (this.scanner.getSource()[lexp.sourceStart] == '(');
7903
	this.listLength = 0; // reset this.listLength after having read all parameters
7805
	this.listLength -= arguments == null ? 0 : arguments.length;  // not necessary really.
7904
	if (this.currentElement != null) {
7905
		this.lastCheckPoint = lexp.sourceEnd + 1;
7906
		this.lastIgnoredToken = -1;
7907
	}
7908
	this.processingLambdaParameterList = false;
7806
	this.processingLambdaParameterList = false;
7807
	if (this.currentElement != null) {
7808
		this.ignoreNextOpeningBrace = true;
7809
		this.currentElement.bracketBalance++;
7810
	}
7909
}
7811
}
7910
protected void consumeLambdaExpression() {
7812
protected void consumeLambdaExpression() {
7911
	
7813
	
Lines 7934-7944 Link Here
7934
		problemReporter().lambdaExpressionsNotBelow18(lexp);
7836
		problemReporter().lambdaExpressionsNotBelow18(lexp);
7935
	}
7837
	}
7936
	pushOnExpressionStack(lexp);
7838
	pushOnExpressionStack(lexp);
7937
	if (this.currentElement != null) {
7839
	if (this.currentElement != null && lexp.body() instanceof Expression) {
7938
		if (this.currentElement.parseTree() == lexp && this.currentElement.parent != null) {
7840
		this.currentElement.bracketBalance--;
7939
			this.currentElement = this.currentElement.parent;
7940
		}
7941
		this.lastCheckPoint = lexp.sourceEnd + 1;
7942
	}
7841
	}
7943
}
7842
}
7944
7843
Lines 7984-7992 Link Here
7984
		pushOnIntStack(arg.declarationSourceEnd);
7883
		pushOnIntStack(arg.declarationSourceEnd);
7985
	}
7884
	}
7986
	pushOnAstStack(arg);
7885
	pushOnAstStack(arg);
7987
	/* if incomplete method header, this.listLength counter will not have been reset,
7886
	this.listLength++;  // not relevant really.
7988
		indicating that some arguments are available on the stack */
7989
	this.listLength++;
7990
}
7887
}
7991
protected void consumeElidedLeftBraceAndReturn() {
7888
protected void consumeElidedLeftBraceAndReturn() {
7992
	/* ElidedLeftBraceAndReturn ::= $empty
7889
	/* ElidedLeftBraceAndReturn ::= $empty
Lines 8740-8765 Link Here
8740
	optimizedConcatNodeLists();
8637
	optimizedConcatNodeLists();
8741
}
8638
}
8742
protected void consumeToken(int type) {
8639
protected void consumeToken(int type) {
8743
	/* remember the last consumed value */
8640
	if (this.commit)
8744
	/* try to minimize the number of build values */
8641
		commit();
8745
//	// clear the commentPtr of the scanner in case we read something different from a modifier
8746
//	switch(type) {
8747
//		case TokenNameabstract :
8748
//		case TokenNamestrictfp :
8749
//		case TokenNamefinal :
8750
//		case TokenNamenative :
8751
//		case TokenNameprivate :
8752
//		case TokenNameprotected :
8753
//		case TokenNamepublic :
8754
//		case TokenNametransient :
8755
//		case TokenNamevolatile :
8756
//		case TokenNamestatic :
8757
//		case TokenNamesynchronized :
8758
//			break;
8759
//		default:
8760
//			this.scanner.commentPtr = -1;
8761
//	}
8762
	//System.out.println(this.scanner.toStringAction(type));
8763
	switch (type) {
8642
	switch (type) {
8764
		case TokenNameARROW:
8643
		case TokenNameARROW:
8765
			consumeLambdaHeader();
8644
			consumeLambdaHeader();
Lines 10464-10487 Link Here
10464
	this.referenceContext = null;
10343
	this.referenceContext = null;
10465
	this.endStatementPosition = 0;
10344
	this.endStatementPosition = 0;
10466
	this.valueLambdaNestDepth = -1;
10345
	this.valueLambdaNestDepth = -1;
10467
10346
	
10468
	//remove objects from stack too, while the same parser/compiler couple is
10469
	//re-used between two compilations ....
10470
10471
	int astLength = this.astStack.length;
10347
	int astLength = this.astStack.length;
10472
	if (this.noAstNodes.length < astLength){
10348
	for (int i = 0; i < astLength; i++)
10473
		this.noAstNodes = new ASTNode[astLength];
10349
		this.astStack[i] = null;
10474
		//System.out.println("Resized AST stacks : "+ astLength);
10475
10476
	}
10477
	System.arraycopy(this.noAstNodes, 0, this.astStack, 0, astLength);
10478
10350
10479
	int expressionLength = this.expressionStack.length;
10351
	int expressionLength = this.expressionStack.length;
10480
	if (this.noExpressions.length < expressionLength){
10352
	for (int i = 0; i < expressionLength; i++)
10481
		this.noExpressions = new Expression[expressionLength];
10353
		this.expressionStack[i] = null;
10482
		//System.out.println("Resized EXPR stacks : "+ expressionLength);
10483
	}
10484
	System.arraycopy(this.noExpressions, 0, this.expressionStack, 0, expressionLength);
10485
10354
10486
	// reset this.scanner state
10355
	// reset this.scanner state
10487
	this.scanner.commentPtr = -1;
10356
	this.scanner.commentPtr = -1;
Lines 10797-10837 Link Here
10797
	         
10666
	         
10798
	    Though this code looks complex, we should exit early in most situations.     
10667
	    Though this code looks complex, we should exit early in most situations.     
10799
	 */
10668
	 */
10800
	int lastAction = this.unstackedAct;
10669
	if (this.unstackedAct == ERROR_ACTION) { // automaton is not running.
10801
	if (lastAction == ERROR_ACTION) { // automaton is not running.
10802
		return false;
10670
		return false;
10803
	}
10671
	}
10804
	int stackTop = this.stateStackTop;        // local copy of stack pointer
10805
	int stackTopState = this.stack[stackTop]; // single cell non write through "alternate stack" - the automaton's stack pointer either stays fixed during this manoeuvre or monotonically decreases.
10806
	int highWaterMark = stackTop;
10807
	
10808
	if (token != TokenNameAT) {
10672
	if (token != TokenNameAT) {
10809
		token = token == TokenNameLPAREN ? TokenNameBeginLambda : TokenNameBeginTypeArguments;
10673
		token = token == TokenNameLPAREN ? TokenNameBeginLambda : TokenNameBeginTypeArguments;
10810
	}
10674
	}
10811
	
10675
	
10812
	// A rotated version of the automaton - cf. parse()'s for(;;)
10676
	return automatonWillShift(token, this.unstackedAct);
10813
	for (;;) {  
10814
		if (lastAction > ERROR_ACTION) {  
10815
			lastAction -= ERROR_ACTION;    /* shift-reduce on loop entry from above, reduce on loop back */
10816
			do { /* reduce */
10817
				stackTop -= rhs[lastAction] - 1;
10818
				if (stackTop < highWaterMark) {
10819
					stackTopState = this.stack[highWaterMark = stackTop];
10820
				} // else stackTopState is upto date already.
10821
				lastAction = ntAction(stackTopState, lhs[lastAction]);
10822
			} while (lastAction <= NUM_RULES);
10823
		}
10824
		highWaterMark = ++stackTop;
10825
		stackTopState = lastAction; // "push"
10826
		lastAction = tAction(lastAction, token); // can be looked up from a precomputed cache.
10827
		if (lastAction <= NUM_RULES) {
10828
			stackTop --; 
10829
		    lastAction += ERROR_ACTION;
10830
			continue;
10831
		}
10832
		// Error => false, Shift, Shift/Reduce => true, Accept => impossible. 
10833
		return lastAction != ERROR_ACTION;
10834
	}
10835
}
10677
}
10836
/*main loop of the automat
10678
/*main loop of the automat
10837
When a rule is reduced, the method consumeRule(int) is called with the number
10679
When a rule is reduced, the method consumeRule(int) is called with the number
Lines 10852-10857 Link Here
10852
10694
10853
	this.hasReportedError = false;
10695
	this.hasReportedError = false;
10854
	int act = START_STATE;
10696
	int act = START_STATE;
10697
	this.unstackedAct = ERROR_ACTION;
10855
	this.stateStackTop = -1;
10698
	this.stateStackTop = -1;
10856
	this.currentToken = getFirstToken();
10699
	this.currentToken = getFirstToken();
10857
	
10700
	
Lines 10866-10873 Link Here
10866
				stackLength);
10709
				stackLength);
10867
		}
10710
		}
10868
		this.stack[this.stateStackTop] = act;
10711
		this.stack[this.stateStackTop] = act;
10869
10712
		this.unstackedAct = act = tAction(act, this.currentToken);
10870
		act = tAction(act, this.currentToken);
10871
		if (act == ERROR_ACTION || this.restartRecovery) {
10713
		if (act == ERROR_ACTION || this.restartRecovery) {
10872
			if (DEBUG_AUTOMATON) {
10714
			if (DEBUG_AUTOMATON) {
10873
				if (this.restartRecovery) {
10715
				if (this.restartRecovery) {
Lines 10879-10901 Link Here
10879
10721
10880
			int errorPos = this.scanner.currentPosition - 1;
10722
			int errorPos = this.scanner.currentPosition - 1;
10881
			if (!this.hasReportedError) {
10723
			if (!this.hasReportedError) {
10882
				this.hasError = true;  // looks incorrect for recovery case ?
10724
				this.hasError = true;
10883
			}
10725
			}
10884
			int previousToken = this.currentToken;
10726
			this.kurrentToken = this.currentToken;
10885
			switch (resumeOnSyntaxError()) {
10727
			switch (resumeOnErrorOrTriggeredRecovery(act == ERROR_ACTION)) {
10886
				case HALT:
10728
				case HALT:
10887
					act = ERROR_ACTION;
10729
					act = ERROR_ACTION;
10888
					break ProcessTerminals;
10730
					break ProcessTerminals;
10889
				case RESTART:
10731
				case RESTART:
10890
					if (act == ERROR_ACTION && previousToken != 0) this.lastErrorEndPosition = errorPos;
10732
					if (act == ERROR_ACTION && this.kurrentToken != 0) this.lastErrorEndPosition = errorPos;
10891
					act = START_STATE;
10733
					act = START_STATE;
10892
					this.stateStackTop = -1;
10734
					this.stateStackTop = -1;
10893
					this.currentToken = getFirstToken();
10735
					this.currentToken = getFirstToken();
10894
					continue ProcessTerminals;
10736
					continue ProcessTerminals;
10895
				case RESUME:
10737
				case RESUME:
10896
					break; // We presume the world is virgin so we can continue exactly from where we left off.
10738
					if (act == ERROR_ACTION) {
10897
				default:
10739
						act = this.unstackedAct;
10898
					throw new IllegalStateException();
10740
						continue ProcessTerminals;
10741
					} else {
10742
						this.currentToken = this.kurrentToken; // Gets trashed all over the place.
10743
					}
10744
					// FALL THROUGH.
10899
			}
10745
			}
10900
		}
10746
		}
10901
		if (act <= NUM_RULES) {
10747
		if (act <= NUM_RULES) {
Lines 10914-10920 Link Here
10914
				this.recordStringLiterals = oldValue;
10760
				this.recordStringLiterals = oldValue;
10915
			}
10761
			}
10916
			try {
10762
			try {
10917
				this.unstackedAct = act;
10918
				this.currentToken = this.scanner.getNextToken();
10763
				this.currentToken = this.scanner.getNextToken();
10919
			} catch(InvalidInputException e){
10764
			} catch(InvalidInputException e){
10920
				if (!this.hasReportedError){
10765
				if (!this.hasReportedError){
Lines 10924-10932 Link Here
10924
				this.lastCheckPoint = this.scanner.currentPosition;
10769
				this.lastCheckPoint = this.scanner.currentPosition;
10925
				this.currentToken = 0;
10770
				this.currentToken = 0;
10926
				this.restartRecovery = true;
10771
				this.restartRecovery = true;
10927
			} finally {
10772
			} 
10928
				this.unstackedAct = ERROR_ACTION;
10929
			}
10930
			if(this.statementRecoveryActivated) {
10773
			if(this.statementRecoveryActivated) {
10931
				jumpOverType();
10774
				jumpOverType();
10932
			}
10775
			}
Lines 10946-10952 Link Here
10946
					this.recordStringLiterals = oldValue;
10789
					this.recordStringLiterals = oldValue;
10947
				}
10790
				}
10948
				try{
10791
				try{
10949
					this.unstackedAct = act;
10950
					this.currentToken = this.scanner.getNextToken();
10792
					this.currentToken = this.scanner.getNextToken();
10951
				} catch(InvalidInputException e){
10793
				} catch(InvalidInputException e){
10952
					if (!this.hasReportedError){
10794
					if (!this.hasReportedError){
Lines 10956-10963 Link Here
10956
					this.lastCheckPoint = this.scanner.currentPosition;
10798
					this.lastCheckPoint = this.scanner.currentPosition;
10957
					this.currentToken = 0;
10799
					this.currentToken = 0;
10958
					this.restartRecovery = true;
10800
					this.restartRecovery = true;
10959
				} finally {
10960
					this.unstackedAct = ERROR_ACTION;
10961
				}
10801
				}
10962
				if(this.statementRecoveryActivated) {
10802
				if(this.statementRecoveryActivated) {
10963
					jumpOverType();
10803
					jumpOverType();
Lines 10994-10999 Link Here
10994
		}
10834
		}
10995
	}
10835
	}
10996
} finally {
10836
} finally {
10837
	this.unstackedAct = ERROR_ACTION;
10997
	this.scanner.setActiveParser(null);
10838
	this.scanner.setActiveParser(null);
10998
}
10839
}
10999
10840
Lines 11993-11998 Link Here
11993
	}
11834
	}
11994
}
11835
}
11995
11836
11837
public boolean requireExtendedRecovery() {
11838
	return false; // for assist parsers.
11839
}
11840
11841
public void startRecovery() {
11842
	this.restartRecovery = true;
11843
}
11844
11996
public void recoveryExitFromVariable() {
11845
public void recoveryExitFromVariable() {
11997
	if(this.currentElement != null && this.currentElement.parent != null) {
11846
	if(this.currentElement != null && this.currentElement.parent != null) {
11998
		if(this.currentElement instanceof RecoveredLocalVariable) {
11847
		if(this.currentElement instanceof RecoveredLocalVariable) {
Lines 12152-12190 Link Here
12152
}
12001
}
12153
/*
12002
/*
12154
 * Reset context so as to resume to regular parse loop
12003
 * Reset context so as to resume to regular parse loop
12155
 */
12156
protected void resetStacks() {
12157
12158
	this.astPtr = -1;
12159
	this.astLengthPtr = -1;
12160
	this.expressionPtr = -1;
12161
	this.expressionLengthPtr = -1;
12162
	this.typeAnnotationLengthPtr = -1;
12163
	this.typeAnnotationPtr = -1;
12164
	this.identifierPtr = -1;
12165
	this.identifierLengthPtr	= -1;
12166
	this.intPtr = -1;
12167
	this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse
12168
	this.variablesCounter[this.nestedType] = 0;
12169
	this.dimensions = 0 ;
12170
	this.realBlockStack[this.realBlockPtr = 0] = 0;
12171
	this.recoveredStaticInitializerStart = 0;
12172
	this.listLength = 0;
12173
	this.listTypeParameterLength = 0;
12174
12175
	this.genericsIdentifiersLengthPtr = -1;
12176
	this.genericsLengthPtr = -1;
12177
	this.genericsPtr = -1;
12178
	this.valueLambdaNestDepth = -1;
12179
}
12180
/*
12181
 * Reset context so as to resume to regular parse loop
12182
 * If unable to reset for resuming, answers false.
12004
 * If unable to reset for resuming, answers false.
12183
 *
12005
 *
12184
 * Move checkpoint location, reset internal stacks and
12006
 * Move checkpoint location, reset internal stacks and
12185
 * decide which grammar goal is activated.
12007
 * decide which grammar goal is activated.
12186
 */
12008
 */
12187
protected boolean resumeAfterRecovery() {
12009
protected int resumeAfterRecovery(boolean errorRecovery) {
12188
	if(!this.methodRecoveryActivated && !this.statementRecoveryActivated) {
12010
	if(!this.methodRecoveryActivated && !this.statementRecoveryActivated) {
12189
12011
12190
		// reset internal stacks
12012
		// reset internal stacks
Lines 12193-12210 Link Here
12193
12015
12194
		/* attempt to move checkpoint location */
12016
		/* attempt to move checkpoint location */
12195
		if (!moveRecoveryCheckpoint()) {
12017
		if (!moveRecoveryCheckpoint()) {
12196
			return false;
12018
			return HALT;
12197
		}
12019
		}
12198
12020
12199
		// only look for headers
12021
		// only look for headers
12200
		if (this.referenceContext instanceof CompilationUnitDeclaration){
12022
		if (this.referenceContext instanceof CompilationUnitDeclaration){
12201
			goForHeaders();
12023
			goForHeaders();
12202
			this.diet = true; // passed this point, will not consider method bodies
12024
			this.diet = true; // passed this point, will not consider method bodies
12203
			return true;
12025
			return RESTART;
12204
		}
12026
		}
12205
12027
12206
		// does not know how to restart
12028
		// does not know how to restart
12207
		return false;
12029
		return HALT;
12208
	} else if(!this.statementRecoveryActivated) {
12030
	} else if(!this.statementRecoveryActivated) {
12209
12031
12210
		// reset internal stacks
12032
		// reset internal stacks
Lines 12213-12229 Link Here
12213
12035
12214
		/* attempt to move checkpoint location */
12036
		/* attempt to move checkpoint location */
12215
		if (!moveRecoveryCheckpoint()) {
12037
		if (!moveRecoveryCheckpoint()) {
12216
			return false;
12038
			return HALT;
12217
		}
12039
		}
12218
12040
12219
		// only look for headers
12041
		// only look for headers
12220
		goForHeaders();
12042
		goForHeaders();
12221
		return true;
12043
		return RESTART;
12222
	} else {
12044
	} else {
12223
		return false;
12045
		return HALT;
12224
	}
12046
	}
12225
}
12047
}
12226
protected int resumeOnSyntaxError() {
12048
protected int resumeOnErrorOrTriggeredRecovery(boolean errorRecovery) {
12227
	if (this.haltOnSyntaxError)
12049
	if (this.haltOnSyntaxError)
12228
		return HALT;
12050
		return HALT;
12229
	/* request recovery initialization */
12051
	/* request recovery initialization */
Lines 12260-12266 Link Here
12260
	}
12082
	}
12261
12083
12262
	/* attempt to reset state in order to resume to parse loop */
12084
	/* attempt to reset state in order to resume to parse loop */
12263
	return resumeAfterRecovery() ? RESTART : HALT;
12085
	return resumeAfterRecovery(errorRecovery);
12264
}
12086
}
12265
public void setMethodsFullRecovery(boolean enabled) {
12087
public void setMethodsFullRecovery(boolean enabled) {
12266
	this.options.performMethodsFullRecovery = enabled;
12088
	this.options.performMethodsFullRecovery = enabled;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredAnnotation.java (-1 / +1 lines)
Lines 194-200 Link Here
194
194
195
	public int sourceEnd() {
195
	public int sourceEnd() {
196
		if (this.annotation == null) {
196
		if (this.annotation == null) {
197
			Parser parser = parser();
197
			CommitRollbackParser parser = parser();
198
			if (this.identifierPtr < parser.identifierPositionStack.length) {
198
			if (this.identifierPtr < parser.identifierPositionStack.length) {
199
				return (int) parser.identifierPositionStack[this.identifierPtr];
199
				return (int) parser.identifierPositionStack[this.identifierPtr];
200
			} else {
200
			} else {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java (-13 / +21 lines)
Lines 1-13 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2013 IBM Corporation and others.
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
7
 *
8
 * This is an implementation of an early-draft specification developed under the Java
9
 * Community Process (JCP) and is made available for testing and evaluation purposes
10
 * only. The code is not compatible with any specification of the JCP.
11
 * Contributors:
8
 * Contributors:
12
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
13
 *******************************************************************************/
10
 *******************************************************************************/
Lines 18-28 Link Here
18
15
19
import org.eclipse.jdt.core.compiler.*;
16
import org.eclipse.jdt.core.compiler.*;
20
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
17
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
18
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
21
import org.eclipse.jdt.internal.compiler.ast.Argument;
19
import org.eclipse.jdt.internal.compiler.ast.Argument;
22
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
20
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
23
import org.eclipse.jdt.internal.compiler.ast.Block;
21
import org.eclipse.jdt.internal.compiler.ast.Block;
24
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
22
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
25
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
26
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
23
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
27
import org.eclipse.jdt.internal.compiler.ast.Statement;
24
import org.eclipse.jdt.internal.compiler.ast.Statement;
28
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
25
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
Lines 59-72 Link Here
59
		}
56
		}
60
	}
57
	}
61
	return super.add(methodDeclaration, bracketBalanceValue);
58
	return super.add(methodDeclaration, bracketBalanceValue);
62
}
63
/*
64
 * Record a Lambda declaration
65
 */
66
public RecoveredElement add(LambdaExpression expression, int bracketBalanceValue) {
67
	RecoveredLambdaExpression element = new RecoveredLambdaExpression(expression, this, bracketBalanceValue);
68
	attach(element);
69
	return element;
70
}
59
}
71
/*
60
/*
72
 * Record a nested block declaration
61
 * Record a nested block declaration
Lines 340-345 Link Here
340
		Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes);
329
		Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes);
341
		if (updatedStatement != null){
330
		if (updatedStatement != null){
342
			updatedStatements[updatedCount++] = updatedStatement;
331
			updatedStatements[updatedCount++] = updatedStatement;
332
			
333
			// Statements inside lambda body have been collected into a block. Replace the block if we see a statement that completely subsumes it.
334
			if (updatedCount > 1) {
335
				Statement penultimateStatement = updatedStatements[updatedCount - 1];
336
				int penultimateStatementStart = penultimateStatement.sourceStart;
337
				int penultimateStatementEnd = penultimateStatement instanceof AbstractVariableDeclaration ? 
338
						((AbstractVariableDeclaration) penultimateStatement).declarationSourceEnd : penultimateStatement.sourceEnd;
339
				int ultimateStatementStart = updatedStatement.sourceStart;
340
				int ultimateStatementEnd =  updatedStatement instanceof AbstractVariableDeclaration ? 
341
						((AbstractVariableDeclaration) updatedStatement).declarationSourceEnd : updatedStatement.sourceEnd;
342
				if (penultimateStatementStart <= ultimateStatementStart && penultimateStatementEnd >= ultimateStatementEnd) {
343
					updatedCount--;
344
					continue;
345
				}
346
				if (ultimateStatementStart <= penultimateStatementStart && ultimateStatementEnd >= penultimateStatementEnd) {
347
					updatedStatements[updatedCount - 1] = updatedStatement;
348
					updatedCount--;
349
				}
350
			}
343
351
344
			if (updatedStatement instanceof LocalDeclaration) {
352
			if (updatedStatement instanceof LocalDeclaration) {
345
				LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement;
353
				LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java (-15 / +3 lines)
Lines 1-13 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2013 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * This is an implementation of an early-draft specification developed under the Java
9
 * Community Process (JCP) and is made available for testing and evaluation purposes
10
 * only. The code is not compatible with any specification of the JCP.
11
 * 
7
 * 
12
 * Contributors:
8
 * Contributors:
13
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
Lines 18-29 Link Here
18
/**
14
/**
19
 * Internal structure for parsing recovery
15
 * Internal structure for parsing recovery
20
 */
16
 */
21
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
22
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
17
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
18
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
23
import org.eclipse.jdt.internal.compiler.ast.Block;
19
import org.eclipse.jdt.internal.compiler.ast.Block;
24
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
20
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
25
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
21
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
26
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
27
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
22
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
28
import org.eclipse.jdt.internal.compiler.ast.Statement;
23
import org.eclipse.jdt.internal.compiler.ast.Statement;
29
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
24
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
Lines 104-116 Link Here
104
	if (this.parent == null) return this; // ignore
99
	if (this.parent == null) return this; // ignore
105
	this.updateSourceEndIfNecessary(previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));
100
	this.updateSourceEndIfNecessary(previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));
106
	return this.parent.add(localDeclaration, bracketBalanceValue);
101
	return this.parent.add(localDeclaration, bracketBalanceValue);
107
}
108
109
/*
110
 * Record a LambdaExpression: Only can occur inside a block. Note: Field initializers are wrapped into a block.
111
 */
112
public RecoveredElement add(LambdaExpression expression, int bracketBalanceValue) {
113
	return this;
114
}
102
}
115
/*
103
/*
116
 * Record a statement
104
 * Record a statement
Lines 248-254 Link Here
248
 */
236
 */
249
public int previousAvailableLineEnd(int position){
237
public int previousAvailableLineEnd(int position){
250
238
251
	Parser parser = parser();
239
	CommitRollbackParser parser = parser();
252
	if (parser == null) return position;
240
	if (parser == null) return position;
253
241
254
	Scanner scanner = parser.scanner;
242
	Scanner scanner = parser.scanner;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java (-24 lines)
Lines 24-30 Link Here
24
import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
24
import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
25
import org.eclipse.jdt.internal.compiler.ast.Expression;
25
import org.eclipse.jdt.internal.compiler.ast.Expression;
26
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
26
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
27
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
28
import org.eclipse.jdt.internal.compiler.ast.Statement;
27
import org.eclipse.jdt.internal.compiler.ast.Statement;
29
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
28
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
30
29
Lines 35-42 Link Here
35
34
36
	public RecoveredAnnotation[] annotations;
35
	public RecoveredAnnotation[] annotations;
37
	public int annotationCount;
36
	public int annotationCount;
38
39
	public RecoveredLambdaExpression initializerLambda;
40
	
37
	
41
	public int modifiers;
38
	public int modifiers;
42
	public int modifiersStart;
39
	public int modifiersStart;
Lines 87-110 Link Here
87
		this.fieldDeclaration.declarationSourceEnd = statement.sourceEnd;
84
		this.fieldDeclaration.declarationSourceEnd = statement.sourceEnd;
88
		this.fieldDeclaration.declarationEnd = statement.sourceEnd;
85
		this.fieldDeclaration.declarationEnd = statement.sourceEnd;
89
		return this;
86
		return this;
90
	}
91
}
92
/*
93
 * Record a lambda expression if field is expecting an initialization expression,
94
 * used for completion inside field initializers.
95
 */
96
public RecoveredElement add(LambdaExpression expression, int bracketBalanceValue) {
97
98
	if (this.alreadyCompletedFieldInitialization) {
99
		return super.add(expression, bracketBalanceValue);
100
	} else {
101
		if (expression.sourceEnd > 0)
102
				this.alreadyCompletedFieldInitialization = true;
103
		// else we may still be inside the initialization, having parsed only a part of it yet
104
		this.fieldDeclaration.initialization = expression;
105
		this.fieldDeclaration.declarationSourceEnd = expression.sourceEnd;
106
		this.fieldDeclaration.declarationEnd = expression.sourceEnd;
107
		return this.initializerLambda = new RecoveredLambdaExpression(expression, this, bracketBalanceValue);
108
	}
87
	}
109
}
88
}
110
/*
89
/*
Lines 269-277 Link Here
269
			}
248
			}
270
		}
249
		}
271
	}
250
	}
272
	if (this.initializerLambda != null)
273
		this.initializerLambda.updateParseTree();
274
	
275
	return this.fieldDeclaration;
251
	return this.fieldDeclaration;
276
}
252
}
277
/*
253
/*
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredLambdaExpression.java (-126 lines)
Lines 1-126 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2013 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * This is an implementation of an early-draft specification developed under the Java
9
 * Community Process (JCP) and is made available for testing and evaluation purposes
10
 * only. The code is not compatible with any specification of the JCP.
11
 *
12
 * Contributors:
13
 *     IBM Corporation - initial API and implementation
14
 *******************************************************************************/
15
16
package org.eclipse.jdt.internal.compiler.parser;
17
18
import java.util.HashSet;
19
import java.util.Set;
20
21
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
22
import org.eclipse.jdt.internal.compiler.ast.Block;
23
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
24
import org.eclipse.jdt.internal.compiler.ast.Statement;
25
26
public class RecoveredLambdaExpression extends RecoveredBlock {
27
28
	private LambdaExpression expression;
29
	private boolean haveBlockBody = false;
30
	private boolean haveExpressionBody = false;
31
	private RecoveredStatement bodyExpression;
32
	
33
	public RecoveredLambdaExpression(LambdaExpression expression, RecoveredElement parent, int bracketBalance){
34
		super(new Block(0), parent, bracketBalance); // don't have a block yet. May never have, in that event will course correct.
35
		this.expression = expression;
36
		this.expression.setBody(this.blockDeclaration);
37
	}
38
	
39
	/*
40
	 * Record a nested block declaration
41
	 */
42
	public RecoveredElement add(Block block, int bracketBalanceValue) {
43
		if (!this.haveBlockBody && !this.haveExpressionBody) {
44
			this.haveBlockBody = true;
45
			this.haveExpressionBody = false;
46
			this.blockDeclaration = block;
47
			return this; 
48
		}
49
		return super.add(block, bracketBalanceValue);
50
	}
51
52
	/*
53
	 * Record a nested block declaration
54
	 */
55
	public RecoveredElement add(LambdaExpression lambda, int bracketBalanceValue) {
56
		if (!this.haveBlockBody && !this.haveExpressionBody) {
57
			this.haveBlockBody = false;
58
			this.haveExpressionBody = true;
59
			this.bodyExpression = new RecoveredLambdaExpression(lambda, this, bracketBalanceValue);
60
			this.expression.setBody(lambda);
61
			return this.bodyExpression;
62
		}
63
		return super.add(lambda, bracketBalanceValue);
64
	}
65
	
66
	/*
67
	 * Record a statement declaration
68
	 */
69
	public RecoveredElement add(Statement stmt, int bracketBalanceValue) {
70
		return this.add(stmt, bracketBalanceValue, false);
71
	}
72
73
	/*
74
	 * Record a statement declaration
75
	 */
76
	public RecoveredElement add(Statement stmt, int bracketBalanceValue, boolean delegatedByParent) {
77
		if (!this.haveBlockBody && !this.haveExpressionBody) {
78
			this.haveBlockBody = false;
79
			this.haveExpressionBody = true;
80
			this.bodyExpression = new RecoveredStatement(stmt, this, bracketBalanceValue);
81
			this.expression.setBody(stmt);
82
			return this.bodyExpression;
83
		}
84
		return super.add(stmt, bracketBalanceValue, delegatedByParent);
85
	}
86
	
87
	/*
88
	 * Answer the associated parsed structure
89
	 */
90
	public ASTNode parseTree(){
91
		return updatedLambdaExpression(0, new HashSet());
92
	}
93
94
	public LambdaExpression updatedLambdaExpression(int depth, Set knownTypes) {
95
		if (this.haveBlockBody)
96
			this.expression.setBody(super.updatedStatement(depth, knownTypes));
97
		else if (this.bodyExpression != null)
98
			this.expression.setBody(this.bodyExpression.updatedStatement(depth, knownTypes));
99
		return this.expression;
100
	}
101
	/*
102
	 * Rebuild a statement from the nested structure which is in scope
103
	 */
104
	public Statement updatedStatement(int depth, Set knownTypes){
105
		return updatedLambdaExpression(depth, knownTypes);
106
	}
107
	/*
108
	 * Final update the corresponding parse node
109
	 */
110
	public void updateParseTree(){
111
		updatedLambdaExpression(0, new HashSet());
112
	}
113
	/*
114
	 * Rebuild a flattened block from the nested structure which is in scope
115
	 */
116
	public Statement updateStatement(int depth, Set knownTypes){
117
		return updatedLambdaExpression(depth, knownTypes);
118
	}
119
	
120
	public String toString(int tab) {
121
		StringBuffer result = new StringBuffer(tabString(tab));
122
		result.append("Recovered Lambda Expression:\n"); //$NON-NLS-1$
123
		this.expression.print(tab + 1, result);
124
		return result.toString();
125
	}
126
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.java (-19 lines)
Lines 21-27 Link Here
21
import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
21
import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
22
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
22
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
23
import org.eclipse.jdt.internal.compiler.ast.Expression;
23
import org.eclipse.jdt.internal.compiler.ast.Expression;
24
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
25
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
24
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
26
import org.eclipse.jdt.internal.compiler.ast.Statement;
25
import org.eclipse.jdt.internal.compiler.ast.Statement;
27
26
Lines 29-35 Link Here
29
28
30
	public RecoveredAnnotation[] annotations;
29
	public RecoveredAnnotation[] annotations;
31
	public int annotationCount;
30
	public int annotationCount;
32
	private RecoveredLambdaExpression initializer;
33
	public int modifiers;
31
	public int modifiers;
34
	public int modifiersStart;
32
	public int modifiersStart;
35
33
Lines 53-73 Link Here
53
		this.localDeclaration.declarationSourceEnd = stmt.sourceEnd;
51
		this.localDeclaration.declarationSourceEnd = stmt.sourceEnd;
54
		this.localDeclaration.declarationEnd = stmt.sourceEnd;
52
		this.localDeclaration.declarationEnd = stmt.sourceEnd;
55
		return this;
53
		return this;
56
	}
57
}
58
/*
59
 * Record an expression statement if local variable is expecting an initialization expression.
60
 */
61
public RecoveredElement add(LambdaExpression expression, int bracketBalanceValue) {
62
63
	if (this.alreadyCompletedLocalInitialization) {
64
		return this;
65
	} else {
66
		this.alreadyCompletedLocalInitialization = true;
67
		this.localDeclaration.initialization = expression;
68
		this.localDeclaration.declarationSourceEnd = expression.sourceEnd;
69
		this.localDeclaration.declarationEnd = expression.sourceEnd;
70
		return this.initializer = new RecoveredLambdaExpression(expression, this, bracketBalanceValue);
71
	}
54
	}
72
}
55
}
73
public void attach(RecoveredAnnotation[] annots, int annotCount, int mods, int modsSourceStart) {
56
public void attach(RecoveredAnnotation[] annots, int annotCount, int mods, int modsSourceStart) {
Lines 133-140 Link Here
133
			this.localDeclaration.declarationSourceStart = start;
116
			this.localDeclaration.declarationSourceStart = start;
134
		}
117
		}
135
	}
118
	}
136
	if (this.initializer != null)
137
		this.initializer.updateParseTree();
138
	return this.localDeclaration;
119
	return this.localDeclaration;
139
}
120
}
140
/*
121
/*
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java (-1 / +1 lines)
Lines 626-632 Link Here
626
626
627
	int lastParameterEnd = parameters[parameters.length - 1].sourceEnd;
627
	int lastParameterEnd = parameters[parameters.length - 1].sourceEnd;
628
628
629
	Parser parser = parser();
629
	CommitRollbackParser parser = parser();
630
	Scanner scanner = parser.scanner;
630
	Scanner scanner = parser.scanner;
631
	if(Util.getLineNumber(this.methodDeclaration.declarationSourceStart, scanner.lineEnds, 0, scanner.linePtr)
631
	if(Util.getLineNumber(this.methodDeclaration.declarationSourceStart, scanner.lineEnds, 0, scanner.linePtr)
632
			!= Util.getLineNumber(lastParameterEnd, scanner.lineEnds, 0, scanner.linePtr)) return;
632
			!= Util.getLineNumber(lastParameterEnd, scanner.lineEnds, 0, scanner.linePtr)) return;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java (-7 lines)
Lines 17-44 Link Here
17
import java.util.Set;
17
import java.util.Set;
18
18
19
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
19
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
20
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
21
import org.eclipse.jdt.internal.compiler.ast.Statement;
20
import org.eclipse.jdt.internal.compiler.ast.Statement;
22
21
23
public class RecoveredStatement extends RecoveredElement {
22
public class RecoveredStatement extends RecoveredElement {
24
23
25
	public Statement statement;
24
	public Statement statement;
26
	public RecoveredLambdaExpression subExpression;
27
	
25
	
28
public RecoveredStatement(Statement statement, RecoveredElement parent, int bracketBalance){
26
public RecoveredStatement(Statement statement, RecoveredElement parent, int bracketBalance){
29
	super(parent, bracketBalance);
27
	super(parent, bracketBalance);
30
	this.statement = statement;
28
	this.statement = statement;
31
}
29
}
32
30
33
public RecoveredElement add(LambdaExpression expression, int bracketBalanceValue) {
34
	return this.subExpression = new RecoveredLambdaExpression(expression, this, bracketBalanceValue);
35
}
36
/*
31
/*
37
 * Answer the associated parsed structure
32
 * Answer the associated parsed structure
38
 */
33
 */
39
public ASTNode parseTree() {
34
public ASTNode parseTree() {
40
	if (this.subExpression != null)
41
		this.subExpression.updateParseTree();
42
	return this.statement;
35
	return this.statement;
43
}
36
}
44
/*
37
/*
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java (-1 / +1 lines)
Lines 753-759 Link Here
753
	// might be an initializer
753
	// might be an initializer
754
	if (this.bracketBalance == 1){
754
	if (this.bracketBalance == 1){
755
		Block block = new Block(0);
755
		Block block = new Block(0);
756
		Parser parser = parser();
756
		CommitRollbackParser parser = parser();
757
		block.sourceStart = parser.scanner.startPosition;
757
		block.sourceStart = parser.scanner.startPosition;
758
		Initializer init;
758
		Initializer init;
759
		if (parser.recoveredStaticInitializerStart == 0){
759
		if (parser.recoveredStaticInitializerStart == 0){
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java (-16 / +103 lines)
Lines 19-24 Link Here
19
import org.eclipse.jdt.core.compiler.CharOperation;
19
import org.eclipse.jdt.core.compiler.CharOperation;
20
import org.eclipse.jdt.core.compiler.InvalidInputException;
20
import org.eclipse.jdt.core.compiler.InvalidInputException;
21
import org.eclipse.jdt.internal.compiler.CompilationResult;
21
import org.eclipse.jdt.internal.compiler.CompilationResult;
22
import org.eclipse.jdt.internal.compiler.ast.Statement;
22
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
23
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
23
import org.eclipse.jdt.internal.compiler.util.Util;
24
import org.eclipse.jdt.internal.compiler.util.Util;
24
25
Lines 200-206 Link Here
200
	private int nextToken = TokenNameNotAToken; // allows for one token push back, only the most recent token can be reliably ungotten.
201
	private int nextToken = TokenNameNotAToken; // allows for one token push back, only the most recent token can be reliably ungotten.
201
	private VanguardScanner vanguardScanner;
202
	private VanguardScanner vanguardScanner;
202
	private VanguardParser vanguardParser;
203
	private VanguardParser vanguardParser;
203
	private ConflictedParser activeParser = null;
204
	protected ConflictedParser activeParser = null;
204
	private boolean consumingEllipsisAnnotations = false;
205
	private boolean consumingEllipsisAnnotations = false;
205
	
206
	
206
	public static final int RoundBracket = 0;
207
	public static final int RoundBracket = 0;
Lines 4241-4252 Link Here
4241
	static int IntersectionCastRule = 0;
4242
	static int IntersectionCastRule = 0;
4242
	static int ReferenceExpressionRule = 0;
4243
	static int ReferenceExpressionRule = 0;
4243
	static int VarargTypeAnnotationsRule  = 0;
4244
	static int VarargTypeAnnotationsRule  = 0;
4245
	static int BlockStatementoptRule = 0;
4244
	
4246
	
4245
	static Goal LambdaParameterListGoal;
4247
	static Goal LambdaParameterListGoal;
4246
	static Goal IntersectionCastGoal;
4248
	static Goal IntersectionCastGoal;
4247
	static Goal VarargTypeAnnotationGoal;
4249
	static Goal VarargTypeAnnotationGoal;
4248
	static Goal ReferenceExpressionGoal;
4250
	static Goal ReferenceExpressionGoal;
4249
	
4251
	static Goal BlockStatementoptGoal;
4250
	static {
4252
	static {
4251
		
4253
		
4252
		for (int i = 1; i <= ParserBasicInformation.NUM_RULES; i++) {  // 0 == $acc
4254
		for (int i = 1; i <= ParserBasicInformation.NUM_RULES; i++) {  // 0 == $acc
Lines 4261-4272 Link Here
4261
			else 
4263
			else 
4262
			if ("TypeAnnotations".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
4264
			if ("TypeAnnotations".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
4263
				VarargTypeAnnotationsRule = i;
4265
				VarargTypeAnnotationsRule = i;
4266
			else
4267
			if ("BlockStatementopt".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
4268
				BlockStatementoptRule = i;
4269
					
4264
		}
4270
		}
4265
		
4271
		
4266
		LambdaParameterListGoal =  new Goal(TokenNameARROW, new int[] { TokenNameARROW }, LambdaParameterListRule);
4272
		LambdaParameterListGoal =  new Goal(TokenNameARROW, new int[] { TokenNameARROW }, LambdaParameterListRule);
4267
		IntersectionCastGoal =     new Goal(TokenNameLPAREN, followSetOfCast(), IntersectionCastRule);
4273
		IntersectionCastGoal =     new Goal(TokenNameLPAREN, followSetOfCast(), IntersectionCastRule);
4268
		VarargTypeAnnotationGoal = new Goal(TokenNameAT, new int[] { TokenNameELLIPSIS }, VarargTypeAnnotationsRule);
4274
		VarargTypeAnnotationGoal = new Goal(TokenNameAT, new int[] { TokenNameELLIPSIS }, VarargTypeAnnotationsRule);
4269
		ReferenceExpressionGoal =  new Goal(TokenNameLESS, new int[] { TokenNameCOLON_COLON }, ReferenceExpressionRule);
4275
		ReferenceExpressionGoal =  new Goal(TokenNameLESS, new int[] { TokenNameCOLON_COLON }, ReferenceExpressionRule);
4276
		BlockStatementoptGoal =    new Goal(TokenNameLBRACE, new int [0], BlockStatementoptRule);
4270
	}
4277
	}
4271
4278
4272
4279
Lines 4279-4288 Link Here
4279
	boolean hasBeenReached(int act, int token) {
4286
	boolean hasBeenReached(int act, int token) {
4280
		/*
4287
		/*
4281
		System.out.println("[Goal = " + Parser.name[Parser.non_terminal_index[Parser.lhs[this.rule]]] + "]  " + "Saw: " + Parser.name[Parser.non_terminal_index[Parser.lhs[act]]] + "::" +  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
4288
		System.out.println("[Goal = " + Parser.name[Parser.non_terminal_index[Parser.lhs[this.rule]]] + "]  " + "Saw: " + Parser.name[Parser.non_terminal_index[Parser.lhs[act]]] + "::" +  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
4282
				Parser.name[Parser.terminal_index[token]]);
4289
					Parser.name[Parser.terminal_index[token]]);
4283
		*/
4290
		*/
4284
		if (act == this.rule) {
4291
		if (act == this.rule) {
4285
			for (int i = 0, length = this.follow.length; i < length; i++)
4292
			final int length = this.follow.length;
4293
			if (length == 0)
4294
				return true;
4295
			for (int i = 0; i < length; i++)
4286
				if (this.follow[i] == token)
4296
				if (this.follow[i] == token)
4287
					return true;
4297
					return true;
4288
		}
4298
		}
Lines 4330-4350 Link Here
4330
				if (act <= NUM_RULES) {
4340
				if (act <= NUM_RULES) {
4331
					this.stateStackTop--;
4341
					this.stateStackTop--;
4332
				} else if (act > ERROR_ACTION) { /* shift-reduce */
4342
				} else if (act > ERROR_ACTION) { /* shift-reduce */
4333
					this.unstackedAct = act;
4343
					this.currentToken = this.scanner.getNextToken();
4334
					try {
4335
						this.currentToken = this.scanner.getNextToken();
4336
					} finally {
4337
						this.unstackedAct = ERROR_ACTION;
4338
					}
4339
					act -= ERROR_ACTION;
4344
					act -= ERROR_ACTION;
4340
				} else {
4345
				} else {
4341
				    if (act < ACCEPT_ACTION) { /* shift */
4346
				    if (act < ACCEPT_ACTION) { /* shift */
4342
				    	this.unstackedAct = act;
4347
				    	this.currentToken = this.scanner.getNextToken();
4343
						try {
4344
							this.currentToken = this.scanner.getNextToken();
4345
						} finally {
4346
							this.unstackedAct = ERROR_ACTION;
4347
						}
4348
						continue ProcessTerminals;
4348
						continue ProcessTerminals;
4349
					}
4349
					}
4350
				    return FAILURE; // accept - we should never reach this state, we accept at reduce with a right member of follow set below.
4350
				    return FAILURE; // accept - we should never reach this state, we accept at reduce with a right member of follow set below.
Lines 4493-4496 Link Here
4493
	}
4493
	}
4494
	return token;
4494
	return token;
4495
}
4495
}
4496
4497
// Position the scanner at the next block statement and return the start token. We recognize empty statements.
4498
public int fastForward(Statement unused) {
4499
	
4500
	int token;
4501
4502
	while (true) {
4503
		try {
4504
			token = getNextToken();
4505
		} catch (InvalidInputException e) {
4506
			return TokenNameEOF;
4507
		}
4508
		/* FOLLOW map of BlockStatement, since the non-terminal is recursive is a super set of its own FIRST set. 
4509
	   	   We use FOLLOW rather than FIRST since we want to recognize empty statements. i.e if (x > 10) {  x = 0 }
4510
		*/
4511
		switch(token) {
4512
			case TokenNameIdentifier:
4513
			case TokenNameabstract:
4514
			case TokenNameassert:
4515
			case TokenNameboolean:
4516
			case TokenNamebreak:
4517
			case TokenNamebyte:
4518
			case TokenNamecase:
4519
			case TokenNamechar:
4520
			case TokenNameclass:
4521
			case TokenNamecontinue:
4522
			case TokenNamedefault:
4523
			case TokenNamedo:
4524
			case TokenNamedouble:
4525
			case TokenNameenum:
4526
			case TokenNamefalse:
4527
			case TokenNamefinal:
4528
			case TokenNamefloat:
4529
			case TokenNamefor:
4530
			case TokenNameif:
4531
			case TokenNameint:
4532
			case TokenNameinterface:
4533
			case TokenNamelong:
4534
			case TokenNamenative:
4535
			case TokenNamenew:
4536
			case TokenNamenull:
4537
			case TokenNameprivate:
4538
			case TokenNameprotected:
4539
			case TokenNamepublic:
4540
			case TokenNamereturn:
4541
			case TokenNameshort:
4542
			case TokenNamestatic:
4543
			case TokenNamestrictfp:
4544
			case TokenNamesuper:
4545
			case TokenNameswitch:
4546
			case TokenNamesynchronized:
4547
			case TokenNamethis:
4548
			case TokenNamethrow:
4549
			case TokenNametransient:
4550
			case TokenNametrue:
4551
			case TokenNametry:
4552
			case TokenNamevoid:
4553
			case TokenNamevolatile:
4554
			case TokenNamewhile:
4555
			case TokenNameIntegerLiteral: // ??!
4556
			case TokenNameLongLiteral:
4557
			case TokenNameFloatingPointLiteral:
4558
			case TokenNameDoubleLiteral:
4559
			case TokenNameCharacterLiteral:
4560
			case TokenNameStringLiteral:
4561
			case TokenNamePLUS_PLUS:
4562
			case TokenNameMINUS_MINUS:
4563
			case TokenNameLESS:
4564
			case TokenNameLPAREN:
4565
			case TokenNameLBRACE:
4566
			case TokenNameAT:
4567
			case TokenNameBeginLambda:
4568
			case TokenNameAT308:
4569
				if(getVanguardParser().parse(Goal.BlockStatementoptGoal) == VanguardParser.SUCCESS)
4570
					return token;
4571
				break;
4572
			case TokenNameSEMICOLON:
4573
			case TokenNameEOF:
4574
				return token;
4575
			case TokenNameRBRACE: // simulate empty statement.
4576
				ungetToken(token);
4577
				return TokenNameSEMICOLON;
4578
			default:
4579
				break;
4580
		}
4581
	}
4582
}
4496
}
4583
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java (+8 lines)
Lines 2588-2591 Link Here
2588
		*/ 
2588
		*/ 
2589
		return (token == TokenNameLPAREN || token == TokenNameAT || (token == TokenNameLESS && !this.lexStream.awaitingColonColon()));
2589
		return (token == TokenNameLPAREN || token == TokenNameAT || (token == TokenNameLESS && !this.lexStream.awaitingColonColon()));
2590
	}
2590
	}
2591
2592
	public void startRecovery() {
2593
		return;       // not in that business.
2594
	}
2595
2596
	public boolean requireExtendedRecovery() {
2597
		return false; // not in that business.
2598
	}
2591
}
2599
}
(-)a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java (-1 / +1 lines)
Lines 790-796 Link Here
790
 * A syntax error was detected. If a method is being parsed, records the number of errors and
790
 * A syntax error was detected. If a method is being parsed, records the number of errors and
791
 * attempts to restart from the last statement by going for an expression.
791
 * attempts to restart from the last statement by going for an expression.
792
 */
792
 */
793
protected int resumeOnSyntaxError() {
793
protected int resumeOnErrorOrTriggeredRecovery(boolean errorRecovery) {
794
	if (this.diet || this.hasRecoveredOnExpression) { // no reentering inside expression recovery
794
	if (this.diet || this.hasRecoveredOnExpression) { // no reentering inside expression recovery
795
		return HALT;
795
		return HALT;
796
	}
796
	}
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java (-1 / +1 lines)
Lines 1511-1517 Link Here
1511
 * Syntax error was detected. Will attempt to perform some recovery action in order
1511
 * Syntax error was detected. Will attempt to perform some recovery action in order
1512
 * to resume to the regular parse loop.
1512
 * to resume to the regular parse loop.
1513
 */
1513
 */
1514
protected int resumeOnSyntaxError() {
1514
protected int resumeOnErrorOrTriggeredRecovery(boolean errorRecovery) {
1515
	return HALT;
1515
	return HALT;
1516
}
1516
}
1517
/*
1517
/*
(-)a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java (-2 / +2 lines)
Lines 41-47 Link Here
41
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
41
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
42
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
42
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
43
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
43
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
44
import org.eclipse.jdt.internal.compiler.parser.Parser;
44
import org.eclipse.jdt.internal.compiler.parser.CommitRollbackParser;
45
import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
45
import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
46
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
46
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
47
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
47
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
Lines 122-128 Link Here
122
	/*
122
	/*
123
	 * The parser this requestor is using.
123
	 * The parser this requestor is using.
124
	 */
124
	 */
125
	protected Parser parser;
125
	protected CommitRollbackParser parser;
126
126
127
	protected HashtableOfObject fieldRefCache;
127
	protected HashtableOfObject fieldRefCache;
128
	protected HashtableOfObject messageRefCache;
128
	protected HashtableOfObject messageRefCache;

Return to bug 422468