KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > codeassist > complete > CompletionParser


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.codeassist.complete;
12
13 /*
14  * Parser able to build specific completion parse nodes, given a cursorLocation.
15  *
16  * Cursor location denotes the position of the last character behind which completion
17  * got requested:
18  * -1 means completion at the very beginning of the source
19  * 0 means completion behind the first character
20  * n means completion behind the n-th character
21  */

22 import org.eclipse.jdt.internal.compiler.*;
23 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
24 import org.eclipse.jdt.internal.compiler.env.*;
25
26 import org.eclipse.jdt.internal.compiler.ast.*;
27 import org.eclipse.jdt.internal.compiler.parser.*;
28 import org.eclipse.jdt.internal.compiler.problem.*;
29 import org.eclipse.jdt.internal.compiler.util.Util;
30 import org.eclipse.jdt.core.compiler.CharOperation;
31 import org.eclipse.jdt.internal.codeassist.impl.*;
32
33 public class CompletionParser extends AssistParser {
34     // OWNER
35
protected static final int COMPLETION_PARSER = 1024;
36     protected static final int COMPLETION_OR_ASSIST_PARSER = ASSIST_PARSER + COMPLETION_PARSER;
37
38     // KIND : all values known by CompletionParser are between 1025 and 1549
39
protected static final int K_BLOCK_DELIMITER = COMPLETION_PARSER + 1; // whether we are inside a block
40
protected static final int K_SELECTOR_INVOCATION_TYPE = COMPLETION_PARSER + 2; // whether we are inside a message send
41
protected static final int K_SELECTOR_QUALIFIER = COMPLETION_PARSER + 3; // whether we are inside a message send
42
protected static final int K_BETWEEN_CATCH_AND_RIGHT_PAREN = COMPLETION_PARSER + 4; // whether we are between the keyword 'catch' and the following ')'
43
protected static final int K_NEXT_TYPEREF_IS_CLASS = COMPLETION_PARSER + 5; // whether the next type reference is a class
44
protected static final int K_NEXT_TYPEREF_IS_INTERFACE = COMPLETION_PARSER + 6; // whether the next type reference is an interface
45
protected static final int K_NEXT_TYPEREF_IS_EXCEPTION = COMPLETION_PARSER + 7; // whether the next type reference is an exception
46
protected static final int K_BETWEEN_NEW_AND_LEFT_BRACKET = COMPLETION_PARSER + 8; // whether we are between the keyword 'new' and the following left braket, ie. '[', '(' or '{'
47
protected static final int K_INSIDE_THROW_STATEMENT = COMPLETION_PARSER + 9; // whether we are between the keyword 'throw' and the end of a throw statement
48
protected static final int K_INSIDE_RETURN_STATEMENT = COMPLETION_PARSER + 10; // whether we are between the keyword 'return' and the end of a return statement
49
protected static final int K_CAST_STATEMENT = COMPLETION_PARSER + 11; // whether we are between ')' and the end of a cast statement
50
protected static final int K_LOCAL_INITIALIZER_DELIMITER = COMPLETION_PARSER + 12;
51     protected static final int K_ARRAY_INITIALIZER = COMPLETION_PARSER + 13;
52     protected static final int K_ARRAY_CREATION = COMPLETION_PARSER + 14;
53     protected static final int K_UNARY_OPERATOR = COMPLETION_PARSER + 15;
54     protected static final int K_BINARY_OPERATOR = COMPLETION_PARSER + 16;
55     protected static final int K_ASSISGNMENT_OPERATOR = COMPLETION_PARSER + 17;
56     protected static final int K_CONDITIONAL_OPERATOR = COMPLETION_PARSER + 18;
57     protected static final int K_BETWEEN_IF_AND_RIGHT_PAREN = COMPLETION_PARSER + 19;
58     protected static final int K_BETWEEN_WHILE_AND_RIGHT_PAREN = COMPLETION_PARSER + 20;
59     protected static final int K_BETWEEN_FOR_AND_RIGHT_PAREN = COMPLETION_PARSER + 21;
60     protected static final int K_BETWEEN_SWITCH_AND_RIGHT_PAREN = COMPLETION_PARSER + 22;
61     protected static final int K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN = COMPLETION_PARSER + 23;
62     protected static final int K_INSIDE_ASSERT_STATEMENT = COMPLETION_PARSER + 24;
63     protected static final int K_SWITCH_LABEL= COMPLETION_PARSER + 25;
64     protected static final int K_BETWEEN_CASE_AND_COLON = COMPLETION_PARSER + 26;
65     protected static final int K_BETWEEN_DEFAULT_AND_COLON = COMPLETION_PARSER + 27;
66     protected static final int K_BETWEEN_LEFT_AND_RIGHT_BRACKET = COMPLETION_PARSER + 28;
67     protected static final int K_EXTENDS_KEYWORD = COMPLETION_PARSER + 29;
68     protected static final int K_PARAMETERIZED_METHOD_INVOCATION = COMPLETION_PARSER + 30;
69     protected static final int K_PARAMETERIZED_ALLOCATION = COMPLETION_PARSER + 31;
70     protected static final int K_PARAMETERIZED_CAST = COMPLETION_PARSER + 32;
71     protected static final int K_BETWEEN_ANNOTATION_NAME_AND_RPAREN = COMPLETION_PARSER + 33;
72     protected static final int K_INSIDE_BREAK_STATEMENT = COMPLETION_PARSER + 34;
73     protected static final int K_INSIDE_CONTINUE_STATEMENT = COMPLETION_PARSER + 35;
74     protected static final int K_LABEL = COMPLETION_PARSER + 36;
75     protected static final int K_MEMBER_VALUE_ARRAY_INITIALIZER = COMPLETION_PARSER + 37;
76
77     public final static char[] FAKE_TYPE_NAME = new char[]{' '};
78     public final static char[] FAKE_METHOD_NAME = new char[]{' '};
79     public final static char[] FAKE_ARGUMENT_NAME = new char[]{' '};
80     public final static char[] VALUE = new char[]{'v', 'a', 'l', 'u', 'e'};
81
82     /* public fields */
83
84     public int cursorLocation;
85     public ASTNode assistNodeParent; // the parent node of assist node
86
/* the following fields are internal flags */
87
88     // block kind
89
static final int IF = 1;
90     static final int TRY = 2;
91     static final int CATCH = 3;
92     static final int WHILE = 4;
93     static final int SWITCH = 5;
94     static final int FOR = 6;
95     static final int DO = 7;
96     static final int SYNCHRONIZED = 8;
97
98     // label kind
99
static final int DEFAULT = 1;
100
101     // invocation type constants
102
static final int EXPLICIT_RECEIVER = 0;
103     static final int NO_RECEIVER = -1;
104     static final int SUPER_RECEIVER = -2;
105     static final int NAME_RECEIVER = -3;
106     static final int ALLOCATION = -4;
107     static final int QUALIFIED_ALLOCATION = -5;
108
109     static final int QUESTION = 1;
110     static final int COLON = 2;
111
112     // K_BETWEEN_ANNOTATION_NAME_AND_RPAREN arguments
113
static final int LPAREN_NOT_CONSUMED = 1;
114     static final int LPAREN_CONSUMED = 2;
115     static final int ANNOTATION_NAME_COMPLETION = 4;
116
117     // K_PARAMETERIZED_METHOD_INVOCATION arguments
118
static final int INSIDE_NAME = 1;
119
120     // the type of the current invocation (one of the invocation type constants)
121
int invocationType;
122
123     // a pointer in the expression stack to the qualifier of a invocation
124
int qualifier;
125
126     // last modifiers info
127
int lastModifiers = ClassFileConstants.AccDefault;
128     int lastModifiersStart = -1;
129
130     // depth of '(', '{' and '[]'
131
int bracketDepth;
132
133     // show if the current token can be an explicit constructor
134
int canBeExplicitConstructor = NO;
135     static final int NO = 0;
136     static final int NEXTTOKEN = 1;
137     static final int YES = 2;
138
139     protected static final int LabelStackIncrement = 10;
140     char[][] labelStack = new char[LabelStackIncrement][];
141     int labelPtr = -1;
142
143     boolean isAlreadyAttached;
144     
145     public boolean record = false;
146     public boolean skipRecord = false;
147     public int recordFrom;
148     public int recordTo;
149     public int potentialVariableNamesPtr;
150     public char[][] potentialVariableNames;
151     public int[] potentialVariableNameStarts;
152     public int[] potentialVariableNameEnds;
153     
154     CompletionOnAnnotationOfType pendingAnnotation;
155     
156 public CompletionParser(ProblemReporter problemReporter) {
157     super(problemReporter);
158     this.reportSyntaxErrorIsRequired = false;
159     this.javadocParser.checkDocComment = true;
160 }
161 private void addPotentialName(char[] potentialVariableName, int start, int end) {
162     int length = this.potentialVariableNames.length;
163     if (this.potentialVariableNamesPtr >= length - 1) {
164         System.arraycopy(
165                 this.potentialVariableNames,
166                 0,
167                 this.potentialVariableNames = new char[length * 2][],
168                 0,
169                 length);
170         System.arraycopy(
171                 this.potentialVariableNameStarts,
172                 0,
173                 this.potentialVariableNameStarts = new int[length * 2],
174                 0,
175                 length);
176         System.arraycopy(
177                 this.potentialVariableNameEnds,
178                 0,
179                 this.potentialVariableNameEnds = new int[length * 2],
180                 0,
181                 length);
182     }
183     this.potentialVariableNames[++this.potentialVariableNamesPtr] = potentialVariableName;
184     this.potentialVariableNameStarts[this.potentialVariableNamesPtr] = start;
185     this.potentialVariableNameEnds[this.potentialVariableNamesPtr] = end;
186 }
187 public void startRecordingIdentifiers(int from, int to) {
188     this.record = true;
189     this.skipRecord = false;
190     this.recordFrom = from;
191     this.recordTo = to;
192     
193     this.potentialVariableNamesPtr = -1;
194     this.potentialVariableNames = new char[10][];
195     this.potentialVariableNameStarts = new int[10];
196     this.potentialVariableNameEnds = new int[10];
197 }
198 public void stopRecordingIdentifiers() {
199     this.record = true;
200     this.skipRecord = false;
201 }
202 public char[] assistIdentifier(){
203     return ((CompletionScanner)scanner).completionIdentifier;
204 }
205 protected void attachOrphanCompletionNode(){
206     if(assistNode == null || this.isAlreadyAttached) return;
207
208     this.isAlreadyAttached = true;
209
210     if (this.isOrphanCompletionNode) {
211         ASTNode orphan = this.assistNode;
212         this.isOrphanCompletionNode = false;
213
214         if (currentElement instanceof RecoveredUnit){
215             if (orphan instanceof ImportReference){
216                 currentElement.add((ImportReference)orphan, 0);
217             }
218         }
219
220         /* if in context of a type, then persists the identifier into a fake field return type */
221         if (currentElement instanceof RecoveredType){
222             RecoveredType recoveredType = (RecoveredType)currentElement;
223             /* filter out cases where scanner is still inside type header */
224             if (recoveredType.foundOpeningBrace) {
225                 /* generate a pseudo field with a completion on type reference */
226                 if (orphan instanceof TypeReference){
227                     TypeReference fieldType;
228
229                     int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
230                     int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
231                     if(kind == K_BINARY_OPERATOR && info == LESS && this.identifierPtr > -1) {
232                         if(this.genericsLengthStack[this.genericsLengthPtr] > 0) {
233                             this.consumeTypeArguments();
234                         }
235                         this.pushOnGenericsStack(orphan);
236                         this.consumeTypeArguments();
237                         fieldType = getTypeReference(0);
238                         this.assistNodeParent = fieldType;
239                     } else {
240                         fieldType = (TypeReference)orphan;
241                     }
242
243                     CompletionOnFieldType fieldDeclaration = new CompletionOnFieldType(fieldType, false);
244
245                     // retrieve available modifiers if any
246
if (intPtr >= 2 && intStack[intPtr-1] == this.lastModifiersStart && intStack[intPtr-2] == this.lastModifiers){
247                         fieldDeclaration.modifiersSourceStart = intStack[intPtr-1];
248                         fieldDeclaration.modifiers = intStack[intPtr-2];
249                     }
250
251                     currentElement = currentElement.add(fieldDeclaration, 0);
252                     return;
253                 }
254             }
255         }
256         /* if in context of a method, persists if inside arguments as a type */
257         if (currentElement instanceof RecoveredMethod){
258             RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
259             /* only consider if inside method header */
260             if (!recoveredMethod.foundOpeningBrace) {
261                 //if (rParenPos < lParenPos){ // inside arguments
262
if (orphan instanceof TypeReference){
263                     currentElement = currentElement.parent.add(
264                         new CompletionOnFieldType((TypeReference)orphan, true), 0);
265                     return;
266                 }
267
268                 if(orphan instanceof Annotation) {
269                     CompletionOnAnnotationOfType fakeType =
270                         new CompletionOnAnnotationOfType(
271                                 FAKE_TYPE_NAME,
272                                 this.compilationUnit.compilationResult(),
273                                 (Annotation)orphan);
274                     currentElement.parent.add(fakeType, 0);
275                     this.pendingAnnotation = fakeType;
276                     return;
277                 }
278             }
279         }
280
281         if(orphan instanceof MemberValuePair) {
282             buildMoreAnnotationCompletionContext((MemberValuePair) orphan);
283             return;
284         }
285
286         if(orphan instanceof Annotation) {
287             popUntilCompletedAnnotationIfNecessary();
288             
289             CompletionOnAnnotationOfType fakeType =
290                 new CompletionOnAnnotationOfType(
291                         FAKE_TYPE_NAME,
292                         this.compilationUnit.compilationResult(),
293                         (Annotation)orphan);
294             currentElement.add(fakeType, 0);
295             
296             if (!isInsideAnnotation()) {
297                 this.pendingAnnotation = fakeType;
298             }
299             
300             return;
301         }
302
303         if ((topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_CATCH_AND_RIGHT_PAREN)) {
304             if (this.assistNode instanceof CompletionOnSingleTypeReference &&
305                     ((CompletionOnSingleTypeReference)this.assistNode).isException()) {
306                 buildMoreTryStatementCompletionContext((TypeReference)this.assistNode);
307                 return;
308             } else if (this.assistNode instanceof CompletionOnQualifiedTypeReference &&
309                     ((CompletionOnQualifiedTypeReference)this.assistNode).isException()) {
310                 buildMoreTryStatementCompletionContext((TypeReference)this.assistNode);
311                 return;
312             } else if (this.assistNode instanceof CompletionOnParameterizedQualifiedTypeReference &&
313                     ((CompletionOnParameterizedQualifiedTypeReference)this.assistNode).isException()) {
314                 buildMoreTryStatementCompletionContext((TypeReference)this.assistNode);
315                 return;
316             }
317         }
318
319         // add the completion node to the method declaration or constructor declaration
320
if (orphan instanceof Statement) {
321             /* check for completion at the beginning of method body
322                 behind an invalid signature
323              */

324             RecoveredMethod method = currentElement.enclosingMethod();
325             if (method != null){
326                 AbstractMethodDeclaration methodDecl = method.methodDeclaration;
327                 if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
328
&& (Util.getLineNumber(orphan.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
329                             == Util.getLineNumber(methodDecl.sourceEnd, scanner.lineEnds, 0, scanner.linePtr))){
330                     return;
331                 }
332             }
333             // add the completion node as a statement to the list of block statements
334
currentElement = currentElement.add((Statement)orphan, 0);
335             return;
336         }
337     }
338
339     if (this.isInsideAnnotation()) {
340         // push top expression on ast stack if it contains the completion node
341
Expression expression;
342         if (this.expressionPtr > -1) {
343             expression = this.expressionStack[this.expressionPtr];
344             if(expression == assistNode) {
345                 if (this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_MEMBER_VALUE_ARRAY_INITIALIZER ) {
346                     ArrayInitializer arrayInitializer = new ArrayInitializer();
347                     arrayInitializer.expressions = new Expression[]{expression};
348                 
349                     MemberValuePair valuePair =
350                             new MemberValuePair(VALUE, expression.sourceStart, expression.sourceEnd, arrayInitializer);
351                         buildMoreAnnotationCompletionContext(valuePair);
352                 } else if(this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN) {
353                     if (expression instanceof SingleNameReference) {
354                         SingleNameReference nameReference = (SingleNameReference) expression;
355                         CompletionOnMemberValueName memberValueName = new CompletionOnMemberValueName(nameReference.token, nameReference.sourceStart, nameReference.sourceEnd);
356
357                         buildMoreAnnotationCompletionContext(memberValueName);
358                         return;
359                     } else if (expression instanceof QualifiedNameReference) {
360                         MemberValuePair valuePair =
361                             new MemberValuePair(VALUE, expression.sourceStart, expression.sourceEnd, expression);
362                         buildMoreAnnotationCompletionContext(valuePair);
363                     }
364                 } else {
365                     int index;
366                     if((index = lastIndexOfElement(K_ATTRIBUTE_VALUE_DELIMITER)) != -1) {
367                         int attributeIndentifierPtr = this.elementInfoStack[index];
368                         int identLengthPtr = this.identifierLengthPtr;
369                         int identPtr = this.identifierPtr;
370                         while (attributeIndentifierPtr < identPtr) {
371                             identPtr -= this.identifierLengthStack[identLengthPtr--];
372                         }
373
374                         if(attributeIndentifierPtr != identPtr) return;
375
376                         this.identifierLengthPtr = identLengthPtr;
377                         this.identifierPtr = identPtr;
378
379                         this.identifierLengthPtr--;
380                         MemberValuePair memberValuePair = new MemberValuePair(
381                                 this.identifierStack[this.identifierPtr--],
382                                 expression.sourceStart,
383                                 expression.sourceEnd,
384                                 expression);
385
386                         buildMoreAnnotationCompletionContext(memberValuePair);
387                         return;
388                     }
389                 }
390             } else {
391                 CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, expression);
392                 if(detector.containsCompletionNode()) {
393                     MemberValuePair valuePair =
394                         new MemberValuePair(VALUE, expression.sourceStart, expression.sourceEnd, expression);
395                     buildMoreAnnotationCompletionContext(valuePair);
396                 }
397             }
398         }
399
400         if (this.astPtr > -1) {
401             ASTNode node = this.astStack[this.astPtr];
402             if(node instanceof MemberValuePair) {
403                 MemberValuePair memberValuePair = (MemberValuePair) node;
404                 CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, memberValuePair);
405                 if(detector.containsCompletionNode()) {
406                     buildMoreAnnotationCompletionContext(memberValuePair);
407                     this.assistNodeParent = detector.getCompletionNodeParent();
408                     return;
409                 }
410             }
411         }
412     }
413
414     if(this.genericsPtr > -1) {
415         ASTNode node = this.genericsStack[this.genericsPtr];
416         if(node instanceof Wildcard && ((Wildcard)node).bound == this.assistNode){
417             int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
418             if (kind == K_BINARY_OPERATOR) {
419                 int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
420                 if (info == LESS) {
421                     buildMoreGenericsCompletionContext(node, true);
422                     return;
423                 }
424             }
425             if(this.identifierLengthPtr > -1 && this.identifierLengthStack[this.identifierLengthPtr]!= 0) {
426                 this.pushOnElementStack(K_BINARY_OPERATOR, LESS);
427                 buildMoreGenericsCompletionContext(node, false);
428                 return;
429             }
430         }
431     }
432
433     if(this.currentElement instanceof RecoveredType || this.currentElement instanceof RecoveredMethod) {
434         if(this.currentElement instanceof RecoveredType) {
435             RecoveredType recoveredType = (RecoveredType)this.currentElement;
436             if(recoveredType.foundOpeningBrace && this.genericsPtr > -1) {
437                 if(this.genericsStack[this.genericsPtr] instanceof TypeParameter) {
438                     TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
439                     CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, typeParameter);
440                     if(detector.containsCompletionNode()) {
441                         this.currentElement.add(new CompletionOnMethodTypeParameter(new TypeParameter[]{typeParameter},this.compilationUnit.compilationResult()), 0);
442                     }
443                     return;
444                 }
445             }
446         }
447
448         if ((!isInsideMethod() && !isInsideFieldInitialization())) {
449             if(this.genericsPtr > -1 && this.genericsLengthPtr > -1 && this.genericsIdentifiersLengthPtr > -1) {
450                 int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
451                 int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
452                 if(kind == K_BINARY_OPERATOR && info == LESS) {
453                     this.consumeTypeArguments();
454                 }
455                 int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
456                 int genPtr = this.genericsPtr;
457                 done : for(int i = 0; i <= this.identifierLengthPtr && numberOfIdentifiers > 0; i++){
458                     int identifierLength = this.identifierLengthStack[this.identifierLengthPtr - i];
459                     int length = this.genericsLengthStack[this.genericsLengthPtr - i];
460                     for(int j = 0; j < length; j++) {
461                         ASTNode node = this.genericsStack[genPtr - j];
462                         CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, node);
463                         if(detector.containsCompletionNode()) {
464                             if(node == this.assistNode){
465                                 if(this.identifierLengthPtr > -1 && this.identifierLengthStack[this.identifierLengthPtr]!= 0) {
466                                     TypeReference ref = this.getTypeReference(0);
467                                     this.assistNodeParent = ref;
468                                 }
469                             } else {
470                                 this.assistNodeParent = detector.getCompletionNodeParent();
471                             }
472                             break done;
473                         }
474                     }
475                     genPtr -= length;
476                     numberOfIdentifiers -= identifierLength;
477                 }
478                 if(this.assistNodeParent != null && this.assistNodeParent instanceof TypeReference) {
479                     if(this.currentElement instanceof RecoveredType) {
480                         this.currentElement = this.currentElement.add(new CompletionOnFieldType((TypeReference)this.assistNodeParent, false), 0);
481                     } else {
482                         this.currentElement = this.currentElement.add((TypeReference)this.assistNodeParent, 0);
483                     }
484                 }
485             }
486         }
487     }
488
489     // the following code applies only in methods, constructors or initializers
490
if ((!isInsideMethod() && !isInsideFieldInitialization() && !isInsideAttributeValue())) {
491         return;
492     }
493
494     if(this.genericsPtr > -1) {
495         ASTNode node = this.genericsStack[this.genericsPtr];
496         CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, node);
497         if(detector.containsCompletionNode()) {
498             /* check for completion at the beginning of method body
499                 behind an invalid signature
500              */

501             RecoveredMethod method = this.currentElement.enclosingMethod();
502             if (method != null){
503                 AbstractMethodDeclaration methodDecl = method.methodDeclaration;
504                 if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
505
&& (Util.getLineNumber(node.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr)
506                         == Util.getLineNumber(methodDecl.sourceEnd, this.scanner.lineEnds, 0, this.scanner.linePtr))){
507                     return;
508                 }
509             }
510             if(node == this.assistNode){
511                 buildMoreGenericsCompletionContext(node, true);
512             }
513         }
514     }
515
516     // push top expression on ast stack if it contains the completion node
517
Expression expression;
518     if (this.expressionPtr > -1) {
519         expression = this.expressionStack[this.expressionPtr];
520         CompletionNodeDetector detector = new CompletionNodeDetector(assistNode, expression);
521         if(detector.containsCompletionNode()) {
522             /* check for completion at the beginning of method body
523                 behind an invalid signature
524              */

525             RecoveredMethod method = currentElement.enclosingMethod();
526             if (method != null){
527                 AbstractMethodDeclaration methodDecl = method.methodDeclaration;
528                 if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
529
&& (Util.getLineNumber(expression.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
530                         == Util.getLineNumber(methodDecl.sourceEnd, scanner.lineEnds, 0, scanner.linePtr))){
531                     return;
532                 }
533             }
534             if(expression == assistNode
535                 || (expression instanceof AllocationExpression
536                     && ((AllocationExpression)expression).type == assistNode)){
537                 buildMoreCompletionContext(expression);
538             } else {
539                 assistNodeParent = detector.getCompletionNodeParent();
540                 if(assistNodeParent != null) {
541                     currentElement = currentElement.add((Statement)assistNodeParent, 0);
542                 } else {
543                     currentElement = currentElement.add(expression, 0);
544                 }
545             }
546         }
547     }
548 }
549 private void buildMoreAnnotationCompletionContext(MemberValuePair memberValuePair) {
550     if(this.identifierPtr < 0 || this.identifierLengthPtr < 0 ) return;
551
552     TypeReference typeReference = this.getAnnotationType();
553
554     int nodesToRemove = this.astPtr > -1 && this.astStack[this.astPtr] == memberValuePair ? 1 : 0;
555
556     NormalAnnotation annotation;
557     if (memberValuePair instanceof CompletionOnMemberValueName) {
558         MemberValuePair[] memberValuePairs = null;
559         int length;
560         if (astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) > nodesToRemove) {
561             if (this.astStack[this.astPtr] instanceof MemberValuePair) {
562                 System.arraycopy(
563                     this.astStack,
564                     (this.astPtr -= length) + 1,
565                     memberValuePairs = new MemberValuePair[length - nodesToRemove],
566                     0,
567                     length - nodesToRemove);
568             }
569         }
570         annotation =
571             new CompletionOnAnnotationMemberValuePair(
572                     typeReference,
573                     this.intStack[this.intPtr--],
574                     memberValuePairs,
575                     memberValuePair);
576
577         this.assistNode = memberValuePair;
578         this.assistNodeParent = annotation;
579
580         if (memberValuePair.sourceEnd >= this.lastCheckPoint) {
581             this.lastCheckPoint = memberValuePair.sourceEnd + 1;
582         }
583     } else {
584         MemberValuePair[] memberValuePairs = null;
585         int length = 0;
586         if (astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) > nodesToRemove) {
587             if (this.astStack[this.astPtr] instanceof MemberValuePair) {
588                 System.arraycopy(
589                     this.astStack,
590                     (this.astPtr -= length) + 1,
591                     memberValuePairs = new MemberValuePair[length - nodesToRemove + 1],
592                     0,
593                     length - nodesToRemove);
594             }
595             if(memberValuePairs != null) {
596                 memberValuePairs[length - nodesToRemove] = memberValuePair;
597             } else {
598                 memberValuePairs = new MemberValuePair[]{memberValuePair};
599             }
600         } else {
601             memberValuePairs = new MemberValuePair[]{memberValuePair};
602         }
603
604         annotation =
605             new NormalAnnotation(
606                     typeReference,
607                     this.intStack[this.intPtr--]);
608         annotation.memberValuePairs = memberValuePairs;
609
610     }
611     CompletionOnAnnotationOfType fakeType =
612         new CompletionOnAnnotationOfType(
613                 FAKE_TYPE_NAME,
614                 this.compilationUnit.compilationResult(),
615                 annotation);
616
617     currentElement.add(fakeType, 0);
618     this.pendingAnnotation = fakeType;
619 }
620 private void buildMoreCompletionContext(Expression expression) {
621     Statement statement = expression;
622     int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
623     if(kind != 0) {
624         int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
625         nextElement : switch (kind) {
626             case K_SELECTOR_QUALIFIER :
627                 int selector = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 2);
628                 if(selector == THIS_CONSTRUCTOR || selector == SUPER_CONSTRUCTOR) {
629                     ExplicitConstructorCall call = new ExplicitConstructorCall(
630                         (selector == THIS_CONSTRUCTOR) ?
631                             ExplicitConstructorCall.This :
632                             ExplicitConstructorCall.Super
633                     );
634                     call.arguments = new Expression[] {expression};
635                     call.sourceStart = expression.sourceStart;
636                     call.sourceEnd = expression.sourceEnd;
637                     assistNodeParent = call;
638                 } else {
639                     int invocType = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER,1);
640                     int qualifierExprPtr = info;
641
642                     // find arguments
643
int length = expressionLengthStack[expressionLengthPtr];
644
645                     // search previous arguments if missing
646
if(this.expressionPtr > 0 && this.expressionLengthPtr > 0 && length == 1) {
647                         int start = (int) (identifierPositionStack[selector] >>> 32);
648                         if(this.expressionStack[expressionPtr-1] != null && this.expressionStack[expressionPtr-1].sourceStart > start) {
649                             length += expressionLengthStack[expressionLengthPtr-1];
650                         }
651
652                     }
653
654                     Expression[] arguments = null;
655                     if (length != 0) {
656                         arguments = new Expression[length];
657                         expressionPtr -= length;
658                         System.arraycopy(expressionStack, expressionPtr + 1, arguments, 0, length-1);
659                         arguments[length-1] = expression;
660                     }
661
662                     if(invocType != ALLOCATION && invocType != QUALIFIED_ALLOCATION) {
663                         MessageSend messageSend = new MessageSend();
664                         messageSend.selector = identifierStack[selector];
665                         messageSend.arguments = arguments;
666
667                         // find receiver
668
switch (invocType) {
669                             case NO_RECEIVER:
670                                 messageSend.receiver = ThisReference.implicitThis();
671                                 break;
672                             case NAME_RECEIVER:
673                                 // remove special flags for primitive types
674
while (this.identifierLengthPtr >= 0 && this.identifierLengthStack[this.identifierLengthPtr] < 0) {
675                                     this.identifierLengthPtr--;
676                                 }
677
678                                 // remove selector
679
this.identifierPtr--;
680                                 if(this.genericsPtr > -1 && this.genericsLengthPtr > -1 && this.genericsLengthStack[this.genericsLengthPtr] > 0) {
681                                     // is inside a paremeterized method: bar.<X>.foo
682
this.identifierLengthPtr--;
683                                 } else {
684                                     this.identifierLengthStack[this.identifierLengthPtr]--;
685                                 }
686                                 // consume the receiver
687
int identifierLength = this.identifierLengthStack[this.identifierLengthPtr];
688                                 if(this.identifierPtr > -1 && identifierLength > 0 && this.identifierPtr + 1 >= identifierLength) {
689                                     messageSend.receiver = this.getUnspecifiedReference();
690                                 } else {
691                                     messageSend = null;
692                                 }
693                                 break;
694                             case SUPER_RECEIVER:
695                                 messageSend.receiver = new SuperReference(0, 0);
696                                 break;
697                             case EXPLICIT_RECEIVER:
698                                 messageSend.receiver = this.expressionStack[qualifierExprPtr];
699                                 break;
700                             default :
701                                 messageSend.receiver = ThisReference.implicitThis();
702                                 break;
703                         }
704                         assistNodeParent = messageSend;
705                     } else {
706                         if(invocType == ALLOCATION) {
707                             AllocationExpression allocationExpr = new AllocationExpression();
708                             allocationExpr.arguments = arguments;
709                             pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
710                             pushOnGenericsLengthStack(0);
711                             allocationExpr.type = getTypeReference(0);
712                             assistNodeParent = allocationExpr;
713                         } else {
714                             QualifiedAllocationExpression allocationExpr = new QualifiedAllocationExpression();
715                             allocationExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
716                             allocationExpr.arguments = arguments;
717                             pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
718                             pushOnGenericsLengthStack(0);
719
720                             allocationExpr.type = getTypeReference(0);
721                             assistNodeParent = allocationExpr;
722                         }
723                     }
724                 }
725                 break nextElement;
726             case K_INSIDE_RETURN_STATEMENT :
727                 if(info == bracketDepth) {
728                     ReturnStatement returnStatement = new ReturnStatement(expression, expression.sourceStart, expression.sourceEnd);
729                     assistNodeParent = returnStatement;
730                 }
731                 break nextElement;
732             case K_CAST_STATEMENT :
733                 Expression castType;
734                 if(this.expressionPtr > 0
735                     && ((castType = this.expressionStack[this.expressionPtr-1]) instanceof TypeReference
736                         || castType instanceof NameReference)) {
737                     CastExpression cast = new CastExpression(expression, getTypeReference(castType));
738                     cast.sourceStart = castType.sourceStart;
739                     cast.sourceEnd= expression.sourceEnd;
740                     assistNodeParent = cast;
741                 }
742                 break nextElement;
743             case K_UNARY_OPERATOR :
744                 if(expressionPtr > -1) {
745                     Expression operatorExpression = null;
746                     switch (info) {
747                         case PLUS_PLUS :
748                             operatorExpression = new PrefixExpression(expression,IntLiteral.One, PLUS, expression.sourceStart);
749                             break;
750                         case MINUS_MINUS :
751                             operatorExpression = new PrefixExpression(expression,IntLiteral.One, MINUS, expression.sourceStart);
752                             break;
753                         default :
754                             operatorExpression = new UnaryExpression(expression, info);
755                             break;
756                     }
757                     assistNodeParent = operatorExpression;
758                 }
759                 break nextElement;
760             case K_BINARY_OPERATOR :
761                 if(expressionPtr > -1) {
762                     Expression operatorExpression = null;
763                     Expression left = null;
764                     if(expressionPtr == 0) {
765                         // it is a ***_NotName rule
766
if(this.identifierPtr > -1) {
767                             left = getUnspecifiedReferenceOptimized();
768                         }
769                     } else {
770                         left = this.expressionStack[expressionPtr-1];
771                         // is it a ***_NotName rule ?
772
if(this.identifierPtr > -1) {
773                             int start = (int) (identifierPositionStack[this.identifierPtr] >>> 32);
774                             if(left.sourceStart < start) {
775                                 left = getUnspecifiedReferenceOptimized();
776                             }
777                         }
778                     }
779
780                     if(left != null) {
781                         switch (info) {
782                             case AND_AND :
783                                 operatorExpression = new AND_AND_Expression(left, expression, info);
784                                 break;
785                             case OR_OR :
786                                 operatorExpression = new OR_OR_Expression(left, expression, info);
787                                 break;
788                             case EQUAL_EQUAL :
789                             case NOT_EQUAL :
790                                 operatorExpression = new EqualExpression(left, expression, info);
791                                 break;
792                             default :
793                                 operatorExpression = new BinaryExpression(left, expression, info);
794                                 break;
795                         }
796                     }
797                     if(operatorExpression != null) {
798                         assistNodeParent = operatorExpression;
799                     }
800                 }
801                 break nextElement;
802             case K_ARRAY_INITIALIZER :
803                 ArrayInitializer arrayInitializer = new ArrayInitializer();
804                 arrayInitializer.expressions = new Expression[]{expression};
805                 expressionPtr -= expressionLengthStack[expressionLengthPtr--];
806
807                 if(expressionLengthPtr > -1
808                     && expressionPtr > -1
809                     && this.expressionStack[expressionPtr] != null
810                     && this.expressionStack[expressionPtr].sourceStart > info) {
811                     expressionLengthPtr--;
812                 }
813
814                 lastCheckPoint = scanner.currentPosition;
815
816                 if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_ARRAY_CREATION) {
817                     ArrayAllocationExpression allocationExpression = new ArrayAllocationExpression();
818                     pushOnGenericsLengthStack(0);
819                     pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
820                     allocationExpression.type = getTypeReference(0);
821                     allocationExpression.type.bits |= ASTNode.IgnoreRawTypeCheck; // no need to worry about raw type usage
822
int length = expressionLengthStack[expressionLengthPtr];
823                     allocationExpression.dimensions = new Expression[length];
824
825                     allocationExpression.initializer = arrayInitializer;
826                     assistNodeParent = allocationExpression;
827                 } else if(currentElement instanceof RecoveredField && !(currentElement instanceof RecoveredInitializer)) {
828                     RecoveredField recoveredField = (RecoveredField) currentElement;
829                     if(recoveredField.fieldDeclaration.type.dimensions() == 0) {
830                         Block block = new Block(0);
831                         block.sourceStart = info;
832                         currentElement = currentElement.add(block, 1);
833                     } else {
834                         statement = arrayInitializer;
835                     }
836                 } else if(currentElement instanceof RecoveredLocalVariable) {
837                     RecoveredLocalVariable recoveredLocalVariable = (RecoveredLocalVariable) currentElement;
838                     if(recoveredLocalVariable.localDeclaration.type.dimensions() == 0) {
839                         Block block = new Block(0);
840                         block.sourceStart = info;
841                         currentElement = currentElement.add(block, 1);
842                     } else {
843                         statement = arrayInitializer;
844                     }
845                 } else {
846                     statement = arrayInitializer;
847                 }
848                 break nextElement;
849             case K_ARRAY_CREATION :
850                 ArrayAllocationExpression allocationExpression = new ArrayAllocationExpression();
851                 allocationExpression.type = getTypeReference(0);
852                 allocationExpression.dimensions = new Expression[]{expression};
853
854                 assistNodeParent = allocationExpression;
855                 break nextElement;
856             case K_ASSISGNMENT_OPERATOR :
857                 if(expressionPtr > 0 && expressionStack[expressionPtr - 1] != null) {
858                     Assignment assignment;
859                     if(info == EQUAL) {
860                         assignment = new Assignment(
861                             expressionStack[expressionPtr - 1],
862                             expression,
863                             expression.sourceEnd
864                         );
865                     } else {
866                         assignment = new CompoundAssignment(
867                             expressionStack[expressionPtr - 1],
868                             expression,
869                             info,
870                             expression.sourceEnd
871                         );
872                     }
873                     assistNodeParent = assignment;
874                 }
875                 break nextElement;
876             case K_CONDITIONAL_OPERATOR :
877                 if(info == QUESTION) {
878                     if(expressionPtr > 0) {
879                         expressionPtr--;
880                         expressionLengthPtr--;
881                         expressionStack[expressionPtr] = expressionStack[expressionPtr+1];
882                         popElement(K_CONDITIONAL_OPERATOR);
883                         buildMoreCompletionContext(expression);
884                         return;
885                     }
886                 } else {
887                     if(expressionPtr > 1) {
888                         expressionPtr = expressionPtr - 2;
889                         expressionLengthPtr = expressionLengthPtr - 2;
890                         expressionStack[expressionPtr] = expressionStack[expressionPtr+2];
891                         popElement(K_CONDITIONAL_OPERATOR);
892                         buildMoreCompletionContext(expression);
893                         return;
894                     }
895                 }
896                 break nextElement;
897             case K_BETWEEN_LEFT_AND_RIGHT_BRACKET :
898                 ArrayReference arrayReference;
899                 if(identifierPtr < 0 && expressionPtr > 0 && expressionStack[expressionPtr] == expression) {
900                     arrayReference =
901                         new ArrayReference(
902                             expressionStack[expressionPtr-1],
903                             expression);
904                 } else {
905                     arrayReference =
906                         new ArrayReference(
907                             getUnspecifiedReferenceOptimized(),
908                             expression);
909                 }
910                 assistNodeParent = arrayReference;
911                 break;
912             case K_BETWEEN_CASE_AND_COLON :
913                 if(this.expressionPtr > 0) {
914                     SwitchStatement switchStatement = new SwitchStatement();
915                     switchStatement.expression = this.expressionStack[this.expressionPtr - 1];
916                     if(this.astLengthPtr > -1 && this.astPtr > -1) {
917                         int length = this.astLengthStack[this.astLengthPtr];
918                         int newAstPtr = this.astPtr - length;
919                         ASTNode firstNode = this.astStack[newAstPtr + 1];
920                         if(length != 0 && firstNode.sourceStart > switchStatement.expression.sourceEnd) {
921                             switchStatement.statements = new Statement[length + 1];
922                             System.arraycopy(
923                                 this.astStack,
924                                 newAstPtr + 1,
925                                 switchStatement.statements,
926                                 0,
927                                 length);
928                         }
929                     }
930                     CaseStatement caseStatement = new CaseStatement(expression, expression.sourceStart, expression.sourceEnd);
931                     if(switchStatement.statements == null) {
932                         switchStatement.statements = new Statement[]{caseStatement};
933                     } else {
934                         switchStatement.statements[switchStatement.statements.length - 1] = caseStatement;
935                     }
936                     assistNodeParent = switchStatement;
937                 }
938                 break;
939         }
940     }
941     if(assistNodeParent != null) {
942         currentElement = currentElement.add((Statement)assistNodeParent, 0);
943     } else {
944         if(currentElement instanceof RecoveredField && !(currentElement instanceof RecoveredInitializer)
945             && ((RecoveredField) currentElement).fieldDeclaration.initialization == null) {
946
947             assistNodeParent = ((RecoveredField) currentElement).fieldDeclaration;
948             currentElement = currentElement.add(statement, 0);
949         } else if(currentElement instanceof RecoveredLocalVariable
950             && ((RecoveredLocalVariable) currentElement).localDeclaration.initialization == null) {
951
952             assistNodeParent = ((RecoveredLocalVariable) currentElement).localDeclaration;
953             currentElement = currentElement.add(statement, 0);
954         } else {
955             currentElement = currentElement.add(expression, 0);
956         }
957     }
958 }
959 private void buildMoreGenericsCompletionContext(ASTNode node, boolean consumeTypeArguments) {
960     int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
961     if(kind != 0) {
962         int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
963         nextElement : switch (kind) {
964             case K_BINARY_OPERATOR :
965                 int prevKind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1);
966                 switch (prevKind) {
967                     case K_PARAMETERIZED_ALLOCATION :
968                         if(this.invocationType == ALLOCATION || this.invocationType == QUALIFIED_ALLOCATION) {
969                             currentElement = currentElement.add((TypeReference)node, 0);
970                         }
971                         break nextElement;
972                     case K_PARAMETERIZED_METHOD_INVOCATION :
973                         if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == 0) {
974                             currentElement = currentElement.add((TypeReference)node, 0);
975                             break nextElement;
976                         }
977                 }
978                 if(info == LESS && node instanceof TypeReference) {
979                     if(this.identifierLengthPtr > -1 && this.identifierLengthStack[this.identifierLengthPtr]!= 0) {
980                         if (consumeTypeArguments) this.consumeTypeArguments();
981                         TypeReference ref = this.getTypeReference(0);
982                         if(prevKind == K_PARAMETERIZED_CAST) {
983                             ref = computeQualifiedGenericsFromRightSide(ref, 0);
984                         }
985                         if(currentElement instanceof RecoveredType) {
986                             currentElement = currentElement.add(new CompletionOnFieldType(ref, false), 0);
987                         } else {
988                             currentElement = currentElement.add(ref, 0);
989                         }
990                     } else if (currentElement.enclosingMethod().methodDeclaration.isConstructor()) {
991                         currentElement = currentElement.add((TypeReference)node, 0);
992                     }
993                 }
994                 break;
995         }
996     }
997 }
998 private void buildMoreTryStatementCompletionContext(TypeReference exceptionRef) {
999     if (this.astLengthPtr > -1 &&
1000            this.astPtr > 1 &&
1001            this.astStack[this.astPtr] instanceof Block &&
1002            this.astStack[this.astPtr - 1] instanceof Argument) {
1003        TryStatement tryStatement = new TryStatement();
1004
1005        int newAstPtr = this.astPtr;
1006
1007        int length = this.astLengthStack[this.astLengthPtr];
1008        Block[] bks = (tryStatement.catchBlocks = new Block[length + 1]);
1009        Argument[] args = (tryStatement.catchArguments = new Argument[length + 1]);
1010        if (length != 0) {
1011            while (length-- > 0) {
1012                bks[length] = (Block) this.astStack[newAstPtr--];
1013                bks[length].statements = null; // statements of catch block won't be used
1014
args[length] = (Argument) this.astStack[newAstPtr--];
1015            }
1016        }
1017
1018        bks[bks.length - 1] = new Block(0);
1019        args[args.length - 1] = new Argument(FAKE_ARGUMENT_NAME,0,exceptionRef,0);
1020
1021        tryStatement.tryBlock = (Block) this.astStack[newAstPtr--];
1022
1023        assistNodeParent = tryStatement;
1024
1025        currentElement.add(tryStatement, 0);
1026    } else if (this.astLengthPtr > -1 &&
1027            this.astPtr > -1 &&
1028            this.astStack[this.astPtr] instanceof Block) {
1029        TryStatement tryStatement = new TryStatement();
1030
1031        int newAstPtr = this.astPtr;
1032
1033        Block[] bks = (tryStatement.catchBlocks = new Block[1]);
1034        Argument[] args = (tryStatement.catchArguments = new Argument[1]);
1035
1036        bks[0] = new Block(0);
1037        args[0] = new Argument(FAKE_ARGUMENT_NAME,0,exceptionRef,0);
1038
1039        tryStatement.tryBlock = (Block) this.astStack[newAstPtr--];
1040
1041        assistNodeParent = tryStatement;
1042
1043        currentElement.add(tryStatement, 0);
1044    }else {
1045        currentElement = currentElement.add(exceptionRef, 0);
1046    }
1047}
1048public int bodyEnd(AbstractMethodDeclaration method){
1049    return cursorLocation;
1050}
1051public int bodyEnd(Initializer initializer){
1052    return cursorLocation;
1053}
1054/**
1055 * Checks if the completion is on the exception type of a catch clause.
1056 * Returns whether we found a completion node.
1057 */

