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 (-8 / +217 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;
18
import junit.framework.Test;
19
import junit.framework.Test;
19
20
20
public class CompletionParserTest18 extends AbstractCompletionTest {
21
public class CompletionParserTest18 extends AbstractCompletionTest {
21
22
22
static {
23
static {
23
//	TESTS_NAMES = new String [] { "test0001" };
24
//	TESTS_NAMES = new String [] { "test405126" };
24
}
25
}
25
26
26
public CompletionParserTest18(String testName) {
27
public CompletionParserTest18(String testName) {
Lines 74-82 Link Here
74
			"  static void goo(J i) {\n" + 
75
			"  static void goo(J i) {\n" + 
75
			"  }\n" + 
76
			"  }\n" + 
76
			"  public static void main(String[] args) {\n" + 
77
			"  public static void main(String[] args) {\n" + 
77
			"    (<no type> first, <no type> second) ->     {\n" + 
78
			"    goo((<no type> first, <no type> second) -> {\n" + 
78
			"      (<no type> xyz, <no type> pqr) -> <CompleteOnName:first.>;\n" + 
79
			"  return (<no type> xyz, <no type> pqr) -> <CompleteOnName:first.>;\n" + 
79
			"    };\n" + 
80
			"});\n" + 
80
			"  }\n" + 
81
			"  }\n" + 
81
			"}\n";
82
			"}\n";
82
83
Lines 177-183 Link Here
177
	int cursorLocation = string.lastIndexOf(completeBehind) + completeBehind.length() - 1;
178
	int cursorLocation = string.lastIndexOf(completeBehind) + completeBehind.length() - 1;
178
179
179
	String expectedCompletionNodeToString = "<CompleteOnName:x>";
180
	String expectedCompletionNodeToString = "<CompleteOnName:x>";
180
	String expectedParentNodeToString = "<NONE>";
181
	String expectedParentNodeToString = "static Foo f = (<no type> x5, <no type> x6) -> {\n" +
182
										"  <CompleteOnName:x>;\n" +
183
										"};";
181
	String completionIdentifier = "x";
184
	String completionIdentifier = "x";
182
	String expectedReplacedSource = "x";
185
	String expectedReplacedSource = "x";
183
	String expectedUnitDisplayString =
186
	String expectedUnitDisplayString =
Lines 233-242 Link Here
233
			"  }\n" + 
236
			"  }\n" + 
234
			"  void go() {\n" + 
237
			"  void go() {\n" + 
235
			"    I i = (<no type> argument) ->     {\n" + 
238
			"    I i = (<no type> argument) ->     {\n" + 
236
			"      {\n" + 
239
			"      if (true)\n" + 
237
			"        if (true)\n" + 
240
			"          {\n" + 
238
			"            return <CompleteOnName:arg>;\n" + 
241
			"            return <CompleteOnName:arg>;\n" + 
239
			"      }\n" + 
242
			"          }\n" + 
240
			"    };\n" + 
243
			"    };\n" + 
241
			"  }\n" + 
244
			"  }\n" + 
242
			"}\n";
245
			"}\n";
Lines 345-348 Link Here
345
		expectedReplacedSource,
348
		expectedReplacedSource,
346
		"diet ast");
349
		"diet ast");
347
}
350
}
351
public void test0010() {
352
	String string =
353
			"interface I {\n" +
354
			"	void foo(String x);\n" +
355
			"}\n" +
356
			"public class X {\n" +
357
			"	String xField;\n" +
358
			"	static void goo(String s) {\n" +
359
			"	}\n" +
360
			"	static void goo(I i) {\n" +
361
			"	}\n" +
362
			"	public static void main(String[] args) {\n" +
363
			"		goo((xyz) -> {\n" +
364
			"			System.out.println(xyz.);\n" +
365
			"		});\n" +
366
			"	}\n" +
367
			"}\n";
368
369
	String completeBehind = "xyz.";
370
	int cursorLocation = string.lastIndexOf(completeBehind) + completeBehind.length() - 1;
371
372
	String expectedCompletionNodeToString = "<CompleteOnName:xyz.>";
373
	String expectedParentNodeToString = "System.out.println(<CompleteOnName:xyz.>)";
374
	String completionIdentifier = "";
375
	String expectedReplacedSource = "xyz.";
376
	String expectedUnitDisplayString =
377
			"interface I {\n" +
378
			"  void foo(String x);\n" +
379
			"}\n" +
380
			"public class X {\n" +
381
			"  String xField;\n" +
382
			"  public X() {\n" +
383
			"  }\n" +
384
			"  static void goo(String s) {\n" +
385
			"  }\n" +
386
			"  static void goo(I i) {\n" +
387
			"  }\n" +
388
			"  public static void main(String[] args) {\n" +
389
			"    goo((<no type> xyz) -> {\n" +
390
			"  System.out.println(<CompleteOnName:xyz.>);\n" +
391
			"});\n" +
392
			"  }\n" +
393
			"}\n";
394
395
	checkMethodParse(
396
		string.toCharArray(),
397
		cursorLocation,
398
		expectedCompletionNodeToString,
399
		expectedParentNodeToString,
400
		expectedUnitDisplayString,
401
		completionIdentifier,
402
		expectedReplacedSource,
403
		"diet ast");
404
}
405
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=417935, [1.8][code select] ICU#codeSelect doesn't work on reference to lambda parameter
406
public void test417935() throws JavaModelException {
407
	String string = 
408
			"import java.util.ArrayList;\n" +
409
			"import java.util.Arrays;\n" +
410
			"import java.util.Collections;\n" +
411
			"import java.util.Comparator;\n" +
412
			"public class X {\n" +
413
			"   int compareTo(X x) { return 0; }\n" +
414
			"	void foo() {\n" +
415
			"		Collections.sort(new ArrayList<X>(Arrays.asList(new X(), new X(), new X())),\n" +
416
			"				(X o1, X o2) -> o1.compareTo(o2)); //[2]\n" +
417
			"	}\n" +
418
			"}\n";
419
420
			String completeBehind = "compa";
421
			int cursorLocation = string.lastIndexOf(completeBehind) + completeBehind.length() - 1;
422
423
			String expectedCompletionNodeToString = "<CompleteOnName:o1.compa>";
424
			String expectedParentNodeToString = "<NONE>";
425
			String completionIdentifier = "compa";
426
			String expectedReplacedSource = "o1.compareTo";
427
			String expectedUnitDisplayString =
428
					"import java.util.ArrayList;\n" + 
429
					"import java.util.Arrays;\n" + 
430
					"import java.util.Collections;\n" + 
431
					"import java.util.Comparator;\n" + 
432
					"public class X {\n" + 
433
					"  public X() {\n" + 
434
					"  }\n" + 
435
					"  int compareTo(X x) {\n" + 
436
					"  }\n" + 
437
					"  void foo() {\n" + 
438
					"    (X o1, X o2) -> <CompleteOnName:o1.compa>;\n" + 
439
					"  }\n" + 
440
					"}\n";
441
442
			checkMethodParse(
443
				string.toCharArray(),
444
				cursorLocation,
445
				expectedCompletionNodeToString,
446
				expectedParentNodeToString,
447
				expectedUnitDisplayString,
448
				completionIdentifier,
449
				expectedReplacedSource,
450
				"diet ast");
451
}
452
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=405126, [1.8][code assist] Lambda parameters incorrectly recovered as fields. 
453
public void test405126() throws JavaModelException {
454
	String string = 
455
			"public interface Foo { \n" +
456
			"	int run(int s1, int s2); \n" +
457
			"}\n" +
458
			"interface X {\n" +
459
			"    static Foo f = (int x5, int x11) -> x\n" +
460
			"    static int x1 = 2;\n" +
461
			"}\n" +
462
			"class C {\n" +
463
			"	void method1(){\n" +
464
			"		int p = X.\n" +
465
			"	}\n" +
466
			"}\n";
467
468
			String completeBehind = "X.";
469
			int cursorLocation = string.lastIndexOf(completeBehind) + completeBehind.length() - 1;
470
471
			String expectedCompletionNodeToString = "<CompleteOnName:X.>";
472
			String expectedParentNodeToString = "int p = <CompleteOnName:X.>;";
473
			String completionIdentifier = "";
474
			String expectedReplacedSource = "X.";
475
			String expectedUnitDisplayString =
476
					"public interface Foo {\n" + 
477
					"  int run(int s1, int s2);\n" + 
478
					"}\n" + 
479
					"interface X {\n" + 
480
					"  static Foo f;\n" + 
481
					"  static int x1;\n" + 
482
					"  <clinit>() {\n" + 
483
					"  }\n" + 
484
					"}\n" + 
485
					"class C {\n" + 
486
					"  C() {\n" + 
487
					"  }\n" + 
488
					"  void method1() {\n" + 
489
					"    int p = <CompleteOnName:X.>;\n" + 
490
					"  }\n" + 
491
					"}\n";
492
493
			checkMethodParse(
494
				string.toCharArray(),
495
				cursorLocation,
496
				expectedCompletionNodeToString,
497
				expectedParentNodeToString,
498
				expectedUnitDisplayString,
499
				completionIdentifier,
500
				expectedReplacedSource,
501
				"diet ast");
502
}
503
// Verify that locals inside a lambda block don't get promoted to the parent block.
504
public void testLocalsPromotion() throws JavaModelException {
505
	String string = 
506
			"interface I {\n" +
507
			"	void foo(int x);\n" +
508
			"}\n" +
509
			"public class X {\n" +
510
			"	static void goo(I i) {}\n" +
511
			"	public static void main(String[] args) {\n" +
512
			"       int outerLocal;\n" +
513
			"		goo ((x) -> {\n" +
514
			"			int lambdaLocal = 10;\n" +
515
			"			System.out.println(\"Statement inside lambda\");\n" +
516
			"			lam\n" +
517
			"		});\n" +
518
			"	}\n" +
519
			"}\n";
520
521
			String completeBehind = "lam";
522
			int cursorLocation = string.lastIndexOf(completeBehind) + completeBehind.length() - 1;
523
524
			String expectedCompletionNodeToString = "<CompleteOnName:lam>";
525
			String expectedParentNodeToString = "<NONE>";
526
			String completionIdentifier = "lam";
527
			String expectedReplacedSource = "lam";
528
			String expectedUnitDisplayString =
529
					"interface I {\n" + 
530
					"  void foo(int x);\n" + 
531
					"}\n" + 
532
					"public class X {\n" + 
533
					"  public X() {\n" + 
534
					"  }\n" + 
535
					"  static void goo(I i) {\n" + 
536
					"  }\n" + 
537
					"  public static void main(String[] args) {\n" + 
538
					"    int outerLocal;\n" + 
539
					"    goo((<no type> x) -> {\n" + 
540
					"  int lambdaLocal;\n" + 
541
					"  System.out.println(\"Statement inside lambda\");\n" + 
542
					"  <CompleteOnName:lam>;\n" + 
543
					"});\n" + 
544
					"  }\n" + 
545
					"}\n";
546
547
			checkMethodParse(
548
				string.toCharArray(),
549
				cursorLocation,
550
				expectedCompletionNodeToString,
551
				expectedParentNodeToString,
552
				expectedUnitDisplayString,
553
				completionIdentifier,
554
				expectedReplacedSource,
555
				"diet ast");
556
}
348
}
557
}
(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionRecoveryTest.java (-2 lines)
Lines 1071-1078 Link Here
1071
		"        e.gc.setLineCap(<CompleteOnName:SWT.CAP_>);\n" + 
1071
		"        e.gc.setLineCap(<CompleteOnName:SWT.CAP_>);\n" + 
1072
		"      }\n" + 
1072
		"      }\n" + 
1073
		"    };\n" + 
1073
		"    };\n" + 
1074
		"    new ControlAdapter() {\n" + 
1075
		"    };\n" + 
1076
		"  }\n" + 
1074
		"  }\n" + 
1077
		"}\n",
1075
		"}\n",
1078
		// expectedCompletionIdentifier:
1076
		// expectedCompletionIdentifier:
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java (-4 / +98 lines)
Lines 23-29 Link Here
23
public class CompletionTests18 extends AbstractJavaModelCompletionTests {
23
public class CompletionTests18 extends AbstractJavaModelCompletionTests {
24
24
25
static {
25
static {
26
//		TESTS_NAMES = new String[] {"test001"};
26
	//	TESTS_NAMES = new String[] {"test015"};
27
}
27
}
28
28
29
public CompletionTests18(String name) {
29
public CompletionTests18(String name) {
Lines 115-126 Link Here
115
	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
115
	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
116
	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
116
	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
117
	assertResults(
117
	assertResults(
118
			// INTERIM RESULTS, WILL FAIL ONCE ELIDED TYPE IS CORRECTLY INFERRED.
119
			"clone[METHOD_REF]{clone(), Ljava.lang.Object;, ()Ljava.lang.Object;, clone, null, 35}\n" +
118
			"clone[METHOD_REF]{clone(), Ljava.lang.Object;, ()Ljava.lang.Object;, clone, null, 35}\n" +
120
			"equals[METHOD_REF]{equals(), Ljava.lang.Object;, (Ljava.lang.Object;)Z, equals, (obj), 35}\n" +
119
			"equals[METHOD_REF]{equals(), Ljava.lang.Object;, (Ljava.lang.Object;)Z, equals, (obj), 35}\n" +
121
			"finalize[METHOD_REF]{finalize(), Ljava.lang.Object;, ()V, finalize, null, 35}\n" +
120
			"finalize[METHOD_REF]{finalize(), Ljava.lang.Object;, ()V, finalize, null, 35}\n" +
122
			"getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<+Ljava.lang.Object;>;, getClass, null, 35}\n" +
121
			"getClass[METHOD_REF]{getClass(), Ljava.lang.Object;, ()Ljava.lang.Class<+Ljava.lang.Object;>;, getClass, null, 35}\n" +
123
			"hashCode[METHOD_REF]{hashCode(), Ljava.lang.Object;, ()I, hashCode, null, 35}\n" +
122
			"hashCode[METHOD_REF]{hashCode(), Ljava.lang.Object;, ()I, hashCode, null, 35}\n" +
123
			"length[METHOD_REF]{length(), Ljava.lang.String;, ()I, length, null, 35}\n" +
124
			"notify[METHOD_REF]{notify(), Ljava.lang.Object;, ()V, notify, null, 35}\n" +
124
			"notify[METHOD_REF]{notify(), Ljava.lang.Object;, ()V, notify, null, 35}\n" +
125
			"notifyAll[METHOD_REF]{notifyAll(), Ljava.lang.Object;, ()V, notifyAll, null, 35}\n" +
125
			"notifyAll[METHOD_REF]{notifyAll(), Ljava.lang.Object;, ()V, notifyAll, null, 35}\n" +
126
			"toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 35}\n" +
126
			"toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 35}\n" +
Lines 331-337 Link Here
331
			"toString[METHOD_DECLARATION]{public String toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 27}",
331
			"toString[METHOD_DECLARATION]{public String toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 27}",
332
			requestor.getResults());
332
			requestor.getResults());
333
}
333
}
334
public void _test010() throws JavaModelException {
334
public void test010() throws JavaModelException {
335
	this.workingCopies = new ICompilationUnit[1];
335
	this.workingCopies = new ICompilationUnit[1];
336
	this.workingCopies[0] = getWorkingCopy(
336
	this.workingCopies[0] = getWorkingCopy(
337
			"/Completion/src/X.java",
337
			"/Completion/src/X.java",
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[] { "testBug408230g" };
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 (-9 / +64 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 156-161 Link Here
156
	int labelPtr = -1;
155
	int labelPtr = -1;
157
156
158
	boolean isAlreadyAttached;
157
	boolean isAlreadyAttached;
158
	boolean shouldStackAssistNode;
159
159
160
	public boolean record = false;
160
	public boolean record = false;
161
	public boolean skipRecord = false;
161
	public boolean skipRecord = false;
Lines 614-620 Link Here
614
public Object becomeSimpleParser() {
614
public Object becomeSimpleParser() {
615
	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
615
	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
616
	int[] parserState = new int[] {this.cursorLocation, completionScanner.cursorLocation};
616
	int[] parserState = new int[] {this.cursorLocation, completionScanner.cursorLocation};
617
	
617
	// ??
618
	this.cursorLocation = Integer.MAX_VALUE;
618
	this.cursorLocation = Integer.MAX_VALUE;
619
	completionScanner.cursorLocation = Integer.MAX_VALUE;
619
	completionScanner.cursorLocation = Integer.MAX_VALUE;
620
	
620
	
Lines 2407-2412 Link Here
2407
	// DimWithOrWithOutExpr ::= '[' ']'
2407
	// DimWithOrWithOutExpr ::= '[' ']'
2408
	pushOnExpressionStack(null);
2408
	pushOnExpressionStack(null);
2409
}
2409
}
2410
protected void consumeEmptyStatement() {
2411
	super.consumeEmptyStatement();
2412
	/* Sneak in the assist node. The reason we can't do that when we see the assist node is that 
2413
	   we don't know whether it is the first or subsequent statement in a block to be able to
2414
	   decide whether to call contactNodeLists. See Parser.consumeBlockStatement(s) 
2415
	*/
2416
	if (this.shouldStackAssistNode) {
2417
		this.shouldStackAssistNode = false;
2418
		if (this.assistNode != null)
2419
		//	this.astStack[this.astPtr] = this.assistNodeParent != null ? this.assistNodeParent : this.assistNode;
2420
		this.astStack[this.astPtr] = this.assistNode;
2421
	}
2422
}
2410
protected void consumeEnhancedForStatement() {
2423
protected void consumeEnhancedForStatement() {
2411
	super.consumeEnhancedForStatement();
2424
	super.consumeEnhancedForStatement();
2412
2425
Lines 2579-2586 Link Here
2579
	if (this.cursorLocation + 1 < variable.initialization.sourceStart ||
2592
	if (this.cursorLocation + 1 < variable.initialization.sourceStart ||
2580
		this.cursorLocation > variable.initialization.sourceEnd) {
2593
		this.cursorLocation > variable.initialization.sourceEnd) {
2581
		variable.initialization = null;
2594
		variable.initialization = null;
2582
	} else if (this.assistNode != null && this.assistNode == variable.initialization) {
2595
	} else if (this.assistNode != null) {
2583
		this.assistNodeParent = variable;
2596
		if (this.assistNode == variable.initialization)
2597
			this.assistNodeParent = variable;
2584
	}
2598
	}
2585
}
2599
}
2586
protected void consumeExitVariableWithoutInitialization() {
2600
protected void consumeExitVariableWithoutInitialization() {
Lines 3470-3475 Link Here
3470
					case K_MEMBER_VALUE_ARRAY_INITIALIZER:
3484
					case K_MEMBER_VALUE_ARRAY_INITIALIZER:
3471
						popElement(K_MEMBER_VALUE_ARRAY_INITIALIZER);
3485
						popElement(K_MEMBER_VALUE_ARRAY_INITIALIZER);
3472
						break;
3486
						break;
3487
					case K_LAMBDA_EXPRESSION_DELIMITER:
3488
						break; // will be popped when the containing block statement is reduced.
3473
					default:
3489
					default:
3474
						popElement(K_ARRAY_INITIALIZER);
3490
						popElement(K_ARRAY_INITIALIZER);
3475
						break;
3491
						break;
Lines 3675-3680 Link Here
3675
								break;
3691
								break;
3676
							case TokenNamedo:
3692
							case TokenNamedo:
3677
								pushOnElementStack(K_BLOCK_DELIMITER, DO);
3693
								pushOnElementStack(K_BLOCK_DELIMITER, DO);
3694
								break;
3695
							case TokenNameARROW:
3678
								break;
3696
								break;
3679
							default :
3697
							default :
3680
								pushOnElementStack(K_BLOCK_DELIMITER);
3698
								pushOnElementStack(K_BLOCK_DELIMITER);
Lines 4609-4614 Link Here
4609
	this.labelPtr = -1;
4627
	this.labelPtr = -1;
4610
	initializeForBlockStatements();
4628
	initializeForBlockStatements();
4611
}
4629
}
4630
public void copyState(CommitRollbackParser from) {
4631
4632
	super.copyState(from);
4633
	
4634
	CompletionParser parser = (CompletionParser) from;
4635
	
4636
	this.invocationType = parser.invocationType;
4637
	this.qualifier = parser.qualifier;
4638
	this.inReferenceExpression = parser.inReferenceExpression;
4639
	this.hasUnusedModifiers = parser.hasUnusedModifiers;
4640
	this.canBeExplicitConstructor = parser.canBeExplicitConstructor;
4641
}
4612
/*
4642
/*
4613
 * Initializes the state of the parser that is about to go for BlockStatements.
4643
 * Initializes the state of the parser that is about to go for BlockStatements.
4614
 */
4644
 */
Lines 4954-4959 Link Here
4954
			break;
4984
			break;
4955
	}
4985
	}
4956
}
4986
}
4987
4988
protected CommitRollbackParser createSnapShotParser() {
4989
	return new CompletionParser(this.problemReporter, this.storeSourceEnds);
4990
}
4957
/*
4991
/*
4958
 * Reset internal state after completion is over
4992
 * Reset internal state after completion is over
4959
 */
4993
 */
Lines 4977-4983 Link Here
4977
	int[] state = (int[]) parserState;
5011
	int[] state = (int[]) parserState;
4978
	
5012
	
4979
	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
5013
	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
4980
	
5014
	// ??
4981
	this.cursorLocation = state[0];
5015
	this.cursorLocation = state[0];
4982
	completionScanner.cursorLocation = state[1];
5016
	completionScanner.cursorLocation = state[1];
4983
}
5017
}
Lines 4988-5000 Link Here
4988
 * Move checkpoint location, reset internal stacks and
5022
 * Move checkpoint location, reset internal stacks and
4989
 * decide which grammar goal is activated.
5023
 * decide which grammar goal is activated.
4990
 */
5024
 */
4991
protected boolean resumeAfterRecovery() {
5025
protected int resumeAfterRecovery(boolean errorRecovery) {
4992
	this.hasUnusedModifiers = false;
5026
	this.hasUnusedModifiers = false;
4993
	if (this.assistNode != null) {
5027
	if (this.assistNode != null) {
5028
		
5029
		if (requireExtendedRecovery()) {
5030
			if (!errorRecovery) {
5031
				return RESUME;
5032
			}
5033
			return super.resumeAfterRecovery(errorRecovery);
5034
		}
5035
		
4994
		/* if reached [eof] inside method body, but still inside nested type,
5036
		/* if reached [eof] inside method body, but still inside nested type,
4995
			or inside a field initializer, should continue in diet mode until
5037
			or inside a field initializer, should continue in diet mode until
4996
			the end of the method body or compilation unit */
5038
			the end of the method body or compilation unit */
4997
		if ((this.scanner.eofPosition == this.cursorLocation+1)
5039
		if ((this.scanner.eofPosition >= this.cursorLocation+1)
4998
			&& (!(this.referenceContext instanceof CompilationUnitDeclaration)
5040
			&& (!(this.referenceContext instanceof CompilationUnitDeclaration)
4999
			|| isIndirectlyInsideFieldInitialization()
5041
			|| isIndirectlyInsideFieldInitialization()
5000
			|| this.assistNodeParent instanceof FieldDeclaration && !(this.assistNodeParent instanceof Initializer))) {
5042
			|| this.assistNodeParent instanceof FieldDeclaration && !(this.assistNodeParent instanceof Initializer))) {
Lines 5022-5027 Link Here
5022
				}
5064
				}
5023
			}
5065
			}
5024
			*/
5066
			*/
5067
5025
			/* restart in diet mode for finding sibling constructs */
5068
			/* restart in diet mode for finding sibling constructs */
5026
			if (this.currentElement instanceof RecoveredType
5069
			if (this.currentElement instanceof RecoveredType
5027
				|| this.currentElement.enclosingType() != null){
5070
				|| this.currentElement.enclosingType() != null){
Lines 5035-5049 Link Here
5035
				this.scanner.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
5078
				this.scanner.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
5036
			} else {
5079
			} else {
5037
				resetStacks();
5080
				resetStacks();
5038
				return false;
5081
				return HALT;
5039
			}
5082
			}
5040
		}
5083
		}
5041
	}
5084
	}
