KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > codeassist > impl > AssistParser


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.impl;
12
13 /*
14  * Parser extension for code assist task
15  *
16  */

17
18 import org.eclipse.jdt.internal.compiler.ast.*;
19 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
20 import org.eclipse.jdt.internal.compiler.lookup.Binding;
21 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
22 import org.eclipse.jdt.internal.compiler.parser.Parser;
23 import org.eclipse.jdt.internal.compiler.parser.RecoveredBlock;
24 import org.eclipse.jdt.internal.compiler.parser.RecoveredElement;
25 import org.eclipse.jdt.internal.compiler.parser.RecoveredField;
26 import org.eclipse.jdt.internal.compiler.parser.RecoveredInitializer;
27 import org.eclipse.jdt.internal.compiler.parser.RecoveredMethod;
28 import org.eclipse.jdt.internal.compiler.parser.RecoveredType;
29 import org.eclipse.jdt.internal.compiler.parser.RecoveredUnit;
30 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
31 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
32
33 public abstract class AssistParser extends Parser {
34     public ASTNode assistNode;
35     public boolean isOrphanCompletionNode;
36         
37     /* recovery */
38     int[] blockStarts = new int[30];
39
40     // the previous token read by the scanner
41
protected int previousToken;
42
43     // the index in the identifier stack of the previous identifier
44
protected int previousIdentifierPtr;
45     
46     // element stack
47
protected static final int ElementStackIncrement = 100;
48     protected int elementPtr;
49     protected int[] elementKindStack = new int[ElementStackIncrement];
50     protected int[] elementInfoStack = new int[ElementStackIncrement];
51     protected int previousKind;
52     protected int previousInfo;
53     
54     // OWNER
55
protected static final int ASSIST_PARSER = 512;
56     
57     // KIND : all values known by AssistParser are between 513 and 1023
58
protected static final int K_SELECTOR = ASSIST_PARSER + 1; // whether we are inside a message send
59
protected static final int K_TYPE_DELIMITER = ASSIST_PARSER + 2; // whether we are inside a type declaration
60
protected static final int K_METHOD_DELIMITER = ASSIST_PARSER + 3; // whether we are inside a method declaration
61
protected static final int K_FIELD_INITIALIZER_DELIMITER = ASSIST_PARSER + 4; // whether we are inside a field initializer
62
protected static final int K_ATTRIBUTE_VALUE_DELIMITER = ASSIST_PARSER + 5; // whether we are inside a annotation attribute valuer
63
protected static final int K_ENUM_CONSTANT_DELIMITER = ASSIST_PARSER + 6; // whether we are inside a field initializer
64

65     // selector constants
66
protected static final int THIS_CONSTRUCTOR = -1;
67     protected static final int SUPER_CONSTRUCTOR = -2;
68     
69     // enum constant constants
70
protected static final int NO_BODY = 0;
71     protected static final int WITH_BODY = 1;
72     
73     protected boolean isFirst = false;
74
75 public AssistParser(ProblemReporter problemReporter) {
76     super(problemReporter, true);
77     this.javadocParser.checkDocComment = false;
78     
79     this.setMethodsFullRecovery(false);
80     this.setStatementsRecovery(false);
81 }
82 public abstract char[] assistIdentifier();
83 public int bodyEnd(AbstractMethodDeclaration method){
84     return method.bodyEnd;
85 }
86 public int bodyEnd(Initializer initializer){
87     return initializer.declarationSourceEnd;
88 }
89 /*
90  * Build initial recovery state.
91  * Recovery state is inferred from the current state of the parser (reduced node stack).
92  */

93 public RecoveredElement buildInitialRecoveryState(){
94     /* recovery in unit structure */
95     if (referenceContext instanceof CompilationUnitDeclaration){
96         RecoveredElement element = super.buildInitialRecoveryState();
97         flushAssistState();
98         flushElementStack();
99         return element;
100     }
101
102     /* recovery in method body */
103     lastCheckPoint = 0;
104
105     RecoveredElement element = null;
106     if (referenceContext instanceof AbstractMethodDeclaration){
107         element = new RecoveredMethod((AbstractMethodDeclaration) referenceContext, null, 0, this);
108         lastCheckPoint = ((AbstractMethodDeclaration) referenceContext).bodyStart;
109     } else {
110         /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
111         if (referenceContext instanceof TypeDeclaration){
112             TypeDeclaration type = (TypeDeclaration) referenceContext;
113             for (int i = 0; i < type.fields.length; i++){
114                 FieldDeclaration field = type.fields[i];
115                 if (field != null
116                         && field.getKind() == AbstractVariableDeclaration.INITIALIZER
117                         && field.declarationSourceStart <= scanner.initialPosition
118                         && scanner.initialPosition <= field.declarationSourceEnd
119                         && scanner.eofPosition <= field.declarationSourceEnd+1){
120                     element = new RecoveredInitializer(field, null, 1, this);
121                     lastCheckPoint = field.declarationSourceStart;
122                     break;
123                 }
124             }
125         }
126     }
127
128     if (element == null) return element;
129
130     /* add initial block */
131     Block block = new Block(0);
132     int lastStart = blockStarts[0];
133     block.sourceStart = lastStart;
134     element = element.add(block, 1);
135     int blockIndex = 1; // ignore first block start, since manually rebuilt here
136

137     for(int i = 0; i <= astPtr; i++){
138         ASTNode node = astStack[i];
139         
140         if(node instanceof ForeachStatement && ((ForeachStatement)node).action == null) {
141             node = ((ForeachStatement)node).elementVariable;
142         }
143
144         /* check for intermediate block creation, so recovery can properly close them afterwards */
145         int nodeStart = node.sourceStart;
146         for (int j = blockIndex; j <= realBlockPtr; j++){
147             if (blockStarts[j] >= 0) {
148                 if (blockStarts[j] > nodeStart){
149                     blockIndex = j; // shift the index to the new block
150
break;
151                 }
152                 if (blockStarts[j] != lastStart){ // avoid multiple block if at same position
153
block = new Block(0);
154                     block.sourceStart = lastStart = blockStarts[j];
155                     element = element.add(block, 1);
156                 }
157             } else {
158                 if (-blockStarts[j] > nodeStart){
159                     blockIndex = j; // shift the index to the new block
160
break;
161                 }
162                 block = new Block(0);
163                 block.sourceStart = lastStart = -blockStarts[j];
164                 element = element.add(block, 1);
165             }
166             blockIndex = j+1; // shift the index to the new block
167
}
168         if (node instanceof LocalDeclaration){
169             LocalDeclaration local = (LocalDeclaration) node;
170             if (local.declarationSourceEnd == 0){
171                 element = element.add(local, 0);
172                 if (local.initialization == null){
173                     lastCheckPoint = local.sourceEnd + 1;
174                 } else {
175                     lastCheckPoint = local.initialization.sourceEnd + 1;
176                 }
177             } else {
178                 element = element.add(local, 0);
179                 lastCheckPoint = local.declarationSourceEnd + 1;
180             }
181             continue;
182         }
183         if (node instanceof AbstractMethodDeclaration){
184             AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
185             if (method.declarationSourceEnd == 0){
186                 element = element.add(method, 0);
187                 lastCheckPoint = method.bodyStart;
188             } else {
189                 element = element.add(method, 0);
190                 lastCheckPoint = method.declarationSourceEnd + 1;
191             }
192             continue;
193         }
194         if (node instanceof Initializer){
195             Initializer initializer = (Initializer) node;
196             if (initializer.declarationSourceEnd == 0){
197                 element = element.add(initializer, 1);
198                 lastCheckPoint = initializer.sourceStart;
199             } else {
200                 element = element.add(initializer, 0);
201                 lastCheckPoint = initializer.declarationSourceEnd + 1;
202             }
203             continue;
204         }
205         if (node instanceof FieldDeclaration){
206             FieldDeclaration field = (FieldDeclaration) node;
207             if (field.declarationSourceEnd == 0){
208                 element = element.add(field, 0);
209                 if (field.initialization == null){
210                     lastCheckPoint = field.sourceEnd + 1;
211                 } else {
212                     lastCheckPoint = field.initialization.sourceEnd + 1;
213                 }
214             } else {
215                 element = element.add(field, 0);
216                 lastCheckPoint = field.declarationSourceEnd + 1;
217             }
218             continue;
219         }
220         if (node instanceof TypeDeclaration){
221             TypeDeclaration type = (TypeDeclaration) node;
222             if (type.declarationSourceEnd == 0){
223                 element = element.add(type, 0);
224                 lastCheckPoint = type.bodyStart;
225             } else {
226                 element = element.add(type, 0);
227                 lastCheckPoint = type.declarationSourceEnd + 1;
228             }
229             continue;
230         }
231         if (node instanceof ImportReference){
232             ImportReference importRef = (ImportReference) node;
233             element = element.add(importRef, 0);
234             lastCheckPoint = importRef.declarationSourceEnd + 1;
235         }
236     }
237     if (this.currentToken == TokenNameRBRACE) {
238         this.currentToken = 0; // closing brace has already been taken care of
239
}
240
241     /* might need some extra block (after the last reduced node) */
242     int pos = this.assistNode == null ? lastCheckPoint : this.assistNode.sourceStart;
243     for (int j = blockIndex; j <= realBlockPtr; j++){
244         if (blockStarts[j] >= 0) {
245             if ((blockStarts[j] < pos) && (blockStarts[j] != lastStart)){ // avoid multiple block if at same position
246
block = new Block(0);
247                 block.sourceStart = lastStart = blockStarts[j];
248                 element = element.add(block, 1);
249             }
250         } else {
251             if ((blockStarts[j] < pos)){ // avoid multiple block if at same position
252
block = new Block(0);
253                 block.sourceStart = lastStart = -blockStarts[j];
254                 element = element.add(block, 1);
255             }
256         }
257     }
258     
259     return element;
260 }
261 protected void consumeAnnotationTypeDeclarationHeader() {
262     super.consumeAnnotationTypeDeclarationHeader();
263     pushOnElementStack(K_TYPE_DELIMITER);
264 }
265 protected void consumeClassBodyDeclaration() {
266     popElement(K_METHOD_DELIMITER);
267     super.consumeClassBodyDeclaration();
268 }
269 protected void consumeClassBodyopt() {
270     super.consumeClassBodyopt();
271     popElement(K_SELECTOR);
272 }
273 protected void consumeClassHeader() {
274     super.consumeClassHeader();
275     pushOnElementStack(K_TYPE_DELIMITER);
276 }
277 protected void consumeConstructorBody() {
278     super.consumeConstructorBody();
279     popElement(K_METHOD_DELIMITER);
280 }
281 protected void consumeConstructorHeader() {
282     super.consumeConstructorHeader();
283     pushOnElementStack(K_METHOD_DELIMITER);
284 }
285 protected void consumeEnterAnonymousClassBody() {
286     super.consumeEnterAnonymousClassBody();
287     popElement(K_SELECTOR);
288     pushOnElementStack(K_TYPE_DELIMITER);
289 }
290 protected void consumeEnterMemberValue() {
291     super.consumeEnterMemberValue();
292     pushOnElementStack(K_ATTRIBUTE_VALUE_DELIMITER, this.identifierPtr);
293 }
294 protected void consumeEnumConstantHeader() {
295     if(this.currentToken == TokenNameLBRACE) {
296         popElement(K_ENUM_CONSTANT_DELIMITER);
297         pushOnElementStack(K_ENUM_CONSTANT_DELIMITER, WITH_BODY);
298         pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
299         pushOnElementStack(K_TYPE_DELIMITER);
300     }
301     super.consumeEnumConstantHeader();
302 }
303 protected void consumeEnumConstantHeaderName() {
304     super.consumeEnumConstantHeaderName();
305     pushOnElementStack(K_ENUM_CONSTANT_DELIMITER);
306 }
307 protected void consumeEnumConstantWithClassBody() {
308     popElement(K_TYPE_DELIMITER);
309     popElement(K_FIELD_INITIALIZER_DELIMITER);
310     popElement(K_ENUM_CONSTANT_DELIMITER);
311     super.consumeEnumConstantWithClassBody();
312 }
313 protected void consumeEnumConstantNoClassBody() {
314     popElement(K_ENUM_CONSTANT_DELIMITER);
315     super.consumeEnumConstantNoClassBody();
316 }
317 protected void consumeEnumHeader() {
318     super.consumeEnumHeader();
319     pushOnElementStack(K_TYPE_DELIMITER);
320 }
321 protected void consumeExitMemberValue() {
322     super.consumeExitMemberValue();
323     popElement(K_ATTRIBUTE_VALUE_DELIMITER);
324 }
325 protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
326     super.consumeExplicitConstructorInvocation(flag, recFlag);
327     popElement(K_SELECTOR);
328 }
329 protected void consumeForceNoDiet() {
330     super.consumeForceNoDiet();
331     // if we are not in a method (ie. we are not in a local variable initializer)
332
// then we are entering a field initializer
333
if (!isInsideMethod()) {
334         if(topKnownElementKind(ASSIST_PARSER) != K_ENUM_CONSTANT_DELIMITER) {
335             if(topKnownElementKind(ASSIST_PARSER, 2) != K_ENUM_CONSTANT_DELIMITER) {
336                 pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
337             }
338         } else {
339             int info = topKnownElementInfo(ASSIST_PARSER);
340             if(info != NO_BODY) {
341                 pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
342             }
343         }
344         
345     }
346 }
347 protected void consumeInterfaceHeader() {
348     super.consumeInterfaceHeader();
349     pushOnElementStack(K_TYPE_DELIMITER);
350 }
351 protected void consumeMethodBody() {
352     super.consumeMethodBody();
353     popElement(K_METHOD_DELIMITER);
354 }
355 protected void consumeMethodHeader() {
356     super.consumeMethodHeader();
357     pushOnElementStack(K_METHOD_DELIMITER);
358 }
359 protected void consumeMethodInvocationName() {
360     super.consumeMethodInvocationName();
361     popElement(K_SELECTOR);
362     MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
363     if (messageSend == assistNode){
364         this.lastCheckPoint = messageSend.sourceEnd + 1;
365     }
366 }
367 protected void consumeMethodInvocationNameWithTypeArguments() {
368     super.consumeMethodInvocationNameWithTypeArguments();
369     popElement(K_SELECTOR);
370     MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
371     if (messageSend == assistNode){
372         this.lastCheckPoint = messageSend.sourceEnd + 1;
373     }
374 }
375 protected void consumeMethodInvocationPrimary() {
376     super.consumeMethodInvocationPrimary();
377     popElement(K_SELECTOR);
378     MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
379     if (messageSend == assistNode){
380         this.lastCheckPoint = messageSend.sourceEnd + 1;
381     }
382 }
383 protected void consumeMethodInvocationPrimaryWithTypeArguments() {
384     super.consumeMethodInvocationPrimaryWithTypeArguments();
385     popElement(K_SELECTOR);
386     MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
387     if (messageSend == assistNode){
388         this.lastCheckPoint = messageSend.sourceEnd + 1;
389     }
390 }
391 protected void consumeMethodInvocationSuper() {
392     super.consumeMethodInvocationSuper();
393     popElement(K_SELECTOR);
394     MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
395     if (messageSend == assistNode){
396         this.lastCheckPoint = messageSend.sourceEnd + 1;
397     }
398 }
399 protected void consumeMethodInvocationSuperWithTypeArguments() {
400     super.consumeMethodInvocationSuperWithTypeArguments();
401     popElement(K_SELECTOR);
402     MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
403     if (messageSend == assistNode){
404         this.lastCheckPoint = messageSend.sourceEnd + 1;
405     }
406 }
407 protected void consumeNestedMethod() {
408     super.consumeNestedMethod();
409     if(!isInsideMethod()) pushOnElementStack(K_METHOD_DELIMITER);
410 }
411 protected void consumeOpenBlock() {
412     // OpenBlock ::= $empty
413

414     super.consumeOpenBlock();
415     int stackLength = this.blockStarts.length;
416     if (this.realBlockPtr >= stackLength) {
417         System.arraycopy(
418             this.blockStarts, 0,
419             this.blockStarts = new int[stackLength + StackIncrement], 0,
420             stackLength);
421     }
422     this.blockStarts[this.realBlockPtr] = scanner.startPosition;
423 }
424 protected void consumeOpenFakeBlock() {
425     // OpenBlock ::= $empty
426

427     super.consumeOpenBlock();
428     int stackLength = this.blockStarts.length;
429     if (this.realBlockPtr >= stackLength) {
430         System.arraycopy(
431             this.blockStarts, 0,
432             this.blockStarts = new int[stackLength + StackIncrement], 0,
433             stackLength);
434     }
435     this.blockStarts[this.realBlockPtr] = -scanner.startPosition;
436 }
437 protected void consumePackageDeclarationName() {
438     // PackageDeclarationName ::= 'package' Name
439
/* build an ImportRef build from the last name
440     stored in the identifier stack. */

441
442     int index;
443
444     /* no need to take action if not inside assist identifiers */
445     if ((index = indexOfAssistIdentifier()) < 0) {
446         super.consumePackageDeclarationName();
447         return;
448     }
449     /* retrieve identifiers subset and whole positions, the assist node positions
450         should include the entire replaced source. */

451     int length = identifierLengthStack[identifierLengthPtr];
452     char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
453
identifierLengthPtr--;
454     identifierPtr -= length;
455     long[] positions = new long[length];
456     System.arraycopy(
457         identifierPositionStack,
458         identifierPtr + 1,
459         positions,
460         0,
461         length);
462
463     /* build specific assist node on package statement */
464     ImportReference reference = this.createAssistPackageReference(subset, positions);
465     assistNode = reference;
466     this.lastCheckPoint = reference.sourceEnd + 1;
467     compilationUnit.currentPackage = reference;
468
469     if (currentToken == TokenNameSEMICOLON){
470         reference.declarationSourceEnd = scanner.currentPosition - 1;
471     } else {
472         reference.declarationSourceEnd = (int) positions[length-1];
473     }
474     //endPosition is just before the ;
475
reference.declarationSourceStart = intStack[intPtr--];
476     // flush comments defined prior to import statements
477
reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
478
479     // recovery
480
if (currentElement != null){
481         lastCheckPoint = reference.declarationSourceEnd+1;
482         restartRecovery = true; // used to avoid branching back into the regular automaton
483
}
484 }
485 protected void consumePackageDeclarationNameWithModifiers() {
486     // PackageDeclarationName ::= Modifiers 'package' PushRealModifiers Name
487
/* build an ImportRef build from the last name
488     stored in the identifier stack. */

489
490     int index;
491
492     /* no need to take action if not inside assist identifiers */
493     if ((index = indexOfAssistIdentifier()) < 0) {
494         super.consumePackageDeclarationNameWithModifiers();
495         return;
496     }
497     /* retrieve identifiers subset and whole positions, the assist node positions
498         should include the entire replaced source. */

499     int length = identifierLengthStack[identifierLengthPtr];
500     char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
501
identifierLengthPtr--;
502     identifierPtr -= length;
503     long[] positions = new long[length];
504     System.arraycopy(
505         identifierPositionStack,
506         identifierPtr + 1,
507         positions,
508         0,
509         length);
510
511     this.intPtr--; // we don't need the modifiers start
512
this.intPtr--; // we don't need the package modifiers
513
ImportReference reference = this.createAssistPackageReference(subset, positions);
514     // consume annotations
515
if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
516         System.arraycopy(
517             this.expressionStack,
518             (this.expressionPtr -= length) + 1,
519             reference.annotations = new Annotation[length],
520             0,
521             length);
522     }
523     /* build specific assist node on package statement */
524     assistNode = reference;
525     this.lastCheckPoint = reference.sourceEnd + 1;
526     compilationUnit.currentPackage = reference;
527
528     if (currentToken == TokenNameSEMICOLON){
529         reference.declarationSourceEnd = scanner.currentPosition - 1;
530     } else {
531         reference.declarationSourceEnd = (int) positions[length-1];
532     }
533     //endPosition is just before the ;
534
reference.declarationSourceStart = intStack[intPtr--];
535     // flush comments defined prior to import statements
536
reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
537
538     // recovery
539
if (currentElement != null){
540         lastCheckPoint = reference.declarationSourceEnd+1;
541         restartRecovery = true; // used to avoid branching back into the regular automaton
542
}
543 }
544 protected void consumeRestoreDiet() {
545     super.consumeRestoreDiet();
546     // if we are not in a method (ie. we were not in a local variable initializer)
547
// then we are exiting a field initializer
548
if (!isInsideMethod()) {
549         popElement(K_FIELD_INITIALIZER_DELIMITER);
550     }
551 }
552 protected void consumeSingleStaticImportDeclarationName() {
553     // SingleTypeImportDeclarationName ::= 'import' 'static' Name
554
/* push an ImportRef build from the last name
555     stored in the identifier stack. */

556
557     int index;
558
559     /* no need to take action if not inside assist identifiers */
560     if ((index = indexOfAssistIdentifier()) < 0) {
561         super.consumeSingleStaticImportDeclarationName();
562         return;
563     }
564     /* retrieve identifiers subset and whole positions, the assist node positions
565         should include the entire replaced source. */

566     int length = identifierLengthStack[identifierLengthPtr];
567     char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
568
identifierLengthPtr--;
569     identifierPtr -= length;
570     long[] positions = new long[length];
571     System.arraycopy(
572         identifierPositionStack,
573         identifierPtr + 1,
574         positions,
575         0,
576         length);
577
578     /* build specific assist node on import statement */
579     ImportReference reference = this.createAssistImportReference(subset, positions, ClassFileConstants.AccStatic);
580     assistNode = reference;
581     this.lastCheckPoint = reference.sourceEnd + 1;
582
583     pushOnAstStack(reference);
584
585     if (currentToken == TokenNameSEMICOLON){
586         reference.declarationSourceEnd = scanner.currentPosition - 1;
587     } else {
588         reference.declarationSourceEnd = (int) positions[length-1];
589     }
590     //endPosition is just before the ;
591
reference.declarationSourceStart = intStack[intPtr--];
592     // flush annotations defined prior to import statements
593
reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
594
595     // recovery
596
if (currentElement != null){
597         lastCheckPoint = reference.declarationSourceEnd+1;
598         currentElement = currentElement.add(reference, 0);
599         lastIgnoredToken = -1;
600         restartRecovery = true; // used to avoid branching back into the regular automaton
601
}
602 }
603 protected void consumeSingleTypeImportDeclarationName() {
604     // SingleTypeImportDeclarationName ::= 'import' Name
605
/* push an ImportRef build from the last name
606     stored in the identifier stack. */

607
608     int index;
609
610     /* no need to take action if not inside assist identifiers */
611     if ((index = indexOfAssistIdentifier()) < 0) {
612         super.consumeSingleTypeImportDeclarationName();
613         return;
614     }
615     /* retrieve identifiers subset and whole positions, the assist node positions
616         should include the entire replaced source. */

617     int length = identifierLengthStack[identifierLengthPtr];
618     char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
619
identifierLengthPtr--;
620     identifierPtr -= length;
621     long[] positions = new long[length];
622     System.arraycopy(
623         identifierPositionStack,
624         identifierPtr + 1,
625         positions,
626         0,
627         length);
628
629     /* build specific assist node on import statement */
630     ImportReference reference = this.createAssistImportReference(subset, positions, ClassFileConstants.AccDefault);
631     assistNode = reference;
632     this.lastCheckPoint = reference.sourceEnd + 1;
633
634     pushOnAstStack(reference);
635
636     if (currentToken == TokenNameSEMICOLON){
637         reference.declarationSourceEnd = scanner.currentPosition - 1;
638     } else {
639         reference.declarationSourceEnd = (int) positions[length-1];
640     }
641     //endPosition is just before the ;
642
reference.declarationSourceStart = intStack[intPtr--];
643     // flush comments defined prior to import statements
644
reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
645
646     // recovery
647
if (currentElement != null){
648         lastCheckPoint = reference.declarationSourceEnd+1;
649         currentElement = currentElement.add(reference, 0);
650         lastIgnoredToken = -1;
651         restartRecovery = true; // used to avoid branching back into the regular automaton
652
}
653 }
654 protected void consumeStaticImportOnDemandDeclarationName() {
655     // TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
656
/* push an ImportRef build from the last name
657     stored in the identifier stack. */

658
659     int index;
660
661     /* no need to take action if not inside assist identifiers */
662     if ((index = indexOfAssistIdentifier()) < 0) {
663         super.consumeStaticImportOnDemandDeclarationName();
664         return;
665     }
666     /* retrieve identifiers subset and whole positions, the assist node positions
667         should include the entire replaced source. */

668     int length = identifierLengthStack[identifierLengthPtr];
669     char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
670
identifierLengthPtr--;
671     identifierPtr -= length;
672     long[] positions = new long[length];
673     System.arraycopy(
674         identifierPositionStack,
675         identifierPtr + 1,
676         positions,
677         0,
678         length);
679
680     /* build specific assist node on import statement */
681     ImportReference reference = this.createAssistImportReference(subset, positions, ClassFileConstants.AccStatic);
682     reference.bits |= ASTNode.OnDemand;
683     assistNode = reference;
684     this.lastCheckPoint = reference.sourceEnd + 1;
685
686     pushOnAstStack(reference);
687
688     if (currentToken == TokenNameSEMICOLON){
689         reference.declarationSourceEnd = scanner.currentPosition - 1;
690     } else {
691         reference.declarationSourceEnd = (int) positions[length-1];
692     }
693     //endPosition is just before the ;
694
reference.declarationSourceStart = intStack[intPtr--];
695     // flush annotations defined prior to import statements
696
reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
697
698     // recovery
699
if (currentElement != null){
700         lastCheckPoint = reference.declarationSourceEnd+1;
701         currentElement = currentElement.add(reference, 0);
702         lastIgnoredToken = -1;
703         restartRecovery = true; // used to avoid branching back into the regular automaton
704
}
705 }
706 protected void consumeStaticInitializer() {
707     super.consumeStaticInitializer();
708     popElement(K_METHOD_DELIMITER);
709 }
710 protected void consumeStaticOnly() {
711     super.consumeStaticOnly();
712     pushOnElementStack(K_METHOD_DELIMITER);
713 }
714 protected void consumeToken(int token) {
715     super.consumeToken(token);
716     
717     if(isFirst) {
718         isFirst = false;
719         return;
720     }
721     // register message send selector only if inside a method or if looking at a field initializer
722
// and if the current token is an open parenthesis
723
if (isInsideMethod() || isInsideFieldInitialization() || isInsideAttributeValue()) {
724         switch (token) {
725             case TokenNameLPAREN :
726                 switch (this.previousToken) {
727                     case TokenNameIdentifier:
728                         this.pushOnElementStack(K_SELECTOR, this.identifierPtr);
729                         break;
730                     case TokenNamethis: // explicit constructor invocation, eg. this(1, 2)
731
this.pushOnElementStack(K_SELECTOR, THIS_CONSTRUCTOR);
732                         break;
733                     case TokenNamesuper: // explicit constructor invocation, eg. super(1, 2)
734
this.pushOnElementStack(K_SELECTOR, SUPER_CONSTRUCTOR);
735                         break;
736                     case TokenNameGREATER: // explicit constructor invocation, eg. Fred<X>[(]1, 2)
737
case TokenNameRIGHT_SHIFT: // or fred<X<X>>[(]1, 2)
738
case TokenNameUNSIGNED_RIGHT_SHIFT: //or Fred<X<X<X>>>[(]1, 2)
739
if(this.identifierPtr > -1) {
740                             this.pushOnElementStack(K_SELECTOR, this.identifierPtr);
741                         }
742                         break;
743                 }
744                 break;
745         }
746     } else {
747         switch (token) {
748             case TokenNameRBRACE :
749                 if(topKnownElementKind(ASSIST_PARSER) == K_TYPE_DELIMITER) {
750                     popElement(K_TYPE_DELIMITER);
751                 }
752                 break;
753         }
754     }
755     this.previousToken = token;
756     if (token == TokenNameIdentifier) {
757         this.previousIdentifierPtr = this.identifierPtr;
758     }
759 }
760 protected void consumeTypeImportOnDemandDeclarationName() {
761     // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
762
/* push an ImportRef build from the last name
763     stored in the identifier stack. */

764
765     int index;
766
767     /* no need to take action if not inside assist identifiers */
768     if ((index = indexOfAssistIdentifier()) < 0) {
769         super.consumeTypeImportOnDemandDeclarationName();
770         return;
771     }
772     /* retrieve identifiers subset and whole positions, the assist node positions
773         should include the entire replaced source. */

774     int length = identifierLengthStack[identifierLengthPtr];
775     char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
776
identifierLengthPtr--;
777     identifierPtr -= length;
778     long[] positions = new long[length];
779     System.arraycopy(
780         identifierPositionStack,
781         identifierPtr + 1,
782         positions,
783         0,
784         length);
785
786     /* build specific assist node on import statement */
787     ImportReference reference = this.createAssistImportReference(subset, positions, ClassFileConstants.AccDefault);
788     reference.bits |= ASTNode.OnDemand;
789     assistNode = reference;
790     this.lastCheckPoint = reference.sourceEnd + 1;
791
792     pushOnAstStack(reference);
793
794     if (currentToken == TokenNameSEMICOLON){
795         reference.declarationSourceEnd = scanner.currentPosition - 1;
796     } else {
797         reference.declarationSourceEnd = (int) positions[length-1];
798     }
799     //endPosition is just before the ;
800
reference.declarationSourceStart = intStack[intPtr--];
801     // flush comments defined prior to import statements
802
reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
803
804     // recovery
805
if (currentElement != null){
806         lastCheckPoint = reference.declarationSourceEnd+1;
807         currentElement = currentElement.add(reference, 0);
808         lastIgnoredToken = -1;
809         restartRecovery = true; // used to avoid branching back into the regular automaton
810
}
811 }
812 public abstract ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod);
813 public abstract ImportReference createAssistPackageReference(char[][] tokens, long[] positions);
814 public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
815 public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
816 public abstract TypeReference createParameterizedQualifiedAssistTypeReference(char[][] previousIdentifiers, TypeReference[][] typeArguments, char[] asistIdentifier, TypeReference[] assistTypeArguments, long[] positions);
817 public abstract NameReference createSingleAssistNameReference(char[] assistName, long position);
818 public abstract TypeReference createSingleAssistTypeReference(char[] assistName, long position);
819 public abstract TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position);
820 /*
821  * Flush parser/scanner state regarding to code assist
822  */