1058private boolean checkCatchClause() {
1059    if ((topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_CATCH_AND_RIGHT_PAREN) && this.identifierPtr > -1) {
1060        // NB: if the cursor is on the variable, then it has been reduced (so identifierPtr is -1),
1061
// thus this can only be a completion on the type of the catch clause
1062
pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
1063        this.assistNode = getTypeReference(0);
1064        popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
1065        this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1066        this.isOrphanCompletionNode = true;
1067        return true;
1068    }
1069    return false;
1070}
1071/**
1072 * Checks if the completion is on the type following a 'new'.
1073 * Returns whether we found a completion node.
1074 */

1075private boolean checkClassInstanceCreation() {
1076    if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_NEW_AND_LEFT_BRACKET) {
1077        int length = identifierLengthStack[identifierLengthPtr];
1078        int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
1079        if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
1080            // no class instance creation with a parameterized type
1081
return true;
1082        }
1083
1084        // completion on type inside an allocation expression
1085

1086        TypeReference type;
1087        if (this.invocationType == ALLOCATION) {
1088            // non qualified allocation expression
1089
AllocationExpression allocExpr = new AllocationExpression();
1090            if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_INSIDE_THROW_STATEMENT
1091                && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == this.bracketDepth) {
1092                pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
1093                type = getTypeReference(0);
1094                popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
1095            } else {
1096                type = getTypeReference(0);
1097            }
1098            if(type instanceof CompletionOnSingleTypeReference) {
1099                ((CompletionOnSingleTypeReference)type).isConstructorType = true;
1100            }
1101            allocExpr.type = type;
1102            allocExpr.sourceStart = type.sourceStart;
1103            allocExpr.sourceEnd = type.sourceEnd;
1104            pushOnExpressionStack(allocExpr);
1105            this.isOrphanCompletionNode = false;
1106        } else {
1107            // qualified allocation expression
1108
QualifiedAllocationExpression allocExpr = new QualifiedAllocationExpression();
1109            pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
1110            pushOnGenericsLengthStack(0);
1111            if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_INSIDE_THROW_STATEMENT
1112                && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == this.bracketDepth) {
1113                pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
1114                type = getTypeReference(0);
1115                popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
1116            } else {
1117                type = getTypeReference(0);
1118            }
1119            allocExpr.type = type;
1120            allocExpr.enclosingInstance = this.expressionStack[this.qualifier];
1121            allocExpr.sourceStart = this.intStack[this.intPtr--];
1122            allocExpr.sourceEnd = type.sourceEnd;
1123            this.expressionStack[this.qualifier] = allocExpr; // attach it now (it replaces the qualifier expression)
1124
this.isOrphanCompletionNode = false;
1125        }
1126        this.assistNode = type;
1127        this.lastCheckPoint = type.sourceEnd + 1;
1128
1129        popElement(K_BETWEEN_NEW_AND_LEFT_BRACKET);
1130        return true;
1131    }
1132    return false;
1133}
1134/**
1135 * Checks if the completion is on the dot following an array type,
1136 * a primitive type or an primitive array type.
1137 * Returns whether we found a completion node.
1138 */