5042
	return super.resumeAfterRecovery();
5085
	return super.resumeAfterRecovery(errorRecovery);
5043
}
5086
}
5044
public void setAssistIdentifier(char[] assistIdent){
5087
public void setAssistIdentifier(char[] assistIdent){
5045
	((CompletionScanner)this.scanner).completionIdentifier = assistIdent;
5088
	((CompletionScanner)this.scanner).completionIdentifier = assistIdent;
5046
}
5089
}
5090
5091
protected void shouldStackAssistNode() {
5092
	this.shouldStackAssistNode = true;
5093
}
5094
5047
public  String toString() {
5095
public  String toString() {
5048
	StringBuffer buffer = new StringBuffer();
5096
	StringBuffer buffer = new StringBuffer();
5049
	buffer.append("elementKindStack : int[] = {"); //$NON-NLS-1$
5097
	buffer.append("elementKindStack : int[] = {"); //$NON-NLS-1$
Lines 5070-5076 Link Here
5070
5118
5071
	/* may be able to retrieve completionNode as an orphan, and then attach it */
5119
	/* may be able to retrieve completionNode as an orphan, and then attach it */
5072
	completionIdentifierCheck();
5120
	completionIdentifierCheck();
5121
	CommitRollbackParser parser = null;
5122
	if (lastIndexOfElement(K_LAMBDA_EXPRESSION_DELIMITER) >= 0) {
5123
		parser = createSnapShotParser();
5124
		parser.copyState(this);
5125
	}
5073
	attachOrphanCompletionNode();
5126
	attachOrphanCompletionNode();
5127
	if (parser != null)
5128
		this.copyState(parser);
5074
5129
5075
	// if an assist node has been found and a recovered element exists,
5130
	// if an assist node has been found and a recovered element exists,
5076
	// mark enclosing blocks as to be preserved
5131
	// mark enclosing blocks as to be preserved
(-)a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java (-4 / +27 lines)
Lines 56-61 Link Here
56
		null/*taskPriorities*/,
56
		null/*taskPriorities*/,
57
		true/*taskCaseSensitive*/);
57
		true/*taskCaseSensitive*/);
58
}
58
}
59
protected boolean isAtAssistIdentifier() {
60
	if (this.cursorLocation < this.startPosition && this.currentPosition == this.startPosition) { // fake empty identifier got issued
61
		return true;
62
	}
63
	if (this.cursorLocation+1 >= this.startPosition && this.cursorLocation < this.currentPosition) {
64
		return true;
65
	}
66
	return false;
67
}
59
/*
68
/*
60
 * Truncate the current identifier if it is containing the cursor location. Since completion is performed
69
 * Truncate the current identifier if it is containing the cursor location. Since completion is performed
61
 * on an identifier prefix.
70
 * on an identifier prefix.
Lines 146-152 Link Here
146
							this.currentPosition = this.startPosition; // for being detected as empty free identifier
155
							this.currentPosition = this.startPosition; // for being detected as empty free identifier
147
							return TokenNameIdentifier;
156
							return TokenNameIdentifier;
148
						}
157
						}
149
						return TokenNameEOF;
158
						return TokenNameEOF; // truly at EOF.
150
					}
159
					}
151
				}
160
				}
152
				if (checkIfUnicode) {
161
				if (checkIfUnicode) {
Lines 199-204 Link Here
199
					this.currentPosition = this.startPosition; // for being detected as empty free identifier
208
					this.currentPosition = this.startPosition; // for being detected as empty free identifier
200
					return TokenNameIdentifier;
209
					return TokenNameIdentifier;
201
				}
210
				}
211
				this.currentPosition = this.startPosition; // fake EOF should not drown the real next token.
202
				return TokenNameEOF;
212
				return TokenNameEOF;
203
			}
213
			}
204
214
Lines 804-810 Link Here
804
					char c = this.currentCharacter;
814
					char c = this.currentCharacter;
805
					if (c < ScannerHelper.MAX_OBVIOUS) {
815
					if (c < ScannerHelper.MAX_OBVIOUS) {
806
						if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
816
						if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
807
							return scanIdentifierOrKeyword();
817
							int id = scanIdentifierOrKeyword(); 
818
//							// Read past the cursor location should return the completion identifier if it was truncated.
819
//							if (id == TokenNameIdentifier && this.startPosition <= this.cursorLocation + 1
820
//									&& this.cursorLocation < this.currentPosition) {
821
//								return getNextToken0();
822
//							}
823
							return id;
808
						} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) {
824
						} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) {
809
								return scanNumber(false);
825
								return scanNumber(false);
810
						} else {
826
						} else {
Lines 833-840 Link Here
833
						// optimized case already checked
849
						// optimized case already checked
834
						isJavaIdStart = Character.isJavaIdentifierStart(c);
850
						isJavaIdStart = Character.isJavaIdentifierStart(c);
835
					}
851
					}
836
					if (isJavaIdStart)
852
					if (isJavaIdStart) {
837
						return scanIdentifierOrKeyword();
853
						int id = scanIdentifierOrKeyword(); 
854
//						// Read past the cursor location should return the completion identifier if it was truncated.
855
//						if (id == TokenNameIdentifier && this.startPosition <= this.cursorLocation + 1
856
//								&& this.cursorLocation < this.currentPosition) {
857
//							return getNextToken0();
858
//						}
859
						return id;
860
					}
838
					if (ScannerHelper.isDigit(this.currentCharacter)) {
861
					if (ScannerHelper.isDigit(this.currentCharacter)) {
839
						return scanNumber(false);
862
						return scanNumber(false);
840
					}
863
					}
(-)a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java (-42 / +183 lines)
Lines 19-28 Link Here
19
 *
19
 *
20
 */