823 public void flushAssistState(){
824     this.assistNode = null;
825     this.isOrphanCompletionNode = false;
826     this.setAssistIdentifier(null);
827 }
828 protected void flushElementStack() {
829     this.elementPtr = -1;
830     this.previousKind = 0;
831     this.previousInfo = 0;
832 }
833 /*
834  * Build specific type reference nodes in case the cursor is located inside the type reference
835  */

836 protected TypeReference getTypeReference(int dim) {
837
838     int index;
839
840     /* no need to take action if not inside completed identifiers */
841     if ((index = indexOfAssistIdentifier(true)) < 0) {
842         return super.getTypeReference(dim);
843     }
844     int length = identifierLengthStack[identifierLengthPtr];
845     TypeReference reference;
846     int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
847     if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
848         identifierLengthPtr--;
849         // generic type
850
reference = getAssistTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
851     } else {
852         /* retrieve identifiers subset and whole positions, the assist node positions
853             should include the entire replaced source. */

854         
855         char[][] subset = identifierSubSet(index);
856         identifierLengthPtr--;
857         identifierPtr -= length;
858         long[] positions = new long[length];
859         System.arraycopy(
860             identifierPositionStack,
861             identifierPtr + 1,
862             positions,
863             0,
864             length);
865     
866         /* build specific assist on type reference */
867         
868         if (index == 0) {
869 // genericsIdentifiersLengthPtr--;
870
genericsLengthPtr--;
871             /* assist inside first identifier */
872             reference = this.createSingleAssistTypeReference(
873                             assistIdentifier(),
874                             positions[0]);
875         } else {
876 // genericsIdentifiersLengthPtr--;
877
genericsLengthPtr--;
878             /* assist inside subsequent identifier */
879             reference = this.createQualifiedAssistTypeReference(
880                             subset,
881                             assistIdentifier(),
882                             positions);
883         }
884         assistNode = reference;
885         this.lastCheckPoint = reference.sourceEnd + 1;
886     }
887     return reference;
888 }
889 protected TypeReference getAssistTypeReferenceForGenericType(int dim, int identifierLength, int numberOfIdentifiers) {
890     /* no need to take action if not inside completed identifiers */
891     if (/*(indexOfAssistIdentifier()) < 0 ||*/ (identifierLength == 1 && numberOfIdentifiers == 1)) {
892         int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
893         TypeReference[] typeArguments = new TypeReference[currentTypeArgumentsLength];
894         this.genericsPtr -= currentTypeArgumentsLength;
895         System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments, 0, currentTypeArgumentsLength);
896         long[] positions = new long[identifierLength];
897         System.arraycopy(
898             identifierPositionStack,
899             identifierPtr,
900             positions,
901             0,
902             identifierLength);
903         
904         this.identifierPtr--;
905                 
906         TypeReference reference = this.createParameterizedSingleAssistTypeReference(
907                 typeArguments,
908                 assistIdentifier(),
909                 positions[0]);
910         
911         this.assistNode = reference;
912         this.lastCheckPoint = reference.sourceEnd + 1;
913         return reference;
914     }
915     
916     TypeReference[][] typeArguments = new TypeReference[numberOfIdentifiers][];
917     char[][] tokens = new char[numberOfIdentifiers][];
918     long[] positions = new long[numberOfIdentifiers];
919     int index = numberOfIdentifiers;
920     int currentIdentifiersLength = identifierLength;
921     while (index > 0) {
922         int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
923         if (currentTypeArgumentsLength != 0) {
924             this.genericsPtr -= currentTypeArgumentsLength;
925             System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments[index - 1] = new TypeReference[currentTypeArgumentsLength], 0, currentTypeArgumentsLength);
926         }
927         switch(currentIdentifiersLength) {
928             case 1 :
929                 // we are in a case A<B>.C<D> or A<B>.C<D>
930
tokens[index - 1] = this.identifierStack[this.identifierPtr];
931                 positions[index - 1] = this.identifierPositionStack[this.identifierPtr--];
932                 break;
933             default:
934                 // we are in a case A.B.C<B>.C<D> or A.B.C<B>...
935
this.identifierPtr -= currentIdentifiersLength;
936                 System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, index - currentIdentifiersLength, currentIdentifiersLength);
937                 System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, index - currentIdentifiersLength, currentIdentifiersLength);
938         }
939         index -= currentIdentifiersLength;
940         if (index > 0) {
941             currentIdentifiersLength = this.identifierLengthStack[this.identifierLengthPtr--];
942         }
943     }
944     
945     // remove completion token
946
int realLength = numberOfIdentifiers;
947     for (int i = 0; i < numberOfIdentifiers; i++) {
948         if(tokens[i] == assistIdentifier()) {
949             realLength = i;
950         }
951     }
952     TypeReference reference;
953     if(realLength == 0) {
954         if(typeArguments[0] != null && typeArguments[0].length > 0) {
955             reference = this.createParameterizedSingleAssistTypeReference(typeArguments[0], assistIdentifier(), positions[0]);
956         } else {
957             reference = this.createSingleAssistTypeReference(assistIdentifier(), positions[0]);
958         }
959     } else {
960         TypeReference[] assistTypeArguments = typeArguments[realLength];
961         System.arraycopy(tokens, 0, tokens = new char[realLength][], 0, realLength);
962         System.arraycopy(typeArguments, 0, typeArguments = new TypeReference[realLength][], 0, realLength);
963         
964         boolean isParameterized = false;
965         for (int i = 0; i < typeArguments.length; i++) {
966             if(typeArguments[i] != null) {
967                 isParameterized = true;
968             }
969         }
970         if(isParameterized || (assistTypeArguments != null && assistTypeArguments.length > 0)) {
971             reference = this.createParameterizedQualifiedAssistTypeReference(tokens, typeArguments, assistIdentifier(), assistTypeArguments, positions);
972         } else {
973             reference = this.createQualifiedAssistTypeReference(tokens, assistIdentifier(), positions);
974         }
975     }
976
977     assistNode = reference;
978     this.lastCheckPoint = reference.sourceEnd + 1;
979     return reference;
980 }
981 /*
982  * Copy of code from superclass with the following change:
983  * In the case of qualified name reference if the cursor location is on the
984  * qualified name reference, then create a CompletionOnQualifiedNameReference
985  * instead.
986  */