1139private boolean checkClassLiteralAccess() {
1140    if (this.identifierLengthPtr >= 1 && this.previousToken == TokenNameDOT) { // (NB: the top id length is 1 and it is for the completion identifier)
1141
int length;
1142        // if the penultimate id length is negative,
1143
// the completion is after a primitive type or a primitive array type
1144
if ((length = this.identifierLengthStack[this.identifierLengthPtr-1]) < 0) {
1145            // build the primitive type node
1146
int dim = this.isAfterArrayType() ? this.intStack[this.intPtr--] : 0;
1147            SingleTypeReference typeRef = (SingleTypeReference)TypeReference.baseTypeReference(-length, dim);
1148            typeRef.sourceStart = this.intStack[this.intPtr--];
1149            if (dim == 0) {
1150                typeRef.sourceEnd = this.intStack[this.intPtr--];
1151            } else {
1152                this.intPtr--;
1153                typeRef.sourceEnd = this.endPosition;
1154            }
1155            //typeRef.sourceEnd = typeRef.sourceStart + typeRef.token.length; // NB: It's ok to use the length of the token since it doesn't contain any unicode
1156

1157            // find the completion identifier and its source positions
1158
char[] source = identifierStack[identifierPtr];
1159            long pos = this.identifierPositionStack[this.identifierPtr--];
1160            this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
1161

1162            // build the completion on class literal access node
1163
CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
1164            access.completionIdentifier = source;
1165            this.identifierLengthPtr--; // pop the length that was used to say it is a primitive type
1166
this.assistNode = access;
1167            this.isOrphanCompletionNode = true;
1168            return true;
1169        }
1170
1171        // if the completion is after a regular array type
1172
if (isAfterArrayType()) {
1173            // find the completion identifier and its source positions
1174
char[] source = identifierStack[identifierPtr];
1175            long pos = this.identifierPositionStack[this.identifierPtr--];
1176            this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
1177

1178            // get the type reference
1179
pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
1180            pushOnGenericsLengthStack(0);
1181
1182            TypeReference typeRef = getTypeReference(this.intStack[this.intPtr--]);
1183
1184            // build the completion on class literal access node
1185
CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
1186            access.completionIdentifier = source;
1187            this.assistNode = access;
1188            this.isOrphanCompletionNode = true;
1189            return true;
1190        }
1191
1192    }
1193    return false;
1194}
1195private boolean checkKeyword() {
1196    if (currentElement instanceof RecoveredUnit) {
1197        RecoveredUnit unit = (RecoveredUnit) currentElement;
1198        int index = -1;
1199        if ((index = this.indexOfAssistIdentifier()) > -1) {
1200            int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
1201
1202            char[] ident = identifierStack[ptr];
1203            long pos = identifierPositionStack[ptr];
1204
1205            char[][] keywords = new char[Keywords.COUNT][];
1206            int count = 0;
1207            if(unit.typeCount == 0
1208                && lastModifiers == ClassFileConstants.AccDefault) {
1209                keywords[count++] = Keywords.IMPORT;
1210            }
1211            if(unit.typeCount == 0
1212                && unit.importCount == 0
1213                && lastModifiers == ClassFileConstants.AccDefault
1214                && compilationUnit.currentPackage == null) {
1215                keywords[count++] = Keywords.PACKAGE;
1216            }
1217            if((lastModifiers & ClassFileConstants.AccPublic) == 0) {
1218                boolean hasNoPublicType = true;
1219                for (int i = 0; i < unit.typeCount; i++) {
1220                    if((unit.types[i].typeDeclaration.modifiers & ClassFileConstants.AccPublic) != 0) {
1221                        hasNoPublicType = false;
1222                    }
1223                }
1224                if(hasNoPublicType) {
1225                    keywords[count++] = Keywords.PUBLIC;
1226                }
1227            }
1228            if((lastModifiers & ClassFileConstants.AccAbstract) == 0
1229                && (lastModifiers & ClassFileConstants.AccFinal) == 0) {
1230                keywords[count++] = Keywords.ABSTRACT;
1231            }
1232            if((lastModifiers & ClassFileConstants.AccAbstract) == 0
1233                && (lastModifiers & ClassFileConstants.AccFinal) == 0) {
1234                keywords[count++] = Keywords.FINAL;
1235            }
1236
1237            keywords[count++] = Keywords.CLASS;
1238
1239            if((lastModifiers & ClassFileConstants.AccFinal) == 0) {
1240                keywords[count++] = Keywords.INTERFACE;
1241            }
1242            if(count != 0) {
1243                System.arraycopy(keywords, 0, keywords = new char[count][], 0, count);
1244
1245                this.assistNode = new CompletionOnKeyword2(ident, pos, keywords);
1246                this.lastCheckPoint = assistNode.sourceEnd + 1;
1247                this.isOrphanCompletionNode = true;
1248                return true;
1249            }
1250        }
1251    }
1252    return false;
1253}
1254private boolean checkInstanceofKeyword() {
1255    if(isInsideMethod()) {
1256        int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
1257        int index;
1258        if(kind != K_BLOCK_DELIMITER
1259            && (index = indexOfAssistIdentifier()) > -1
1260            && expressionPtr > -1
1261            && expressionLengthStack[expressionPtr] == 1) {
1262
1263            int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
1264            if(identifierStack[ptr].length > 0 && CharOperation.prefixEquals(identifierStack[ptr], Keywords.INSTANCEOF)) {
1265                this.assistNode = new CompletionOnKeyword3(
1266                        identifierStack[ptr],
1267                        identifierPositionStack[ptr],
1268                        Keywords.INSTANCEOF);
1269                this.lastCheckPoint = assistNode.sourceEnd + 1;
1270                this.isOrphanCompletionNode = true;
1271                return true;
1272            }
1273        }
1274    }
1275    return false;
1276}
1277/**
1278 * Checks if the completion is inside a method invocation or a constructor invocation.
1279 * Returns whether we found a completion node.
1280 */

1281private boolean checkInvocation() {
1282    Expression topExpression = this.expressionPtr >= 0 ?
1283        this.expressionStack[this.expressionPtr] :
1284        null;
1285    boolean isEmptyNameCompletion = false;
1286    boolean isEmptyAssistIdentifier = false;
1287    if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR_QUALIFIER
1288        && ((isEmptyNameCompletion = topExpression == this.assistNode && this.isEmptyNameCompletion()) // eg. it is something like "this.fred([cursor]" but it is not something like "this.fred(1 + [cursor]"
1289
|| (isEmptyAssistIdentifier = this.indexOfAssistIdentifier() >= 0 && this.identifierStack[this.identifierPtr].length == 0))) { // eg. it is something like "this.fred(1 [cursor]"
1290

1291        // pop empty name completion
1292
if (isEmptyNameCompletion) {
1293            this.expressionPtr--;
1294            this.expressionLengthStack[this.expressionLengthPtr]--;
1295        } else if (isEmptyAssistIdentifier) {
1296            this.identifierPtr--;
1297            this.identifierLengthPtr--;
1298        }
1299
1300        // find receiver and qualifier
1301
int invocType = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1);
1302        int qualifierExprPtr = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
1303
1304        // find arguments
1305
int numArgs = this.expressionPtr - qualifierExprPtr;
1306        int argStart = qualifierExprPtr + 1;
1307        Expression[] arguments = null;
1308        if (numArgs > 0) {
1309            // remember the arguments
1310
arguments = new Expression[numArgs];
1311            System.arraycopy(this.expressionStack, argStart, arguments, 0, numArgs);
1312
1313            // consume the expression arguments
1314
this.expressionPtr -= numArgs;
1315            int count = numArgs;
1316            while (count > 0) {
1317                count -= this.expressionLengthStack[this.expressionLengthPtr--];
1318            }
1319        }
1320
1321        // build ast node
1322
if (invocType != ALLOCATION && invocType != QUALIFIED_ALLOCATION) {
1323            // creates completion on message send
1324
CompletionOnMessageSend messageSend = new CompletionOnMessageSend();
1325            messageSend.arguments = arguments;
1326            switch (invocType) {
1327                case NO_RECEIVER:
1328                    // implicit this
1329
messageSend.receiver = ThisReference.implicitThis();
1330                    break;
1331                case NAME_RECEIVER:
1332                    // remove special flags for primitive types
1333
while (this.identifierLengthPtr >= 0 && this.identifierLengthStack[this.identifierLengthPtr] < 0) {
1334                        this.identifierLengthPtr--;
1335                    }
1336
1337                    // remove selector
1338
this.identifierPtr--;
1339                    if(this.genericsPtr > -1 && this.genericsLengthPtr > -1 && this.genericsLengthStack[this.genericsLengthPtr] > 0) {
1340                        // is inside a paremeterized method: bar.<X>.foo
1341
this.identifierLengthPtr--;
1342                    } else {
1343                        this.identifierLengthStack[this.identifierLengthPtr]--;
1344                    }
1345                    // consume the receiver
1346
messageSend.receiver = this.getUnspecifiedReference();
1347                    break;
1348                case SUPER_RECEIVER:
1349                    messageSend.receiver = new SuperReference(0, 0);
1350                    break;
1351                case EXPLICIT_RECEIVER:
1352                    messageSend.receiver = this.expressionStack[qualifierExprPtr];
1353            }
1354
1355            // set selector
1356
int selectorPtr = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 2);
1357            messageSend.selector = this.identifierStack[selectorPtr];
1358            // remove selector
1359
if (this.identifierLengthPtr >=0 && this.identifierLengthStack[this.identifierLengthPtr] == 1) {
1360                this.identifierPtr--;
1361                this.identifierLengthPtr--;
1362            }
1363
1364            // the entire message may be replaced in case qualification is needed
1365
messageSend.sourceStart = (int)(this.identifierPositionStack[selectorPtr] >> 32); //this.cursorLocation + 1;
1366
messageSend.sourceEnd = this.cursorLocation;
1367
1368            // remember the message send as an orphan completion node
1369
this.assistNode = messageSend;
1370            this.lastCheckPoint = messageSend.sourceEnd + 1;
1371            this.isOrphanCompletionNode = true;
1372            return true;
1373        } else {
1374            int selectorPtr = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 2);
1375            if (selectorPtr == THIS_CONSTRUCTOR || selectorPtr == SUPER_CONSTRUCTOR) {
1376                // creates an explicit constructor call
1377
CompletionOnExplicitConstructorCall call = new CompletionOnExplicitConstructorCall(
1378                    (selectorPtr == THIS_CONSTRUCTOR) ? ExplicitConstructorCall.This : ExplicitConstructorCall.Super);
1379                call.arguments = arguments;
1380                if (invocType == QUALIFIED_ALLOCATION) {
1381                    call.qualification = this.expressionStack[qualifierExprPtr];
1382                }
1383
1384                // no source is going to be replaced
1385
call.sourceStart = this.cursorLocation + 1;
1386                call.sourceEnd = this.cursorLocation;
1387
1388                // remember the explicit constructor call as an orphan completion node
1389
this.assistNode = call;
1390                this.lastCheckPoint = call.sourceEnd + 1;
1391                this.isOrphanCompletionNode = true;
1392                return true;
1393            } else {
1394                // creates an allocation expression
1395
CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression();
1396                allocExpr.arguments = arguments;
1397                if(this.genericsLengthPtr < 0) {
1398                    pushOnGenericsLengthStack(0);
1399                    pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
1400                }
1401                allocExpr.type = super.getTypeReference(0); // we don't want a completion node here, so call super
1402
if (invocType == QUALIFIED_ALLOCATION) {
1403                    allocExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
1404                }
1405                // no source is going to be replaced
1406
allocExpr.sourceStart = this.cursorLocation + 1;
1407                allocExpr.sourceEnd = this.cursorLocation;
1408
1409                // remember the allocation expression as an orphan completion node
1410
this.assistNode = allocExpr;
1411                this.lastCheckPoint = allocExpr.sourceEnd + 1;
1412                this.isOrphanCompletionNode = true;
1413                return true;
1414            }
1415        }
1416    }
1417    return false;
1418}
1419private boolean checkLabelStatement() {
1420    if(isInsideMethod() || isInsideFieldInitialization()) {
1421
1422        int kind = this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
1423        if(kind != K_INSIDE_BREAK_STATEMENT && kind != K_INSIDE_CONTINUE_STATEMENT) return false;
1424
1425        if (indexOfAssistIdentifier() != 0) return false;
1426
1427        char[][] labels = new char[this.labelPtr + 1][];
1428        int labelCount = 0;
1429
1430        int labelKind = kind;
1431        int index = 1;
1432        while(labelKind != 0 && labelKind != K_METHOD_DELIMITER) {
1433            labelKind = this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, index);
1434            if(labelKind == K_LABEL) {
1435                int ptr = this.topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, index);
1436                labels[labelCount++] = this.labelStack[ptr];
1437            }
1438            index++;
1439        }
1440        System.arraycopy(labels, 0, labels = new char[labelCount][], 0, labelCount);
1441
1442        long position = this.identifierPositionStack[this.identifierPtr];
1443        CompletionOnBrankStatementLabel statementLabel =
1444            new CompletionOnBrankStatementLabel(
1445                    kind == K_INSIDE_BREAK_STATEMENT ? CompletionOnBrankStatementLabel.BREAK : CompletionOnBrankStatementLabel.CONTINUE,
1446                    this.identifierStack[this.identifierPtr--],
1447                    (int) (position >>> 32),
1448                    (int)position,
1449                    labels);
1450
1451        this.assistNode = statementLabel;
1452        this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1453        this.isOrphanCompletionNode = true;
1454        return true;
1455    }
1456    return false;
1457}
1458/**
1459 * Checks if the completion is on a member access (ie. in an identifier following a dot).
1460 * Returns whether we found a completion node.
1461 */

1462private boolean checkMemberAccess() {
1463    if (this.previousToken == TokenNameDOT && this.qualifier > -1 && this.expressionPtr == this.qualifier) {
1464        if (this.identifierLengthPtr > 1 && this.identifierLengthStack[this.identifierLengthPtr - 1] < 0) {
1465            // its not a member access because the receiver is a base type
1466
// fix for bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=137623
1467
return false;
1468        }
1469        // the receiver is an expression
1470
pushCompletionOnMemberAccessOnExpressionStack(false);
1471        return true;
1472    }
1473    return false;
1474}
1475/**
1476 * Checks if the completion is on a name reference.
1477 * Returns whether we found a completion node.
1478 */

1479private boolean checkNameCompletion() {
1480    /*
1481        We didn't find any other completion, but the completion identifier is on the identifier stack,
1482        so it can only be a completion on name.
1483        Note that we allow the completion on a name even if nothing is expected (eg. foo() b[cursor] would
1484        be a completion on 'b'). This policy gives more to the user than he/she would expect, but this
1485        simplifies the problem. To fix this, the recovery must be changed to work at a 'statement' granularity
1486        instead of at the 'expression' granularity as it does right now.
1487    */

1488
1489    // NB: at this point the completion identifier is on the identifier stack
1490
this.assistNode = getUnspecifiedReferenceOptimized();
1491    this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1492    this.isOrphanCompletionNode = true;
1493    return true;
1494}
1495private boolean checkParemeterizedMethodName() {
1496    if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_METHOD_INVOCATION &&
1497            topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == INSIDE_NAME) {
1498        if(this.identifierLengthPtr > -1 && this.genericsLengthPtr > -1 && this.genericsIdentifiersLengthPtr == -1) {
1499            CompletionOnMessageSendName m = null;
1500            switch (this.invocationType) {
1501                case EXPLICIT_RECEIVER:
1502                case NO_RECEIVER: // this case occurs with 'bar().foo'
1503
if(this.expressionPtr > -1 && this.expressionLengthStack[this.expressionLengthPtr] == 1) {
1504                        char[] selector = this.identifierStack[this.identifierPtr];
1505                        long position = this.identifierPositionStack[identifierPtr--];
1506                        this.identifierLengthPtr--;
1507                        int end = (int) position;
1508                        int start = (int) (position >>> 32);
1509                        m = new CompletionOnMessageSendName(selector, start, end);
1510
1511                        // handle type arguments
1512
int length = this.genericsLengthStack[this.genericsLengthPtr--];
1513                        this.genericsPtr -= length;
1514                        System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
1515                        intPtr--;
1516
1517                        m.receiver = this.expressionStack[this.expressionPtr--];
1518                        this.expressionLengthPtr--;
1519                    }
1520                    break;
1521                case NAME_RECEIVER:
1522                    if(this.identifierPtr > 0) {
1523                        char[] selector = this.identifierStack[this.identifierPtr];
1524                        long position = this.identifierPositionStack[identifierPtr--];
1525                        this.identifierLengthPtr--;
1526                        int end = (int) position;
1527                        int start = (int) (position >>> 32);
1528                        m = new CompletionOnMessageSendName(selector, start, end);
1529
1530                        // handle type arguments
1531
int length = this.genericsLengthStack[this.genericsLengthPtr--];
1532                        this.genericsPtr -= length;
1533                        System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
1534                        intPtr--;
1535
1536                        m.receiver = getUnspecifiedReference();
1537                    }
1538                    break;
1539                case SUPER_RECEIVER:
1540                    char[] selector = this.identifierStack[this.identifierPtr];
1541                    long position = this.identifierPositionStack[identifierPtr--];
1542                    this.identifierLengthPtr--;
1543                    int end = (int) position;
1544                    int start = (int) (position >>> 32);
1545                    m = new CompletionOnMessageSendName(selector, start, end);
1546
1547                    // handle type arguments
1548
int length = this.genericsLengthStack[this.genericsLengthPtr--];
1549                    this.genericsPtr -= length;
1550                    System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
1551                    intPtr--;
1552
1553                    m.receiver = new SuperReference(start, end);
1554                    break;
1555            }
1556
1557            if(m != null) {
1558                pushOnExpressionStack(m);
1559
1560                this.assistNode = m;
1561                this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1562                this.isOrphanCompletionNode = true;
1563                return true;
1564            }
1565        }
1566    }
1567    return false;
1568}
1569private boolean checkParemeterizedType() {
1570    if(this.identifierLengthPtr > -1 && this.genericsLengthPtr > -1 && this.genericsIdentifiersLengthPtr > -1) {
1571        int length = this.identifierLengthStack[this.identifierLengthPtr];
1572        int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
1573        if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
1574            this.genericsIdentifiersLengthPtr--;
1575            this.identifierLengthPtr--;
1576            // generic type
1577
this.assistNode = getAssistTypeReferenceForGenericType(0, length, numberOfIdentifiers);
1578            this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1579            this.isOrphanCompletionNode = true;
1580            return true;
1581        } else if(this.genericsPtr > -1 && this.genericsStack[this.genericsPtr] instanceof TypeReference) {
1582            // type of a cast expression
1583
numberOfIdentifiers++;
1584
1585            this.genericsIdentifiersLengthPtr--;
1586            this.identifierLengthPtr--;
1587            // generic type
1588
this.assistNode = getAssistTypeReferenceForGenericType(0, length, numberOfIdentifiers);
1589            this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1590            this.isOrphanCompletionNode = true;
1591            return true;
1592        }
1593    }
1594    return false;
1595}
1596/**
1597 * Checks if the completion is in the context of a method and on the type of one of its arguments
1598 * Returns whether we found a completion node.
1599 */