20
 */
21
21
22
import org.eclipse.jdt.internal.codeassist.complete.CompletionOnKeyword2;
22
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
23
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
23
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
24
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
24
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
25
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
25
import org.eclipse.jdt.internal.compiler.ast.Annotation;
26
import org.eclipse.jdt.internal.compiler.ast.Annotation;
27
import org.eclipse.jdt.internal.compiler.ast.Argument;
26
import org.eclipse.jdt.internal.compiler.ast.Block;
28
import org.eclipse.jdt.internal.compiler.ast.Block;
27
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
29
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
28
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
30
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
Lines 44-49 Link Here
44
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
46
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
45
import org.eclipse.jdt.internal.compiler.lookup.Binding;
47
import org.eclipse.jdt.internal.compiler.lookup.Binding;
46
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
48
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
49
import org.eclipse.jdt.internal.compiler.parser.CommitRollbackParser;
47
import org.eclipse.jdt.internal.compiler.parser.Parser;
50
import org.eclipse.jdt.internal.compiler.parser.Parser;
48
import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock;
51
import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock;
49
import org.eclipse.jdt.internal.compiler.parser.RecoveredElement;
52
import org.eclipse.jdt.internal.compiler.parser.RecoveredElement;
Lines 58-63 Link Here
58
public abstract class AssistParser extends Parser {
61
public abstract class AssistParser extends Parser {
59
	public ASTNode assistNode;
62
	public ASTNode assistNode;
60
	public boolean isOrphanCompletionNode;
63
	public boolean isOrphanCompletionNode;
64
	private boolean resumedAfterRepair = false;
61
	// last modifiers info
65
	// last modifiers info
62
	protected int lastModifiers = ClassFileConstants.AccDefault;
66
	protected int lastModifiers = ClassFileConstants.AccDefault;
63
	protected int lastModifiersStart = -1;
67
	protected int lastModifiersStart = -1;
Lines 93-99 Link Here
93
	protected static final int K_FIELD_INITIALIZER_DELIMITER = ASSIST_PARSER + 4; // whether we are inside a field initializer
97
	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
98
	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
99
	protected static final int K_ENUM_CONSTANT_DELIMITER = ASSIST_PARSER + 6; // whether we are inside a field initializer
96
100
	protected static final int K_LAMBDA_EXPRESSION_DELIMITER = ASSIST_PARSER + 7; // whether we are inside a lambda expression
101
	
97
	// selector constants
102
	// selector constants
98
	protected static final int THIS_CONSTRUCTOR = -1;
103
	protected static final int THIS_CONSTRUCTOR = -1;
99
	protected static final int SUPER_CONSTRUCTOR = -2;
104
	protected static final int SUPER_CONSTRUCTOR = -2;
Lines 101-109 Link Here
101
	// enum constant constants
106
	// enum constant constants
102
	protected static final int NO_BODY = 0;
107
	protected static final int NO_BODY = 0;
103
	protected static final int WITH_BODY = 1;
108
	protected static final int WITH_BODY = 1;
109
	
110
	protected static final int EXPRESSION_BODY = 0;
111
	protected static final int BLOCK_BODY = 1;
104
112
105
	protected boolean isFirst = false;
113
	protected boolean isFirst = false;
106
	protected boolean lambdaNeedsClosure = false; // :)
114
107
115
108
public AssistParser(ProblemReporter problemReporter) {
116
public AssistParser(ProblemReporter problemReporter) {
109
	super(problemReporter, true);
117
	super(problemReporter, true);
Lines 112-119 Link Here
112
	setMethodsFullRecovery(false);
120
	setMethodsFullRecovery(false);
113
	setStatementsRecovery(false);
121
	setStatementsRecovery(false);
114
}
122
}
123
115
public abstract char[] assistIdentifier();
124
public abstract char[] assistIdentifier();
116
125
126
public void copyState(CommitRollbackParser from) {
127
	
128
	super.copyState(from);
129
130
	AssistParser parser = (AssistParser) from;
131
	
132
	this.previousToken = parser.previousToken;
133
	this.previousIdentifierPtr = parser.previousIdentifierPtr;
134
	
135
	this.lastModifiers = parser.lastModifiers;
136
	this.lastModifiersStart = parser.lastModifiersStart;
137
	
138
	this.bracketDepth = parser.bracketDepth;
139
	this.elementPtr = parser.elementPtr;
140
	
141
	int length;
142
	System.arraycopy(parser.blockStarts, 0, this.blockStarts = new int [length = parser.blockStarts.length], 0, length);
143
	System.arraycopy(parser.elementKindStack, 0, this.elementKindStack = new int [length = parser.elementKindStack.length], 0, length);
144
	System.arraycopy(parser.elementInfoStack, 0, this.elementInfoStack = new int [length = parser.elementInfoStack.length], 0, length);
145
	System.arraycopy(parser.elementObjectInfoStack, 0, this.elementObjectInfoStack = new Object [length = parser.elementObjectInfoStack.length], 0, length);
146
	
147
	this.previousKind = parser.previousKind;
148
	this.previousInfo = parser.previousInfo;
149
	this.previousObjectInfo = parser.previousObjectInfo;
150
}
117
/**
151
/**
118
 * The parser become a simple parser which behave like a Parser
152
 * 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
153
 * @return the state of the assist parser to be able to restore the assist parser state
Lines 144-149 Link Here
144
		RecoveredElement element = super.buildInitialRecoveryState();
178
		RecoveredElement element = super.buildInitialRecoveryState();
145
		flushAssistState();
179
		flushAssistState();
146
		flushElementStack();
180
		flushElementStack();
181
		this.cryogenicallyFrozenParser = null;
147
		return element;
182
		return element;
148
	}
183
	}
149
184
Lines 184-191 Link Here
184
	element = element.add(block, 1);
219
	element = element.add(block, 1);
185
	int blockIndex = 1;	// ignore first block start, since manually rebuilt here
220
	int blockIndex = 1;	// ignore first block start, since manually rebuilt here
186
221
187
	for(int i = 0; i <= this.astPtr; i++){
222
	ASTNode node = null, lastNode = null;
188
		ASTNode node = this.astStack[i];
223
	for (int i = 0; i <= this.astPtr; i++, lastNode = node) {
224
		node = this.astStack[i];
189
		if(node instanceof ForeachStatement && ((ForeachStatement)node).action == null) {
225
		if(node instanceof ForeachStatement && ((ForeachStatement)node).action == null) {
190
			node = ((ForeachStatement)node).elementVariable;
226
			node = ((ForeachStatement)node).elementVariable;
191
		}
227
		}
Lines 198-204 Link Here
198
					break;
234
					break;
199
				}
235
				}
200
				if (this.blockStarts[j] != lastStart){ // avoid multiple block if at same position
236
				if (this.blockStarts[j] != lastStart){ // avoid multiple block if at same position
201
					block = new Block(0);
237
					block = new Block(0, lastNode instanceof LambdaExpression);
202
					block.sourceStart = lastStart = this.blockStarts[j];
238
					block.sourceStart = lastStart = this.blockStarts[j];
203
					element = element.add(block, 1);
239
					element = element.add(block, 1);
204
				}
240
				}
Lines 277-288 Link Here
277
			}
313
			}
278
			continue;
314
			continue;
279
		}
315
		}
280
		if (node instanceof LambdaExpression) {
281
			LambdaExpression lambda = (LambdaExpression) node;
282
			element = element.add(lambda, 0);
283
			this.lastCheckPoint = lambda.sourceEnd + 1;
284
			continue;
285
		}
286
		if (this.assistNode != null && node instanceof Statement) {
316
		if (this.assistNode != null && node instanceof Statement) {
287
			Statement stmt = (Statement) node;
317
			Statement stmt = (Statement) node;
288
			if (!(stmt instanceof Expression) || ((Expression) stmt).statementExpression()) {
318
			if (!(stmt instanceof Expression) || ((Expression) stmt).statementExpression()) {
Lines 305-317 Link Here
305
	}
335
	}
306
336
307
	/* might need some extra block (after the last reduced node) */
337
	/* might need some extra block (after the last reduced node) */
338
	/* For block bodied lambdas we should create a block even though the lambda header appears before it, so elements from within don't get misattributed. */
308
	int pos = this.assistNode == null ? this.lastCheckPoint : this.assistNode.sourceStart;
339
	int pos = this.assistNode == null ? this.lastCheckPoint : this.assistNode.sourceStart;
340
	boolean createLambdaBlock = lastNode instanceof LambdaExpression && ((LambdaExpression) node).body() instanceof Block;
309
	for (int j = blockIndex; j <= this.realBlockPtr; j++){
341
	for (int j = blockIndex; j <= this.realBlockPtr; j++){
310
		if (this.blockStarts[j] >= 0) {
342
		if (this.blockStarts[j] >= 0) {
311
			if ((this.blockStarts[j] < pos) && (this.blockStarts[j] != lastStart)){ // avoid multiple block if at same position
343
			if ((this.blockStarts[j] < pos || createLambdaBlock) && (this.blockStarts[j] != lastStart)){ // avoid multiple block if at same position
312
				block = new Block(0);
344
				block = new Block(0, createLambdaBlock);
313
				block.sourceStart = lastStart = this.blockStarts[j];
345
				block.sourceStart = lastStart = this.blockStarts[j];
314
				element = element.add(block, 1);
346
				element = element.add(block, 1);
347
				createLambdaBlock = false;
315
			}
348
			}
316
		} else {
349
		} else {
317
			if ((this.blockStarts[j] < pos)){ // avoid multiple block if at same position
350
			if ((this.blockStarts[j] < pos)){ // avoid multiple block if at same position
Lines 401-427 Link Here
401
protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
434
protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
402
	super.consumeExplicitConstructorInvocation(flag, recFlag);
435
	super.consumeExplicitConstructorInvocation(flag, recFlag);
403
	popElement(K_SELECTOR);
436
	popElement(K_SELECTOR);
404
	triggerRecoveryUponLambdaClosure();
405
}
437
}
438
406
protected void triggerRecoveryUponLambdaClosure() {
439
protected void triggerRecoveryUponLambdaClosure() {
407
	if (this.assistNode == null || !this.lambdaNeedsClosure)
440
	// Last block statement reduced is required to be on the AST stack top.
408
		return;
441
	this.restartRecovery = false;
409
	ASTNode node = this.astStack[this.astPtr];
442
	Statement statement = (Statement) this.astStack[this.astPtr];
410
	if (this.assistNode.sourceStart >= node.sourceStart && this.assistNode.sourceEnd <= node.sourceEnd) {
443
	int statementStart, statementEnd;
411
		for (int i = 0; i <= this.astPtr; i++) {
444
	statementStart = statement.sourceStart;
412
			if (this.astStack[i] instanceof LambdaExpression)
445
	statementEnd = statement instanceof AbstractVariableDeclaration ? ((AbstractVariableDeclaration)statement).declarationSourceEnd : statement.sourceEnd;
413
				return;
446
	for (int i = this.elementPtr; i >= 0; --i) {
447
		if (this.elementKindStack[i] != K_LAMBDA_EXPRESSION_DELIMITER)
448
			continue;
449
		LambdaExpression expression = (LambdaExpression) this.elementObjectInfoStack[i];
450
		if (expression.sourceStart >= statementStart && expression.sourceEnd <= statementEnd) {
451
			this.elementPtr = i - 1;
452
			if (this.currentElement != null) {
453
				this.restartRecovery = true;
454
			}
455
		} else {
456
			int stackLength = this.stack.length;
457
			if (++this.stateStackTop >= stackLength) {
458
				System.arraycopy(
459
					this.stack, 0,
460
					this.stack = new int[stackLength + StackIncrement], 0,
461
					stackLength);
462
			}
463
			this.stack[this.stateStackTop] = this.unstackedAct;
464
			commit();
465
			this.stateStackTop --;
466
			return;
414
		}
467
		}
415
		this.restartRecovery = true;
416
		this.isOrphanCompletionNode = false;
417
		this.lambdaNeedsClosure = false;
418
	}
468
	}
469
	
470
	if (this.restartRecovery && this.currentElement != null) {
471
		if (!(statement instanceof AbstractVariableDeclaration)) // added already as part of standard recovery since these contribute a name to the scope prevailing at the cursor.
472
			this.currentElement.add(statement, 0);
473
	}
474
	this.cryogenicallyFrozenParser = null;
419
}
475
}
420
protected void consumeExplicitConstructorInvocationWithTypeArguments(int flag, int recFlag) {
476
protected boolean isAssistParser() {
421
	super.consumeExplicitConstructorInvocationWithTypeArguments(flag, recFlag);
477
	return true;
478
}
479
protected void consumeBlockStatement() {
480
	super.consumeBlockStatement();
422
	triggerRecoveryUponLambdaClosure();
481
	triggerRecoveryUponLambdaClosure();
423
}
482
}
424
483
484
protected void consumeBlockStatements() {
485
	super.consumeBlockStatements();
486
	triggerRecoveryUponLambdaClosure();
487
}
488
protected void consumeFieldDeclaration() {
489
	super.consumeFieldDeclaration();
490
	triggerRecoveryUponLambdaClosure();
491
}
425
protected void consumeForceNoDiet() {
492
protected void consumeForceNoDiet() {
426
	super.consumeForceNoDiet();
493
	super.consumeForceNoDiet();
427
	// if we are not in a method (i.e. we are not in a local variable initializer)
494
	// 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();
511
	super.consumeInterfaceHeader();
445
	pushOnElementStack(K_TYPE_DELIMITER);
512
	pushOnElementStack(K_TYPE_DELIMITER);
446
}
513
}
447
protected void consumeExpressionStatement() {
514
448
	super.consumeExpressionStatement();
515
LocalDeclaration fakeLocalFromArgument(Argument argument) {
449
	triggerRecoveryUponLambdaClosure();
516
	LocalDeclaration local = new LocalDeclaration(argument.name, argument.sourceStart, argument.sourceEnd);
517
	local.declarationSourceStart = argument.declarationSourceStart;
518
	local.declarationSourceEnd = argument.declarationSourceEnd;
519
	local.modifiers = argument.modifiers;
520
	local.modifiersSourceStart = argument.modifiersSourceStart;
521
	local.annotations = argument.annotations;
522
	local.type = argument.type;
523
	return local;
524
}
525
protected void consumeLambdaHeader() {
526
	super.consumeLambdaHeader();
527
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr];
528
	pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, EXPRESSION_BODY, lexp);
529
530
//	if (this.currentElement != null) {
531
//		for (int i = 0, length = arguments.length; i < length; i++) {
532
//			this.currentElement = this.currentElement.add(fakeLocalFromArgument(arguments[i]), 0);
533
//		}
534
//	}
450
}
535
}
451
protected void consumeMethodBody() {
536
protected void consumeMethodBody() {
452
	super.consumeMethodBody();
537
	super.consumeMethodBody();
Lines 457-463 Link Here
457
		popElement(K_METHOD_DELIMITER);
542
		popElement(K_METHOD_DELIMITER);
458
	}
543
	}
459
	super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
544
	super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
460
	triggerRecoveryUponLambdaClosure();
461
}
545
}
462
protected void consumeMethodHeader() {
546
protected void consumeMethodHeader() {
463
	super.consumeMethodHeader();
547
	super.consumeMethodHeader();
Lines 517-532 Link Here
517
}
601
}
518
protected void consumeOpenBlock() {
602
protected void consumeOpenBlock() {
519
	// OpenBlock ::= $empty
603
	// OpenBlock ::= $empty
520
521
	super.consumeOpenBlock();
604
	super.consumeOpenBlock();
605
522
	int stackLength = this.blockStarts.length;
606
	int stackLength = this.blockStarts.length;
523
	if (this.realBlockPtr >= stackLength) {
607
	if (this.realBlockPtr >= stackLength) {
524
		System.arraycopy(
608
		System.arraycopy(
525
			this.blockStarts, 0,
609
				this.blockStarts, 0,
526
			this.blockStarts = new int[stackLength + StackIncrement], 0,
610
				this.blockStarts = new int[stackLength + StackIncrement], 0,
527
			stackLength);
611
				stackLength);
528
	}
612
	}
529
	this.blockStarts[this.realBlockPtr] = this.scanner.startPosition;
613
	this.blockStarts[this.realBlockPtr] = this.scanner.startPosition;
614
	if (requireExtendedRecovery()) {
615
		// This is an epsilon production: We are in the state with kernel item: Block ::= .OpenBlock LBRACE BlockStatementsopt RBRACE
616
		stackLength = this.stack.length;
617
		if (++this.stateStackTop >= stackLength - 1) {   // Need two slots.
618
			System.arraycopy(
619
				this.stack, 0,
620
				this.stack = new int[stackLength + StackIncrement], 0,
621
				stackLength);
622
		}
623
		this.stack[this.stateStackTop++] = this.unstackedAct; // transition to Block ::= OpenBlock  .LBRACE BlockStatementsopt RBRACE
624
		this.stack[this.stateStackTop] = tAction(this.unstackedAct, this.currentToken); // transition to Block ::= OpenBlock LBRACE  .BlockStatementsopt RBRACE 
625
		commit();
626
		this.stateStackTop -= 2;
627
	}
530
}
628
}
531
protected void consumeOpenFakeBlock() {
629
protected void consumeOpenFakeBlock() {
532
	// OpenBlock ::= $empty
630
	// OpenBlock ::= $empty
Lines 853-858 Link Here
853
				}
951
				}
854
				break;
952
				break;
855
			case TokenNameLBRACE:
953
			case TokenNameLBRACE:
954
				if (this.previousToken == TokenNameARROW) {
955
					popElement(K_LAMBDA_EXPRESSION_DELIMITER);
956
					pushOnElementStack(K_LAMBDA_EXPRESSION_DELIMITER, BLOCK_BODY, this.previousObjectInfo);
957
				}
856
				this.bracketDepth++;
958
				this.bracketDepth++;
857
				break;
959
				break;
858
			case TokenNameLBRACKET:
960
			case TokenNameLBRACKET:
Lines 1264-1269 Link Here
1264
	}
1366
	}