987 protected NameReference getUnspecifiedReferenceOptimized() {
988
989     int completionIndex;
990
991     /* no need to take action if not inside completed identifiers */
992     if ((completionIndex = indexOfAssistIdentifier()) < 0) {
993         return super.getUnspecifiedReferenceOptimized();
994     }
995
996     /* retrieve identifiers subset and whole positions, the completion node positions
997         should include the entire replaced source. */

998     int length = identifierLengthStack[identifierLengthPtr];
999     char[][] subset = identifierSubSet(completionIndex);
1000    identifierLengthPtr--;
1001    identifierPtr -= length;
1002    long[] positions = new long[length];
1003    System.arraycopy(
1004        identifierPositionStack,
1005        identifierPtr + 1,
1006        positions,
1007        0,
1008        length);
1009
1010    /* build specific completion on name reference */
1011    NameReference reference;
1012    if (completionIndex == 0) {
1013        /* completion inside first identifier */
1014        reference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
1015    } else {
1016        /* completion inside subsequent identifier */
1017        reference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
1018    }
1019    reference.bits &= ~ASTNode.RestrictiveFlagMASK;
1020    reference.bits |= Binding.LOCAL | Binding.FIELD;
1021    
1022    assistNode = reference;
1023    lastCheckPoint = reference.sourceEnd + 1;
1024    return reference;
1025}
1026public void goForBlockStatementsopt() {
1027    super.goForBlockStatementsopt();
1028    isFirst = true;
1029}
1030public void goForHeaders(){
1031    super.goForHeaders();
1032    isFirst = true;
1033}
1034public void goForCompilationUnit(){
1035    super.goForCompilationUnit();
1036    isFirst = true;
1037}
1038public void goForBlockStatementsOrCatchHeader() {
1039    super.goForBlockStatementsOrCatchHeader();
1040    isFirst = true;
1041}
1042/*
1043 * Retrieve a partial subset of a qualified name reference up to the completion point.
1044 * It does not pop the actual awaiting identifiers, so as to be able to retrieve position
1045 * information afterwards.
1046 */