1600private boolean checkRecoveredMethod() {
1601    if (currentElement instanceof RecoveredMethod){
1602        /* check if current awaiting identifier is the completion identifier */
1603        if (this.indexOfAssistIdentifier() < 0) return false;
1604
1605        /* check if on line with an error already - to avoid completing inside
1606            illegal type names e.g. int[<cursor> */

1607        if (lastErrorEndPosition <= cursorLocation+1
1608            && Util.getLineNumber(lastErrorEndPosition, scanner.lineEnds, 0, scanner.linePtr)
1609                    == Util.getLineNumber(((CompletionScanner)scanner).completedIdentifierStart, scanner.lineEnds, 0, scanner.linePtr)){
1610            return false;
1611        }
1612        RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
1613        /* only consider if inside method header */
1614        if (!recoveredMethod.foundOpeningBrace
1615            && lastIgnoredToken == -1) {
1616            //if (rParenPos < lParenPos){ // inside arguments
1617
this.assistNode = this.getTypeReference(0);
1618            this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1619            this.isOrphanCompletionNode = true;
1620            return true;
1621        }
1622    }
1623    return false;
1624}
1625private boolean checkMemberValueName() {
1626    /* check if current awaiting identifier is the completion identifier */
1627    if (this.indexOfAssistIdentifier() < 0) return false;
1628
1629    if (this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_BETWEEN_ANNOTATION_NAME_AND_RPAREN) return false;
1630
1631    if(this.identifierPtr > -1 && this.identifierLengthPtr > -1 && this.identifierLengthStack[this.identifierLengthPtr] == 1) {
1632        char[] simpleName = this.identifierStack[this.identifierPtr];
1633        long position = this.identifierPositionStack[this.identifierPtr--];
1634        this.identifierLengthPtr--;
1635        int end = (int) position;
1636        int start = (int) (position >>> 32);
1637
1638
1639        CompletionOnMemberValueName memberValueName = new CompletionOnMemberValueName(simpleName,start, end);
1640        this.assistNode = memberValueName;
1641        this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1642        this.isOrphanCompletionNode = true;
1643
1644        return true;
1645    }
1646    return false;
1647}
1648/**
1649 * Checks if the completion is in the context of a type and on a type reference in this type.
1650 * Persists the identifier into a fake field return type
1651 * Returns whether we found a completion node.
1652 */

1653private boolean checkRecoveredType() {
1654    if (currentElement instanceof RecoveredType){
1655        /* check if current awaiting identifier is the completion identifier */
1656        if (this.indexOfAssistIdentifier() < 0) return false;
1657
1658        /* check if on line with an error already - to avoid completing inside
1659            illegal type names e.g. int[<cursor> */

1660        if ((lastErrorEndPosition <= cursorLocation+1)
1661            && Util.getLineNumber(lastErrorEndPosition, scanner.lineEnds, 0, scanner.linePtr)
1662                    == Util.getLineNumber(((CompletionScanner)scanner).completedIdentifierStart, scanner.lineEnds, 0, scanner.linePtr)){
1663            return false;
1664        }
1665        RecoveredType recoveredType = (RecoveredType)currentElement;
1666        /* filter out cases where scanner is still inside type header */
1667        if (recoveredType.foundOpeningBrace) {
1668            // complete generics stack if necessary
1669
if((this.genericsIdentifiersLengthPtr < 0 && this.identifierPtr > -1)
1670                    || (this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] <= this.identifierPtr)) {
1671                pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
1672                pushOnGenericsLengthStack(0); // handle type arguments
1673
}
1674            this.assistNode = this.getTypeReference(0);
1675            this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1676            this.isOrphanCompletionNode = true;
1677            return true;
1678        } else {
1679            if(recoveredType.typeDeclaration.superclass == null &&
1680                    this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_EXTENDS_KEYWORD) {
1681                this.consumeClassOrInterfaceName();
1682                this.pushOnElementStack(K_NEXT_TYPEREF_IS_CLASS);
1683                this.assistNode = this.getTypeReference(0);
1684                this.popElement(K_NEXT_TYPEREF_IS_CLASS);
1685                this.lastCheckPoint = this.assistNode.sourceEnd + 1;
1686                this.isOrphanCompletionNode = true;
1687                return true;
1688            }
1689        }
1690    }
1691    return false;
1692}
1693private void classHeaderExtendsOrImplements(boolean isInterface) {
1694    if (currentElement != null
1695            && currentToken == TokenNameIdentifier
1696            && this.cursorLocation+1 >= scanner.startPosition
1697            && this.cursorLocation < scanner.currentPosition){
1698            this.pushIdentifier();
1699        int index = -1;
1700        /* check if current awaiting identifier is the completion identifier */
1701        if ((index = this.indexOfAssistIdentifier()) > -1) {
1702            int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
1703            RecoveredType recoveredType = (RecoveredType)currentElement;
1704            /* filter out cases where scanner is still inside type header */
1705            if (!recoveredType.foundOpeningBrace) {
1706                TypeDeclaration type = recoveredType.typeDeclaration;
1707                if(!isInterface) {
1708                    char[][] keywords = new char[Keywords.COUNT][];
1709                    int count = 0;
1710
1711
1712                    if(type.superInterfaces == null) {
1713                        if(type.superclass == null) {
1714                            keywords[count++] = Keywords.EXTENDS;
1715                        }
1716                        keywords[count++] = Keywords.IMPLEMENTS;
1717                    }
1718
1719                    System.arraycopy(keywords, 0, keywords = new char[count][], 0, count);
1720
1721                    if(count > 0) {
1722                        CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
1723                            identifierStack[ptr],
1724                            identifierPositionStack[ptr],
1725                            keywords);
1726                        completionOnKeyword.canCompleteEmptyToken = true;
1727                        type.superclass = completionOnKeyword;
1728                        type.superclass.bits |= ASTNode.IsSuperType;
1729                        this.assistNode = completionOnKeyword;
1730                        this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
1731                    }
1732                } else {
1733                    if(type.superInterfaces == null) {
1734                        CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
1735                            identifierStack[ptr],
1736                            identifierPositionStack[ptr],
1737                            Keywords.EXTENDS);
1738                        completionOnKeyword.canCompleteEmptyToken = true;
1739                        type.superInterfaces = new TypeReference[]{completionOnKeyword};
1740                        type.superInterfaces[0].bits |= ASTNode.IsSuperType;
1741                        this.assistNode = completionOnKeyword;
1742                        this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
1743                    }
1744                }
1745            }
1746        }
1747    }
1748}
1749/*
1750 * Check whether about to shift beyond the completion token.
1751 * If so, depending on the context, a special node might need to be created
1752 * and attached to the existing recovered structure so as to be remember in the
1753 * resulting parsed structure.
1754 */

1755public void completionIdentifierCheck(){
1756    //if (assistNode != null) return;
1757

1758    if (checkMemberValueName()) return;
1759    if (checkKeyword()) return;
1760    if (checkRecoveredType()) return;
1761    if (checkRecoveredMethod()) return;
1762
1763    // if not in a method in non diet mode and if not inside a field initializer, only record references attached to types
1764
if (!(isInsideMethod() && !this.diet)
1765        && !isIndirectlyInsideFieldInitialization()
1766        && !isInsideAttributeValue()) return;
1767
1768    /*
1769        In some cases, the completion identifier may not have yet been consumed,
1770        e.g. int.[cursor]
1771        This is because the grammar does not allow any (empty) identifier to follow
1772        a base type. We thus have to manually force the identifier to be consumed
1773        (that is, pushed).
1774     */

1775    if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
1776
if (cursorLocation < this.scanner.startPosition && this.scanner.currentPosition == this.scanner.startPosition){ // fake empty identifier got issued
1777
this.pushIdentifier();
1778        } else if (cursorLocation+1 >= this.scanner.startPosition && cursorLocation < this.scanner.currentPosition){
1779            this.pushIdentifier();
1780        }
1781    }
1782
1783    // check for different scenarii
1784
// no need to go further if we found a non empty completion node
1785
// (we still need to store labels though)
1786
if (this.assistNode != null) {
1787        // however inside an invocation, the completion identifier may already have been consumed into an empty name
1788
// completion, so this check should be before we check that we are at the cursor location
1789
if (!isEmptyNameCompletion() || checkInvocation()) return;
1790    }
1791
1792    // no need to check further if we are not at the cursor location
1793
if (this.indexOfAssistIdentifier() < 0) return;
1794
1795    if (checkClassInstanceCreation()) return;
1796    if (checkCatchClause()) return;
1797    if (checkMemberAccess()) return;
1798    if (checkClassLiteralAccess()) return;
1799    if (checkInstanceofKeyword()) return;
1800
1801    // if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor])
1802
// (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
1803
if (checkInvocation()) return;
1804
1805    if (checkParemeterizedType()) return;
1806    if (checkParemeterizedMethodName()) return;
1807    if (checkLabelStatement()) return;
1808    if (checkNameCompletion()) return;
1809}
1810protected void consumeArrayCreationExpressionWithInitializer() {
1811    super.consumeArrayCreationExpressionWithInitializer();
1812    popElement(K_ARRAY_CREATION);
1813}
1814protected void consumeArrayCreationExpressionWithoutInitializer() {
1815    super.consumeArrayCreationExpressionWithoutInitializer();
1816    popElement(K_ARRAY_CREATION);
1817}
1818protected void consumeArrayCreationHeader() {
1819    // nothing to do
1820
}
1821protected void consumeAssignment() {
1822    popElement(K_ASSISGNMENT_OPERATOR);
1823    super.consumeAssignment();
1824}
1825protected void consumeAssignmentOperator(int pos) {
1826    super.consumeAssignmentOperator(pos);
1827    pushOnElementStack(K_ASSISGNMENT_OPERATOR, pos);
1828}
1829protected void consumeBinaryExpression(int op) {
1830    super.consumeBinaryExpression(op);
1831    popElement(K_BINARY_OPERATOR);
1832
1833    if(expressionStack[expressionPtr] instanceof BinaryExpression) {
1834        BinaryExpression exp = (BinaryExpression) expressionStack[expressionPtr];
1835        if(assistNode != null && exp.right == assistNode) {
1836            assistNodeParent = exp;
1837        }
1838    }
1839}
1840protected void consumeBinaryExpressionWithName(int op) {
1841    super.consumeBinaryExpressionWithName(op);
1842    popElement(K_BINARY_OPERATOR);
1843
1844    if(expressionStack[expressionPtr] instanceof BinaryExpression) {
1845        BinaryExpression exp = (BinaryExpression) expressionStack[expressionPtr];
1846        if(assistNode != null && exp.right == assistNode) {
1847            assistNodeParent = exp;
1848        }
1849    }
1850}
1851protected void consumeCaseLabel() {
1852    super.consumeCaseLabel();
1853    if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_SWITCH_LABEL) {
1854        pushOnElementStack(K_SWITCH_LABEL);
1855    }
1856}
1857protected void consumeCastExpressionWithPrimitiveType() {
1858    popElement(K_CAST_STATEMENT);
1859
1860    Expression exp, cast, castType;
1861    expressionPtr--;
1862    expressionLengthPtr--;
1863    expressionStack[expressionPtr] = cast = new CastExpression(exp = expressionStack[expressionPtr+1], castType = expressionStack[expressionPtr]);
1864    cast.sourceStart = castType.sourceStart - 1;
1865    cast.sourceEnd = exp.sourceEnd;
1866}
1867protected void consumeCastExpressionWithGenericsArray() {
1868    popElement(K_CAST_STATEMENT);
1869
1870    Expression exp, cast, castType;
1871    expressionPtr--;
1872    expressionLengthPtr--;
1873    this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr + 1], castType = this.expressionStack[this.expressionPtr]);
1874    cast.sourceStart = castType.sourceStart - 1;
1875    cast.sourceEnd = exp.sourceEnd;
1876}
1877
1878protected void consumeCastExpressionWithQualifiedGenericsArray() {
1879    popElement(K_CAST_STATEMENT);
1880
1881    Expression exp, cast, castType;
1882    expressionPtr--;
1883    expressionLengthPtr--;
1884    this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr + 1], castType = this.expressionStack[this.expressionPtr]);
1885    cast.sourceStart = castType.sourceStart - 1;
1886    cast.sourceEnd = exp.sourceEnd;
1887}
1888protected void consumeCastExpressionWithNameArray() {
1889    // CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
1890
popElement(K_CAST_STATEMENT);
1891
1892    Expression exp, cast, castType;
1893
1894    expressionPtr--;
1895    expressionLengthPtr--;
1896    expressionStack[expressionPtr] = cast = new CastExpression(exp = expressionStack[expressionPtr+1], castType = this.expressionStack[this.expressionPtr]);
1897    cast.sourceStart = castType.sourceStart - 1;
1898    cast.sourceEnd = exp.sourceEnd;
1899}
1900protected void consumeCastExpressionLL1() {
1901    popElement(K_CAST_STATEMENT);
1902    super.consumeCastExpressionLL1();
1903}
1904protected void consumeClassBodyDeclaration() {
1905    popElement(K_BLOCK_DELIMITER);
1906    super.consumeClassBodyDeclaration();
1907    this.pendingAnnotation = null; // the pending annotation cannot be attached to next nodes
1908
}
1909protected void consumeClassBodyopt() {
1910    popElement(K_SELECTOR_QUALIFIER);
1911    popElement(K_SELECTOR_INVOCATION_TYPE);
1912    super.consumeClassBodyopt();
1913}
1914/* (non-Javadoc)
1915 * @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeClassDeclaration()
1916 */

1917protected void consumeClassDeclaration() {
1918    if (this.astPtr >= 0) {
1919        int length = this.astLengthStack[this.astLengthPtr];
1920        TypeDeclaration typeDeclaration = (TypeDeclaration) this.astStack[this.astPtr-length];
1921        this.javadoc = null;
1922        CompletionJavadocParser completionJavadocParser = (CompletionJavadocParser)this.javadocParser;
1923        completionJavadocParser.allPossibleTags = true;
1924        checkComment();
1925        if (this.javadoc != null && this.cursorLocation > this.javadoc.sourceStart && this.cursorLocation < this.javadoc.sourceEnd) {
1926            // completion is in an orphan javadoc comment => replace in last read declaration to allow completion resolution
1927
typeDeclaration.javadoc = this.javadoc;
1928        }
1929        completionJavadocParser.allPossibleTags = false;
1930    }
1931    super.consumeClassDeclaration();
1932}
1933protected void consumeClassHeaderName1() {
1934    super.consumeClassHeaderName1();
1935    if (this.pendingAnnotation != null) {
1936        this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
1937        this.pendingAnnotation = null;
1938    }
1939    classHeaderExtendsOrImplements(false);
1940}
1941
1942protected void consumeClassHeaderExtends() {
1943    pushOnElementStack(K_NEXT_TYPEREF_IS_CLASS);
1944    super.consumeClassHeaderExtends();
1945    popElement(K_NEXT_TYPEREF_IS_CLASS);
1946    popElement(K_EXTENDS_KEYWORD);
1947
1948    if (currentElement != null
1949        && currentToken == TokenNameIdentifier
1950        && this.cursorLocation+1 >= scanner.startPosition
1951        && this.cursorLocation < scanner.currentPosition){
1952        this.pushIdentifier();
1953
1954        int index = -1;
1955        /* check if current awaiting identifier is the completion identifier */
1956        if ((index = this.indexOfAssistIdentifier()) > -1) {
1957            int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
1958            RecoveredType recoveredType = (RecoveredType)currentElement;
1959            /* filter out cases where scanner is still inside type header */
1960            if (!recoveredType.foundOpeningBrace) {
1961                TypeDeclaration type = recoveredType.typeDeclaration;
1962                if(type.superInterfaces == null) {
1963                    type.superclass = new CompletionOnKeyword1(
1964                        identifierStack[ptr],
1965                        identifierPositionStack[ptr],
1966                        Keywords.IMPLEMENTS);
1967                    type.superclass.bits |= ASTNode.IsSuperType;
1968                    this.assistNode = type.superclass;
1969                    this.lastCheckPoint = type.superclass.sourceEnd + 1;
1970                }
1971            }
1972        }
1973    }
1974}
1975protected void consumeClassTypeElt() {
1976    pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
1977    super.consumeClassTypeElt();
1978    popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
1979}
1980
1981/* (non-Javadoc)
1982 * @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeCompilationUnit()
1983 */

1984protected void consumeCompilationUnit() {
1985    this.javadoc = null;
1986    checkComment();
1987    if (this.javadoc != null && this.cursorLocation > this.javadoc.sourceStart && this.cursorLocation < this.javadoc.sourceEnd) {
1988        // completion is in an orphan javadoc comment => replace compilation unit one to allow completion resolution
1989
compilationUnit.javadoc = this.javadoc;
1990        // create a fake interface declaration to allow resolution
1991
if (this.compilationUnit.types == null) {
1992            this.compilationUnit.types = new TypeDeclaration[1];
1993            TypeDeclaration declaration = new TypeDeclaration(compilationUnit.compilationResult);
1994            declaration.name = FAKE_TYPE_NAME;
1995            declaration.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccInterface;
1996            this.compilationUnit.types[0] = declaration;
1997        }
1998    }
1999    super.consumeCompilationUnit();
2000}
2001protected void consumeConditionalExpression(int op) {
2002    popElement(K_CONDITIONAL_OPERATOR);
2003    super.consumeConditionalExpression(op);
2004}
2005protected void consumeConditionalExpressionWithName(int op) {
2006    popElement(K_CONDITIONAL_OPERATOR);
2007    super.consumeConditionalExpressionWithName(op);
2008}
2009protected void consumeConstructorBody() {
2010    popElement(K_BLOCK_DELIMITER);
2011    super.consumeConstructorBody();
2012}
2013protected void consumeConstructorHeader() {
2014    super.consumeConstructorHeader();
2015    pushOnElementStack(K_BLOCK_DELIMITER);
2016}
2017protected void consumeConstructorHeaderName() {
2018
2019    /* no need to take action if not inside assist identifiers */
2020    if (indexOfAssistIdentifier() < 0) {
2021        /* recovering - might be an empty message send */
2022        if (this.currentElement != null && this.lastIgnoredToken == TokenNamenew){ // was an allocation expression
2023
super.consumeConstructorHeaderName();
2024        } else {
2025            super.consumeConstructorHeaderName();
2026            if (this.pendingAnnotation != null) {
2027                this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2028                this.pendingAnnotation = null;
2029            }
2030        }
2031        return;
2032    }
2033
2034    /* force to start recovering in order to get fake field behavior */
2035    if (currentElement == null){
2036        this.hasReportedError = true; // do not report any error
2037
}
2038    pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
2039    pushOnGenericsLengthStack(0); // handle type arguments
2040
this.restartRecovery = true;
2041}
2042protected void consumeConstructorHeaderNameWithTypeParameters() {
2043    if (this.currentElement != null && this.lastIgnoredToken == TokenNamenew){ // was an allocation expression
2044
super.consumeConstructorHeaderNameWithTypeParameters();
2045    } else {
2046        super.consumeConstructorHeaderNameWithTypeParameters();
2047        if (this.pendingAnnotation != null) {
2048            this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2049            this.pendingAnnotation = null;
2050        }
2051    }
2052}
2053protected void consumeDefaultLabel() {
2054    super.consumeDefaultLabel();
2055    if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SWITCH_LABEL) {
2056        popElement(K_SWITCH_LABEL);
2057    }
2058    pushOnElementStack(K_SWITCH_LABEL, DEFAULT);
2059}
2060protected void consumeDimWithOrWithOutExpr() {
2061    // DimWithOrWithOutExpr ::= '[' ']'
2062
pushOnExpressionStack(null);
2063}
2064protected void consumeEnhancedForStatementHeaderInit(boolean hasModifiers) {
2065    super.consumeEnhancedForStatementHeaderInit(hasModifiers);
2066    if (this.pendingAnnotation != null) {
2067        this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2068        this.pendingAnnotation = null;
2069    }
2070}
2071protected void consumeEnterAnonymousClassBody() {
2072    popElement(K_SELECTOR_QUALIFIER);
2073    popElement(K_SELECTOR_INVOCATION_TYPE);
2074    super.consumeEnterAnonymousClassBody();
2075}
2076protected void consumeEnterVariable() {
2077    identifierPtr--;
2078    identifierLengthPtr--;
2079
2080    boolean isLocalDeclaration = nestedMethod[nestedType] != 0;
2081    int variableIndex = variablesCounter[nestedType];
2082    int extendedDimension = intStack[intPtr + 1];
2083
2084    if(isLocalDeclaration || indexOfAssistIdentifier() < 0 || variableIndex != 0 || extendedDimension != 0) {
2085        identifierPtr++;
2086        identifierLengthPtr++;
2087        
2088        if (this.pendingAnnotation != null &&
2089                this.assistNode != null &&
2090                this.currentElement != null &&
2091                this.currentElement instanceof RecoveredMethod &&
2092                !this.currentElement.foundOpeningBrace &&
2093                ((RecoveredMethod)this.currentElement).methodDeclaration.declarationSourceEnd == 0) {
2094            // this is a method parameter
2095
super.consumeEnterVariable();
2096            this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2097            this.pendingAnnotation.isParameter = true;
2098            this.pendingAnnotation = null;
2099            
2100        } else {
2101            super.consumeEnterVariable();
2102            if (this.pendingAnnotation != null) {
2103                this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2104                this.pendingAnnotation = null;
2105            }
2106        }
2107    } else {
2108        restartRecovery = true;
2109
2110        // recovery
2111
if (currentElement != null) {
2112            if(!checkKeyword() && !(currentElement instanceof RecoveredUnit && ((RecoveredUnit)currentElement).typeCount == 0)) {
2113                int nameSourceStart = (int)(identifierPositionStack[identifierPtr] >>> 32);
2114                intPtr--;
2115                TypeReference type = getTypeReference(intStack[intPtr--]);
2116                intPtr--;
2117
2118                if (!(currentElement instanceof RecoveredType)
2119                    && (currentToken == TokenNameDOT
2120                        || (Util.getLineNumber(type.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
2121                                != Util.getLineNumber(nameSourceStart, scanner.lineEnds, 0, scanner.linePtr)))){
2122                    lastCheckPoint = nameSourceStart;
2123                    restartRecovery = true;
2124                    return;
2125                }
2126
2127                FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
2128                completionFieldDecl.modifiers = intStack[intPtr--];
2129                assistNode = completionFieldDecl;
2130                lastCheckPoint = type.sourceEnd + 1;
2131                currentElement = currentElement.add(completionFieldDecl, 0);
2132                lastIgnoredToken = -1;
2133            }
2134        }
2135    }
2136}
2137protected void consumeEnumConstantHeaderName() {
2138    if (this.currentElement != null) {
2139        if (!(this.currentElement instanceof RecoveredType
2140                    || (this.currentElement instanceof RecoveredField && ((RecoveredField)currentElement).fieldDeclaration.type == null))
2141                || (this.lastIgnoredToken == TokenNameDOT)) {
2142            super.consumeEnumConstantHeaderName();
2143            return;
2144        }
2145    }
2146    super.consumeEnumConstantHeaderName();
2147    if (this.pendingAnnotation != null) {
2148        this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2149        this.pendingAnnotation = null;
2150    }
2151}
2152protected void consumeEnumHeaderName() {
2153    super.consumeEnumHeaderName();
2154    if (this.pendingAnnotation != null) {
2155        this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2156        this.pendingAnnotation = null;
2157    }
2158}
2159protected void consumeEqualityExpression(int op) {
2160    super.consumeEqualityExpression(op);
2161    popElement(K_BINARY_OPERATOR);
2162
2163    BinaryExpression exp = (BinaryExpression) expressionStack[expressionPtr];
2164    if(assistNode != null && exp.right == assistNode) {
2165        assistNodeParent = exp;
2166    }
2167}
2168protected void consumeEqualityExpressionWithName(int op) {
2169    super.consumeEqualityExpressionWithName(op);
2170    popElement(K_BINARY_OPERATOR);
2171
2172    BinaryExpression exp = (BinaryExpression) expressionStack[expressionPtr];
2173    if(assistNode != null && exp.right == assistNode) {
2174        assistNodeParent = exp;
2175    }
2176}
2177protected void consumeExitVariableWithInitialization() {
2178    super.consumeExitVariableWithInitialization();
2179
2180    // does not keep the initialization if completion is not inside
2181
AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
2182    if (cursorLocation + 1 < variable.initialization.sourceStart ||
2183        cursorLocation > variable.initialization.sourceEnd) {
2184        variable.initialization = null;
2185    } else if (assistNode != null && assistNode == variable.initialization) {
2186        assistNodeParent = variable;
2187    }
2188}
2189protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
2190    popElement(K_SELECTOR_QUALIFIER);
2191    popElement(K_SELECTOR_INVOCATION_TYPE);
2192    super.consumeExplicitConstructorInvocation(flag, recFlag);
2193}
2194/*
2195 * Copy of code from superclass with the following change:
2196 * If the cursor location is on the field access, then create a
2197 * CompletionOnMemberAccess instead.
2198 */