1265
	return false;
1367
	return false;
1266
}
1368
}
1369
protected boolean isIndirectlyInsideLambdaExpression(){
1370
	int i = this.elementPtr;
1371
	while (i > -1) {
1372
		if (this.elementKindStack[i] == K_LAMBDA_EXPRESSION_DELIMITER)
1373
			return true;
1374
		i--;
1375
	}
1376
	return false;
1377
}
1267
protected boolean isIndirectlyInsideType(){
1378
protected boolean isIndirectlyInsideType(){
1268
	int i = this.elementPtr;
1379
	int i = this.elementPtr;
1269
	while(i > -1) {
1380
	while(i > -1) {
Lines 1597-1602 Link Here
1597
		flushElementStack();
1708
		flushElementStack();
1598
	}
1709
	}
1599
}
1710
}
1711
1712
public boolean requireExtendedRecovery() {
1713
	if (this.assistNode instanceof TypeReference || this.assistNode instanceof CompletionOnKeyword2)
1714
		return false;
1715
	return lastIndexOfElement(K_LAMBDA_EXPRESSION_DELIMITER) >= 0;
1716
}
1717
1600
protected void pushOnElementStack(int kind){
1718
protected void pushOnElementStack(int kind){
1601
	this.pushOnElementStack(kind, 0, null);
1719
	this.pushOnElementStack(kind, 0, null);
1602
}
1720
}
Lines 1659-1665 Link Here
1659
			break;
1777
			break;
1660
		case TokenNameRBRACE :
1778
		case TokenNameRBRACE :
1661
			super.recoveryTokenCheck();
1779
			super.recoveryTokenCheck();
1662
			if(this.currentElement != oldElement && !isInsideAttributeValue()) {
1780
			if(this.currentElement != oldElement && !isInsideAttributeValue() && !isIndirectlyInsideLambdaExpression()) {
1663
				if(oldElement instanceof RecoveredInitializer
1781
				if(oldElement instanceof RecoveredInitializer
1664
					|| oldElement instanceof RecoveredMethod
1782
					|| oldElement instanceof RecoveredMethod
1665
					|| (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredInitializer)
1783
					|| (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredInitializer)
Lines 1691-1698 Link Here
1691
 * Move checkpoint location, reset internal stacks and
1809
 * Move checkpoint location, reset internal stacks and
1692
 * decide which grammar goal is activated.
1810
 * decide which grammar goal is activated.
1693
 */
1811
 */
1694
protected boolean resumeAfterRecovery() {
1812
protected int resumeAfterRecovery(boolean errorRecovery) {
1695
1813
	if (requireExtendedRecovery()) {
1814
		if (errorRecovery) {
1815
			int mode = fallBackToSpringForward((Statement) null);
1816
			this.resumedAfterRepair = mode == RESUME;
1817
			if (mode == RESUME || mode == HALT)
1818
				return mode;
1819
			// else fall through and RESTART
1820
		} else {
1821
			return RESUME;
1822
		}
1823
	}
1824
		
1696
	// reset internal stacks
1825
	// reset internal stacks
1697
	this.astPtr = -1;
1826
	this.astPtr = -1;
1698
	this.astLengthPtr = -1;
1827
	this.astLengthPtr = -1;
Lines 1700-1723 Link Here
1700
	this.expressionLengthPtr = -1;
1829
	this.expressionLengthPtr = -1;
1701
	this.typeAnnotationLengthPtr = -1;
1830
	this.typeAnnotationLengthPtr = -1;
1702
	this.typeAnnotationPtr = -1;
1831
	this.typeAnnotationPtr = -1;
1832
	
1703
	this.identifierPtr = -1;
1833
	this.identifierPtr = -1;
1704
	this.identifierLengthPtr	= -1;
1834
	this.identifierLengthPtr	= -1;
1705
	this.intPtr = -1;
1835
	this.intPtr = -1;
1836
	
1837
	
1706
	this.dimensions = 0 ;
1838
	this.dimensions = 0 ;
1707
	this.recoveredStaticInitializerStart = 0;
1839
	this.recoveredStaticInitializerStart = 0;
1708
1840
1709
	this.genericsIdentifiersLengthPtr = -1;
1841
	this.genericsIdentifiersLengthPtr = -1;
1710
	this.genericsLengthPtr = -1;
1842
	this.genericsLengthPtr = -1;
1711
	this.genericsPtr = -1;
1843
	this.genericsPtr = -1;
1844
	
1845
	this.valueLambdaNestDepth = -1;
1712
1846
1713
	this.modifiers = ClassFileConstants.AccDefault;
1847
	this.modifiers = ClassFileConstants.AccDefault;
1714
	this.modifiersSourceStart = -1;
1848
	this.modifiersSourceStart = -1;
1715
1849
1850
	// Assist state should require some rewinding too ???
1851
	
1716
	// if in diet mode, reset the diet counter because we're going to restart outside an initializer.
1852
	// if in diet mode, reset the diet counter because we're going to restart outside an initializer.
1717
	if (this.diet) this.dietInt = 0;
1853
	if (this.diet) this.dietInt = 0;
1718
1854
1719
	/* attempt to move checkpoint location */
1855
	/* attempt to move checkpoint location */
1720
	if (!moveRecoveryCheckpoint()) return false;
1856
	if (!errorRecovery && this.resumedAfterRepair) {
1857
		this.scanner.ungetToken(this.currentToken);  // effectively move recovery checkpoint *backwards*.
1858
	} else {
1859
		if (!moveRecoveryCheckpoint()) return HALT;
1860
	}
1861
	this.resumedAfterRepair = false;
1721
1862
1722
	// only look for headers
1863
	// only look for headers
1723
	if (this.referenceContext instanceof CompilationUnitDeclaration
1864
	if (this.referenceContext instanceof CompilationUnitDeclaration
Lines 1738-1744 Link Here
1738
			goForHeaders();
1879
			goForHeaders();
1739
			this.diet = true; // passed this point, will not consider method bodies
1880
			this.diet = true; // passed this point, will not consider method bodies
1740
		}
1881
		}
1741
		return true;
1882
		return RESTART;
1742
	}
1883
	}
1743
	if (this.referenceContext instanceof AbstractMethodDeclaration
1884
	if (this.referenceContext instanceof AbstractMethodDeclaration
1744
		|| this.referenceContext instanceof TypeDeclaration){
1885
		|| this.referenceContext instanceof TypeDeclaration){
Lines 1750-1759 Link Here
1750
			prepareForBlockStatements();
1891
			prepareForBlockStatements();
1751
			goForBlockStatementsOrCatchHeader();
1892
			goForBlockStatementsOrCatchHeader();
1752
		}
1893
		}
1753
		return true;
1894
		return RESTART;
1754
	}
1895
	}
1755
	// does not know how to restart
1896
	// does not know how to restart
1756
	return false;
1897
	return HALT;
1757
}
1898
}
1758
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292087
1899
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=292087
1759
// To be implemented in children viz. CompletionParser that are aware of array initializers
1900
// To be implemented in children viz. CompletionParser that are aware of array initializers
Lines 1826-1829 Link Here
1826
		return ast;
1967
		return ast;
1827
	}
1968
	}
1828
}
1969
}
1829
}
1970
}
(-)a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java (-42 / +35 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 115-122 Link Here
115
		if (orphan instanceof Expression) {
115
		if (orphan instanceof Expression) {
116
			buildMoreCompletionContext((Expression)orphan);
116
			buildMoreCompletionContext((Expression)orphan);
117
		} else {
117
		} else {
118
			Statement statement = (Statement) orphan;
118
			if (lastIndexOfElement(K_LAMBDA_EXPRESSION_DELIMITER) < 0) { // lambdas are recovered upto the containing expression statement and will carry along the assist node anyways.
119
			this.currentElement = this.currentElement.add(statement, 0);
119
				Statement statement = (Statement) orphan;
120
				this.currentElement = this.currentElement.add(statement, 0);
121
			}
120
		}
122
		}
121
		this.currentToken = 0; // given we are not on an eof, we do not want side effects caused by looked-ahead token
123
		this.currentToken = 0; // given we are not on an eof, we do not want side effects caused by looked-ahead token
122
	}
124
	}
Lines 176-187 Link Here
176
				break nextElement;
178
				break nextElement;
177
		}
179
		}
178
	}
180
	}