1047protected char[][] identifierSubSet(int subsetLength){
1048
1049    if (subsetLength == 0) return null;
1050    
1051    char[][] subset;
1052    System.arraycopy(
1053        identifierStack,
1054        identifierPtr - identifierLengthStack[identifierLengthPtr] + 1,
1055        (subset = new char[subsetLength][]),
1056        0,
1057        subsetLength);
1058    return subset;
1059}
1060
1061protected int indexOfAssistIdentifier(){
1062    return this.indexOfAssistIdentifier(false);
1063}
1064/*
1065 * Iterate the most recent group of awaiting identifiers (grouped for qualified name reference (eg. aa.bb.cc)
1066 * so as to check whether one of them is the assist identifier.
1067 * If so, then answer the index of the assist identifier (0 being the first identifier of the set).
1068 * eg. aa(0).bb(1).cc(2)
1069 * If no assist identifier was found, answers -1.
1070 */

1071protected int indexOfAssistIdentifier(boolean useGenericsStack){
1072
1073    if (identifierLengthPtr < 0){
1074        return -1; // no awaiting identifier
1075
}
1076
1077    char[] assistIdentifier ;
1078    if ((assistIdentifier = this.assistIdentifier()) == null){
1079        return -1; // no assist identifier found yet
1080
}
1081
1082    // iterate awaiting identifiers backwards
1083
int length = identifierLengthStack[identifierLengthPtr];
1084    if(useGenericsStack && length > 0 && this.genericsIdentifiersLengthPtr > -1 ) {
1085        length = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
1086    }
1087    for (int i = 0; i < length; i++){
1088        if (identifierStack[identifierPtr - i] == assistIdentifier){
1089            return length - i - 1;
1090        }
1091    }
1092    // none of the awaiting identifiers is the completion one
1093
return -1;
1094}
1095public void initialize() {
1096    super.initialize();
1097    this.flushAssistState();
1098    this.flushElementStack();
1099    this.previousIdentifierPtr = -1;
1100}
1101public void initialize(boolean initializeNLS) {
1102    super.initialize(initializeNLS);
1103    this.flushAssistState();
1104    this.flushElementStack();
1105    this.previousIdentifierPtr = -1;
1106}
1107public abstract void initializeScanner();
1108protected boolean isIndirectlyInsideFieldInitialization(){
1109    int i = elementPtr;
1110    while(i > -1) {
1111        if(elementKindStack[i] == K_FIELD_INITIALIZER_DELIMITER)
1112            return true;
1113        i--;
1114    }
1115    return false;
1116}
1117protected boolean isIndirectlyInsideMethod(){
1118    int i = elementPtr;
1119    while(i > -1) {
1120        if(elementKindStack[i] == K_METHOD_DELIMITER)
1121            return true;
1122        i--;
1123    }
1124    return false;
1125}
1126protected boolean isIndirectlyInsideType(){
1127    int i = elementPtr;
1128    while(i > -1) {
1129        if(elementKindStack[i] == K_TYPE_DELIMITER)
1130            return true;
1131        i--;
1132    }
1133    return false;
1134}
1135protected boolean isInsideAttributeValue(){
1136    int i = elementPtr;
1137    while(i > -1) {
1138        switch (elementKindStack[i]) {
1139            case K_TYPE_DELIMITER : return false;
1140            case K_METHOD_DELIMITER : return false;
1141            case K_FIELD_INITIALIZER_DELIMITER : return false;
1142            case K_ATTRIBUTE_VALUE_DELIMITER : return true;
1143        }
1144        i--;
1145    }
1146    return false;
1147}
1148protected boolean isInsideFieldInitialization(){
1149    int i = elementPtr;
1150    while(i > -1) {
1151        switch (elementKindStack[i]) {
1152            case K_TYPE_DELIMITER : return false;
1153            case K_METHOD_DELIMITER : return false;
1154            case K_FIELD_INITIALIZER_DELIMITER : return true;
1155        }
1156        i--;
1157    }
1158    return false;
1159}
1160protected boolean isInsideMethod(){
1161    int i = elementPtr;
1162    while(i > -1) {
1163        switch (elementKindStack[i]) {
1164            case K_TYPE_DELIMITER : return false;
1165            case K_METHOD_DELIMITER : return true;
1166            case K_FIELD_INITIALIZER_DELIMITER : return false;
1167        }
1168        i--;
1169    }
1170    return false;
1171}
1172protected boolean isInsideType(){
1173    int i = elementPtr;
1174    while(i > -1) {
1175        switch (elementKindStack[i]) {
1176            case K_TYPE_DELIMITER : return true;
1177            case K_METHOD_DELIMITER : return false;
1178            case K_FIELD_INITIALIZER_DELIMITER : return false;
1179        }
1180        i--;
1181    }
1182    return false;
1183}
1184protected int lastIndexOfElement(int kind) {
1185    int i = elementPtr;
1186    while(i > -1) {
1187        if(elementKindStack[i] == kind) return i;
1188        i--;
1189    }
1190    return -1;
1191}
1192/**
1193 * Parse the block statements inside the given method declaration and try to complete at the
1194 * cursor location.
1195 */