2199protected void consumeFieldAccess(boolean isSuperAccess) {
2200    // FieldAccess ::= Primary '.' 'Identifier'
2201
// FieldAccess ::= 'super' '.' 'Identifier'
2202

2203    // potential receiver is being poped, so reset potential receiver
2204
this.invocationType = NO_RECEIVER;
2205    this.qualifier = -1;
2206
2207    if (this.indexOfAssistIdentifier() < 0) {
2208        super.consumeFieldAccess(isSuperAccess);
2209    } else {
2210        this.pushCompletionOnMemberAccessOnExpressionStack(isSuperAccess);
2211    }
2212}
2213protected void consumeForceNoDiet() {
2214    super.consumeForceNoDiet();
2215    if (isInsideMethod()) {
2216        pushOnElementStack(K_LOCAL_INITIALIZER_DELIMITER);
2217    }
2218}
2219protected void consumeFormalParameter(boolean isVarArgs) {
2220    if (this.indexOfAssistIdentifier() < 0) {
2221        super.consumeFormalParameter(isVarArgs);
2222        if (this.pendingAnnotation != null) {
2223            this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2224            this.pendingAnnotation = null;
2225        }
2226    } else {
2227
2228        identifierLengthPtr--;
2229        char[] identifierName = identifierStack[identifierPtr];
2230        long namePositions = identifierPositionStack[identifierPtr--];
2231        int extendedDimensions = this.intStack[this.intPtr--];
2232        int endOfEllipsis = 0;
2233        if (isVarArgs) {
2234            endOfEllipsis = this.intStack[this.intPtr--];
2235        }
2236        int firstDimensions = this.intStack[this.intPtr--];
2237        final int typeDimensions = firstDimensions + extendedDimensions;
2238        TypeReference type = getTypeReference(typeDimensions);
2239        if (isVarArgs) {
2240            type = copyDims(type, typeDimensions + 1);
2241            if (extendedDimensions == 0) {
2242                type.sourceEnd = endOfEllipsis;
2243            }
2244            type.bits |= ASTNode.IsVarArgs; // set isVarArgs
2245
}
2246        intPtr -= 2;
2247        CompletionOnArgumentName arg =
2248            new CompletionOnArgumentName(
2249                identifierName,
2250                namePositions,
2251                type,
2252                intStack[intPtr + 1] & ~ClassFileConstants.AccDeprecated); // modifiers
2253
// consume annotations
2254
int length;
2255        if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
2256            System.arraycopy(
2257                this.expressionStack,
2258                (this.expressionPtr -= length) + 1,
2259                arg.annotations = new Annotation[length],
2260                0,
2261                length);
2262        }
2263
2264        arg.isCatchArgument = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_CATCH_AND_RIGHT_PAREN;
2265        pushOnAstStack(arg);
2266
2267        assistNode = arg;
2268        this.lastCheckPoint = (int) namePositions;
2269        isOrphanCompletionNode = true;
2270
2271        /* if incomplete method header, listLength counter will not have been reset,
2272            indicating that some arguments are available on the stack */

2273        listLength++;
2274    }
2275}
2276protected void consumeInsideCastExpression() {
2277    int end = intStack[intPtr--];
2278    boolean isParameterized =(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_CAST);
2279    if(isParameterized) {
2280        popElement(K_PARAMETERIZED_CAST);
2281
2282        if(this.identifierLengthStack[this.identifierLengthPtr] > 0) {
2283            pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
2284        }
2285    } else {
2286        if(this.identifierLengthStack[this.identifierLengthPtr] > 0) {
2287            pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
2288            pushOnGenericsLengthStack(0);
2289        }
2290    }
2291    Expression castType = getTypeReference(intStack[intPtr--]);
2292    if(isParameterized) {
2293        intPtr--;
2294    }
2295    castType.sourceEnd = end - 1;
2296    castType.sourceStart = intStack[intPtr--] + 1;
2297    pushOnExpressionStack(castType);
2298
2299    pushOnElementStack(K_CAST_STATEMENT);
2300}
2301protected void consumeInsideCastExpressionLL1() {
2302    if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_CAST) {
2303        popElement(K_PARAMETERIZED_CAST);
2304    }
2305    if (!this.record) {
2306        super.consumeInsideCastExpressionLL1();
2307    } else {
2308        boolean temp = this.skipRecord;
2309        try {
2310            this.skipRecord = true;
2311            super.consumeInsideCastExpressionLL1();
2312            if (this.record) {
2313                Expression typeReference = this.expressionStack[this.expressionPtr];
2314                if (!isAlreadyPotentialName(typeReference.sourceStart)) {
2315                    this.addPotentialName(null, typeReference.sourceStart, typeReference.sourceEnd);
2316                }
2317            }
2318        } finally {
2319            this.skipRecord = temp;
2320        }
2321    }
2322    pushOnElementStack(K_CAST_STATEMENT);
2323}
2324protected void consumeInsideCastExpressionWithQualifiedGenerics() {
2325    popElement(K_PARAMETERIZED_CAST);
2326
2327    Expression castType;
2328    int end = this.intStack[this.intPtr--];
2329
2330    int dim = this.intStack[this.intPtr--];
2331    TypeReference rightSide = getTypeReference(0);
2332
2333    castType = computeQualifiedGenericsFromRightSide(rightSide, dim);
2334    this.intPtr--;
2335    castType.sourceEnd = end - 1;
2336    castType.sourceStart = this.intStack[this.intPtr--] + 1;
2337    pushOnExpressionStack(castType);
2338
2339    pushOnElementStack(K_CAST_STATEMENT);
2340}
2341protected void consumeInstanceOfExpression() {
2342    super.consumeInstanceOfExpression();
2343    popElement(K_BINARY_OPERATOR);
2344
2345    InstanceOfExpression exp = (InstanceOfExpression) expressionStack[expressionPtr];
2346    if(assistNode != null && exp.type == assistNode) {
2347        assistNodeParent = exp;
2348    }
2349}
2350protected void consumeInstanceOfExpressionWithName() {
2351    super.consumeInstanceOfExpressionWithName();
2352    popElement(K_BINARY_OPERATOR);
2353
2354    InstanceOfExpression exp = (InstanceOfExpression) expressionStack[expressionPtr];
2355    if(assistNode != null && exp.type == assistNode) {
2356        assistNodeParent = exp;
2357    }
2358}
2359protected void consumeInterfaceHeaderName1() {
2360    super.consumeInterfaceHeaderName1();
2361    if (this.pendingAnnotation != null) {
2362        this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2363        this.pendingAnnotation = null;
2364    }
2365    classHeaderExtendsOrImplements(true);
2366}
2367protected void consumeInterfaceHeaderExtends() {
2368    super.consumeInterfaceHeaderExtends();
2369    popElement(K_EXTENDS_KEYWORD);
2370}
2371protected void consumeInterfaceType() {
2372    pushOnElementStack(K_NEXT_TYPEREF_IS_INTERFACE);
2373    super.consumeInterfaceType();
2374    popElement(K_NEXT_TYPEREF_IS_INTERFACE);
2375}
2376protected void consumeMethodInvocationName() {
2377    popElement(K_SELECTOR_QUALIFIER);
2378    popElement(K_SELECTOR_INVOCATION_TYPE);
2379    super.consumeMethodInvocationName();
2380}
2381protected void consumeMethodInvocationNameWithTypeArguments() {
2382    popElement(K_SELECTOR_QUALIFIER);
2383    popElement(K_SELECTOR_INVOCATION_TYPE);
2384    super.consumeMethodInvocationNameWithTypeArguments();
2385}
2386protected void consumeMethodInvocationPrimary() {
2387    popElement(K_SELECTOR_QUALIFIER);
2388    popElement(K_SELECTOR_INVOCATION_TYPE);
2389    super.consumeMethodInvocationPrimary();
2390}
2391protected void consumeMethodInvocationPrimaryWithTypeArguments() {
2392    popElement(K_SELECTOR_QUALIFIER);
2393    popElement(K_SELECTOR_INVOCATION_TYPE);
2394    super.consumeMethodInvocationPrimaryWithTypeArguments();
2395}
2396protected void consumeMethodInvocationSuper() {
2397    popElement(K_SELECTOR_QUALIFIER);
2398    popElement(K_SELECTOR_INVOCATION_TYPE);
2399    super.consumeMethodInvocationSuper();
2400}
2401protected void consumeMethodInvocationSuperWithTypeArguments() {
2402    popElement(K_SELECTOR_QUALIFIER);
2403    popElement(K_SELECTOR_INVOCATION_TYPE);
2404    super.consumeMethodInvocationSuperWithTypeArguments();
2405}
2406protected void consumeMethodHeaderName(boolean isAnnotationMethod) {
2407    if(this.indexOfAssistIdentifier() < 0) {
2408        identifierPtr--;
2409        identifierLengthPtr--;
2410        if(this.indexOfAssistIdentifier() != 0 ||
2411            this.identifierLengthStack[this.identifierLengthPtr] != this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr]) {
2412            identifierPtr++;
2413            identifierLengthPtr++;
2414            super.consumeMethodHeaderName(isAnnotationMethod);
2415            if (this.pendingAnnotation != null) {
2416                this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2417                this.pendingAnnotation = null;
2418            }
2419        } else {
2420            restartRecovery = true;
2421
2422            // recovery
2423
if (currentElement != null) {
2424                //name
2425
char[] selector = identifierStack[identifierPtr + 1];
2426                long selectorSource = identifierPositionStack[identifierPtr + 1];
2427
2428                //type
2429
TypeReference type = getTypeReference(intStack[intPtr--]);
2430                ((CompletionOnSingleTypeReference)type).isCompletionNode = false;
2431                //modifiers
2432
int declarationSourceStart = intStack[intPtr--];
2433                int mod = intStack[intPtr--];
2434
2435                if(Util.getLineNumber(type.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
2436                        != Util.getLineNumber((int) (selectorSource >>> 32), scanner.lineEnds, 0, scanner.linePtr)) {
2437                    FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
2438                    // consume annotations
2439
int length;
2440                    if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
2441                        System.arraycopy(
2442                            this.expressionStack,
2443                            (this.expressionPtr -= length) + 1,
2444                            completionFieldDecl.annotations = new Annotation[length],
2445                            0,
2446                            length);
2447                    }
2448                    completionFieldDecl.modifiers = mod;
2449                    assistNode = completionFieldDecl;
2450                    lastCheckPoint = type.sourceEnd + 1;
2451                    currentElement = currentElement.add(completionFieldDecl, 0);
2452                    lastIgnoredToken = -1;
2453                } else {
2454                    CompletionOnMethodReturnType md = new CompletionOnMethodReturnType(type, this.compilationUnit.compilationResult);
2455                    // consume annotations
2456
int length;
2457                    if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
2458                        System.arraycopy(
2459                            this.expressionStack,
2460                            (this.expressionPtr -= length) + 1,
2461                            md.annotations = new Annotation[length],
2462                            0,
2463                            length);
2464                    }
2465                    md.selector = selector;
2466                    md.declarationSourceStart = declarationSourceStart;
2467                    md.modifiers = mod;
2468                    md.bodyStart = lParenPos+1;
2469                    listLength = 0; // initialize listLength before reading parameters/throws
2470
assistNode = md;
2471                    this.lastCheckPoint = md.bodyStart;
2472                    currentElement = currentElement.add(md, 0);
2473                    lastIgnoredToken = -1;
2474                    // javadoc
2475
md.javadoc = this.javadoc;
2476                    this.javadoc = null;
2477                }
2478            }
2479        }
2480    } else {
2481        // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
2482
CompletionOnMethodName md = new CompletionOnMethodName(this.compilationUnit.compilationResult);
2483
2484        //name
2485
md.selector = identifierStack[identifierPtr];
2486        long selectorSource = identifierPositionStack[identifierPtr--];
2487        identifierLengthPtr--;
2488        //type
2489
md.returnType = getTypeReference(intStack[intPtr--]);
2490        //modifiers
2491
md.declarationSourceStart = intStack[intPtr--];
2492        md.modifiers = intStack[intPtr--];
2493        // consume annotations
2494
int length;
2495        if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
2496            System.arraycopy(
2497                this.expressionStack,
2498                (this.expressionPtr -= length) + 1,
2499                md.annotations = new Annotation[length],
2500                0,
2501                length);
2502        }
2503        // javadoc
2504
md.javadoc = this.javadoc;
2505        this.javadoc = null;
2506
2507        //highlight starts at selector start
2508
md.sourceStart = (int) (selectorSource >>> 32);
2509        md.selectorEnd = (int) selectorSource;
2510        pushOnAstStack(md);
2511        md.sourceEnd = lParenPos;
2512        md.bodyStart = lParenPos+1;
2513        listLength = 0; // initialize listLength before reading parameters/throws
2514