179
	if(parentNode != null) {
181
	// Do not add assist node/parent into the recovery system if we are inside a lambda. The lambda will be fully reovered including the containing statement and added.
180
		this.currentElement = this.currentElement.add((Statement)parentNode, 0);
182
	if (lastIndexOfElement(K_LAMBDA_EXPRESSION_DELIMITER) < 0) {
181
	} else {
183
		if(parentNode != null) {
182
		this.currentElement = this.currentElement.add((Statement)wrapWithExplicitConstructorCallIfNeeded(expression), 0);
184
			this.currentElement = this.currentElement.add((Statement)parentNode, 0);
183
		if(this.lastCheckPoint < expression.sourceEnd) {
185
		} else {
184
			this.lastCheckPoint = expression.sourceEnd + 1;
186
			this.currentElement = this.currentElement.add((Statement)wrapWithExplicitConstructorCallIfNeeded(expression), 0);
187
			if(this.lastCheckPoint < expression.sourceEnd) {
188
				this.lastCheckPoint = expression.sourceEnd + 1;
189
			}
185
		}
190
		}
186
	}
191
	}
187
}
192
}
Lines 1184-1189 Link Here
1184
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
1189
		this.restartRecovery = true; // used to avoid branching back into the regular automaton
1185
	}
1190
	}
1186
}
1191
}
1192
protected CommitRollbackParser createSnapShotParser() {
1193
	return new SelectionParser(this.problemReporter);
1194
}
1187
public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
1195
public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
1188
	return new SelectionOnImportReference(tokens, positions, mod);
1196
	return new SelectionOnImportReference(tokens, positions, mod);
1189
}
1197
}
Lines 1413-1440 Link Here
1413
	return super.parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
1421
	return super.parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
1414
}
1422
}
1415
1423
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
/*
1424
/*
1439
 * Reset context so as to resume to regular parse loop
1425
 * Reset context so as to resume to regular parse loop
1440
 * If unable to reset for resuming, answers false.
1426
 * If unable to reset for resuming, answers false.
Lines 1442-1468 Link Here
1442
 * Move checkpoint location, reset internal stacks and
1428
 * Move checkpoint location, reset internal stacks and
1443
 * decide which grammar goal is activated.
1429
 * decide which grammar goal is activated.
1444
 */
1430
 */