1196public void parseBlockStatements(AbstractMethodDeclaration md, CompilationUnitDeclaration unit) {
1197    if (md instanceof MethodDeclaration) {
1198        parseBlockStatements((MethodDeclaration) md, unit);
1199    } else if (md instanceof ConstructorDeclaration) {
1200        parseBlockStatements((ConstructorDeclaration) md, unit);
1201    }
1202}
1203/**
1204 * Parse the block statements inside the given constructor declaration and try to complete at the
1205 * cursor location.
1206 */

1207public void parseBlockStatements(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
1208    //only parse the method body of cd
1209
//fill out its statements
1210

1211    //convert bugs into parse error
1212

1213    initialize();
1214    
1215    // simulate goForConstructorBody except that we don't want to balance brackets because they are not going to be balanced
1216
goForBlockStatementsopt();
1217
1218    referenceContext = cd;
1219    compilationUnit = unit;
1220
1221    scanner.resetTo(cd.bodyStart, bodyEnd(cd));
1222    consumeNestedMethod();
1223    try {
1224        parse();
1225    } catch (AbortCompilation ex) {
1226        lastAct = ERROR_ACTION;
1227    }
1228    
1229    if (lastAct == ERROR_ACTION) {
1230        return;
1231    }
1232
1233    // attach the statements as we might be searching for a reference to a local type
1234
cd.explicitDeclarations = realBlockStack[realBlockPtr--];
1235    int length;
1236    if ((length = astLengthStack[astLengthPtr--]) != 0) {
1237        astPtr -= length;
1238        if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
1239            //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
1240
{
1241            System.arraycopy(
1242                astStack,
1243                astPtr + 2,
1244                cd.statements = new Statement[length - 1],
1245                0,
1246                length - 1);
1247            cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
1248        } else { //need to add explicitly the super();
1249
System.arraycopy(
1250                astStack,
1251                astPtr + 1,
1252                cd.statements = new Statement[length],
1253                0,
1254                length);
1255            cd.constructorCall = SuperReference.implicitSuperConstructorCall();
1256        }
1257    } else {
1258        cd.constructorCall = SuperReference.implicitSuperConstructorCall();
1259        if (!containsComment(cd.bodyStart, cd.bodyEnd)) {
1260            cd.bits |= ASTNode.UndocumentedEmptyBlock;
1261        }
1262    }
1263
1264    if (cd.constructorCall.sourceEnd == 0) {
1265        cd.constructorCall.sourceEnd = cd.sourceEnd;
1266        cd.constructorCall.sourceStart = cd.sourceStart;
1267    }
1268}
1269/**
1270 * Parse the block statements inside the given initializer and try to complete at the
1271 * cursor location.
1272 */