2515        this.assistNode = md;
2516        this.lastCheckPoint = md.sourceEnd;
2517        // recovery
2518
if (currentElement != null){
2519            if (currentElement instanceof RecoveredType
2520                //|| md.modifiers != 0
2521
|| (Util.getLineNumber(md.returnType.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
2522                        == Util.getLineNumber(md.sourceStart, scanner.lineEnds, 0, scanner.linePtr))){
2523                lastCheckPoint = md.bodyStart;
2524                currentElement = currentElement.add(md, 0);
2525                lastIgnoredToken = -1;
2526            } else {
2527                lastCheckPoint = md.sourceStart;
2528                restartRecovery = true;
2529            }
2530        }
2531    }
2532}
2533protected void consumeMethodHeaderNameWithTypeParameters( boolean isAnnotationMethod) {
2534    super.consumeMethodHeaderNameWithTypeParameters(isAnnotationMethod);
2535    if (this.pendingAnnotation != null) {
2536        this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2537        this.pendingAnnotation = null;
2538    }
2539}
2540protected void consumeMethodHeaderRightParen() {
2541    super.consumeMethodHeaderRightParen();
2542
2543    if (currentElement != null
2544        && currentToken == TokenNameIdentifier
2545        && this.cursorLocation+1 >= scanner.startPosition
2546        && this.cursorLocation < scanner.currentPosition){
2547        this.pushIdentifier();
2548
2549        int index = -1;
2550        /* check if current awaiting identifier is the completion identifier */
2551        if ((index = this.indexOfAssistIdentifier()) > -1) {
2552            int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
2553            if (currentElement instanceof RecoveredMethod){
2554                RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
2555                /* filter out cases where scanner is still inside type header */
2556                if (!recoveredMethod.foundOpeningBrace) {
2557                    AbstractMethodDeclaration method = recoveredMethod.methodDeclaration;
2558                    if(method.thrownExceptions == null) {
2559                        CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
2560                            identifierStack[ptr],
2561                            identifierPositionStack[ptr],
2562                            Keywords.THROWS);
2563                        method.thrownExceptions = new TypeReference[]{completionOnKeyword};
2564                        recoveredMethod.foundOpeningBrace = true;
2565                        this.assistNode = completionOnKeyword;
2566                        this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
2567                    }
2568                }
2569            }
2570        }
2571    }
2572}
2573protected void consumeMethodHeaderExtendedDims() {
2574    super.consumeMethodHeaderExtendedDims();
2575
2576    if (currentElement != null
2577        && currentToken == TokenNameIdentifier
2578        && this.cursorLocation+1 >= scanner.startPosition
2579        && this.cursorLocation < scanner.currentPosition){
2580        this.pushIdentifier();
2581
2582        int index = -1;
2583        /* check if current awaiting identifier is the completion identifier */
2584        if ((index = this.indexOfAssistIdentifier()) > -1) {
2585            int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
2586            RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
2587            /* filter out cases where scanner is still inside type header */
2588            if (!recoveredMethod.foundOpeningBrace) {
2589                AbstractMethodDeclaration method = recoveredMethod.methodDeclaration;
2590                if(method.thrownExceptions == null) {
2591                    CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
2592                        identifierStack[ptr],
2593                        identifierPositionStack[ptr],
2594                        Keywords.THROWS);
2595                    method.thrownExceptions = new TypeReference[]{completionOnKeyword};
2596                    recoveredMethod.foundOpeningBrace = true;
2597                    this.assistNode = completionOnKeyword;
2598                    this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
2599                }
2600            }
2601        }
2602    }
2603}
2604protected void consumeAnnotationName() {
2605    int index;
2606
2607    if ((index = this.indexOfAssistIdentifier()) < 0) {
2608        super.consumeAnnotationName();
2609        this.pushOnElementStack(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN, LPAREN_NOT_CONSUMED);
2610        return;
2611    }
2612
2613    MarkerAnnotation markerAnnotation = null;
2614    int length = this.identifierLengthStack[this.identifierLengthPtr];
2615    TypeReference typeReference;
2616
2617    /* retrieve identifiers subset and whole positions, the assist node positions
2618        should include the entire replaced source. */

2619
2620    char[][] subset = identifierSubSet(index);
2621    identifierLengthPtr--;
2622    identifierPtr -= length;
2623    long[] positions = new long[length];
2624    System.arraycopy(
2625        identifierPositionStack,
2626        identifierPtr + 1,
2627        positions,
2628        0,
2629        length);
2630
2631    /* build specific assist on type reference */
2632
2633    if (index == 0) {
2634        /* assist inside first identifier */
2635        typeReference = this.createSingleAssistTypeReference(
2636                        assistIdentifier(),
2637                        positions[0]);
2638    } else {
2639        /* assist inside subsequent identifier */
2640        typeReference = this.createQualifiedAssistTypeReference(
2641                        subset,
2642                        assistIdentifier(),
2643                        positions);
2644    }
2645
2646    markerAnnotation = new CompletionOnMarkerAnnotationName(typeReference, typeReference.sourceStart);
2647    this.intPtr--;
2648    markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd;
2649    pushOnExpressionStack(markerAnnotation);
2650
2651    assistNode = markerAnnotation;
2652    this.isOrphanCompletionNode = true;
2653
2654    this.lastCheckPoint = markerAnnotation.sourceEnd + 1;
2655    
2656    this.pushOnElementStack(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN, LPAREN_NOT_CONSUMED | ANNOTATION_NAME_COMPLETION);
2657}
2658protected void consumeAnnotationTypeDeclarationHeaderName() {
2659    super.consumeAnnotationTypeDeclarationHeaderName();
2660    if (this.pendingAnnotation != null) {
2661        this.pendingAnnotation.potentialAnnotatedNode = this.astStack[this.astPtr];
2662        this.pendingAnnotation = null;
2663    }
2664}
2665protected void consumeLabel() {
2666    super.consumeLabel();
2667    this.pushOnLabelStack(this.identifierStack[this.identifierPtr]);
2668    this.pushOnElementStack(K_LABEL, this.labelPtr);
2669}
2670protected void consumeMarkerAnnotation() {
2671    if (this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN &&
2672            (this.topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) & ANNOTATION_NAME_COMPLETION) != 0 ) {
2673        this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
2674        this.restartRecovery = true;
2675    } else {
2676        this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
2677        super.consumeMarkerAnnotation();
2678    }
2679}
2680protected void consumeMemberValuePair() {
2681    /* check if current awaiting identifier is the completion identifier */
2682    if (this.indexOfAssistIdentifier() < 0){
2683        super.consumeMemberValuePair();
2684        MemberValuePair memberValuePair = (MemberValuePair) this.astStack[this.astPtr];
2685        if(this.assistNode != null && memberValuePair.value == this.assistNode) {
2686            this.assistNodeParent = memberValuePair;
2687        }
2688        return;
2689    }
2690
2691    char[] simpleName = this.identifierStack[this.identifierPtr];
2692    long position = this.identifierPositionStack[this.identifierPtr--];
2693    this.identifierLengthPtr--;
2694    int end = (int) position;
2695    int start = (int) (position >>> 32);
2696
2697    this.expressionPtr--;
2698    this.expressionLengthPtr--;
2699
2700    CompletionOnMemberValueName memberValueName = new CompletionOnMemberValueName(simpleName,start, end);
2701    this.pushOnAstStack(memberValueName);
2702    this.assistNode = memberValueName;
2703    this.lastCheckPoint = this.assistNode.sourceEnd + 1;
2704    this.isOrphanCompletionNode = true;
2705
2706    this.restartRecovery = true;
2707}
2708protected void consumeMemberValueAsName() {
2709    if ((indexOfAssistIdentifier()) < 0) {
2710        super.consumeMemberValueAsName();
2711    } else {
2712        super.consumeMemberValueAsName();
2713        if(this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN) {
2714            this.restartRecovery = true;
2715        }
2716    }
2717}
2718protected void consumeMethodBody() {
2719    popElement(K_BLOCK_DELIMITER);
2720    super.consumeMethodBody();
2721}
2722protected void consumeMethodHeader() {
2723    super.consumeMethodHeader();
2724    pushOnElementStack(K_BLOCK_DELIMITER);
2725}
2726protected void consumeModifiers() {
2727    super.consumeModifiers();
2728    // save from stack values
2729
this.lastModifiersStart = intStack[intPtr];
2730    this.lastModifiers = intStack[intPtr-1];
2731}
2732protected void consumeReferenceType() {
2733    if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
2734
// potential receiver is being poped, so reset potential receiver
2735
this.invocationType = NO_RECEIVER;
2736        this.qualifier = -1;
2737    }
2738    super.consumeReferenceType();
2739}
2740protected void consumeRestoreDiet() {
2741    super.consumeRestoreDiet();
2742    if (isInsideMethod()) {
2743        popElement(K_LOCAL_INITIALIZER_DELIMITER);
2744    }
2745}
2746protected void consumeSingleMemberAnnotation() {
2747    if (this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN &&
2748            (this.topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) & ANNOTATION_NAME_COMPLETION) != 0 ) {
2749        this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
2750        this.restartRecovery = true;
2751    } else {
2752        this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
2753        super.consumeSingleMemberAnnotation();
2754    }
2755}
2756protected void consumeSingleStaticImportDeclarationName() {
2757    super.consumeSingleStaticImportDeclarationName();
2758    this.pendingAnnotation = null; // the pending annotation cannot be attached to next nodes
2759
}
2760protected void consumeSingleTypeImportDeclarationName() {
2761    super.consumeSingleTypeImportDeclarationName();
2762    this.pendingAnnotation = null; // the pending annotation cannot be attached to next nodes
2763
}
2764protected void consumeStatementBreakWithLabel() {
2765    super.consumeStatementBreakWithLabel();
2766    if (this.record) {
2767        ASTNode breakStatement = this.astStack[this.astPtr];
2768        if (!isAlreadyPotentialName(breakStatement.sourceStart)) {
2769            this.addPotentialName(null, breakStatement.sourceStart, breakStatement.sourceEnd);
2770        }
2771    }
2772    
2773}
2774protected void consumeStatementLabel() {
2775    this.popElement(K_LABEL);
2776    super.consumeStatementLabel();
2777}
2778protected void consumeStatementSwitch() {
2779    super.consumeStatementSwitch();
2780    if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SWITCH_LABEL) {
2781        popElement(K_SWITCH_LABEL);
2782        popElement(K_BLOCK_DELIMITER);
2783    }
2784}
2785protected void consumeStaticImportOnDemandDeclarationName() {
2786    super.consumeStaticImportOnDemandDeclarationName();
2787    this.pendingAnnotation = null; // the pending annotation cannot be attached to next nodes
2788
}
2789protected void consumeStaticInitializer() {
2790    super.consumeStaticInitializer();
2791    this.pendingAnnotation = null; // the pending annotation cannot be attached to next nodes
2792
}
2793protected void consumeNestedMethod() {
2794    super.consumeNestedMethod();
2795    if(!(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BLOCK_DELIMITER)) pushOnElementStack(K_BLOCK_DELIMITER);
2796}
2797protected void consumeNormalAnnotation() {
2798    if (this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN &&
2799            (this.topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) & ANNOTATION_NAME_COMPLETION) != 0 ) {
2800        this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
2801        this.restartRecovery = true;
2802    } else {
2803        this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
2804        super.consumeNormalAnnotation();
2805    }
2806}
2807protected void consumePackageDeclarationName() {
2808    super.consumePackageDeclarationName();
2809    if (this.pendingAnnotation != null) {
2810        this.pendingAnnotation.potentialAnnotatedNode = this.compilationUnit.currentPackage;
2811        this.pendingAnnotation = null;
2812    }
2813}
2814protected void consumePackageDeclarationNameWithModifiers() {
2815    super.consumePackageDeclarationNameWithModifiers();
2816    if (this.pendingAnnotation != null) {
2817        this.pendingAnnotation.potentialAnnotatedNode = this.compilationUnit.currentPackage;
2818        this.pendingAnnotation = null;
2819    }
2820}
2821protected void consumePrimaryNoNewArrayName() {
2822    // this is class literal access, so reset potential receiver
2823
this.invocationType = NO_RECEIVER;
2824    this.qualifier = -1;
2825
2826    super.consumePrimaryNoNewArrayName();
2827}
2828protected void consumePrimaryNoNewArrayNameSuper() {
2829    // this is class literal access, so reset potential receiver
2830
this.invocationType = NO_RECEIVER;
2831    this.qualifier = -1;
2832
2833    super.consumePrimaryNoNewArrayNameSuper();
2834}
2835protected void consumePrimaryNoNewArrayNameThis() {
2836    // this is class literal access, so reset potential receiver
2837
this.invocationType = NO_RECEIVER;
2838    this.qualifier = -1;
2839
2840    super.consumePrimaryNoNewArrayNameThis();
2841}
2842protected void consumePushPosition() {
2843    super.consumePushPosition();
2844    if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BINARY_OPERATOR) {
2845        int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
2846        popElement(K_BINARY_OPERATOR);
2847        pushOnElementStack(K_UNARY_OPERATOR, info);
2848    }
2849}
2850protected void consumeToken(int token) {
2851    if(isFirst) {
2852        super.consumeToken(token);
2853        return;
2854    }
2855    if(canBeExplicitConstructor == NEXTTOKEN) {
2856        canBeExplicitConstructor = YES;
2857    } else {
2858        canBeExplicitConstructor = NO;
2859    }
2860
2861    int previous = this.previousToken;
2862    int prevIdentifierPtr = this.previousIdentifierPtr;
2863
2864    if (isInsideMethod() || isInsideFieldInitialization() || isInsideAnnotation()) {
2865        switch(token) {
2866            case TokenNameLPAREN:
2867                if(previous == TokenNameIdentifier &&
2868                        topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_METHOD_INVOCATION) {
2869                    popElement(K_PARAMETERIZED_METHOD_INVOCATION);
2870                } else {
2871                    popElement(K_BETWEEN_NEW_AND_LEFT_BRACKET);
2872                }
2873                break;
2874            case TokenNameLBRACE:
2875                popElement(K_BETWEEN_NEW_AND_LEFT_BRACKET);
2876                break;
2877            case TokenNameLBRACKET:
2878                if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_NEW_AND_LEFT_BRACKET) {
2879                    popElement(K_BETWEEN_NEW_AND_LEFT_BRACKET);
2880                    pushOnElementStack(K_ARRAY_CREATION);
2881                }
2882                break;
2883            case TokenNameRBRACE:
2884                int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
2885                switch (kind) {
2886                    case K_BLOCK_DELIMITER:
2887                        popElement(K_BLOCK_DELIMITER);
2888                        break;
2889                    case K_MEMBER_VALUE_ARRAY_INITIALIZER:
2890                        popElement(K_MEMBER_VALUE_ARRAY_INITIALIZER);
2891                        break;
2892                    default:
2893                        popElement(K_ARRAY_INITIALIZER);
2894                        break;
2895                }
2896                break;
2897            case TokenNameRBRACKET:
2898                if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_LEFT_AND_RIGHT_BRACKET) {
2899                    popElement(K_BETWEEN_LEFT_AND_RIGHT_BRACKET);
2900                }
2901                break;
2902
2903        }
2904    }
2905    super.consumeToken(token);
2906
2907    // if in field initializer (directly or not), on the completion identifier and not in recovery mode yet
2908
// then position end of file at cursor location (so that we have the same behavior as
2909
// in method bodies)
2910
if (token == TokenNameIdentifier
2911            && this.identifierStack[this.identifierPtr] == assistIdentifier()
2912            && this.currentElement == null
2913            && this.isIndirectlyInsideFieldInitialization()) {
2914        this.scanner.eofPosition = cursorLocation < Integer.MAX_VALUE ? cursorLocation+1 : cursorLocation;
2915    }
2916
2917    // if in a method or if in a field initializer
2918
if (isInsideMethod() || isInsideFieldInitialization() || isInsideAttributeValue()) {
2919        switch (token) {
2920            case TokenNameDOT:
2921                switch (previous) {
2922                    case TokenNamethis: // eg. this[.]fred()
2923
this.invocationType = EXPLICIT_RECEIVER;
2924                        break;
2925                    case TokenNamesuper: // eg. super[.]fred()
2926
this.invocationType = SUPER_RECEIVER;
2927                        break;
2928                    case TokenNameIdentifier: // eg. bar[.]fred()
2929
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_BETWEEN_NEW_AND_LEFT_BRACKET) {
2930                            if (this.identifierPtr != prevIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred()
2931
this.invocationType = EXPLICIT_RECEIVER;
2932                            } else {
2933                                this.invocationType = NAME_RECEIVER;
2934                            }
2935                        }
2936                        break;
2937                }
2938                break;
2939            case TokenNameIdentifier:
2940                if (previous == TokenNameDOT) { // eg. foo().[fred]()
2941
if (this.invocationType != SUPER_RECEIVER // eg. not super.[fred]()
2942
&& this.invocationType != NAME_RECEIVER // eg. not bar.[fred]()
2943
&& this.invocationType != ALLOCATION // eg. not new foo.[Bar]()
2944
&& this.invocationType != QUALIFIED_ALLOCATION) { // eg. not fred().new foo.[Bar]()
2945

2946                        this.invocationType = EXPLICIT_RECEIVER;
2947                        this.qualifier = this.expressionPtr;
2948                    }
2949                }
2950                break;
2951            case TokenNamenew:
2952                pushOnElementStack(K_BETWEEN_NEW_AND_LEFT_BRACKET);
2953                this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed
2954
if (previous == TokenNameDOT) { // eg. fred().[new] X()
2955
this.invocationType = QUALIFIED_ALLOCATION;
2956                } else { // eg. [new] X()
2957
this.invocationType = ALLOCATION;
2958                }
2959                break;
2960            case TokenNamethis:
2961                if (previous == TokenNameDOT) { // eg. fred().[this]()
2962
this.invocationType = QUALIFIED_ALLOCATION;
2963                    this.qualifier = this.expressionPtr;
2964                }
2965                break;
2966            case TokenNamesuper:
2967                if (previous == TokenNameDOT) { // eg. fred().[super]()
2968
this.invocationType = QUALIFIED_ALLOCATION;
2969                    this.qualifier = this.expressionPtr;
2970                }
2971                break;
2972            case TokenNamecatch:
2973                pushOnElementStack(K_BETWEEN_CATCH_AND_RIGHT_PAREN);
2974                break;
2975            case TokenNameLPAREN:
2976                if (this.invocationType == NO_RECEIVER || this.invocationType == NAME_RECEIVER || this.invocationType == SUPER_RECEIVER) {
2977                    this.qualifier = this.expressionPtr; // remenber the last expression so that arguments are correctly computed
2978
}
2979                switch (previous) {
2980                    case TokenNameIdentifier: // eg. fred[(]) or foo.fred[(])
2981
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) {
2982                            int info = 0;
2983                            if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER,1) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN &&
2984                                    (info=topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER,1) & LPAREN_NOT_CONSUMED) != 0) {
2985                                this.popElement(K_SELECTOR);
2986                                this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
2987                                if ((info & ANNOTATION_NAME_COMPLETION) != 0) {
2988                                    this.pushOnElementStack(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN, LPAREN_CONSUMED | ANNOTATION_NAME_COMPLETION);
2989                                } else {
2990                                    this.pushOnElementStack(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN, LPAREN_CONSUMED);
2991                                }
2992                            } else {
2993                                this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, this.invocationType);
2994                                this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
2995                            }
2996                        }
2997                        this.qualifier = -1;
2998                        this.invocationType = NO_RECEIVER;
2999                        break;
3000                    case TokenNamethis: // explicit constructor invocation, eg. this[(]1, 2)
3001
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) {
3002                            this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION);
3003                            this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
3004                        }
3005                        this.qualifier = -1;
3006                        this.invocationType = NO_RECEIVER;
3007                        break;
3008                    case TokenNamesuper: // explicit constructor invocation, eg. super[(]1, 2)
3009
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) {
3010                            this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION);
3011                            this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
3012                        }
3013                        this.qualifier = -1;
3014                        this.invocationType = NO_RECEIVER;
3015                        break;
3016                    case TokenNameGREATER: // explicit constructor invocation, eg. Fred<X>[(]1, 2)
3017
case TokenNameRIGHT_SHIFT: // or fred<X<X>>[(]1, 2)
3018
case TokenNameUNSIGNED_RIGHT_SHIFT: //or Fred<X<X<X>>>[(]1, 2)
3019
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) {
3020                            if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_BINARY_OPERATOR &&
3021                                    topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == GREATER) {
3022                                // it's not a selector invocation
3023
popElement(K_SELECTOR);
3024                            } else {
3025                                this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION);
3026                                this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
3027                            }
3028                        }
3029                        this.qualifier = -1;
3030                        this.invocationType = NO_RECEIVER;
3031                        break;
3032                }
3033                break;
3034            case TokenNameLBRACE:
3035                this.bracketDepth++;
3036                int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
3037                if(kind == K_FIELD_INITIALIZER_DELIMITER
3038                    || kind == K_LOCAL_INITIALIZER_DELIMITER
3039                    || kind == K_ARRAY_CREATION) {
3040                    pushOnElementStack(K_ARRAY_INITIALIZER, endPosition);
3041                } else if (kind == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN) {
3042                    pushOnElementStack(K_MEMBER_VALUE_ARRAY_INITIALIZER, endPosition);
3043                } else {
3044                    switch(previous) {
3045                        case TokenNameRPAREN :
3046                            switch(previousKind) {
3047                                case K_BETWEEN_IF_AND_RIGHT_PAREN :
3048                                    pushOnElementStack(K_BLOCK_DELIMITER, IF);
3049                                    break;
3050                                case K_BETWEEN_CATCH_AND_RIGHT_PAREN :
3051                                    pushOnElementStack(K_BLOCK_DELIMITER, CATCH);
3052                                    break;
3053                                case K_BETWEEN_WHILE_AND_RIGHT_PAREN :
3054                                    pushOnElementStack(K_BLOCK_DELIMITER, WHILE);
3055                                    break;
3056                                case K_BETWEEN_SWITCH_AND_RIGHT_PAREN :
3057                                    pushOnElementStack(K_BLOCK_DELIMITER, SWITCH);
3058                                    break;
3059                                case K_BETWEEN_FOR_AND_RIGHT_PAREN :
3060                                    pushOnElementStack(K_BLOCK_DELIMITER, FOR);
3061                                    break;
3062                                case K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN :
3063                                    pushOnElementStack(K_BLOCK_DELIMITER, SYNCHRONIZED);
3064                                    break;
3065                                default :
3066                                    pushOnElementStack(K_BLOCK_DELIMITER);
3067                                    break;
3068                            }
3069                            break;
3070                        case TokenNametry :
3071                            pushOnElementStack(K_BLOCK_DELIMITER, TRY);
3072                            break;
3073                        case TokenNamedo:
3074                            pushOnElementStack(K_BLOCK_DELIMITER, DO);
3075                            break;
3076                        default :
3077                            pushOnElementStack(K_BLOCK_DELIMITER);
3078                            break;
3079                    }
3080                }
3081                break;
3082            case TokenNameLBRACKET:
3083                if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_ARRAY_CREATION) {
3084                    pushOnElementStack(K_BETWEEN_LEFT_AND_RIGHT_BRACKET);
3085                } else {
3086                    if(previous == TokenNameIdentifier) {
3087                        invocationType = NO_RECEIVER;
3088                        qualifier = -1;
3089                    }
3090                }
3091                this.bracketDepth++;
3092                break;
3093            case TokenNameRBRACE:
3094                this.bracketDepth--;
3095                break;
3096            case TokenNameRBRACKET:
3097                this.bracketDepth--;
3098                break;
3099            case TokenNameRPAREN:
3100                switch(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
3101                    case K_BETWEEN_CATCH_AND_RIGHT_PAREN :
3102                        popElement(K_BETWEEN_CATCH_AND_RIGHT_PAREN);
3103                        break;
3104                    case K_BETWEEN_IF_AND_RIGHT_PAREN :
3105                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
3106                            popElement(K_BETWEEN_IF_AND_RIGHT_PAREN);
3107                        }
3108                        break;
3109                    case K_BETWEEN_WHILE_AND_RIGHT_PAREN :
3110                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
3111                            popElement(K_BETWEEN_WHILE_AND_RIGHT_PAREN);
3112                        }
3113                        break;
3114                    case K_BETWEEN_FOR_AND_RIGHT_PAREN :
3115                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
3116                            popElement(K_BETWEEN_FOR_AND_RIGHT_PAREN);
3117                        }
3118                        break;
3119                    case K_BETWEEN_SWITCH_AND_RIGHT_PAREN :
3120                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
3121                            popElement(K_BETWEEN_SWITCH_AND_RIGHT_PAREN);
3122                        }
3123                        break;
3124                    case K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN :
3125                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
3126                            popElement(K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN);
3127                        }
3128                        break;
3129                }
3130                break;
3131            case TokenNamethrow:
3132                pushOnElementStack(K_INSIDE_THROW_STATEMENT, bracketDepth);
3133                break;
3134            case TokenNameSEMICOLON:
3135                switch(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
3136                    case K_INSIDE_THROW_STATEMENT :
3137                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
3138                            popElement(K_INSIDE_THROW_STATEMENT);
3139                        }
3140                        break;
3141                    case K_INSIDE_RETURN_STATEMENT :
3142                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
3143                            popElement(K_INSIDE_RETURN_STATEMENT);
3144                        }
3145                        break;
3146                    case K_INSIDE_ASSERT_STATEMENT :
3147                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
3148                            popElement(K_INSIDE_ASSERT_STATEMENT);
3149                        }
3150                        break;
3151                    case K_INSIDE_BREAK_STATEMENT:
3152                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
3153                            popElement(K_INSIDE_BREAK_STATEMENT);
3154                        }
3155                        break;
3156                    case K_INSIDE_CONTINUE_STATEMENT:
3157                        if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
3158                            popElement(K_INSIDE_CONTINUE_STATEMENT);
3159                        }
3160                        break;
3161                }
3162                break;
3163            case TokenNamereturn:
3164                pushOnElementStack(K_INSIDE_RETURN_STATEMENT, this.bracketDepth);
3165                break;
3166            case TokenNameMULTIPLY:
3167                pushOnElementStack(K_BINARY_OPERATOR, MULTIPLY);
3168                break;
3169            case TokenNameDIVIDE:
3170                pushOnElementStack(K_BINARY_OPERATOR, DIVIDE);
3171                break;
3172            case TokenNameREMAINDER:
3173                pushOnElementStack(K_BINARY_OPERATOR, REMAINDER);
3174                break;
3175            case TokenNamePLUS:
3176                pushOnElementStack(K_BINARY_OPERATOR, PLUS);
3177                break;
3178            case TokenNameMINUS:
3179                pushOnElementStack(K_BINARY_OPERATOR, MINUS);
3180                break;
3181            case TokenNameLEFT_SHIFT:
3182                pushOnElementStack(K_BINARY_OPERATOR, LEFT_SHIFT);
3183                break;
3184            case TokenNameRIGHT_SHIFT:
3185                pushOnElementStack(K_BINARY_OPERATOR, RIGHT_SHIFT);
3186                break;
3187            case TokenNameUNSIGNED_RIGHT_SHIFT:
3188                pushOnElementStack(K_BINARY_OPERATOR, UNSIGNED_RIGHT_SHIFT);
3189                break;
3190            case TokenNameLESS:
3191                switch(previous) {
3192                    case TokenNameDOT :
3193                        pushOnElementStack(K_PARAMETERIZED_METHOD_INVOCATION);
3194                        break;
3195                    case TokenNamenew :
3196                        pushOnElementStack(K_PARAMETERIZED_ALLOCATION);
3197                        break;
3198                }
3199                pushOnElementStack(K_BINARY_OPERATOR, LESS);
3200                break;
3201            case TokenNameGREATER:
3202                pushOnElementStack(K_BINARY_OPERATOR, GREATER);
3203                break;
3204            case TokenNameLESS_EQUAL:
3205                pushOnElementStack(K_BINARY_OPERATOR, LESS_EQUAL);
3206                break;
3207            case TokenNameGREATER_EQUAL:
3208                pushOnElementStack(K_BINARY_OPERATOR, GREATER_EQUAL);
3209                break;
3210            case TokenNameAND:
3211                pushOnElementStack(K_BINARY_OPERATOR, AND);
3212                break;
3213            case TokenNameXOR:
3214                pushOnElementStack(K_BINARY_OPERATOR, XOR);
3215                break;
3216            case TokenNameOR:
3217                pushOnElementStack(K_BINARY_OPERATOR, OR);
3218                break;
3219            case TokenNameAND_AND:
3220                pushOnElementStack(K_BINARY_OPERATOR, AND_AND);
3221                break;
3222            case TokenNameOR_OR:
3223                pushOnElementStack(K_BINARY_OPERATOR, OR_OR);
3224                break;
3225            case TokenNamePLUS_PLUS:
3226                pushOnElementStack(K_UNARY_OPERATOR, PLUS_PLUS);
3227                break;
3228            case TokenNameMINUS_MINUS:
3229                pushOnElementStack(K_UNARY_OPERATOR, MINUS_MINUS);
3230                break;
3231            case TokenNameTWIDDLE:
3232                pushOnElementStack(K_UNARY_OPERATOR, TWIDDLE);
3233                break;
3234            case TokenNameNOT:
3235                pushOnElementStack(K_UNARY_OPERATOR, NOT);
3236                break;
3237            case TokenNameEQUAL_EQUAL:
3238                pushOnElementStack(K_BINARY_OPERATOR, EQUAL_EQUAL);
3239                break;
3240            case TokenNameNOT_EQUAL:
3241                pushOnElementStack(K_BINARY_OPERATOR, NOT_EQUAL);
3242                break;
3243            case TokenNameinstanceof:
3244                pushOnElementStack(K_BINARY_OPERATOR, INSTANCEOF);
3245                break;
3246            case TokenNameQUESTION:
3247                if(previous != TokenNameLESS) {
3248                    pushOnElementStack(K_CONDITIONAL_OPERATOR, QUESTION);
3249                }
3250                break;
3251            case TokenNameCOLON:
3252                if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_CONDITIONAL_OPERATOR
3253                    && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == QUESTION) {
3254                    popElement(K_CONDITIONAL_OPERATOR);
3255                    pushOnElementStack(K_CONDITIONAL_OPERATOR, COLON);
3256                } else {
3257                    if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_CASE_AND_COLON) {
3258                        popElement(K_BETWEEN_CASE_AND_COLON);
3259                    } else {
3260                        popElement(K_BETWEEN_DEFAULT_AND_COLON);
3261                    }
3262                }
3263                break;
3264            case TokenNameif:
3265                pushOnElementStack(K_BETWEEN_IF_AND_RIGHT_PAREN, bracketDepth);
3266                break;
3267            case TokenNamewhile:
3268                pushOnElementStack(K_BETWEEN_WHILE_AND_RIGHT_PAREN, bracketDepth);
3269                break;
3270            case TokenNamefor:
3271                pushOnElementStack(K_BETWEEN_FOR_AND_RIGHT_PAREN, bracketDepth);
3272                break;
3273            case TokenNameswitch:
3274                pushOnElementStack(K_BETWEEN_SWITCH_AND_RIGHT_PAREN, bracketDepth);
3275                break;
3276            case TokenNamesynchronized:
3277                pushOnElementStack(K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN, bracketDepth);
3278                break;
3279            case TokenNameassert:
3280                pushOnElementStack(K_INSIDE_ASSERT_STATEMENT, this.bracketDepth);
3281                break;
3282            case TokenNamecase :
3283                pushOnElementStack(K_BETWEEN_CASE_AND_COLON);
3284                break;
3285            case TokenNamedefault :
3286                pushOnElementStack(K_BETWEEN_DEFAULT_AND_COLON);
3287                break;
3288            case TokenNameextends:
3289                pushOnElementStack(K_EXTENDS_KEYWORD);
3290                break;
3291            case TokenNamebreak:
3292                pushOnElementStack(K_INSIDE_BREAK_STATEMENT, bracketDepth);
3293                break;
3294            case TokenNamecontinue:
3295                pushOnElementStack(K_INSIDE_CONTINUE_STATEMENT, bracketDepth);
3296                break;
3297        }
3298    } else if (isInsideAnnotation()){
3299        switch (token) {
3300            case TokenNameLBRACE:
3301                this.bracketDepth++;
3302                int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
3303                if (kind == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN) {
3304                    pushOnElementStack(K_MEMBER_VALUE_ARRAY_INITIALIZER, endPosition);
3305                }
3306                break;
3307        }
3308    } else {
3309        switch(token) {
3310            case TokenNameextends:
3311                pushOnElementStack(K_EXTENDS_KEYWORD);
3312                break;
3313            case TokenNameLESS:
3314                pushOnElementStack(K_BINARY_OPERATOR, LESS);
3315                break;
3316            case TokenNameGREATER:
3317                pushOnElementStack(K_BINARY_OPERATOR, GREATER);
3318                break;
3319            case TokenNameRIGHT_SHIFT:
3320                pushOnElementStack(K_BINARY_OPERATOR, RIGHT_SHIFT);
3321                break;
3322            case TokenNameUNSIGNED_RIGHT_SHIFT:
3323                pushOnElementStack(K_BINARY_OPERATOR, UNSIGNED_RIGHT_SHIFT);
3324                break;
3325
3326        }
3327    }
3328}
3329protected void consumeOnlyTypeArguments() {
3330    super.consumeOnlyTypeArguments();
3331    popElement(K_BINARY_OPERATOR);
3332    if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_METHOD_INVOCATION) {
3333        popElement(K_PARAMETERIZED_METHOD_INVOCATION);
3334        pushOnElementStack(K_PARAMETERIZED_METHOD_INVOCATION, INSIDE_NAME);
3335    } else {
3336        popElement(K_PARAMETERIZED_ALLOCATION);
3337    }
3338}
3339protected void consumeOnlyTypeArgumentsForCastExpression() {
3340    super.consumeOnlyTypeArgumentsForCastExpression();
3341    pushOnElementStack(K_PARAMETERIZED_CAST);
3342}
3343protected void consumeRightParen() {
3344    super.consumeRightParen();
3345}
3346protected void consumeReferenceType1() {
3347    super.consumeReferenceType1();
3348    popElement(K_BINARY_OPERATOR);
3349}
3350protected void consumeReferenceType2() {
3351    super.consumeReferenceType2();
3352    popElement(K_BINARY_OPERATOR);
3353}
3354protected void consumeReferenceType3() {
3355    super.consumeReferenceType3();
3356    popElement(K_BINARY_OPERATOR);
3357}
3358protected void consumeTypeArgumentReferenceType1() {
3359    super.consumeTypeArgumentReferenceType1();
3360    popElement(K_BINARY_OPERATOR);
3361}
3362protected void consumeTypeArgumentReferenceType2() {
3363    super.consumeTypeArgumentReferenceType2();
3364    popElement(K_BINARY_OPERATOR);
3365}
3366protected void consumeTypeArguments() {
3367    super.consumeTypeArguments();
3368    popElement(K_BINARY_OPERATOR);
3369}
3370protected void consumeTypeHeaderNameWithTypeParameters() {
3371    super.consumeTypeHeaderNameWithTypeParameters();
3372
3373    TypeDeclaration typeDecl = (TypeDeclaration)this.astStack[this.astPtr];
3374    classHeaderExtendsOrImplements((typeDecl.modifiers & ClassFileConstants.AccInterface) != 0);
3375}
3376protected void consumeTypeImportOnDemandDeclarationName() {
3377    super.consumeTypeImportOnDemandDeclarationName();
3378    this.pendingAnnotation = null; // the pending annotation cannot be attached to next nodes
3379
}
3380protected void consumeTypeParameters() {
3381    super.consumeTypeParameters();
3382    popElement(K_BINARY_OPERATOR);
3383}
3384protected void consumeTypeParameterHeader() {
3385    super.consumeTypeParameterHeader();
3386    TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
3387    if(typeParameter.type != null || (typeParameter.bounds != null && typeParameter.bounds.length > 0)) return;
3388
3389    if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
3390
if (cursorLocation < this.scanner.startPosition && this.scanner.currentPosition == this.scanner.startPosition){ // fake empty identifier got issued
3391
this.pushIdentifier();
3392        } else if (cursorLocation+1 >= this.scanner.startPosition && cursorLocation < this.scanner.currentPosition){
3393            this.pushIdentifier();
3394        } else {
3395            return;
3396        }
3397    } else {
3398        return;
3399    }
3400
3401    CompletionOnKeyword1 keyword = new CompletionOnKeyword1(
3402        identifierStack[this.identifierPtr],
3403        identifierPositionStack[this.identifierPtr],
3404        Keywords.EXTENDS);
3405    keyword.canCompleteEmptyToken = true;
3406    typeParameter.type = keyword;
3407
3408    this.identifierPtr--;
3409    this.identifierLengthPtr--;
3410
3411    this.assistNode = typeParameter.type;
3412    this.lastCheckPoint = typeParameter.type.sourceEnd + 1;
3413}
3414protected void consumeTypeParameter1() {
3415    super.consumeTypeParameter1();
3416    popElement(K_BINARY_OPERATOR);
3417}
3418protected void consumeTypeParameterWithExtends() {
3419    super.consumeTypeParameterWithExtends();
3420    popElement(K_EXTENDS_KEYWORD);
3421}
3422protected void consumeTypeParameterWithExtendsAndBounds() {
3423    super.consumeTypeParameterWithExtendsAndBounds();
3424    popElement(K_EXTENDS_KEYWORD);
3425}
3426protected void consumeTypeParameter1WithExtends() {
3427    super.consumeTypeParameter1WithExtends();
3428    popElement(K_EXTENDS_KEYWORD);
3429}
3430protected void consumeTypeParameter1WithExtendsAndBounds() {
3431    super.consumeTypeParameter1WithExtendsAndBounds();
3432    popElement(K_EXTENDS_KEYWORD);
3433}
3434protected void consumeWildcard() {
3435    super.consumeWildcard();
3436    if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
3437
if (cursorLocation < this.scanner.startPosition && this.scanner.currentPosition == this.scanner.startPosition){ // fake empty identifier got issued
3438
this.pushIdentifier();
3439        } else if (cursorLocation+1 >= this.scanner.startPosition && cursorLocation < this.scanner.currentPosition){
3440            this.pushIdentifier();
3441        } else {
3442            return;
3443        }
3444    } else {
3445        return;
3446    }
3447    Wildcard wildcard = (Wildcard) this.genericsStack[this.genericsPtr];
3448    CompletionOnKeyword1 keyword = new CompletionOnKeyword1(
3449        identifierStack[this.identifierPtr],
3450        identifierPositionStack[this.identifierPtr],
3451        new char[][]{Keywords.EXTENDS, Keywords.SUPER} );
3452    keyword.canCompleteEmptyToken = true;
3453    wildcard.kind = Wildcard.EXTENDS;
3454    wildcard.bound = keyword;
3455
3456    this.identifierPtr--;
3457    this.identifierLengthPtr--;
3458
3459    this.assistNode = wildcard.bound;
3460    this.lastCheckPoint = wildcard.bound.sourceEnd + 1;
3461}
3462protected void consumeWildcard1() {
3463    super.consumeWildcard1();
3464    popElement(K_BINARY_OPERATOR);
3465}
3466protected void consumeWildcard2() {
3467    super.consumeWildcard2();
3468    popElement(K_BINARY_OPERATOR);
3469}
3470protected void consumeWildcard3() {
3471    super.consumeWildcard3();
3472    popElement(K_BINARY_OPERATOR);
3473}
3474protected void consumeWildcardBoundsExtends() {
3475    super.consumeWildcardBoundsExtends();
3476    popElement(K_EXTENDS_KEYWORD);
3477}
3478protected void consumeWildcardBounds1Extends() {
3479    super.consumeWildcardBounds1Extends();
3480    popElement(K_EXTENDS_KEYWORD);
3481}
3482protected void consumeWildcardBounds2Extends() {
3483    super.consumeWildcardBounds2Extends();
3484    popElement(K_EXTENDS_KEYWORD);
3485}
3486protected void consumeWildcardBounds3Extends() {
3487    super.consumeWildcardBounds3Extends();
3488    popElement(K_EXTENDS_KEYWORD);
3489}
3490protected void consumeUnaryExpression(int op) {
3491    super.consumeUnaryExpression(op);
3492    popElement(K_UNARY_OPERATOR);
3493
3494    if(expressionStack[expressionPtr] instanceof UnaryExpression) {
3495        UnaryExpression exp = (UnaryExpression) expressionStack[expressionPtr];
3496        if(assistNode != null && exp.expression == assistNode) {
3497            assistNodeParent = exp;
3498        }
3499    }
3500}
3501protected void consumeUnaryExpression(int op, boolean post) {
3502    super.consumeUnaryExpression(op, post);
3503    popElement(K_UNARY_OPERATOR);
3504
3505    if(expressionStack[expressionPtr] instanceof UnaryExpression) {
3506        UnaryExpression exp = (UnaryExpression) expressionStack[expressionPtr];
3507        if(assistNode != null && exp.expression == assistNode) {
3508            assistNodeParent = exp;
3509        }
3510    }
3511}
3512
3513public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
3514    return new CompletionOnImportReference(tokens, positions, mod);
3515}
3516public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
3517    return new CompletionOnPackageReference(tokens, positions);
3518}
3519public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
3520    return new CompletionOnQualifiedNameReference(
3521                    previousIdentifiers,
3522                    assistName,
3523                    positions,
3524                    isInsideAttributeValue());
3525}
3526public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
3527    switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
3528        case K_NEXT_TYPEREF_IS_EXCEPTION :
3529            return new CompletionOnQualifiedTypeReference(
3530                    previousIdentifiers,
3531                    assistName,
3532                    positions,
3533                    CompletionOnQualifiedTypeReference.K_EXCEPTION);
3534        case K_NEXT_TYPEREF_IS_CLASS :
3535            return new CompletionOnQualifiedTypeReference(
3536                    previousIdentifiers,
3537                    assistName,
3538                    positions,
3539                    CompletionOnQualifiedTypeReference.K_CLASS);
3540        case K_NEXT_TYPEREF_IS_INTERFACE :
3541            return new CompletionOnQualifiedTypeReference(
3542                    previousIdentifiers,
3543                    assistName,
3544                    positions,
3545                    CompletionOnQualifiedTypeReference.K_INTERFACE);
3546        default :
3547            return new CompletionOnQualifiedTypeReference(
3548                    previousIdentifiers,
3549                    assistName,
3550                    positions);
3551    }
3552}
3553public TypeReference createParameterizedQualifiedAssistTypeReference(char[][] previousIdentifiers, TypeReference[][] typeArguments, char[] assistName, TypeReference[] assistTypeArguments, long[] positions) {
3554    boolean isParameterized = false;
3555    for (int i = 0; i < typeArguments.length; i++) {
3556        if(typeArguments[i] != null) {
3557            isParameterized = true;
3558        }
3559    }
3560    if(!isParameterized) {
3561        return this.createQualifiedAssistTypeReference(previousIdentifiers, assistName, positions);
3562    } else {
3563        switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
3564            case K_NEXT_TYPEREF_IS_EXCEPTION :
3565                return new CompletionOnParameterizedQualifiedTypeReference(
3566                    previousIdentifiers,
3567                    typeArguments,
3568                    assistName,
3569                    positions,
3570                    CompletionOnParameterizedQualifiedTypeReference.K_EXCEPTION);
3571            case K_NEXT_TYPEREF_IS_CLASS :
3572                return new CompletionOnParameterizedQualifiedTypeReference(
3573                    previousIdentifiers,
3574                    typeArguments,
3575                    assistName,
3576                    positions,
3577                    CompletionOnParameterizedQualifiedTypeReference.K_CLASS);
3578            case K_NEXT_TYPEREF_IS_INTERFACE :
3579                return new CompletionOnParameterizedQualifiedTypeReference(
3580                    previousIdentifiers,
3581                    typeArguments,
3582                    assistName,
3583                    positions,
3584                    CompletionOnParameterizedQualifiedTypeReference.K_INTERFACE);
3585            default :
3586                return new CompletionOnParameterizedQualifiedTypeReference(
3587                    previousIdentifiers,
3588                    typeArguments,
3589                    assistName,
3590                    positions);
3591        }
3592    }
3593}
3594public NameReference createSingleAssistNameReference(char[] assistName, long position) {
3595    int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
3596    if(!isInsideMethod()) {
3597        if (isInsideFieldInitialization()) {
3598            return new CompletionOnSingleNameReference(
3599                    assistName,
3600                    position,
3601                    new char[][]{Keywords.FALSE, Keywords.TRUE},
3602                    false,
3603                    isInsideAttributeValue());
3604        }
3605        return new CompletionOnSingleNameReference(assistName, position, isInsideAttributeValue());
3606    } else {
3607        boolean canBeExplicitConstructorCall = false;
3608        if(kind == K_BLOCK_DELIMITER
3609            && previousKind == K_BLOCK_DELIMITER
3610            && previousInfo == DO) {
3611            return new CompletionOnKeyword3(assistName, position, Keywords.WHILE);
3612        } else if(kind == K_BLOCK_DELIMITER
3613            && previousKind == K_BLOCK_DELIMITER
3614            && previousInfo == TRY) {
3615            return new CompletionOnKeyword3(assistName, position, new char[][]{Keywords.CATCH, Keywords.FINALLY});
3616        } else if(kind == K_BLOCK_DELIMITER
3617            && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) {
3618            return new CompletionOnKeyword3(assistName, position, new char[][]{Keywords.CASE, Keywords.DEFAULT});
3619        } else {
3620            char[][] keywords = new char[Keywords.COUNT][];
3621            int count = 0;
3622
3623            if((lastModifiers & ClassFileConstants.AccStatic) == 0) {
3624                keywords[count++]= Keywords.SUPER;
3625                keywords[count++]= Keywords.THIS;
3626            }
3627            keywords[count++]= Keywords.NEW;
3628
3629            if(kind == K_BLOCK_DELIMITER) {
3630                if(canBeExplicitConstructor == YES) {
3631                    canBeExplicitConstructorCall = true;
3632                }
3633
3634                keywords[count++]= Keywords.ASSERT;
3635                keywords[count++]= Keywords.DO;
3636                keywords[count++]= Keywords.FOR;
3637                keywords[count++]= Keywords.IF;
3638                keywords[count++]= Keywords.RETURN;
3639                keywords[count++]= Keywords.SWITCH;
3640                keywords[count++]= Keywords.SYNCHRONIZED;
3641                keywords[count++]= Keywords.THROW;
3642                keywords[count++]= Keywords.TRY;
3643                keywords[count++]= Keywords.WHILE;
3644
3645                keywords[count++]= Keywords.FINAL;
3646                keywords[count++]= Keywords.CLASS;
3647
3648                if(previousKind == K_BLOCK_DELIMITER) {
3649                    switch (previousInfo) {
3650                        case IF :
3651                            keywords[count++]= Keywords.ELSE;
3652                            break;
3653                        case CATCH :
3654                            keywords[count++]= Keywords.CATCH;
3655                            keywords[count++]= Keywords.FINALLY;
3656                            break;
3657                    }
3658                }
3659                if(isInsideLoop()) {
3660                    keywords[count++]= Keywords.CONTINUE;
3661                }
3662                if(isInsideBreakable()) {
3663                    keywords[count++]= Keywords.BREAK;
3664                }
3665            } else if(kind != K_BETWEEN_CASE_AND_COLON && kind != K_BETWEEN_DEFAULT_AND_COLON) {
3666                keywords[count++]= Keywords.TRUE;
3667                keywords[count++]= Keywords.FALSE;
3668                keywords[count++]= Keywords.NULL;
3669
3670                if(kind == K_SWITCH_LABEL) {
3671                    if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) != DEFAULT) {
3672                        keywords[count++]= Keywords.DEFAULT;
3673                    }
3674                    keywords[count++]= Keywords.BREAK;
3675                    keywords[count++]= Keywords.CASE;
3676                    
3677                    keywords[count++]= Keywords.ASSERT;
3678                    keywords[count++]= Keywords.DO;
3679                    keywords[count++]= Keywords.FOR;
3680                    keywords[count++]= Keywords.IF;
3681                    keywords[count++]= Keywords.RETURN;
3682                    keywords[count++]= Keywords.SWITCH;
3683                    keywords[count++]= Keywords.SYNCHRONIZED;
3684                    keywords[count++]= Keywords.THROW;
3685                    keywords[count++]= Keywords.TRY;
3686                    keywords[count++]= Keywords.WHILE;
3687    
3688                    keywords[count++]= Keywords.FINAL;
3689                    keywords[count++]= Keywords.CLASS;
3690                    
3691                    if(isInsideLoop()) {
3692                        keywords[count++]= Keywords.CONTINUE;
3693                    }
3694                }
3695            }
3696            System.arraycopy(keywords, 0 , keywords = new char[count][], 0, count);
3697
3698            return new CompletionOnSingleNameReference(assistName, position, keywords, canBeExplicitConstructorCall, isInsideAttributeValue());
3699        }
3700    }
3701}
3702public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
3703    switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
3704        case K_NEXT_TYPEREF_IS_EXCEPTION :
3705            return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_EXCEPTION) ;
3706        case K_NEXT_TYPEREF_IS_CLASS :
3707            return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_CLASS);
3708        case K_NEXT_TYPEREF_IS_INTERFACE :
3709            return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_INTERFACE);
3710        default :
3711            return new CompletionOnSingleTypeReference(assistName, position);
3712    }
3713}
3714public TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position) {
3715    return this.createSingleAssistTypeReference(assistName, position);
3716}
3717protected StringLiteral createStringLiteral(char[] token, int start, int end, int lineNumber) {
3718    if (start <= this.cursorLocation && this.cursorLocation <= end){
3719        char[] source = this.scanner.source;
3720
3721        int contentStart = start;
3722        int contentEnd = end;
3723
3724        // " could be as unicode \u0022
3725
int pos = contentStart;
3726        if(source[pos] == '\"') {
3727            contentStart = pos + 1;
3728        } else if(source[pos] == '\\' && source[pos+1] == 'u') {
3729            pos += 2;
3730            while (source[pos] == 'u') {
3731                pos++;
3732            }
3733            if(source[pos] == 0 && source[pos + 1] == 0 && source[pos + 2] == 2 && source[pos + 3] == 2) {
3734                contentStart = pos + 4;
3735            }
3736        }
3737
3738        pos = contentEnd;
3739        if(source[pos] == '\"') {
3740            contentEnd = pos - 1;
3741        } else if(source.length > 5 && source[pos-4] == 'u') {
3742            if(source[pos - 3] == 0 && source[pos - 2] == 0 && source[pos - 1] == 2 && source[pos] == 2) {
3743                pos -= 5;
3744                while (pos > -1 && source[pos] == 'u') {
3745                    pos--;
3746                }
3747                if(pos > -1 && source[pos] == '\\') {
3748                    contentEnd = pos - 1;
3749                }
3750            }
3751        }
3752
3753        if(contentEnd < start) {
3754            contentEnd = end;
3755        }
3756
3757        if(this.cursorLocation != end || end == contentEnd) {
3758            CompletionOnStringLiteral stringLiteral = new CompletionOnStringLiteral(
3759                    token,
3760                    start,
3761                    end,
3762                    contentStart,
3763                    contentEnd,
3764                    lineNumber);
3765
3766            this.assistNode = stringLiteral;
3767            this.restartRecovery = true;
3768            this.lastCheckPoint = end;
3769
3770            return stringLiteral;
3771        }
3772    }
3773    return super.createStringLiteral(token, start, end, lineNumber);
3774}
3775protected TypeReference copyDims(TypeReference typeRef, int dim) {
3776    if (this.assistNode == typeRef) {
3777        return typeRef;
3778    }
3779    TypeReference result = super.copyDims(typeRef, dim);
3780    if (this.assistNodeParent == typeRef) {
3781        this.assistNodeParent = result;
3782    }
3783    return result;
3784}
3785public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLoc) {
3786
3787    this.cursorLocation = cursorLoc;
3788    CompletionScanner completionScanner = (CompletionScanner)this.scanner;
3789    completionScanner.completionIdentifier = null;
3790    completionScanner.cursorLocation = cursorLoc;
3791    return this.dietParse(sourceUnit, compilationResult);
3792}
3793/*
3794 * Flush parser/scanner state regarding to code assist
3795 */