1445
protected boolean resumeAfterRecovery() {
1431
protected int resumeAfterRecovery(boolean errorRecovery) {
1446
1432
1447
	/* if reached assist node inside method body, but still inside nested type,
1433
	/* 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 */
1434
		should continue in diet mode until the end of the method body */
1449
	if (this.assistNode != null
1435
	if (this.assistNode != null
1450
		&& !(this.referenceContext instanceof CompilationUnitDeclaration)){
1436
		&& !(this.referenceContext instanceof CompilationUnitDeclaration)){
1451
		this.currentElement.preserveEnclosingBlocks();
1437
		this.currentElement.preserveEnclosingBlocks();
1438
		if (requireExtendedRecovery()) {
1439
			if (!errorRecovery) {
1440
				return RESUME;
1441
			}
1442
			return super.resumeAfterRecovery(errorRecovery);
1443
		}
1452
		if (this.currentElement.enclosingType() == null) {
1444
		if (this.currentElement.enclosingType() == null) {
1453
			if(!(this.currentElement instanceof RecoveredType)) {
1445
			if (!(this.currentElement instanceof RecoveredType)) {
1454
				resetStacks();
1446
				resetStacks();
1455
				return false;
1447
				return HALT;
1456
	}
1448
			}
1457
1449
1458
			RecoveredType recoveredType = (RecoveredType)this.currentElement;
1450
			RecoveredType recoveredType = (RecoveredType) this.currentElement;
1459
			if(recoveredType.typeDeclaration != null && recoveredType.typeDeclaration.allocation == this.assistNode){
1451
			if (recoveredType.typeDeclaration != null && recoveredType.typeDeclaration.allocation == this.assistNode) {
1460
				resetStacks();
1452
				resetStacks();
1461
				return false;
1453
				return HALT;
1462
			}
1454
			}
1463
		}
1455
		}
1464
	}
1456
	}
1465
	return super.resumeAfterRecovery();
1457
	return super.resumeAfterRecovery(errorRecovery);
1466
}
1458
}
1467
1459
1468
public void selectionIdentifierCheck(){
1460
public void selectionIdentifierCheck(){
Lines 1504-1518 Link Here
1504
	char[] identifierName = this.identifierStack[this.identifierPtr];
1496
	char[] identifierName = this.identifierStack[this.identifierPtr];
1505
	long namePositions = this.identifierPositionStack[this.identifierPtr--];
1497
	long namePositions = this.identifierPositionStack[this.identifierPtr--];
1506
1498
1507
	Argument arg =
1499
	Argument argument =
1508
		new SelectionOnArgumentName(
1500
		new SelectionOnArgumentName(
1509
			identifierName,
1501
			identifierName,
1510
			namePositions,
1502
			namePositions,
1511
			null, // elided type
1503
			null, // elided type
1512
			ClassFileConstants.AccDefault,
1504
			ClassFileConstants.AccDefault,
1513
			true);
1505
			true);
1514
	arg.declarationSourceStart = (int) (namePositions >>> 32);
1506
	argument.declarationSourceStart = (int) (namePositions >>> 32);
1515
	return arg;
1507
	this.assistNode = argument;
1508
	return argument;
1516
}
1509
}
1517
public  String toString() {
1510
public  String toString() {
1518
	String s = Util.EMPTY_STRING;
1511
	String s = Util.EMPTY_STRING;
(-)a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionScanner.java (+4 lines)
Lines 32-37 Link Here
32
	super(false /*comment*/, false /*whitespace*/, false /*nls*/, sourceLevel, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
32
	super(false /*comment*/, false /*whitespace*/, false /*nls*/, sourceLevel, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
33
}
33
}
34
34
35
protected boolean isAtAssistIdentifier() {
36
	return this.selectionStart == this.startPosition && this.selectionEnd == this.currentPosition - 1;
37
}
38
35
public char[] getCurrentIdentifierSource() {
39
public char[] getCurrentIdentifierSource() {
36
40
37
	if (this.selectionIdentifier == null){
41
	if (this.selectionIdentifier == null){
(-)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/Block.java (+9 lines)
Lines 5-10 Link Here
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
 * 
8
 * Contributors:
12
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
13
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contributions for
14
 *     Stephan Herrmann - Contributions for
Lines 27-33 Link Here
27
	public int explicitDeclarations;
31
	public int explicitDeclarations;
28
	// the number of explicit declaration , used to create scope
32
	// the number of explicit declaration , used to create scope
29
	public BlockScope scope;
33
	public BlockScope scope;
34
	public boolean lambdaBody;
30
35
36
public Block(int explicitDeclarations, boolean lambdaBody) {
37
	this.explicitDeclarations = explicitDeclarations;
38
	this.lambdaBody = lambdaBody;
39
}
31
public Block(int explicitDeclarations) {
40
public Block(int explicitDeclarations) {
32
	this.explicitDeclarations = explicitDeclarations;
41
	this.explicitDeclarations = explicitDeclarations;
33
}
42
}
(-)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 (+313 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.Expression;
21
import org.eclipse.jdt.internal.compiler.ast.Statement;
22
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
23
24
public abstract class CommitRollbackParser implements TerminalTokens, ParserBasicInformation {
25
	
26
	// resumeOnSyntaxError codes:
27
	protected static final int HALT = 0;     // halt and throw up hands.
28
	protected static final int RESTART = 1;  // stacks adjusted, alternate goal from check point.
29
	protected static final int RESUME = 2;   // stacks untouched, just continue from where left off.
30
31
	public static byte rhs[] = null;
32
	public static char lhs[] =  null;
33
	public static char term_action[] = null;
34
	public static byte term_check[] = null;
35
	public static char base_action[] = null;
36
	
37
	public ReferenceContext referenceContext;
38
39
40
	// Constants.
41
	protected static final int AstStackIncrement = 100;
42
	protected static final int ExpressionStackIncrement = 100;
43
	protected static final int GenericsStackIncrement = 10;
44
	protected static final int StackIncrement = 255;
45
	protected static final int TypeAnnotationStackIncrement = 100;
46
	
47
	public Scanner scanner;
48
	public int currentToken;
49
	protected int kurrentToken; // copy of currentToken as it is trampled over all over the place :-(
50
	
51
	// -------------  Stack pointers ---------------
52
53
	protected int stateStackTop;
54
	protected int unstackedAct;
55
56
	protected int identifierPtr;
57
	protected int identifierLengthPtr;
58
	
59
	protected int astPtr;
60
	protected int astLengthPtr;
61
	
62
	protected int expressionPtr;
63
	protected int expressionLengthPtr;
64
	
65
	protected int genericsPtr;
66
	protected int genericsLengthPtr;
67
	protected int genericsIdentifiersLengthPtr;
68
	
69
	protected int typeAnnotationPtr;
70
	protected int typeAnnotationLengthPtr;
71
	
72
	protected int intPtr;
73
	protected int nestedType;
74
	protected int realBlockPtr;
75
	public int valueLambdaNestDepth = -1;
76
	
77
	// ---------------- Stacks ----------------
78
	
79
	protected int[] stack = new int[StackIncrement];
80
	
81
	protected char[][] identifierStack;
82
	protected int[] identifierLengthStack;
83
	protected long[] identifierPositionStack;
84
85
	protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
86
	protected int[] astLengthStack;
87
	
88
	protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
89
	protected int[] expressionLengthStack;
90
91
	protected ASTNode[] genericsStack = new ASTNode[GenericsStackIncrement];
92
	protected int[] genericsLengthStack = new int[GenericsStackIncrement];
93
	protected int[] genericsIdentifiersLengthStack = new int[GenericsStackIncrement];
94
	
95
	protected Annotation [] typeAnnotationStack = new Annotation[TypeAnnotationStackIncrement];
96
	protected int [] typeAnnotationLengthStack;
97
	
98
	protected int[] intStack;
99
	protected int[] nestedMethod;
100
	protected int[] realBlockStack;
101
	protected int stateStackLengthStack[] = new int[0];
102
	protected int[] variablesCounter;
103
	
104
	// Loose variables.
105
	
106
	protected int listLength;
107
	protected int listTypeParameterLength;
108
	protected int modifiers;
109
	protected int modifiersSourceStart;
110
	protected int dimensions;
111
	protected int recoveredStaticInitializerStart;
112
	
113
	public CommitRollbackParser cryogenicallyFrozenParser;
114
	private static final int[] RECOVERY_TOKENS = new int [] { TokenNameSEMICOLON, TokenNameRPAREN,};
115
	
116
	public void copyState(CommitRollbackParser parser) {
117
118
		// Stack pointers.
119
		
120
		this.stateStackTop = parser.stateStackTop;
121
		this.unstackedAct = parser.unstackedAct;
122
		this.identifierPtr = parser.identifierPtr;
123
		this.identifierLengthPtr = parser.identifierLengthPtr;
124
		this.astPtr = parser.astPtr;
125
		this.astLengthPtr = parser.astLengthPtr;
126
		this.expressionPtr = parser.expressionPtr;
127
		this.expressionLengthPtr = parser.expressionLengthPtr;
128
		this.genericsPtr = parser.genericsPtr;
129
		this.genericsLengthPtr = parser.genericsLengthPtr;
130
		this.genericsIdentifiersLengthPtr = parser.genericsIdentifiersLengthPtr;
131
		this.typeAnnotationPtr = parser.typeAnnotationPtr;
132
		this.typeAnnotationLengthPtr = parser.typeAnnotationLengthPtr;
133
		this.intPtr = parser.intPtr;
134
		this.nestedType = parser.nestedType;
135
		this.realBlockPtr = parser.realBlockPtr;
136
		this.valueLambdaNestDepth = parser.valueLambdaNestDepth;
137
		
138
		// Stacks.
139
		
140
		int length;
141
		System.arraycopy(parser.stack, 0, this.stack = new int [length = parser.stack.length], 0, length);
142
		System.arraycopy(parser.identifierStack, 0, this.identifierStack = new char [length = parser.identifierStack.length][], 0, length);
143
		System.arraycopy(parser.identifierLengthStack, 0, this.identifierLengthStack = new int [length = parser.identifierLengthStack.length], 0, length);
144
		System.arraycopy(parser.identifierPositionStack, 0, this.identifierPositionStack = new long[length = parser.identifierPositionStack.length], 0, length);
145
		System.arraycopy(parser.astStack, 0, this.astStack = new ASTNode [length = parser.astStack.length], 0, length);
146
		System.arraycopy(parser.astLengthStack, 0, this.astLengthStack = new int [length = parser.astLengthStack.length], 0, length);
147
		System.arraycopy(parser.expressionStack, 0, this.expressionStack = new Expression [length = parser.expressionStack.length], 0, length);
148
		System.arraycopy(parser.expressionLengthStack, 0, this.expressionLengthStack = new int [length = parser.expressionLengthStack.length], 0, length);
149
		System.arraycopy(parser.genericsStack, 0, this.genericsStack = new ASTNode [length = parser.genericsStack.length], 0, length);
150
		System.arraycopy(parser.genericsLengthStack, 0, this.genericsLengthStack = new int [length = parser.genericsLengthStack.length], 0, length);
151
		System.arraycopy(parser.genericsIdentifiersLengthStack, 0, this.genericsIdentifiersLengthStack = new int [length = parser.genericsIdentifiersLengthStack.length], 0, length);
152
		System.arraycopy(parser.typeAnnotationStack, 0, this.typeAnnotationStack = new Annotation [length = parser.typeAnnotationStack.length], 0, length);
153
		System.arraycopy(parser.typeAnnotationLengthStack, 0, this.typeAnnotationLengthStack = new int [length = parser.typeAnnotationLengthStack.length], 0, length);
154
		System.arraycopy(parser.intStack, 0, this.intStack = new int [length = parser.intStack.length], 0, length);
155
		System.arraycopy(parser.nestedMethod, 0, this.nestedMethod = new int [length = parser.nestedMethod.length], 0, length);
156
		System.arraycopy(parser.realBlockStack, 0, this.realBlockStack = new int [length = parser.realBlockStack.length], 0, length);
157
		System.arraycopy(parser.stateStackLengthStack, 0, this.stateStackLengthStack = new int [length = parser.stateStackLengthStack.length], 0, length);
158
		System.arraycopy(parser.variablesCounter, 0, this.variablesCounter = new int [length = parser.variablesCounter.length], 0, length);
159
		System.arraycopy(parser.stack, 0, this.stack = new int [length = parser.stack.length], 0, length);
160
		System.arraycopy(parser.stack, 0, this.stack = new int [length = parser.stack.length], 0, length);
161
		System.arraycopy(parser.stack, 0, this.stack = new int [length = parser.stack.length], 0, length);
162
163
		// Loose variables.
164
		
165
		this.listLength = parser.listLength;
166
		this.listTypeParameterLength = parser.listTypeParameterLength;
167
		this.dimensions = parser.dimensions;
168
		this.recoveredStaticInitializerStart = parser.recoveredStaticInitializerStart;
169
170
		// Parser.resetStacks is not clearing the modifiers, but AssistParser.resumeAfterRecovery is - why ? (the former doesn't)
171
		// this.modifiers = parser.modifiers;
172
		// this.modifiersSourceStart = parser.modifiersSourceStart;
173
	}
174
	
175
	protected CommitRollbackParser createSnapShotParser() {
176
		return new Parser();
177
	}
178
	
179
	/* Must be called from Parser.parse ONLY. Rule reduction routine must simply set the flag to request commit. 
180
	   This ensures the end state of chain rule reductions gets committed rather than some intermediate state.
181
	   See the reduce do-while loop.
182
	*/
183
	protected void commit() {
184
		if (this.cryogenicallyFrozenParser == null) {
185
			this.cryogenicallyFrozenParser = createSnapShotParser();
186
		}
187
		this.cryogenicallyFrozenParser.copyState(this);
188
	}
189
	
190
	protected int getNextToken() {
191
		try {
192
			return this.scanner.getNextToken();
193
		} catch (InvalidInputException e) {
194
			return TokenNameEOF;
195
		}
196
	}
197
	
198
	protected void shouldStackAssistNode() {
199
		// Not relevant here.
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
		boolean atCompletionSite = false;
205
		int lastAction = this.stack[this.stateStackTop];
206
				
207
		// If triggered fake EOF at completion site, see if the real next token would have passed muster.
208
		if (this.kurrentToken == TokenNameEOF) {
209
			if (this.scanner.eofPosition < this.scanner.source.length) {
210
				atCompletionSite = true;
211
				this.scanner.eofPosition = this.scanner.source.length;
212
				nextToken = getNextToken();
213
				if (automatonWillShift(nextToken, lastAction)) {
214
					this.currentToken = this.kurrentToken = nextToken;
215
					return RESUME;
216
				}
217
			} else {
218
				nextToken = TokenNameEOF;
219
			}
220
		} else {
221
			nextToken = this.kurrentToken;
222
		}
223
		if (nextToken == TokenNameEOF)
224
			return HALT; // don't know how to proceed.
225
		this.scanner.ungetToken(nextToken); // spit out what has been bitten more than we can chew.
226
		// OK, next token is no good to resume "in place", attempt some local repair.
227
		for (int i = 0, length = RECOVERY_TOKENS.length; i < length; i++) {
228
			if (automatonWillShift(RECOVERY_TOKENS[i], lastAction)) {
229
				this.currentToken = this.kurrentToken = RECOVERY_TOKENS[i];
230
				return RESUME;
231
			}
232
		}
233
		// OK, no in place resumption, no local repair, fast forward to next statement.
234
		if (this.cryogenicallyFrozenParser == null)
235
			return RESTART;
236
237
		this.copyState(this.cryogenicallyFrozenParser);
238
		if (atCompletionSite) {
239
			this.currentToken = TokenNameSEMICOLON;
240
			shouldStackAssistNode();
241
			return RESUME;
242
		}
243
		this.currentToken = this.scanner.fastForward(unused);
244
		return RESUME;
245
	}
246
247
	protected void resetStacks() {
248
	
249
		this.astPtr = -1;
250
		this.astLengthPtr = -1;
251
		this.expressionPtr = -1;
252
		this.expressionLengthPtr = -1;
253
		this.typeAnnotationLengthPtr = -1;
254
		this.typeAnnotationPtr = -1;
255
		this.identifierPtr = -1;
256
		this.identifierLengthPtr	= -1;
257
		this.intPtr = -1;
258
		
259
		this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse
260
		this.variablesCounter[this.nestedType] = 0;
261
		
262
		this.dimensions = 0 ;
263
		this.realBlockStack[this.realBlockPtr = 0] = 0;
264
		this.recoveredStaticInitializerStart = 0;
265
		this.listLength = 0;
266
		this.listTypeParameterLength = 0;
267
	
268
		this.genericsIdentifiersLengthPtr = -1;
269
		this.genericsLengthPtr = -1;
270
		this.genericsPtr = -1;
271
		this.valueLambdaNestDepth = -1;
272
	}
273
274
	protected boolean automatonWillShift(int token, int lastAction) {
275
		int stackTop = this.stateStackTop;        // local copy of stack pointer
276
		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.
277
		int highWaterMark = stackTop;
278
		// A rotated version of the automaton - cf. parse()'s for(;;)
279
		for (;;) {  
280
			if (lastAction > ERROR_ACTION) {  
281
				lastAction -= ERROR_ACTION;    /* shift-reduce on loop entry from above, reduce on loop back */
282
				do { /* reduce */
283
					stackTop -= rhs[lastAction] - 1;
284
					if (stackTop < highWaterMark) {
285
						stackTopState = this.stack[highWaterMark = stackTop];
286
					} // else stackTopState is upto date already.
287
					lastAction = ntAction(stackTopState, lhs[lastAction]);
288
				} while (lastAction <= NUM_RULES);
289
			}
290
			highWaterMark = ++stackTop;
291
			stackTopState = lastAction; // "push"
292
			lastAction = tAction(lastAction, token); // can be looked up from a precomputed cache.
293
			if (lastAction <= NUM_RULES) {
294
				stackTop --; 
295
			    lastAction += ERROR_ACTION;
296
				continue;
297
			}
298
			// Error => false, Shift, Shift/Reduce => true, Accept => impossible. 
299
			return lastAction != ERROR_ACTION;
300
		}
301
	}
302
303
public static int tAction(int state, int sym) {
304
	return term_action[term_check[base_action[state]+sym] == sym ? base_action[state] + sym : base_action[state]];
305
}
306
307
public static int ntAction(int state, int sym) {
308
	return base_action[state + sym];
309
}
310
311
312
}
313
(-)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 (-236 / +63 lines)
Lines 45-51 Link Here
45
45
46
import org.eclipse.jdt.core.compiler.CharOperation;
46
import org.eclipse.jdt.core.compiler.CharOperation;
47
import org.eclipse.jdt.core.compiler.InvalidInputException;
47
import org.eclipse.jdt.core.compiler.InvalidInputException;
48
import org.eclipse.jdt.internal.codeassist.impl.AssistParser;
49
import org.eclipse.jdt.internal.compiler.ASTVisitor;
48
import org.eclipse.jdt.internal.compiler.ASTVisitor;
50
import org.eclipse.jdt.internal.compiler.CompilationResult;
49
import org.eclipse.jdt.internal.compiler.CompilationResult;
51
import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
50
import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
Lines 159-165 Link Here
159
import org.eclipse.jdt.internal.compiler.util.Messages;
158
import org.eclipse.jdt.internal.compiler.util.Messages;
160
import org.eclipse.jdt.internal.compiler.util.Util;
159
import org.eclipse.jdt.internal.compiler.util.Util;
161
160
162
public class Parser implements ConflictedParser, ParserBasicInformation, TerminalTokens, OperatorIds, TypeIds {
161
public class Parser extends CommitRollbackParser implements ConflictedParser, OperatorIds, TypeIds {
163
	
162
	
164
	protected static final int THIS_CALL = ExplicitConstructorCall.This;
163
	protected static final int THIS_CALL = ExplicitConstructorCall.This;
165
	protected static final int SUPER_CALL = ExplicitConstructorCall.Super;
164
	protected static final int SUPER_CALL = ExplicitConstructorCall.Super;
Lines 168-176 Link Here
168
	
167
	
169
	public static char asb[] = null;
168
	public static char asb[] = null;
170
	public static char asr[] = null;
169
	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;
170
	public static final int BracketKinds = 3;
175
171
176
	public static short check_table[] = null;
172
	public static short check_table[] = null;
Lines 179-193 Link Here
179
	private static final boolean DEBUG_AUTOMATON = false;
175
	private static final boolean DEBUG_AUTOMATON = false;
180
	private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
176
	private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
181
	private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
177
	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$
178
	private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
188
    public static char in_symb[] = null;
179
    public static char in_symb[] = null;
189
	private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
180
	private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
190
	public static char lhs[] =  null;
191
181
192
	public static String name[] = null;
182
	public static String name[] = null;
193
	public static char nasb[] = null;
183
	public static char nasb[] = null;
Lines 197-203 Link Here
197
187
198
	public static String readableName[] = null;
188
	public static String readableName[] = null;
199
189
200
	public static byte rhs[] = null;
201
190
202
	public static int[] reverse_index = null;
191
	public static int[] reverse_index = null;
203
	public static char[] recovery_templates_index = null;
192
	public static char[] recovery_templates_index = null;
Lines 219-229 Link Here
219
    public static char scope_suffix[] = null;
208
    public static char scope_suffix[] = null;
220
	public static final int SquareBracket = 1;
209
	public static final int SquareBracket = 1;
221
210
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
211
228
	public static char terminal_index[] = null;
212
	public static char terminal_index[] = null;
229
213
Lines 737-745 Link Here
737
	public static int nasi(int state) {
721
	public static int nasi(int state) {
738
		return nasb[original_state(state)];
722
		return nasb[original_state(state)];
739
	}
723
	}
740
	public static int ntAction(int state, int sym) {
741
		return base_action[state + sym];
742
	}
743
	protected static int original_state(int state) {
724
	protected static int original_state(int state) {
744
		return -base_check(state);
725
		return -base_check(state);
745
	}
726
	}
Lines 885-949 Link Here
885
		}
866
		}
886
		return chars;
867
		return chars;
887
	}
868
	}
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()*/
869
	public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
897
870
898
	protected RecoveredElement currentElement;
871
	protected RecoveredElement currentElement;
899
	public int currentToken;
872
	
900
	protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
873
	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...]
874
	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)
875
	protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
903
	protected int endStatementPosition;
876
	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
877
	public int firstToken ; // handle for multiple parsing goals
909
	
878
	
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;
879
	protected boolean hasError;
934
	protected boolean hasReportedError;
880
	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;
881
	protected boolean ignoreNextOpeningBrace;
942
882
943
	//positions , dimensions , .... (int stacks)
944
	protected int intPtr;
945
946
	protected int[] intStack;
947
	public int lastAct ; //handle for multiple parsing goals
883
	public int lastAct ; //handle for multiple parsing goals
948
	//error recovery management
884
	//error recovery management
949
	protected int lastCheckPoint;
885
	protected int lastCheckPoint;
Lines 951-968 Link Here
951
	protected int lastErrorEndPositionBeforeRecovery = -1;
887
	protected int lastErrorEndPositionBeforeRecovery = -1;
952
	protected int lastIgnoredToken, nextIgnoredToken;
888
	protected int lastIgnoredToken, nextIgnoredToken;
953
889
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 !
890
	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.......
891
	//modifiers dimensions nestedType etc.......
967
	protected boolean optimizeStringLiterals =true;
892
	protected boolean optimizeStringLiterals =true;
968
	protected CompilerOptions options;
893
	protected CompilerOptions options;
Lines 970-979 Link Here
970
	protected ProblemReporter problemReporter;
895
	protected ProblemReporter problemReporter;
971
896
972
	protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
897
	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;
898
public boolean reportOnlyOneSyntaxError = false;
978
public boolean reportSyntaxErrorIsRequired = true;
899
public boolean reportSyntaxErrorIsRequired = true;
979
protected boolean restartRecovery;
900
protected boolean restartRecovery;
Lines 988-999 Link Here
988
protected TypeDeclaration pendingRecoveredType;
909
protected TypeDeclaration pendingRecoveredType;
989
public RecoveryScanner recoveryScanner;
910
public RecoveryScanner recoveryScanner;
990
//scanner token
911
//scanner token
991
public Scanner scanner;
992
protected int[] stack = new int[StackIncrement];
993
protected int stateStackTop;
994
protected int synchronizedBlockSourceStart;
912
protected int synchronizedBlockSourceStart;
995
996
protected int[] variablesCounter;
997
913
998
protected boolean checkExternalizeStrings;
914
protected boolean checkExternalizeStrings;
999
915
Lines 1004-1026 Link Here
1004
// used for recovery
920
// used for recovery
1005
protected int lastJavadocEnd;
921
protected int lastJavadocEnd;
1006
public org.eclipse.jdt.internal.compiler.ReadManager readManager;
922
public org.eclipse.jdt.internal.compiler.ReadManager readManager;
1007
private int valueLambdaNestDepth = -1;
923
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;
924
private boolean haltOnSyntaxError = false;
1012
private boolean tolerateDefaultClassMethods = false;
925
private boolean tolerateDefaultClassMethods = false;
1013
private boolean processingLambdaParameterList = false;
926
private boolean processingLambdaParameterList = false;
1014
private boolean expectTypeAnnotation = false;
927
private boolean expectTypeAnnotation = false;
1015
928
1016
// resumeOnSyntaxError codes:
929
public Parser () {
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
1023
protected Parser () {
1024
	// Caveat Emptor: For inheritance purposes and then only in very special needs. Only minimal state is initialized !
930
	// Caveat Emptor: For inheritance purposes and then only in very special needs. Only minimal state is initialized !
1025
}
931
}
1026
public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
932
public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
Lines 2251-2257 Link Here
2251
	pushOnAstStack(block);
2157
	pushOnAstStack(block);
2252
}
2158
}
2253
protected void consumeBlockStatement() {
2159
protected void consumeBlockStatement() {
2254
	// todo.
2160
	// for assist parsers.
2255
}
2161
}
2256
protected void consumeBlockStatements() {
2162
protected void consumeBlockStatements() {
2257
	// BlockStatements ::= BlockStatements BlockStatement
2163
	// BlockStatements ::= BlockStatements BlockStatement
Lines 7855-7871 Link Here
7855
	pushOnIntStack(0);  // signal explicit this
7761
	pushOnIntStack(0);  // signal explicit this
7856
}
7762
}
7857
7763
7764
protected boolean isAssistParser() {
7765
	return false;
7766
}
7858
protected void consumeNestedLambda() {
7767
protected void consumeNestedLambda() {
7859
	// NestedLambda ::= $empty - we get here just after the type+parenthesis elided singleton parameter or just before the '(' of the parameter list. 
7768
	// NestedLambda ::= $empty - we get here just after the type+parenthesis elided singleton parameter or just before the '(' of the parameter list. 
7860
	consumeNestedType();
7769
	consumeNestedType();
7861
	this.nestedMethod[this.nestedType] ++;
7770
	this.nestedMethod[this.nestedType] ++;
7862
	LambdaExpression lambda = new LambdaExpression(this.compilationUnit.compilationResult, this instanceof AssistParser);
7771
	LambdaExpression lambda = new LambdaExpression(this.compilationUnit.compilationResult, isAssistParser());
7863
	pushOnAstStack(lambda);
7772
	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;	
7773
	this.processingLambdaParameterList = true;	
7870
}
7774
}
7871
7775
Lines 7896-7911 Link Here
7896
	}