1273public void parseBlockStatements(
1274    Initializer initializer,
1275    TypeDeclaration type,
1276    CompilationUnitDeclaration unit) {
1277
1278    initialize();
1279
1280    // simulate goForInitializer except that we don't want to balance brackets because they are not going to be balanced
1281
goForBlockStatementsopt();
1282    
1283    referenceContext = type;
1284    compilationUnit = unit;
1285
1286    scanner.resetTo(initializer.sourceStart, bodyEnd(initializer)); // just after the beginning {
1287
consumeNestedMethod();
1288    try {
1289        parse();
1290    } catch (AbortCompilation ex) {
1291        lastAct = ERROR_ACTION;
1292    } finally {
1293        nestedMethod[nestedType]--;
1294    }
1295    
1296    if (lastAct == ERROR_ACTION) {
1297        return;
1298    }
1299
1300    // attach the statements as we might be searching for a reference to a local type
1301
initializer.block.explicitDeclarations = realBlockStack[realBlockPtr--];
1302    int length;
1303    if ((length = astLengthStack[astLengthPtr--]) > 0) {
1304        System.arraycopy(astStack, (astPtr -= length) + 1, initializer.block.statements = new Statement[length], 0, length);
1305    } else {
1306        // check whether this block at least contains some comment in it
1307
if (!containsComment(initializer.block.sourceStart, initializer.block.sourceEnd)) {
1308            initializer.block.bits |= ASTNode.UndocumentedEmptyBlock;
1309        }
1310    }
1311    
1312    // mark initializer with local type if one was found during parsing
1313
if ((type.bits & ASTNode.HasLocalType) != 0) {
1314        initializer.bits |= ASTNode.HasLocalType;
1315    }
1316}
1317/**
1318 * Parse the block statements inside the given method declaration and try to complete at the
1319 * cursor location.
1320 */