3796public void flushAssistState() {
3797
3798    super.flushAssistState();
3799    this.isOrphanCompletionNode = false;
3800    this.isAlreadyAttached = false;
3801    assistNodeParent = null;
3802    CompletionScanner completionScanner = (CompletionScanner)this.scanner;
3803    completionScanner.completedIdentifierStart = 0;
3804    completionScanner.completedIdentifierEnd = -1;
3805}
3806
3807protected TypeReference getTypeReferenceForGenericType(int dim, int identifierLength, int numberOfIdentifiers) {
3808    TypeReference ref = super.getTypeReferenceForGenericType(dim, identifierLength, numberOfIdentifiers);
3809
3810    if(this.assistNode != null) {
3811        if (identifierLength == 1 && numberOfIdentifiers == 1) {
3812            ParameterizedSingleTypeReference singleRef = (ParameterizedSingleTypeReference) ref;
3813            TypeReference[] typeArguments = singleRef.typeArguments;
3814            for (int i = 0; i < typeArguments.length; i++) {
3815                if(typeArguments[i] == this.assistNode) {
3816                    this.assistNodeParent = ref;
3817                    return ref;
3818                }
3819            }
3820        } else {
3821            ParameterizedQualifiedTypeReference qualifiedRef = (ParameterizedQualifiedTypeReference) ref;
3822            TypeReference[][] typeArguments = qualifiedRef.typeArguments;
3823            for (int i = 0; i < typeArguments.length; i++) {
3824                if(typeArguments[i] != null) {
3825                    for (int j = 0; j < typeArguments[i].length; j++) {
3826                        if(typeArguments[i][j] == this.assistNode) {
3827                            this.assistNodeParent = ref;
3828                            return ref;
3829                        }
3830                    }
3831                }
3832            }
3833
3834        }
3835    }
3836
3837    return ref;
3838}
3839protected NameReference getUnspecifiedReference() {
3840    NameReference nameReference = super.getUnspecifiedReference();
3841    if (this.record) {
3842        recordReference(nameReference);
3843    }
3844    return nameReference;
3845}
3846protected NameReference getUnspecifiedReferenceOptimized() {
3847    if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
3848
// potential receiver is being poped, so reset potential receiver
3849
this.invocationType = NO_RECEIVER;
3850        this.qualifier = -1;
3851    }
3852    NameReference nameReference = super.getUnspecifiedReferenceOptimized();
3853    if (this.record) {
3854        recordReference(nameReference);
3855    }
3856    return nameReference;
3857}
3858private boolean isAlreadyPotentialName(int identifierStart) {
3859    if (this.potentialVariableNamesPtr < 0) return false;
3860    
3861    return identifierStart <= this.potentialVariableNameEnds[this.potentialVariableNamesPtr];
3862}
3863protected int indexOfAssistIdentifier(boolean useGenericsStack) {
3864    if (this.record) return -1; // when names are recorded there is no assist identifier
3865
return super.indexOfAssistIdentifier(useGenericsStack);
3866}
3867public void initialize() {
3868    super.initialize();
3869    this.labelPtr = -1;
3870    this.initializeForBlockStatements();
3871}
3872public void initialize(boolean initializeNLS) {
3873    super.initialize(initializeNLS);
3874    this.labelPtr = -1;
3875    this.initializeForBlockStatements();
3876}
3877/*
3878 * Initializes the state of the parser that is about to go for BlockStatements.
3879 */