7800
	}
7897
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr];
7801
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr];
7898
	lexp.setArguments(arguments);
7802
	lexp.setArguments(arguments);
7899
	lexp.setArrowPosition(arrowPosition); // '->' position
7803
	lexp.setArrowPosition(arrowPosition);
7900
	lexp.sourceEnd = this.intStack[this.intPtr--];   // ')' position or identifier position.
7804
	lexp.sourceEnd = this.intStack[this.intPtr--];   // ')' position or identifier position.
7901
	lexp.sourceStart = this.intStack[this.intPtr--]; // '(' position or identifier position.
7805
	lexp.sourceStart = this.intStack[this.intPtr--]; // '(' position or identifier position.
7902
	lexp.hasParentheses = (this.scanner.getSource()[lexp.sourceStart] == '(');
7806
	lexp.hasParentheses = (this.scanner.getSource()[lexp.sourceStart] == '(');
7903
	this.listLength = 0; // reset this.listLength after having read all parameters
7807
	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;
7808
	this.processingLambdaParameterList = false;
7809
	if (this.currentElement != null) {
7810
		this.lastCheckPoint = arrowPosition + 1;
7811
//		this.ignoreNextOpeningBrace = true;
7812
//		this.currentElement.bracketBalance++;
7813
	}
7909
}
7814
}
7910
protected void consumeLambdaExpression() {
7815
protected void consumeLambdaExpression() {
7911
	
7816
	
Lines 7919-7924 Link Here
7919
		if (this.options.ignoreMethodBodies) {
7824
		if (this.options.ignoreMethodBodies) {
7920
			body = new Block(0);
7825
			body = new Block(0);
7921
		}
7826
		}
7827
		((Block) body).lambdaBody = true; // for consistency's sakes.
7922
	}
7828
	}
7923
7829
7924
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr--];
7830
	LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr--];
Lines 7935-7944 Link Here
7935
	}
7841
	}
7936
	pushOnExpressionStack(lexp);
7842
	pushOnExpressionStack(lexp);
7937
	if (this.currentElement != null) {
7843
	if (this.currentElement != null) {
7938
		if (this.currentElement.parseTree() == lexp && this.currentElement.parent != null) {
7844
		this.lastCheckPoint = body.sourceEnd + 1;
7939
			this.currentElement = this.currentElement.parent;
7845
//		if (body instanceof Expression)
7940
		}
7846
//		    this.currentElement.bracketBalance --;
7941
		this.lastCheckPoint = lexp.sourceEnd + 1;
7942
	}
7847
	}
7943
}
7848
}
7944
7849
Lines 7984-7992 Link Here
7984
		pushOnIntStack(arg.declarationSourceEnd);
7889
		pushOnIntStack(arg.declarationSourceEnd);
7985
	}
7890
	}
7986
	pushOnAstStack(arg);
7891
	pushOnAstStack(arg);
7987
	/* if incomplete method header, this.listLength counter will not have been reset,
7892
	this.listLength++;  // not relevant really.
7988
		indicating that some arguments are available on the stack */
7989
	this.listLength++;
7990
}
7893
}
7991
protected void consumeElidedLeftBraceAndReturn() {
7894
protected void consumeElidedLeftBraceAndReturn() {
7992
	/* ElidedLeftBraceAndReturn ::= $empty
7895
	/* ElidedLeftBraceAndReturn ::= $empty
Lines 8740-8765 Link Here
8740
	optimizedConcatNodeLists();
8643
	optimizedConcatNodeLists();
8741
}
8644
}
8742
protected void consumeToken(int type) {
8645
protected void consumeToken(int type) {
8743
	/* remember the last consumed value */
8744
	/* try to minimize the number of build values */
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) {
8646
	switch (type) {
8764
		case TokenNameARROW:
8647
		case TokenNameARROW:
8765
			consumeLambdaHeader();
8648
			consumeLambdaHeader();
Lines 10464-10487 Link Here
10464
	this.referenceContext = null;
10347
	this.referenceContext = null;
10465
	this.endStatementPosition = 0;
10348
	this.endStatementPosition = 0;
10466
	this.valueLambdaNestDepth = -1;
10349
	this.valueLambdaNestDepth = -1;
10467
10350
	
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;
10351
	int astLength = this.astStack.length;
10472
	if (this.noAstNodes.length < astLength){
10352
	for (int i = 0; i < astLength; i++)
10473
		this.noAstNodes = new ASTNode[astLength];
10353
		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
10354
10479
	int expressionLength = this.expressionStack.length;
10355
	int expressionLength = this.expressionStack.length;
10480
	if (this.noExpressions.length < expressionLength){
10356
	for (int i = 0; i < expressionLength; i++)
10481
		this.noExpressions = new Expression[expressionLength];
10357
		this.expressionStack[i] = null;
10482
		//System.out.println("Resized EXPR stacks : "+ expressionLength);
10483
	}
10484
	System.arraycopy(this.noExpressions, 0, this.expressionStack, 0, expressionLength);
10485
10358
10486
	// reset this.scanner state
10359
	// reset this.scanner state
10487
	this.scanner.commentPtr = -1;
10360
	this.scanner.commentPtr = -1;
Lines 10797-10837 Link Here
10797
	         
10670
	         
10798
	    Though this code looks complex, we should exit early in most situations.     
10671
	    Though this code looks complex, we should exit early in most situations.     
10799
	 */
10672
	 */
10800
	int lastAction = this.unstackedAct;
10673
	if (this.unstackedAct == ERROR_ACTION) { // automaton is not running.
10801
	if (lastAction == ERROR_ACTION) { // automaton is not running.
10802
		return false;
10674
		return false;
10803
	}
10675
	}
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) {
10676
	if (token != TokenNameAT) {
10809
		token = token == TokenNameLPAREN ? TokenNameBeginLambda : TokenNameBeginTypeArguments;
10677
		token = token == TokenNameLPAREN ? TokenNameBeginLambda : TokenNameBeginTypeArguments;
10810
	}
10678
	}
10811
	
10679
	
10812
	// A rotated version of the automaton - cf. parse()'s for(;;)
10680
	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
}
10681
}
10836
/*main loop of the automat
10682
/*main loop of the automat
10837
When a rule is reduced, the method consumeRule(int) is called with the number
10683
When a rule is reduced, the method consumeRule(int) is called with the number
Lines 10852-10857 Link Here
10852
10698
10853
	this.hasReportedError = false;
10699
	this.hasReportedError = false;
10854
	int act = START_STATE;
10700
	int act = START_STATE;
10701
	this.unstackedAct = ERROR_ACTION;
10855
	this.stateStackTop = -1;
10702
	this.stateStackTop = -1;
10856
	this.currentToken = getFirstToken();
10703
	this.currentToken = getFirstToken();
10857
	
10704
	
Lines 10866-10873 Link Here
10866
				stackLength);
10713
				stackLength);
10867
		}
10714
		}
10868
		this.stack[this.stateStackTop] = act;
10715
		this.stack[this.stateStackTop] = act;
10869
10716
		this.unstackedAct = act = tAction(act, this.currentToken);
10870
		act = tAction(act, this.currentToken);
10871
		if (act == ERROR_ACTION || this.restartRecovery) {
10717
		if (act == ERROR_ACTION || this.restartRecovery) {
10872
			if (DEBUG_AUTOMATON) {
10718
			if (DEBUG_AUTOMATON) {
10873
				if (this.restartRecovery) {
10719
				if (this.restartRecovery) {
Lines 10879-10901 Link Here
10879
10725
10880
			int errorPos = this.scanner.currentPosition - 1;
10726
			int errorPos = this.scanner.currentPosition - 1;
10881
			if (!this.hasReportedError) {
10727
			if (!this.hasReportedError) {
10882
				this.hasError = true;  // looks incorrect for recovery case ?
10728
				this.hasError = true;
10883
			}
10729
			}
10884
			int previousToken = this.currentToken;
10730
			this.kurrentToken = this.currentToken;
10885
			switch (resumeOnSyntaxError()) {
10731
			switch (resumeOnErrorOrTriggeredRecovery(act == ERROR_ACTION)) {
10886
				case HALT:
10732
				case HALT:
10887
					act = ERROR_ACTION;
10733
					act = ERROR_ACTION;
10888
					break ProcessTerminals;
10734
					break ProcessTerminals;
10889
				case RESTART:
10735
				case RESTART:
10890
					if (act == ERROR_ACTION && previousToken != 0) this.lastErrorEndPosition = errorPos;
10736
					if (act == ERROR_ACTION && this.kurrentToken != 0) this.lastErrorEndPosition = errorPos;
10891
					act = START_STATE;
10737
					act = START_STATE;
10892
					this.stateStackTop = -1;
10738
					this.stateStackTop = -1;
10893
					this.currentToken = getFirstToken();
10739
					this.currentToken = getFirstToken();
10894
					continue ProcessTerminals;
10740
					continue ProcessTerminals;
10895
				case RESUME:
10741
				case RESUME:
10896
					break; // We presume the world is virgin so we can continue exactly from where we left off.
10742
					if (act == ERROR_ACTION) {
10897
				default:
10743
						act = this.stack[this.stateStackTop--];
10898
					throw new IllegalStateException();
10744
						continue ProcessTerminals;
10745
					} else {
10746
						this.currentToken = this.kurrentToken; // Gets trashed all over the place.
10747
					}
10748
					// FALL THROUGH.
10899
			}
10749
			}
10900
		}
10750
		}
10901
		if (act <= NUM_RULES) {
10751
		if (act <= NUM_RULES) {
Lines 10914-10920 Link Here
10914
				this.recordStringLiterals = oldValue;
10764
				this.recordStringLiterals = oldValue;
10915
			}
10765
			}
10916
			try {
10766
			try {
10917
				this.unstackedAct = act;
10918
				this.currentToken = this.scanner.getNextToken();
10767
				this.currentToken = this.scanner.getNextToken();
10919
			} catch(InvalidInputException e){
10768
			} catch(InvalidInputException e){
10920
				if (!this.hasReportedError){
10769
				if (!this.hasReportedError){
Lines 10924-10936 Link Here
10924
				this.lastCheckPoint = this.scanner.currentPosition;
10773
				this.lastCheckPoint = this.scanner.currentPosition;
10925
				this.currentToken = 0;
10774
				this.currentToken = 0;
10926
				this.restartRecovery = true;
10775
				this.restartRecovery = true;
10927
			} finally {
10776
			} 
10928
				this.unstackedAct = ERROR_ACTION;
10929
			}
10930
			if(this.statementRecoveryActivated) {
10777
			if(this.statementRecoveryActivated) {
10931
				jumpOverType();
10778
				jumpOverType();
10932
			}
10779
			}
10933
			act -= ERROR_ACTION;
10780
			this.unstackedAct = act -= ERROR_ACTION;
10934
10781
10935
			if (DEBUG_AUTOMATON) {
10782
			if (DEBUG_AUTOMATON) {
10936
				System.out.print("Shift/Reduce - (" + name[terminal_index[this.currentToken]]+") ");  //$NON-NLS-1$  //$NON-NLS-2$
10783
				System.out.print("Shift/Reduce - (" + name[terminal_index[this.currentToken]]+") ");  //$NON-NLS-1$  //$NON-NLS-2$
Lines 10946-10952 Link Here
10946
					this.recordStringLiterals = oldValue;
10793
					this.recordStringLiterals = oldValue;
10947
				}
10794
				}
10948
				try{
10795
				try{
10949
					this.unstackedAct = act;
10950
					this.currentToken = this.scanner.getNextToken();
10796
					this.currentToken = this.scanner.getNextToken();
10951
				} catch(InvalidInputException e){
10797
				} catch(InvalidInputException e){
10952
					if (!this.hasReportedError){
10798
					if (!this.hasReportedError){
Lines 10956-10963 Link Here
10956
					this.lastCheckPoint = this.scanner.currentPosition;
10802
					this.lastCheckPoint = this.scanner.currentPosition;
10957
					this.currentToken = 0;
10803
					this.currentToken = 0;
10958
					this.restartRecovery = true;
10804
					this.restartRecovery = true;
10959
				} finally {
10960
					this.unstackedAct = ERROR_ACTION;
10961
				}
10805
				}
10962
				if(this.statementRecoveryActivated) {
10806
				if(this.statementRecoveryActivated) {
10963
					jumpOverType();
10807
					jumpOverType();
Lines 10978-10985 Link Here
10978
			}
10822
			}
10979
10823
10980
			this.stateStackTop -= (rhs[act] - 1);
10824
			this.stateStackTop -= (rhs[act] - 1);
10825
			this.unstackedAct = ntAction(this.stack[this.stateStackTop], lhs[act]);
10981
			consumeRule(act);
10826
			consumeRule(act);
10982
			act = ntAction(this.stack[this.stateStackTop], lhs[act]);
10827
			act = this.unstackedAct;
10983
10828
10984
			if (DEBUG_AUTOMATON) {
10829
			if (DEBUG_AUTOMATON) {
10985
				if (act <= NUM_RULES) {
10830
				if (act <= NUM_RULES) {
Lines 10994-10999 Link Here
10994
		}
10839
		}
10995
	}
10840
	}
10996
} finally {
10841
} finally {
10842
	this.unstackedAct = ERROR_ACTION;
10997
	this.scanner.setActiveParser(null);
10843
	this.scanner.setActiveParser(null);
10998
}
10844
}
10999
10845
Lines 11993-11998 Link Here
11993
	}
11839
	}
11994
}
11840
}
11995
11841
11842
public boolean requireExtendedRecovery() {
11843
	return false; // for assist parsers.
11844
}
11845
11846
public void startRecovery() {
11847
	this.restartRecovery = true;
11848
}
11849
11996
public void recoveryExitFromVariable() {
11850
public void recoveryExitFromVariable() {
11997
	if(this.currentElement != null && this.currentElement.parent != null) {
11851
	if(this.currentElement != null && this.currentElement.parent != null) {
11998
		if(this.currentElement instanceof RecoveredLocalVariable) {
11852
		if(this.currentElement instanceof RecoveredLocalVariable) {
Lines 12152-12190 Link Here
12152
}
12006
}
12153
/*
12007
/*
12154
 * Reset context so as to resume to regular parse loop
12008
 * 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.
12009
 * If unable to reset for resuming, answers false.
12183
 *
12010
 *
12184
 * Move checkpoint location, reset internal stacks and
12011
 * Move checkpoint location, reset internal stacks and
12185
 * decide which grammar goal is activated.
12012
 * decide which grammar goal is activated.
12186
 */
12013
 */
12187
protected boolean resumeAfterRecovery() {
12014
protected int resumeAfterRecovery(boolean errorRecovery) {
12188
	if(!this.methodRecoveryActivated && !this.statementRecoveryActivated) {
12015
	if(!this.methodRecoveryActivated && !this.statementRecoveryActivated) {
12189
12016
12190
		// reset internal stacks
12017
		// reset internal stacks
Lines 12193-12210 Link Here
12193
12020
12194
		/* attempt to move checkpoint location */
12021
		/* attempt to move checkpoint location */
12195
		if (!moveRecoveryCheckpoint()) {
12022
		if (!moveRecoveryCheckpoint()) {
12196
			return false;
12023
			return HALT;
12197
		}
12024
		}
12198
12025
12199
		// only look for headers
12026
		// only look for headers
12200
		if (this.referenceContext instanceof CompilationUnitDeclaration){
12027
		if (this.referenceContext instanceof CompilationUnitDeclaration){
12201
			goForHeaders();
12028
			goForHeaders();
12202
			this.diet = true; // passed this point, will not consider method bodies
12029
			this.diet = true; // passed this point, will not consider method bodies
12203
			return true;
12030
			return RESTART;
12204
		}
12031
		}
12205
12032
12206
		// does not know how to restart
12033
		// does not know how to restart
12207
		return false;
12034
		return HALT;
12208
	} else if(!this.statementRecoveryActivated) {
12035
	} else if(!this.statementRecoveryActivated) {
12209
12036
12210
		// reset internal stacks
12037
		// reset internal stacks
Lines 12213-12229 Link Here
12213
12040
12214
		/* attempt to move checkpoint location */
12041
		/* attempt to move checkpoint location */
12215
		if (!moveRecoveryCheckpoint()) {
12042
		if (!moveRecoveryCheckpoint()) {
12216
			return false;
12043
			return HALT;
12217
		}
12044
		}
12218
12045
12219
		// only look for headers
12046
		// only look for headers
12220
		goForHeaders();
12047
		goForHeaders();
12221
		return true;
12048
		return RESTART;
12222
	} else {
12049
	} else {
12223
		return false;
12050
		return HALT;
12224
	}
12051
	}
12225
}
12052
}
12226
protected int resumeOnSyntaxError() {
12053
protected int resumeOnErrorOrTriggeredRecovery(boolean errorRecovery) {
12227
	if (this.haltOnSyntaxError)
12054
	if (this.haltOnSyntaxError)
12228
		return HALT;
12055
		return HALT;
12229
	/* request recovery initialization */
12056
	/* request recovery initialization */
Lines 12260-12266 Link Here
12260
	}
12087
	}
12261
12088
12262
	/* attempt to reset state in order to resume to parse loop */
12089
	/* attempt to reset state in order to resume to parse loop */
12263
	return resumeAfterRecovery() ? RESTART : HALT;
12090
	return resumeAfterRecovery(errorRecovery);
12264
}
12091
}
12265
public void setMethodsFullRecovery(boolean enabled) {
12092
public void setMethodsFullRecovery(boolean enabled) {
12266
	this.options.performMethodsFullRecovery = enabled;
12093
	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 / +33 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 22-28 Link Here
22
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
19
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
23
import org.eclipse.jdt.internal.compiler.ast.Block;
20
import org.eclipse.jdt.internal.compiler.ast.Block;
24
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
21
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;
22
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
27
import org.eclipse.jdt.internal.compiler.ast.Statement;
23
import org.eclipse.jdt.internal.compiler.ast.Statement;
28
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
24
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
Lines 59-72 Link Here
59
		}
55
		}