1321public void parseBlockStatements(MethodDeclaration md, CompilationUnitDeclaration unit) {
1322    //only parse the method body of md
1323
//fill out method statements
1324

1325    //convert bugs into parse error
1326

1327    if (md.isAbstract())
1328        return;
1329    if (md.isNative())
1330        return;
1331    if ((md.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0)
1332        return;
1333
1334    initialize();
1335
1336    // simulate goForMethodBody except that we don't want to balance brackets because they are not going to be balanced
1337
goForBlockStatementsopt();
1338
1339    referenceContext = md;
1340    compilationUnit = unit;
1341    
1342    scanner.resetTo(md.bodyStart, bodyEnd(md)); // reset the scanner to parser from { down to the cursor location
1343
consumeNestedMethod();
1344    try {
1345        parse();
1346    } catch (AbortCompilation ex) {
1347        lastAct = ERROR_ACTION;
1348    } finally {
1349        nestedMethod[nestedType]--;
1350    }
1351    
1352    if (lastAct == ERROR_ACTION) {
1353        return;
1354    }
1355
1356    // attach the statements as we might be searching for a reference to a local type
1357
md.explicitDeclarations = realBlockStack[realBlockPtr--];
1358    int length;
1359    if ((length = astLengthStack[astLengthPtr--]) != 0) {
1360        System.arraycopy(
1361            astStack,
1362            (astPtr -= length) + 1,
1363            md.statements = new Statement[length],
1364            0,
1365            length);
1366    } else {
1367        if (!containsComment(md.bodyStart, md.bodyEnd)) {
1368            md.bits |= ASTNode.UndocumentedEmptyBlock;
1369        }
1370    }
1371
1372}
1373protected void popElement(int kind){
1374    if(elementPtr < 0 || elementKindStack[elementPtr] != kind) return;
1375    
1376    previousKind = elementKindStack[elementPtr];
1377    previousInfo = elementInfoStack[elementPtr];
1378    
1379    switch (kind) {
1380        default :
1381            elementPtr--;
1382            break;
1383    }
1384}
1385protected void popUntilElement(int kind){
1386    if(elementPtr < 0) return;
1387    int i = elementPtr;
1388    while (i >= 0 && elementKindStack[i] != kind) {
1389        i--;
1390    }
1391    if(i >= 0) {
1392        if(i < elementPtr) {
1393            previousKind = elementKindStack[i+1];
1394            previousInfo = elementInfoStack[i+1];
1395        }
1396        elementPtr = i;
1397    }
1398}
1399/*
1400 * Prepares the state of the parser to go for BlockStatements.
1401 */

1402protected void prepareForBlockStatements() {
1403    this.nestedMethod[this.nestedType = 0] = 1;
1404    this.variablesCounter[this.nestedType] = 0;
1405    this.realBlockStack[this.realBlockPtr = 1] = 0;
1406    
1407    // initialize element stack
1408
int fieldInitializerIndex = lastIndexOfElement(K_FIELD_INITIALIZER_DELIMITER);
1409    int methodIndex = lastIndexOfElement(K_METHOD_DELIMITER);
1410    if(methodIndex == fieldInitializerIndex) {
1411        // there is no method and no field initializer
1412
flushElementStack();
1413    } else if(methodIndex > fieldInitializerIndex) {
1414        popUntilElement(K_METHOD_DELIMITER);
1415    } else {
1416        popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
1417    }
1418}
1419/*
1420 * Prepares the state of the parser to go for Headers.
1421 */

1422protected void prepareForHeaders() {
1423    nestedMethod[nestedType = 0] = 0;
1424    variablesCounter[nestedType] = 0;
1425    realBlockStack[realBlockPtr = 0] = 0;
1426    
1427    popUntilElement(K_TYPE_DELIMITER);
1428
1429    if(this.topKnownElementKind(ASSIST_PARSER) != K_TYPE_DELIMITER) {
1430        // is outside a type and inside a compilation unit.
1431
// remove all elements.
1432
this.flushElementStack();
1433    }
1434}
1435protected void pushOnElementStack(int kind){
1436    this.pushOnElementStack(kind, 0);
1437}
1438protected void pushOnElementStack(int kind, int info){
1439    if (this.elementPtr < -1) return;
1440    
1441    this.previousKind = 0;
1442    this.previousInfo = 0;
1443    
1444    int stackLength = this.elementKindStack.length;
1445    if (++this.elementPtr >= stackLength) {
1446        System.arraycopy(
1447            this.elementKindStack, 0,
1448            this.elementKindStack = new int[stackLength + StackIncrement], 0,
1449            stackLength);
1450        System.arraycopy(
1451            this.elementInfoStack, 0,
1452            this.elementInfoStack = new int[stackLength + StackIncrement], 0,
1453            stackLength);
1454    }
1455    this.elementKindStack[this.elementPtr] = kind;
1456    this.elementInfoStack[this.elementPtr] = info;
1457}
1458public void recoveryExitFromVariable() {
1459    if(currentElement != null && currentElement instanceof RecoveredField
1460        && !(currentElement instanceof RecoveredInitializer)) {
1461        RecoveredElement oldElement = currentElement;
1462        super.recoveryExitFromVariable();
1463        if(oldElement != currentElement) {
1464            popElement(K_FIELD_INITIALIZER_DELIMITER);
1465        }
1466    } else {
1467        super.recoveryExitFromVariable();
1468    }
1469}
1470public void recoveryTokenCheck() {
1471    RecoveredElement oldElement = currentElement;
1472    switch (currentToken) {
1473        case TokenNameLBRACE :
1474            super.recoveryTokenCheck();
1475            if(currentElement instanceof RecoveredInitializer) {
1476                if(oldElement instanceof RecoveredField) {
1477                    popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
1478                    popElement(K_FIELD_INITIALIZER_DELIMITER);
1479                }
1480                if(currentElement != oldElement
1481                    && topKnownElementKind(ASSIST_PARSER) != K_METHOD_DELIMITER) {
1482                    pushOnElementStack(K_METHOD_DELIMITER);
1483                }
1484            }
1485            break;
1486        case TokenNameRBRACE :
1487            super.recoveryTokenCheck();
1488            if(currentElement != oldElement && !isInsideAttributeValue()) {
1489                if(oldElement instanceof RecoveredInitializer
1490                    || oldElement instanceof RecoveredMethod
1491                    || (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredInitializer)
1492                    || (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredMethod)) {
1493                    popUntilElement(K_METHOD_DELIMITER);
1494                    popElement(K_METHOD_DELIMITER);
1495                } else if(oldElement instanceof RecoveredType) {
1496                    popUntilElement(K_TYPE_DELIMITER);
1497                    if(!(referenceContext instanceof CompilationUnitDeclaration)
1498                            || isIndirectlyInsideFieldInitialization()
1499                            || currentElement instanceof RecoveredUnit) {
1500                        popElement(K_TYPE_DELIMITER);
1501                    }
1502                }
1503            }
1504            break;
1505        default :
1506            super.recoveryTokenCheck();
1507            break;
1508    }
1509}
1510public void reset(){
1511    this.flushAssistState();
1512}
1513/*
1514 * Reset context so as to resume to regular parse loop
1515 * If unable to reset for resuming, answers false.
1516 *
1517 * Move checkpoint location, reset internal stacks and
1518 * decide which grammar goal is activated.
1519 */

1520protected boolean resumeAfterRecovery() {
1521
1522    // reset internal stacks
1523
this.astPtr = -1;
1524    this.astLengthPtr = -1;
1525    this.expressionPtr = -1;
1526    this.expressionLengthPtr = -1;
1527    this.identifierPtr = -1;
1528    this.identifierLengthPtr = -1;
1529    this.intPtr = -1;
1530    this.dimensions = 0 ;
1531    this.recoveredStaticInitializerStart = 0;
1532    
1533    this.genericsIdentifiersLengthPtr = -1;
1534    this.genericsLengthPtr = -1;
1535    this.genericsPtr = -1;
1536    
1537    this.modifiers = ClassFileConstants.AccDefault;
1538    this.modifiersSourceStart = -1;
1539
1540    // if in diet mode, reset the diet counter because we're going to restart outside an initializer.
1541
if (diet) dietInt = 0;
1542
1543    /* attempt to move checkpoint location */
1544    if (!this.moveRecoveryCheckpoint()) return false;
1545
1546    // only look for headers
1547
if (referenceContext instanceof CompilationUnitDeclaration
1548        || this.assistNode != null){
1549        if(isInsideMethod() &&
1550            isIndirectlyInsideFieldInitialization() &&
1551            this.assistNode == null
1552            ){
1553            this.prepareForBlockStatements();
1554            goForBlockStatementsOrCatchHeader();
1555        } else {
1556            this.prepareForHeaders();
1557            goForHeaders();
1558            diet = true; // passed this point, will not consider method bodies
1559
}
1560        return true;
1561    }
1562    if (referenceContext instanceof AbstractMethodDeclaration
1563        || referenceContext instanceof TypeDeclaration){
1564            
1565        if (currentElement instanceof RecoveredType){
1566            this.prepareForHeaders();
1567            goForHeaders();
1568        } else {
1569            this.prepareForBlockStatements();
1570            goForBlockStatementsOrCatchHeader();
1571        }
1572        return true;
1573    }
1574    // does not know how to restart
1575
return false;
1576}
1577public abstract void setAssistIdentifier(char[] assistIdent);
1578protected int topKnownElementInfo(int owner) {
1579    return topKnownElementInfo(owner, 0);
1580}
1581protected int topKnownElementInfo(int owner, int offSet) {
1582    int i = elementPtr;
1583    while(i > -1) {
1584        if((elementKindStack[i] & owner) != 0) {
1585            if(offSet <= 0) return elementInfoStack[i];
1586            offSet--;
1587        }
1588        i--;
1589    }
1590    return 0;
1591}
1592protected int topKnownElementKind(int owner) {
1593    return topKnownElementKind(owner, 0);
1594}
1595protected int topKnownElementKind(int owner, int offSet) {
1596    int i = elementPtr;
1597    while(i > -1) {
1598        if((elementKindStack[i] & owner) != 0) {
1599            if(offSet <= 0) return elementKindStack[i];
1600            offSet--;
1601        }
1602        i--;
1603    }
1604    return 0;
1605}
1606/**
1607 * If the given ast node is inside an explicit constructor call
1608 * then wrap it with a fake constructor call.
1609 * Returns the wrapped completion node or the completion node itself.
1610 */

1611protected ASTNode wrapWithExplicitConstructorCallIfNeeded(ASTNode ast) {
1612    int selector;
1613    if (ast != null && topKnownElementKind(ASSIST_PARSER) == K_SELECTOR && ast instanceof Expression &&
1614            (((selector = topKnownElementInfo(ASSIST_PARSER)) == THIS_CONSTRUCTOR) ||
1615            (selector == SUPER_CONSTRUCTOR))) {
1616        ExplicitConstructorCall call = new ExplicitConstructorCall(
1617            (selector == THIS_CONSTRUCTOR) ?
1618                ExplicitConstructorCall.This :
1619                ExplicitConstructorCall.Super
1620        );
1621        call.arguments = new Expression[] {(Expression)ast};
1622        call.sourceStart = ast.sourceStart;
1623        call.sourceEnd = ast.sourceEnd;
1624        return call;
1625    } else {
1626        return ast;
1627    }
1628}
1629}
1630
Popular Tags