3880private void initializeForBlockStatements() {
3881    this.previousToken = -1;
3882    this.previousIdentifierPtr = -1;
3883    this.bracketDepth = 0;
3884    this.invocationType = NO_RECEIVER;
3885    this.qualifier = -1;
3886    popUntilElement(K_SWITCH_LABEL);
3887    if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_SWITCH_LABEL) {
3888        this.popUntilElement(K_BLOCK_DELIMITER);
3889    }
3890}
3891public void initializeScanner(){
3892    this.scanner = new CompletionScanner(this.options.sourceLevel);
3893}
3894/**
3895 * Returns whether the completion is just after an array type
3896 * eg. String[].[cursor]
3897 */

3898private boolean isAfterArrayType() {
3899    // TBD: The following relies on the fact that array dimensions are small: it says that if the
3900
// top of the intStack is less than 11, then it must be a dimension
3901
// (smallest position of array type in a compilation unit is 11 as in "class X{Y[]")
3902
if ((this.intPtr > -1) && (this.intStack[this.intPtr] < 11)) {
3903        return true;
3904    }
3905    return false;
3906}
3907private boolean isEmptyNameCompletion() {
3908    return
3909        this.assistNode != null &&
3910        this.assistNode instanceof CompletionOnSingleNameReference &&
3911        (((CompletionOnSingleNameReference)this.assistNode).token.length == 0);
3912}
3913protected boolean isInsideAnnotation() {
3914    int i = elementPtr;
3915    while(i > -1) {
3916        if(elementKindStack[i] == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN)
3917            return true;
3918        i--;
3919    }
3920    return false;
3921}
3922
3923protected boolean isIndirectlyInsideBlock(){
3924    int i = elementPtr;
3925    while(i > -1) {
3926        if(elementKindStack[i] == K_BLOCK_DELIMITER)
3927            return true;
3928        i--;
3929    }
3930    return false;
3931}
3932
3933protected boolean isInsideBlock(){
3934    int i = elementPtr;
3935    while(i > -1) {
3936        switch (elementKindStack[i]) {
3937            case K_TYPE_DELIMITER : return false;
3938            case K_METHOD_DELIMITER : return false;
3939            case K_FIELD_INITIALIZER_DELIMITER : return false;
3940            case K_BLOCK_DELIMITER : return true;
3941        }
3942        i--;
3943    }
3944    return false;
3945}
3946protected boolean isInsideBreakable(){
3947    int i = elementPtr;
3948    while(i > -1) {
3949        switch (elementKindStack[i]) {
3950            case K_TYPE_DELIMITER : return false;
3951            case K_METHOD_DELIMITER : return false;
3952            case K_FIELD_INITIALIZER_DELIMITER : return false;
3953            case K_SWITCH_LABEL : return true;
3954            case K_BLOCK_DELIMITER :
3955                switch(elementInfoStack[i]) {
3956                    case FOR :
3957                    case DO :
3958                    case WHILE :
3959                        return true;
3960                }
3961        }
3962        i--;
3963    }
3964    return false;
3965}
3966protected boolean isInsideLoop(){
3967    int i = elementPtr;
3968    while(i > -1) {
3969        switch (elementKindStack[i]) {
3970            case K_TYPE_DELIMITER : return false;
3971            case K_METHOD_DELIMITER : return false;
3972            case K_FIELD_INITIALIZER_DELIMITER : return false;
3973            case K_BLOCK_DELIMITER :
3974                switch(elementInfoStack[i]) {
3975                    case FOR :
3976                    case DO :
3977                    case WHILE :
3978                        return true;
3979                }
3980        }
3981        i--;
3982    }
3983    return false;
3984}
3985protected boolean isInsideReturn(){
3986    int i = elementPtr;
3987    while(i > -1) {
3988        switch (elementKindStack[i]) {
3989            case K_TYPE_DELIMITER : return false;
3990            case K_METHOD_DELIMITER : return false;
3991            case K_FIELD_INITIALIZER_DELIMITER : return false;
3992            case K_BLOCK_DELIMITER : return false;
3993            case K_INSIDE_RETURN_STATEMENT : return true;
3994        }
3995        i--;
3996    }
3997    return false;
3998}
3999public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLoc) {
4000
4001    this.cursorLocation = cursorLoc;
4002    CompletionScanner completionScanner = (CompletionScanner)this.scanner;
4003    completionScanner.completionIdentifier = null;
4004    completionScanner.cursorLocation = cursorLoc;
4005    return this.parse(sourceUnit, compilationResult);
4006}
4007public void parseBlockStatements(
4008    ConstructorDeclaration cd,
4009    CompilationUnitDeclaration unit) {
4010    canBeExplicitConstructor = 1;
4011    super.parseBlockStatements(cd, unit);
4012}
4013public MethodDeclaration parseSomeStatements(int start, int end, int fakeBlocksCount, CompilationUnitDeclaration unit) {
4014    this.methodRecoveryActivated = true;
4015
4016    initialize();
4017
4018    // simulate goForMethodBody except that we don't want to balance brackets because they are not going to be balanced
4019
goForBlockStatementsopt();
4020
4021    MethodDeclaration fakeMethod = new MethodDeclaration(unit.compilationResult());
4022    fakeMethod.selector = FAKE_METHOD_NAME;
4023    fakeMethod.bodyStart = start;
4024    fakeMethod.bodyEnd = end;
4025    fakeMethod.declarationSourceStart = start;
4026    fakeMethod.declarationSourceEnd = end;
4027    fakeMethod.sourceStart = start;
4028    fakeMethod.sourceEnd = start; //fake method must ignore the method header
4029

4030    referenceContext = fakeMethod;
4031    compilationUnit = unit;
4032
4033    this.diet = false;
4034    this.restartRecovery = true;
4035
4036    scanner.resetTo(start, end);
4037    consumeNestedMethod();
4038    for (int i = 0; i < fakeBlocksCount; i++) {
4039        consumeOpenFakeBlock();
4040    }
4041    try {
4042        parse();
4043    } catch (AbortCompilation ex) {
4044        lastAct = ERROR_ACTION;
4045    } finally {
4046        nestedMethod[nestedType]--;
4047    }
4048    if (!this.hasError) {
4049        int length;
4050        if (astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) {
4051            System.arraycopy(
4052                this.astStack,
4053                (this.astPtr -= length) + 1,
4054                fakeMethod.statements = new Statement[length],
4055                0,
4056                length);
4057        }
4058    }
4059
4060    return fakeMethod;
4061}
4062protected void popUntilCompletedAnnotationIfNecessary() {
4063    if(elementPtr < 0) return;
4064    
4065    int i = elementPtr;
4066    while(i > -1 &&
4067            (elementKindStack[i] != K_BETWEEN_ANNOTATION_NAME_AND_RPAREN ||
4068                    (elementInfoStack[i] & ANNOTATION_NAME_COMPLETION) == 0)) {
4069        i--;
4070    }
4071    
4072    if(i >= 0) {
4073        previousKind = elementKindStack[i];
4074        previousInfo = elementInfoStack[i];
4075        elementPtr = i - 1;
4076    }
4077}
4078/*
4079 * Prepares the state of the parser to go for BlockStatements.
4080 */

4081protected void prepareForBlockStatements() {
4082    this.nestedMethod[this.nestedType = 0] = 1;
4083    this.variablesCounter[this.nestedType] = 0;
4084    this.realBlockStack[this.realBlockPtr = 1] = 0;
4085
4086    this.initializeForBlockStatements();
4087}
4088protected void pushOnLabelStack(char[] label){
4089    if (this.labelPtr < -1) return;
4090
4091    int stackLength = this.labelStack.length;
4092    if (++this.labelPtr >= stackLength) {
4093        System.arraycopy(
4094            this.labelStack, 0,
4095            this.labelStack = new char[stackLength + LabelStackIncrement][], 0,
4096            stackLength);
4097    }
4098    this.labelStack[this.labelPtr] = label;
4099}
4100/**
4101 * Creates a completion on member access node and push it
4102 * on the expression stack.
4103 */

4104private void pushCompletionOnMemberAccessOnExpressionStack(boolean isSuperAccess) {
4105    char[] source = identifierStack[identifierPtr];
4106    long pos = identifierPositionStack[identifierPtr--];
4107    CompletionOnMemberAccess fr = new CompletionOnMemberAccess(source, pos, isInsideAnnotation());
4108    this.assistNode = fr;
4109    this.lastCheckPoint = fr.sourceEnd + 1;
4110    identifierLengthPtr--;
4111    if (isSuperAccess) { //considerates the fieldReference beginning at the 'super' ....
4112
fr.sourceStart = intStack[intPtr--];
4113        fr.receiver = new SuperReference(fr.sourceStart, endPosition);
4114        pushOnExpressionStack(fr);
4115    } else { //optimize push/pop
4116
if ((fr.receiver = expressionStack[expressionPtr]).isThis()) { //fieldreference begins at the this
4117
fr.sourceStart = fr.receiver.sourceStart;
4118        }
4119        expressionStack[expressionPtr] = fr;
4120    }
4121}
4122public void recordCompletionOnReference(){
4123
4124    if (currentElement instanceof RecoveredType){
4125        RecoveredType recoveredType = (RecoveredType)currentElement;
4126
4127        /* filter out cases where scanner is still inside type header */
4128        if (!recoveredType.foundOpeningBrace) return;
4129
4130        /* generate a pseudo field with a completion on type reference */
4131        currentElement.add(
4132            new CompletionOnFieldType(this.getTypeReference(0), false), 0);
4133        return;
4134    }
4135    if (!diet) return; // only record references attached to types
4136

4137}
4138private void recordReference(NameReference nameReference) {
4139    if (!this.skipRecord &&
4140            this.recordFrom <= nameReference.sourceStart &&
4141            nameReference.sourceEnd <= this.recordTo &&
4142            !isAlreadyPotentialName(nameReference.sourceStart)) {
4143        char[] token;
4144        if (nameReference instanceof SingleNameReference) {
4145            token = ((SingleNameReference) nameReference).token;
4146        } else {
4147            token = ((QualifiedNameReference) nameReference).tokens[0];
4148        }
4149        
4150        // Most of the time a name which start with an uppercase is a type name.
4151
// As we don't want to resolve names to avoid to slow down performances then this name will be ignored
4152
if (Character.isUpperCase(token[0])) return;
4153        
4154        addPotentialName(token, nameReference.sourceStart, nameReference.sourceEnd);
4155    }
4156}
4157public void recoveryExitFromVariable() {
4158    if(currentElement != null && currentElement instanceof RecoveredLocalVariable) {
4159        RecoveredElement oldElement = currentElement;
4160        super.recoveryExitFromVariable();
4161        if(oldElement != currentElement) {
4162            popElement(K_LOCAL_INITIALIZER_DELIMITER);
4163        }
4164    } else {
4165        super.recoveryExitFromVariable();
4166    }
4167}
4168public void recoveryTokenCheck() {
4169    RecoveredElement oldElement = currentElement;
4170    switch (currentToken) {
4171        case TokenNameLBRACE :
4172            if(!this.ignoreNextOpeningBrace) {
4173                this.pendingAnnotation = null; // the pending annotation cannot be attached to next nodes
4174
}
4175            super.recoveryTokenCheck();
4176            break;
4177        case TokenNameRBRACE :
4178            super.recoveryTokenCheck();
4179            if(currentElement != oldElement && oldElement instanceof RecoveredBlock) {
4180                popElement(K_BLOCK_DELIMITER);
4181            }
4182            break;
4183        case TokenNamecase :
4184            super.recoveryTokenCheck();
4185            if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BLOCK_DELIMITER
4186                && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) {
4187                pushOnElementStack(K_SWITCH_LABEL);
4188            }
4189            break;
4190        case TokenNamedefault :
4191            super.recoveryTokenCheck();
4192            if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BLOCK_DELIMITER
4193                && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) {
4194                pushOnElementStack(K_SWITCH_LABEL, DEFAULT);
4195            } else if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SWITCH_LABEL) {
4196                popElement(K_SWITCH_LABEL);
4197                pushOnElementStack(K_SWITCH_LABEL, DEFAULT);
4198            }
4199            break;
4200        default :
4201            super.recoveryTokenCheck();
4202            break;
4203    }
4204}
4205/*
4206 * Reset internal state after completion is over
4207 */

4208
4209public void reset() {
4210    super.reset();
4211    this.cursorLocation = 0;
4212}
4213/*
4214 * Reset internal state after completion is over
4215 */

4216
4217public void resetAfterCompletion() {
4218    this.cursorLocation = 0;
4219    this.flushAssistState();
4220}
4221/*
4222 * Reset context so as to resume to regular parse loop
4223 * If unable to reset for resuming, answers false.
4224 *
4225 * Move checkpoint location, reset internal stacks and
4226 * decide which grammar goal is activated.
4227 */

4228protected boolean resumeAfterRecovery() {
4229    if (this.assistNode != null) {
4230        /* if reached [eof] inside method body, but still inside nested type,
4231            or inside a field initializer, should continue in diet mode until
4232            the end of the method body or compilation unit */

4233        if ((scanner.eofPosition == cursorLocation+1)
4234            && (!(referenceContext instanceof CompilationUnitDeclaration)
4235            || isIndirectlyInsideFieldInitialization()
4236            || assistNodeParent instanceof FieldDeclaration && !(assistNodeParent instanceof Initializer))) {
4237
4238            /* disabled since does not handle possible field/message refs, that is, Obj[ASSIST HERE]ect.registerNatives()
4239            // consume extra tokens which were part of the qualified reference
4240            // so that the replaced source comprises them as well
4241            if (this.assistNode instanceof NameReference){
4242                int oldEof = scanner.eofPosition;
4243                scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
4244                scanner.currentPosition = this.cursorLocation+1;
4245                int token = -1;
4246                try {
4247                    do {
4248                        // first token might not have to be a dot
4249                        if (token >= 0 || !this.completionBehindDot){
4250                            if ((token = scanner.getNextToken()) != TokenNameDOT) break;
4251                        }
4252                        if ((token = scanner.getNextToken()) != TokenNameIdentifier) break;
4253                        this.assistNode.sourceEnd = scanner.currentPosition - 1;
4254                    } while (token != TokenNameEOF);
4255                } catch (InvalidInputException e){
4256                } finally {
4257                    scanner.eofPosition = oldEof;
4258                }
4259            }
4260            */

4261            /* restart in diet mode for finding sibling constructs */
4262            if (currentElement instanceof RecoveredType
4263                || currentElement.enclosingType() != null){
4264                    
4265                this.pendingAnnotation = null;
4266                
4267                if(lastCheckPoint <= this.assistNode.sourceEnd) {
4268                    lastCheckPoint = this.assistNode.sourceEnd+1;
4269                }
4270                int end = currentElement.topElement().sourceEnd();
4271                scanner.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
4272            } else {
4273                this.resetStacks();
4274                return false;
4275            }
4276        }
4277    }
4278    return super.resumeAfterRecovery();
4279}
4280public void setAssistIdentifier(char[] assistIdent){
4281    ((CompletionScanner)scanner).completionIdentifier = assistIdent;
4282}
4283public String JavaDoc toString() {
4284    StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
4285    buffer.append("elementKindStack : int[] = {"); //$NON-NLS-1$
4286
for (int i = 0; i <= elementPtr; i++) {
4287        buffer.append(String.valueOf(elementKindStack[i])).append(',');
4288    }
4289    buffer.append("}\n"); //$NON-NLS-1$
4290
buffer.append("elementInfoStack : int[] = {"); //$NON-NLS-1$
4291
for (int i = 0; i <= elementPtr; i++) {
4292        buffer.append(String.valueOf(elementInfoStack[i])).append(',');
4293    }
4294    buffer.append("}\n"); //$NON-NLS-1$
4295
buffer.append(super.toString());
4296    return String.valueOf(buffer);
4297}
4298
4299/*
4300 * Update recovery state based on current parser/scanner state
4301 */

4302protected void updateRecoveryState() {
4303
4304    /* expose parser state to recovery state */
4305    currentElement.updateFromParserState();
4306
4307    /* may be able to retrieve completionNode as an orphan, and then attach it */
4308    this.completionIdentifierCheck();
4309    this.attachOrphanCompletionNode();
4310
4311    // if an assist node has been found and a recovered element exists,
4312
// mark enclosing blocks as to be preserved
4313
if (this.assistNode != null && this.currentElement != null) {
4314        currentElement.preserveEnclosingBlocks();
4315    }
4316
4317    /* check and update recovered state based on current token,
4318        this action is also performed when shifting token after recovery
4319        got activated once.
4320    */

4321    this.recoveryTokenCheck();
4322
4323    this.recoveryExitFromVariable();
4324}
4325
4326protected LocalDeclaration createLocalDeclaration(char[] assistName, int sourceStart, int sourceEnd) {
4327    if (this.indexOfAssistIdentifier() < 0) {
4328        return super.createLocalDeclaration(assistName, sourceStart, sourceEnd);
4329    } else {
4330        CompletionOnLocalName local = new CompletionOnLocalName(assistName, sourceStart, sourceEnd);
4331        this.assistNode = local;
4332        this.lastCheckPoint = sourceEnd + 1;
4333        return local;
4334    }
4335}
4336
4337protected JavadocParser createJavadocParser() {
4338    return new CompletionJavadocParser(this);
4339}
4340
4341protected FieldDeclaration createFieldDeclaration(char[] assistName, int sourceStart, int sourceEnd) {
4342    if (this.indexOfAssistIdentifier() < 0 || (currentElement instanceof RecoveredUnit && ((RecoveredUnit)currentElement).typeCount == 0)) {
4343        return super.createFieldDeclaration(assistName, sourceStart, sourceEnd);
4344    } else {
4345        CompletionOnFieldName field = new CompletionOnFieldName(assistName, sourceStart, sourceEnd);
4346        this.assistNode = field;
4347        this.lastCheckPoint = sourceEnd + 1;
4348        return field;
4349    }
4350}
4351}
Popular Tags