60
	}
56
	}
61
	return super.add(methodDeclaration, bracketBalanceValue);
57
	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
}
58
}
71
/*
59
/*
72
 * Record a nested block declaration
60
 * Record a nested block declaration
Lines 295-300 Link Here
295
283
296
	// if block was not marked to be preserved or empty, then ignore it
284
	// if block was not marked to be preserved or empty, then ignore it
297
	if (!this.preserveContent || this.statementCount == 0) return null;
285
	if (!this.preserveContent || this.statementCount == 0) return null;
286
	
287
	/* If this block stands for the lambda body, trash the contents. Lambda expressions are recovered as part of the enclosing statement.
288
	   We still have left in a block here to make sure that contained elements can be trapped and tossed out.
289
	*/
290
	if (this.blockDeclaration.lambdaBody) return null; 
298
291
299
	Statement[] updatedStatements = new Statement[this.statementCount];
292
	Statement[] updatedStatements = new Statement[this.statementCount];
300
	int updatedCount = 0;
293
	int updatedCount = 0;
Lines 340-345 Link Here
340
		Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes);
333
		Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes);
341
		if (updatedStatement != null){
334
		if (updatedStatement != null){
342
			updatedStatements[updatedCount++] = updatedStatement;
335
			updatedStatements[updatedCount++] = updatedStatement;
336
			
337
			/* Statements inside lambda body have been collected into a block attached to this block. 
338
			   Replace the lambda block if we see a sibling statement that completely subsumes it.
339
			   See (Assist)consumeBlockStatement(s)
340
			*/
341
//			if (updatedCount > 1) {
342
//				Statement penultimateStatement = updatedStatements[updatedCount - 2];
343
//				int penultimateStatementStart = penultimateStatement.sourceStart;
344
//				int penultimateStatementEnd = penultimateStatement instanceof AbstractVariableDeclaration ? 
345
//						((AbstractVariableDeclaration) penultimateStatement).declarationSourceEnd : penultimateStatement.sourceEnd;
346
//				int ultimateStatementStart = updatedStatement.sourceStart;
347
//				int ultimateStatementEnd =  updatedStatement instanceof AbstractVariableDeclaration ? 
348
//						((AbstractVariableDeclaration) updatedStatement).declarationSourceEnd : updatedStatement.sourceEnd;
349
//				if (penultimateStatementStart <= ultimateStatementStart && penultimateStatementEnd >= ultimateStatementEnd) {
350
//					updatedCount--;
351
//					continue;
352
//				}
353
//				if (ultimateStatementStart <= penultimateStatementStart && ultimateStatementEnd >= penultimateStatementEnd) {
354
//					updatedStatements[updatedCount - 2] = updatedStatement;
355
//					updatedCount--;
356
//				}
357
//			}
343
358
344
			if (updatedStatement instanceof LocalDeclaration) {
359
			if (updatedStatement instanceof LocalDeclaration) {
345
				LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement;
360
				LocalDeclaration localDeclaration = (LocalDeclaration) updatedStatement;
Lines 431-436 Link Here
431
446
432
	// if block was closed or empty, then ignore it
447
	// if block was closed or empty, then ignore it
433
	if (this.blockDeclaration.sourceEnd != 0 || this.statementCount == 0) return null;
448
	if (this.blockDeclaration.sourceEnd != 0 || this.statementCount == 0) return null;
449
	
450
	/* If this block stands for the lambda body, trash the contents. Lambda expressions are recovered as part of the enclosing statement.
451
	   We still have left in a block here to make sure that contained elements can be trapped and tossed out.
452
	*/
453
	if (this.blockDeclaration.lambdaBody) return null; 
434
454
435
	Statement[] updatedStatements = new Statement[this.statementCount];
455
	Statement[] updatedStatements = new Statement[this.statementCount];
436
	int updatedCount = 0;
456
	int updatedCount = 0;
(-)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 (-6 / +110 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 4332-4338 Link Here
4332
				} else if (act > ERROR_ACTION) { /* shift-reduce */
4342
				} else if (act > ERROR_ACTION) { /* shift-reduce */
4333
					this.unstackedAct = act;
4343
					this.unstackedAct = act;
4334
					try {
4344
					try {
4335
						this.currentToken = this.scanner.getNextToken();
4345
					this.currentToken = this.scanner.getNextToken();
4336
					} finally {
4346
					} finally {
4337
						this.unstackedAct = ERROR_ACTION;
4347
						this.unstackedAct = ERROR_ACTION;
4338
					}
4348
					}
Lines 4341-4347 Link Here
4341
				    if (act < ACCEPT_ACTION) { /* shift */
4351
				    if (act < ACCEPT_ACTION) { /* shift */
4342
				    	this.unstackedAct = act;
4352
				    	this.unstackedAct = act;
4343
						try {
4353
						try {
4344
							this.currentToken = this.scanner.getNextToken();
4354
				    	this.currentToken = this.scanner.getNextToken();
4345
						} finally {
4355
						} finally {
4346
							this.unstackedAct = ERROR_ACTION;
4356
							this.unstackedAct = ERROR_ACTION;
4347
						}
4357
						}
Lines 4493-4496 Link Here
4493
	}
4503
	}
4494
	return token;
4504
	return token;
4495
}
4505
}
4506
4507
protected boolean isAtAssistIdentifier() {
4508
	return false;
4509
}
4510
4511
// Position the scanner at the next block statement and return the start token. We recognize empty statements.
4512
public int fastForward(Statement unused) {
4513
	
4514
	int token;
4515
4516
	while (true) {
4517
		try {
4518
			token = getNextToken();
4519
		} catch (InvalidInputException e) {
4520
			return TokenNameEOF;
4521
		}
4522
		/* FOLLOW map of BlockStatement, since the non-terminal is recursive is a super set of its own FIRST set. 
4523
	   	   We use FOLLOW rather than FIRST since we want to recognize empty statements. i.e if (x > 10) {  x = 0 }
4524
		*/
4525
		switch(token) {
4526
			case TokenNameIdentifier:
4527
				if (isAtAssistIdentifier()) // do not fast forward past the assist identifier ! We don't handle collections as of now.
4528
					return token;
4529
				//$FALL-THROUGH$
4530
			case TokenNameabstract:
4531
			case TokenNameassert:
4532
			case TokenNameboolean:
4533
			case TokenNamebreak:
4534
			case TokenNamebyte:
4535
			case TokenNamecase:
4536
			case TokenNamechar:
4537
			case TokenNameclass:
4538
			case TokenNamecontinue:
4539
			case TokenNamedefault:
4540
			case TokenNamedo:
4541
			case TokenNamedouble:
4542
			case TokenNameenum:
4543
			case TokenNamefalse:
4544
			case TokenNamefinal:
4545
			case TokenNamefloat:
4546
			case TokenNamefor:
4547
			case TokenNameif:
4548
			case TokenNameint:
4549
			case TokenNameinterface:
4550
			case TokenNamelong:
4551
			case TokenNamenative:
4552
			case TokenNamenew:
4553
			case TokenNamenull:
4554
			case TokenNameprivate:
4555
			case TokenNameprotected:
4556
			case TokenNamepublic:
4557
			case TokenNamereturn:
4558
			case TokenNameshort:
4559
			case TokenNamestatic:
4560
			case TokenNamestrictfp:
4561
			case TokenNamesuper:
4562
			case TokenNameswitch:
4563
			case TokenNamesynchronized:
4564
			case TokenNamethis:
4565
			case TokenNamethrow:
4566
			case TokenNametransient:
4567
			case TokenNametrue:
4568
			case TokenNametry:
4569
			case TokenNamevoid:
4570
			case TokenNamevolatile:
4571
			case TokenNamewhile:
4572
			case TokenNameIntegerLiteral: // ??!
4573
			case TokenNameLongLiteral:
4574
			case TokenNameFloatingPointLiteral:
4575
			case TokenNameDoubleLiteral:
4576
			case TokenNameCharacterLiteral:
4577
			case TokenNameStringLiteral:
4578
			case TokenNamePLUS_PLUS:
4579
			case TokenNameMINUS_MINUS:
4580
			case TokenNameLESS:
4581
			case TokenNameLPAREN:
4582
			case TokenNameLBRACE:
4583
			case TokenNameAT:
4584
			case TokenNameBeginLambda:
4585
			case TokenNameAT308:
4586
				if(getVanguardParser().parse(Goal.BlockStatementoptGoal) == VanguardParser.SUCCESS)
4587
					return token;
4588
				break;
4589
			case TokenNameSEMICOLON:
4590
			case TokenNameEOF:
4591
				return token;
4592
			case TokenNameRBRACE: // simulate empty statement.
4593
				ungetToken(token);
4594
				return TokenNameSEMICOLON;
4595
			default:
4596
				break;
4597
		}
4598
	}
4599
}
4496
}
4600
}
(-)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