KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > codeassist > select > SelectionParser


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.select;
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  
23 import org.eclipse.jdt.internal.compiler.*;
24 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
25 import org.eclipse.jdt.internal.compiler.env.*;
26
27 import org.eclipse.jdt.core.compiler.CharOperation;
28 import org.eclipse.jdt.internal.codeassist.impl.*;
29 import org.eclipse.jdt.internal.compiler.ast.*;
30 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
31 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
32 import org.eclipse.jdt.internal.compiler.parser.*;
33 import org.eclipse.jdt.internal.compiler.problem.*;
34 import org.eclipse.jdt.internal.compiler.util.Util;
35
36 public class SelectionParser extends AssistParser {
37     // OWNER
38
protected static final int SELECTION_PARSER = 1024;
39     protected static final int SELECTION_OR_ASSIST_PARSER = ASSIST_PARSER + SELECTION_PARSER;
40     
41     // KIND : all values known by SelectionParser are between 1025 and 1549
42
protected static final int K_BETWEEN_CASE_AND_COLON = SELECTION_PARSER + 1; // whether we are inside a block
43

44     public ASTNode assistNodeParent; // the parent node of assist node
45

46     /* public fields */
47
48     public int selectionStart, selectionEnd;
49
50     public static final char[] SUPER = "super".toCharArray(); //$NON-NLS-1$
51
public static final char[] THIS = "this".toCharArray(); //$NON-NLS-1$
52

53 public SelectionParser(ProblemReporter problemReporter) {
54     super(problemReporter);
55     this.javadocParser.checkDocComment = true;
56 }
57 public char[] assistIdentifier(){
58     return ((SelectionScanner)scanner).selectionIdentifier;
59 }
60 protected void attachOrphanCompletionNode(){
61     if (isOrphanCompletionNode){
62         ASTNode orphan = this.assistNode;
63         isOrphanCompletionNode = false;
64         
65         
66         /* if in context of a type, then persists the identifier into a fake field return type */
67         if (currentElement instanceof RecoveredType){
68             RecoveredType recoveredType = (RecoveredType)currentElement;
69             /* filter out cases where scanner is still inside type header */
70             if (recoveredType.foundOpeningBrace) {
71                 /* generate a pseudo field with a completion on type reference */
72                 if (orphan instanceof TypeReference){
73                     currentElement = currentElement.add(new SelectionOnFieldType((TypeReference)orphan), 0);
74                     return;
75                 }
76             }
77         }
78         
79         if (orphan instanceof Expression) {
80             buildMoreCompletionContext((Expression)orphan);
81         } else {
82             Statement statement = (Statement) orphan;
83             currentElement = currentElement.add(statement, 0);
84         }
85         currentToken = 0; // given we are not on an eof, we do not want side effects caused by looked-ahead token
86
}
87 }
88 private void buildMoreCompletionContext(Expression expression) {
89     ASTNode parentNode = null;
90     
91     int kind = topKnownElementKind(SELECTION_OR_ASSIST_PARSER);
92     if(kind != 0) {
93 // int info = topKnownElementInfo(SELECTION_OR_ASSIST_PARSER);
94
switch (kind) {
95             case K_BETWEEN_CASE_AND_COLON :
96                 if(this.expressionPtr > 0) {
97                     SwitchStatement switchStatement = new SwitchStatement();
98                     switchStatement.expression = this.expressionStack[this.expressionPtr - 1];
99                     if(this.astLengthPtr > -1 && this.astPtr > -1) {
100                         int length = this.astLengthStack[this.astLengthPtr];
101                         int newAstPtr = this.astPtr - length;
102                         ASTNode firstNode = this.astStack[newAstPtr + 1];
103                         if(length != 0 && firstNode.sourceStart > switchStatement.expression.sourceEnd) {
104                             switchStatement.statements = new Statement[length + 1];
105                             System.arraycopy(
106                                 this.astStack,
107                                 newAstPtr + 1,
108                                 switchStatement.statements,
109                                 0,
110                                 length);
111                         }
112                     }
113                     CaseStatement caseStatement = new CaseStatement(expression, expression.sourceStart, expression.sourceEnd);
114                     if(switchStatement.statements == null) {
115                         switchStatement.statements = new Statement[]{caseStatement};
116                     } else {
117                         switchStatement.statements[switchStatement.statements.length - 1] = caseStatement;
118                     }
119                     parentNode = switchStatement;
120                     this.assistNodeParent = parentNode;
121                 }
122                 break;
123         }
124     }
125     if(parentNode != null) {
126         currentElement = currentElement.add((Statement)parentNode, 0);
127     } else {
128         currentElement = currentElement.add((Statement)wrapWithExplicitConstructorCallIfNeeded(expression), 0);
129         if(lastCheckPoint < expression.sourceEnd) {
130             lastCheckPoint = expression.sourceEnd + 1;
131         }
132     }
133 }
134 private boolean checkRecoveredType() {
135     if (currentElement instanceof RecoveredType){
136         /* check if current awaiting identifier is the completion identifier */
137         if (this.indexOfAssistIdentifier() < 0) return false;
138
139         if ((lastErrorEndPosition >= selectionStart)
140             && (lastErrorEndPosition <= selectionEnd+1)){
141             return false;
142         }
143         RecoveredType recoveredType = (RecoveredType)currentElement;
144         /* filter out cases where scanner is still inside type header */
145         if (recoveredType.foundOpeningBrace) {
146             this.assistNode = this.getTypeReference(0);
147             this.lastCheckPoint = this.assistNode.sourceEnd + 1;
148             this.isOrphanCompletionNode = true;
149             return true;
150         }
151     }
152     return false;
153 }
154 protected void classInstanceCreation(boolean hasClassBody) {
155     
156     // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
157

158     // ClassBodyopt produces a null item on the astStak if it produces NO class body
159
// An empty class body produces a 0 on the length stack.....
160

161     
162     if ((astLengthStack[astLengthPtr] == 1)
163         && (astStack[astPtr] == null)) {
164
165         
166         int index;
167         if ((index = this.indexOfAssistIdentifier()) < 0) {
168             super.classInstanceCreation(hasClassBody);
169             return;
170         } else if(this.identifierLengthPtr > -1 &&
171                     (this.identifierLengthStack[this.identifierLengthPtr] - 1) != index) {
172             super.classInstanceCreation(hasClassBody);
173             return;
174         }
175         QualifiedAllocationExpression alloc;
176         astPtr--;
177         astLengthPtr--;
178         alloc = new SelectionOnQualifiedAllocationExpression();
179         alloc.sourceEnd = endPosition; //the position has been stored explicitly
180

181         int length;
182         if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
183             expressionPtr -= length;
184             System.arraycopy(
185                 expressionStack,
186                 expressionPtr + 1,
187                 alloc.arguments = new Expression[length],
188                 0,
189                 length);
190         }
191         // trick to avoid creating a selection on type reference
192
char [] oldIdent = this.assistIdentifier();
193         this.setAssistIdentifier(null);
194         alloc.type = getTypeReference(0);
195         
196         this.setAssistIdentifier(oldIdent);
197         
198         //the default constructor with the correct number of argument
199
//will be created and added by the TC (see createsInternalConstructorWithBinding)
200
alloc.sourceStart = intStack[intPtr--];
201         pushOnExpressionStack(alloc);
202
203         this.assistNode = alloc;
204         this.lastCheckPoint = alloc.sourceEnd + 1;
205         if (!diet){
206             this.restartRecovery = true; // force to restart in recovery mode
207
this.lastIgnoredToken = -1;
208         }
209         this.isOrphanCompletionNode = true;
210     } else {
211         super.classInstanceCreation(hasClassBody);
212     }
213 }
214 protected void consumeArrayCreationExpressionWithoutInitializer() {
215     // ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
216
// ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
217

218     super.consumeArrayCreationExpressionWithoutInitializer();
219
220     ArrayAllocationExpression alloc = (ArrayAllocationExpression)expressionStack[expressionPtr];
221     if (alloc.type == assistNode){
222         if (!diet){
223             this.restartRecovery = true; // force to restart in recovery mode
224
this.lastIgnoredToken = -1;
225         }
226         this.isOrphanCompletionNode = true;
227     }
228 }
229 protected void consumeArrayCreationExpressionWithInitializer() {
230     // ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
231

232     super.consumeArrayCreationExpressionWithInitializer();
233
234     ArrayAllocationExpression alloc = (ArrayAllocationExpression)expressionStack[expressionPtr];
235     if (alloc.type == assistNode){
236         if (!diet){
237             this.restartRecovery = true; // force to restart in recovery mode
238
this.lastIgnoredToken = -1;
239         }
240         this.isOrphanCompletionNode = true;
241     }
242 }
243 protected void consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() {
244     // ClassInstanceCreationExpression ::= Primary '.' 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
245
// ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
246

247     QualifiedAllocationExpression alloc;
248     int length;
249     if (((length = this.astLengthStack[this.astLengthPtr]) == 1) && (this.astStack[this.astPtr] == null)) {
250         
251         if (this.indexOfAssistIdentifier() < 0) {
252             super.consumeClassInstanceCreationExpressionQualifiedWithTypeArguments();
253             return;
254         }
255         
256         //NO ClassBody
257
this.astPtr--;
258         this.astLengthPtr--;
259         alloc = new SelectionOnQualifiedAllocationExpression();
260         alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
261

262         if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
263             this.expressionPtr -= length;
264             System.arraycopy(
265                 this.expressionStack,
266                 this.expressionPtr + 1,
267                 alloc.arguments = new Expression[length],
268                 0,
269                 length);
270         }
271         
272         // trick to avoid creating a selection on type reference
273
char [] oldIdent = this.assistIdentifier();
274         this.setAssistIdentifier(null);
275         alloc.type = getTypeReference(0);
276         
277         this.setAssistIdentifier(oldIdent);
278
279         length = this.genericsLengthStack[this.genericsLengthPtr--];
280         this.genericsPtr -= length;
281         System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
282         intPtr--; // remove the position of the '<'
283

284         //the default constructor with the correct number of argument
285
//will be created and added by the TC (see createsInternalConstructorWithBinding)
286
alloc.sourceStart = this.intStack[this.intPtr--];
287         pushOnExpressionStack(alloc);
288         
289         this.assistNode = alloc;
290         this.lastCheckPoint = alloc.sourceEnd + 1;
291         if (!diet){
292             this.restartRecovery = true; // force to restart in recovery mode
293
this.lastIgnoredToken = -1;
294         }
295         this.isOrphanCompletionNode = true;
296     } else {
297         super.consumeClassInstanceCreationExpressionQualifiedWithTypeArguments();
298     }
299
300     this.expressionLengthPtr--;
301     QualifiedAllocationExpression qae =
302         (QualifiedAllocationExpression) this.expressionStack[this.expressionPtr--];
303     qae.enclosingInstance = this.expressionStack[this.expressionPtr];
304     this.expressionStack[this.expressionPtr] = qae;
305     qae.sourceStart = qae.enclosingInstance.sourceStart;
306 }
307 protected void consumeClassInstanceCreationExpressionWithTypeArguments() {
308     // ClassInstanceCreationExpression ::= 'new' TypeArguments ClassType '(' ArgumentListopt ')' ClassBodyopt
309
AllocationExpression alloc;
310     int length;
311     if (((length = this.astLengthStack[this.astLengthPtr]) == 1)
312         && (this.astStack[this.astPtr] == null)) {
313         
314         if (this.indexOfAssistIdentifier() < 0) {
315             super.consumeClassInstanceCreationExpressionWithTypeArguments();
316             return;
317         }
318         
319         //NO ClassBody
320
this.astPtr--;
321         this.astLengthPtr--;
322         alloc = new SelectionOnQualifiedAllocationExpression();
323         alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
324

325         if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
326             this.expressionPtr -= length;
327             System.arraycopy(
328                 this.expressionStack,
329                 this.expressionPtr + 1,
330                 alloc.arguments = new Expression[length],
331                 0,
332                 length);
333         }
334         
335         // trick to avoid creating a selection on type reference
336
char [] oldIdent = this.assistIdentifier();
337         this.setAssistIdentifier(null);
338         alloc.type = getTypeReference(0);
339         
340         this.setAssistIdentifier(oldIdent);
341
342         length = this.genericsLengthStack[this.genericsLengthPtr--];
343         this.genericsPtr -= length;
344         System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
345         intPtr--; // remove the position of the '<'
346

347         //the default constructor with the correct number of argument
348
//will be created and added by the TC (see createsInternalConstructorWithBinding)
349
alloc.sourceStart = this.intStack[this.intPtr--];
350         pushOnExpressionStack(alloc);
351         
352         this.assistNode = alloc;
353         this.lastCheckPoint = alloc.sourceEnd + 1;
354         if (!diet){
355             this.restartRecovery = true; // force to restart in recovery mode
356
this.lastIgnoredToken = -1;
357         }
358         this.isOrphanCompletionNode = true;
359     } else {
360         super.consumeClassInstanceCreationExpressionWithTypeArguments();
361     }
362 }
363 protected void consumeEnterAnonymousClassBody() {
364     // EnterAnonymousClassBody ::= $empty
365

366     if (this.indexOfAssistIdentifier() < 0) {
367         super.consumeEnterAnonymousClassBody();
368         return;
369     }
370     
371     // trick to avoid creating a selection on type reference
372
char [] oldIdent = this.assistIdentifier();
373     this.setAssistIdentifier(null);
374     TypeReference typeReference = getTypeReference(0);
375     this.setAssistIdentifier(oldIdent);
376
377     TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
378     anonymousType.name = CharOperation.NO_CHAR;
379     anonymousType.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType);
380     QualifiedAllocationExpression alloc = new SelectionOnQualifiedAllocationExpression(anonymousType);
381     markEnclosingMemberWithLocalType();
382     pushOnAstStack(anonymousType);
383
384     alloc.sourceEnd = rParenPos; //the position has been stored explicitly
385
int argumentLength;
386     if ((argumentLength = expressionLengthStack[expressionLengthPtr--]) != 0) {
387         expressionPtr -= argumentLength;
388         System.arraycopy(
389             expressionStack,
390             expressionPtr + 1,
391             alloc.arguments = new Expression[argumentLength],
392             0,
393             argumentLength);
394     }
395
396     alloc.type = typeReference;
397
398     anonymousType.sourceEnd = alloc.sourceEnd;
399     //position at the type while it impacts the anonymous declaration
400
anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
401     alloc.sourceStart = intStack[intPtr--];
402     pushOnExpressionStack(alloc);
403
404     assistNode = alloc;
405     this.lastCheckPoint = alloc.sourceEnd + 1;
406     if (!diet){
407         this.restartRecovery = true; // force to restart in recovery mode
408
this.lastIgnoredToken = -1;
409         currentToken = 0; // opening brace already taken into account
410
hasReportedError = true;
411     }
412
413     anonymousType.bodyStart = scanner.currentPosition;
414     listLength = 0; // will be updated when reading super-interfaces
415
// recovery
416
if (currentElement != null){
417         lastCheckPoint = anonymousType.bodyStart;
418         currentElement = currentElement.add(anonymousType, 0);
419         currentToken = 0; // opening brace already taken into account
420
lastIgnoredToken = -1;
421     }
422 }
423 protected void consumeEnterVariable() {
424     // EnterVariable ::= $empty
425
// do nothing by default
426

427     super.consumeEnterVariable();
428
429     AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
430     if (variable.type == assistNode){
431         if (!diet){
432             this.restartRecovery = true; // force to restart in recovery mode
433
this.lastIgnoredToken = -1;
434         }
435         isOrphanCompletionNode = false; // already attached inside variable decl
436
}
437 }
438
439 protected void consumeExitVariableWithInitialization() {
440     super.consumeExitVariableWithInitialization();
441     
442     // does not keep the initialization if selection is not inside
443
AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
444     int start = variable.initialization.sourceStart;
445     int end = variable.initialization.sourceEnd;
446     if ((selectionStart < start) && (selectionEnd < start) ||
447             (selectionStart > end) && (selectionEnd > end)) {
448         variable.initialization = null;
449     }
450
451 }
452
453 protected void consumeFieldAccess(boolean isSuperAccess) {
454     // FieldAccess ::= Primary '.' 'Identifier'
455
// FieldAccess ::= 'super' '.' 'Identifier'
456

457     if (this.indexOfAssistIdentifier() < 0) {
458         super.consumeFieldAccess(isSuperAccess);
459         return;
460     }
461     FieldReference fieldReference =
462         new SelectionOnFieldReference(
463             identifierStack[identifierPtr],
464             identifierPositionStack[identifierPtr--]);
465     identifierLengthPtr--;
466     if (isSuperAccess) { //considerates the fieldReferenceerence beginning at the 'super' ....
467
fieldReference.sourceStart = intStack[intPtr--];
468         fieldReference.receiver = new SuperReference(fieldReference.sourceStart, endPosition);
469         pushOnExpressionStack(fieldReference);
470     } else { //optimize push/pop
471
if ((fieldReference.receiver = expressionStack[expressionPtr]).isThis()) { //fieldReferenceerence begins at the this
472
fieldReference.sourceStart = fieldReference.receiver.sourceStart;
473         }
474         expressionStack[expressionPtr] = fieldReference;
475     }
476     assistNode = fieldReference;
477     this.lastCheckPoint = fieldReference.sourceEnd + 1;
478     if (!diet){
479         this.restartRecovery = true; // force to restart in recovery mode
480
this.lastIgnoredToken = -1;
481     }
482     this.isOrphanCompletionNode = true;
483 }
484 protected void consumeFormalParameter(boolean isVarArgs) {
485     if (this.indexOfAssistIdentifier() < 0) {
486         super.consumeFormalParameter(isVarArgs);
487         if((!diet || dietInt != 0) && astPtr > -1) {
488             Argument argument = (Argument) astStack[astPtr];
489             if(argument.type == assistNode) {
490                 isOrphanCompletionNode = true;
491                 this.restartRecovery = true; // force to restart in recovery mode
492
this.lastIgnoredToken = -1;
493             }
494         }
495     } else {
496         identifierLengthPtr--;
497         char[] identifierName = identifierStack[identifierPtr];
498         long namePositions = identifierPositionStack[identifierPtr--];
499         int extendedDimensions = this.intStack[this.intPtr--];
500         int endOfEllipsis = 0;
501         if (isVarArgs) {
502             endOfEllipsis = this.intStack[this.intPtr--];
503         }
504         int firstDimensions = this.intStack[this.intPtr--];
505         final int typeDimensions = firstDimensions + extendedDimensions;
506         TypeReference type = getTypeReference(typeDimensions);
507         if (isVarArgs) {
508             type = copyDims(type, typeDimensions + 1);
509             if (extendedDimensions == 0) {
510                 type.sourceEnd = endOfEllipsis;
511             }
512             type.bits |= ASTNode.IsVarArgs; // set isVarArgs
513
}
514         int modifierPositions = intStack[intPtr--];
515         intPtr--;
516         Argument arg =
517             new SelectionOnArgumentName(
518                 identifierName,
519                 namePositions,
520                 type,
521                 intStack[intPtr + 1] & ~ClassFileConstants.AccDeprecated); // modifiers
522
arg.declarationSourceStart = modifierPositions;
523         pushOnAstStack(arg);
524         
525         assistNode = arg;
526         this.lastCheckPoint = (int) namePositions;
527         isOrphanCompletionNode = true;
528         
529         if (!diet){
530             this.restartRecovery = true; // force to restart in recovery mode
531
this.lastIgnoredToken = -1;
532         }
533
534         /* if incomplete method header, listLength counter will not have been reset,
535             indicating that some arguments are available on the stack */

536         listLength++;
537     }
538 }
539 protected void consumeInstanceOfExpression() {
540     if (indexOfAssistIdentifier() < 0) {
541         super.consumeInstanceOfExpression();
542     } else {
543         getTypeReference(intStack[intPtr--]);
544         this.isOrphanCompletionNode = true;
545         this.restartRecovery = true;
546         this.lastIgnoredToken = -1;
547     }
548 }
549 protected void consumeInstanceOfExpressionWithName() {
550     if (indexOfAssistIdentifier() < 0) {
551         super.consumeInstanceOfExpressionWithName();
552     } else {
553         getTypeReference(intStack[intPtr--]);
554         this.isOrphanCompletionNode = true;
555         this.restartRecovery = true;
556         this.lastIgnoredToken = -1;
557     }
558 }
559 protected void consumeLocalVariableDeclarationStatement() {
560     super.consumeLocalVariableDeclarationStatement();
561     
562     // force to restart in recovery mode if the declaration contains the selection
563
if (!this.diet) {
564         LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr];
565         if ((this.selectionStart >= localDeclaration.sourceStart)
566                 && (this.selectionEnd <= localDeclaration.sourceEnd)) {
567             this.restartRecovery = true;
568             this.lastIgnoredToken = -1;
569         }
570     }
571 }
572 protected void consumeMarkerAnnotation() {
573     int index;
574     
575     if ((index = this.indexOfAssistIdentifier()) < 0) {
576         super.consumeMarkerAnnotation();
577         return;
578     }
579     
580     MarkerAnnotation markerAnnotation = null;
581     int length = this.identifierLengthStack[this.identifierLengthPtr];
582     TypeReference typeReference;
583
584     /* retrieve identifiers subset and whole positions, the assist node positions
585         should include the entire replaced source. */

586     
587     char[][] subset = identifierSubSet(index);
588     identifierLengthPtr--;
589     identifierPtr -= length;
590     long[] positions = new long[length];
591     System.arraycopy(
592         identifierPositionStack,
593         identifierPtr + 1,
594         positions,
595         0,
596         length);
597
598     /* build specific assist on type reference */
599     
600     if (index == 0) {
601         /* assist inside first identifier */
602         typeReference = this.createSingleAssistTypeReference(
603                         assistIdentifier(),
604                         positions[0]);
605     } else {
606         /* assist inside subsequent identifier */
607         typeReference = this.createQualifiedAssistTypeReference(
608                         subset,
609                         assistIdentifier(),
610                         positions);
611     }
612     assistNode = typeReference;
613     this.lastCheckPoint = typeReference.sourceEnd + 1;
614
615     markerAnnotation = new MarkerAnnotation(typeReference, this.intStack[this.intPtr--]);
616     markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd;
617     pushOnExpressionStack(markerAnnotation);
618 }
619 protected void consumeMemberValuePair() {
620     if (this.indexOfAssistIdentifier() < 0) {
621         super.consumeMemberValuePair();
622         return;
623     }
624     
625     char[] simpleName = this.identifierStack[this.identifierPtr];
626     long position = this.identifierPositionStack[this.identifierPtr--];
627     this.identifierLengthPtr--;
628     int end = (int) position;
629     int start = (int) (position >>> 32);
630     Expression value = this.expressionStack[this.expressionPtr--];
631     this.expressionLengthPtr--;
632     MemberValuePair memberValuePair = new SelectionOnNameOfMemberValuePair(simpleName, start, end, value);
633     pushOnAstStack(memberValuePair);
634     
635     assistNode = memberValuePair;
636     this.lastCheckPoint = memberValuePair.sourceEnd + 1;
637     
638     
639 }
640 protected void consumeMethodInvocationName() {
641     // MethodInvocation ::= Name '(' ArgumentListopt ')'
642

643     // when the name is only an identifier...we have a message send to "this" (implicit)
644

645     char[] selector = identifierStack[identifierPtr];
646     int accessMode;
647     if(selector == this.assistIdentifier()) {
648         if(CharOperation.equals(selector, SUPER)) {
649             accessMode = ExplicitConstructorCall.Super;
650         } else if(CharOperation.equals(selector, THIS)) {
651             accessMode = ExplicitConstructorCall.This;
652         } else {
653             super.consumeMethodInvocationName();
654             return;
655         }
656     } else {
657         super.consumeMethodInvocationName();
658         return;
659     }
660     
661     final ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(accessMode);
662     constructorCall.sourceEnd = rParenPos;
663     constructorCall.sourceStart = (int) (identifierPositionStack[identifierPtr] >>> 32);
664     int length;
665     if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
666         expressionPtr -= length;
667         System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
668     }
669
670     if (!diet){
671         pushOnAstStack(constructorCall);
672         this.restartRecovery = true; // force to restart in recovery mode
673
this.lastIgnoredToken = -1;
674     } else {
675         pushOnExpressionStack(new Expression(){
676             public TypeBinding resolveType(BlockScope scope) {
677                 constructorCall.resolve(scope);
678                 return null;
679             }
680             public StringBuffer JavaDoc printExpression(int indent, StringBuffer JavaDoc output) {
681                 return output;
682             }
683         });
684     }
685     this.assistNode = constructorCall;
686     this.lastCheckPoint = constructorCall.sourceEnd + 1;
687     this.isOrphanCompletionNode = true;
688 }
689 protected void consumeMethodInvocationPrimary() {
690     //optimize the push/pop
691
//MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
692

693     char[] selector = identifierStack[identifierPtr];
694     int accessMode;
695     if(selector == this.assistIdentifier()) {
696         if(CharOperation.equals(selector, SUPER)) {
697             accessMode = ExplicitConstructorCall.Super;
698         } else if(CharOperation.equals(selector, THIS)) {
699             accessMode = ExplicitConstructorCall.This;
700         } else {
701             super.consumeMethodInvocationPrimary();
702             return;
703         }
704     } else {
705         super.consumeMethodInvocationPrimary();
706         return;
707     }
708     
709     final ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(accessMode);
710     constructorCall.sourceEnd = rParenPos;
711     int length;
712     if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
713         expressionPtr -= length;
714         System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
715     }
716     constructorCall.qualification = expressionStack[expressionPtr--];
717     constructorCall.sourceStart = constructorCall.qualification.sourceStart;
718     
719     if (!diet){
720         pushOnAstStack(constructorCall);
721         this.restartRecovery = true; // force to restart in recovery mode
722
this.lastIgnoredToken = -1;
723     } else {
724         pushOnExpressionStack(new Expression(){
725             public TypeBinding resolveType(BlockScope scope) {
726                 constructorCall.resolve(scope);
727                 return null;
728             }
729             public StringBuffer JavaDoc printExpression(int indent, StringBuffer JavaDoc output) {
730                 return output;
731             }
732         });
733     }
734     
735     this.assistNode = constructorCall;
736     this.lastCheckPoint = constructorCall.sourceEnd + 1;
737     this.isOrphanCompletionNode = true;
738 }
739 protected void consumeNormalAnnotation() {
740     int index;
741     
742     if ((index = this.indexOfAssistIdentifier()) < 0) {
743         super.consumeNormalAnnotation();
744         return;
745     }
746     
747     NormalAnnotation normalAnnotation = null;
748     int length = this.identifierLengthStack[this.identifierLengthPtr];
749     TypeReference typeReference;
750     
751     /* retrieve identifiers subset and whole positions, the assist node positions
752         should include the entire replaced source. */

753     
754     char[][] subset = identifierSubSet(index);
755     identifierLengthPtr--;
756     identifierPtr -= length;
757     long[] positions = new long[length];
758     System.arraycopy(
759         identifierPositionStack,
760         identifierPtr + 1,
761         positions,
762         0,
763         length);
764
765     /* build specific assist on type reference */
766     
767     if (index == 0) {
768         /* assist inside first identifier */
769         typeReference = this.createSingleAssistTypeReference(
770                         assistIdentifier(),
771                         positions[0]);
772     } else {
773         /* assist inside subsequent identifier */
774         typeReference = this.createQualifiedAssistTypeReference(
775                         subset,
776                         assistIdentifier(),
777                         positions);
778     }
779     assistNode = typeReference;
780     this.lastCheckPoint = typeReference.sourceEnd + 1;
781         
782     normalAnnotation = new NormalAnnotation(typeReference, this.intStack[this.intPtr--]);
783     if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
784         System.arraycopy(
785             this.astStack,
786             (this.astPtr -= length) + 1,
787             normalAnnotation.memberValuePairs = new MemberValuePair[length],
788             0,
789             length);
790     }
791     normalAnnotation.declarationSourceEnd = this.rParenPos;
792     pushOnExpressionStack(normalAnnotation);
793 }
794 protected void consumeSingleMemberAnnotation() {
795     int index;
796     
797     if ((index = this.indexOfAssistIdentifier()) < 0) {
798         super.consumeSingleMemberAnnotation();
799         return;
800     }
801     
802     SingleMemberAnnotation singleMemberAnnotation = null;
803     int length = this.identifierLengthStack[this.identifierLengthPtr];
804     TypeReference typeReference;
805     
806     /* retrieve identifiers subset and whole positions, the assist node positions
807         should include the entire replaced source. */

808     
809     char[][] subset = identifierSubSet(index);
810     identifierLengthPtr--;
811     identifierPtr -= length;
812     long[] positions = new long[length];
813     System.arraycopy(
814         identifierPositionStack,
815         identifierPtr + 1,
816         positions,
817         0,
818         length);
819
820     /* build specific assist on type reference */
821     
822     if (index == 0) {
823         /* assist inside first identifier */
824         typeReference = this.createSingleAssistTypeReference(
825                         assistIdentifier(),
826                         positions[0]);
827     } else {
828         /* assist inside subsequent identifier */
829         typeReference = this.createQualifiedAssistTypeReference(
830                         subset,
831                         assistIdentifier(),
832                         positions);
833     }
834     assistNode = typeReference;
835     this.lastCheckPoint = typeReference.sourceEnd + 1;
836
837     singleMemberAnnotation = new SingleMemberAnnotation(typeReference, this.intStack[this.intPtr--]);
838     singleMemberAnnotation.memberValue = this.expressionStack[this.expressionPtr--];
839     this.expressionLengthPtr--;
840     singleMemberAnnotation.declarationSourceEnd = this.rParenPos;
841     pushOnExpressionStack(singleMemberAnnotation);
842 }
843 protected void consumeStaticImportOnDemandDeclarationName() {
844     // TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
845
/* push an ImportRef build from the last name
846     stored in the identifier stack. */

847
848     int index;
849
850     /* no need to take action if not inside assist identifiers */
851     if ((index = indexOfAssistIdentifier()) < 0) {
852         super.consumeStaticImportOnDemandDeclarationName();
853         return;
854     }
855     /* retrieve identifiers subset and whole positions, the assist node positions
856         should include the entire replaced source. */

857     int length = identifierLengthStack[identifierLengthPtr];
858     char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
859
identifierLengthPtr--;
860     identifierPtr -= length;
861     long[] positions = new long[length];
862     System.arraycopy(
863         identifierPositionStack,
864         identifierPtr + 1,
865         positions,
866         0,
867         length);
868
869     /* build specific assist node on import statement */
870     ImportReference reference = this.createAssistImportReference(subset, positions, ClassFileConstants.AccStatic);
871     reference.bits |= ASTNode.OnDemand;
872     assistNode = reference;
873     this.lastCheckPoint = reference.sourceEnd + 1;
874     
875     pushOnAstStack(reference);
876
877     if (currentToken == TokenNameSEMICOLON){
878         reference.declarationSourceEnd = scanner.currentPosition - 1;
879     } else {
880         reference.declarationSourceEnd = (int) positions[length-1];
881     }
882     //endPosition is just before the ;
883
reference.declarationSourceStart = intStack[intPtr--];
884     // flush annotations defined prior to import statements
885
reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
886
887     // recovery
888
if (currentElement != null){
889         lastCheckPoint = reference.declarationSourceEnd+1;
890         currentElement = currentElement.add(reference, 0);
891         lastIgnoredToken = -1;
892         restartRecovery = true; // used to avoid branching back into the regular automaton
893
}
894 }
895 protected void consumeToken(int token) {
896     super.consumeToken(token);
897     
898     // if in a method or if in a field initializer
899
if (isInsideMethod() || isInsideFieldInitialization()) {
900         switch (token) {
901             case TokenNamecase :
902                 pushOnElementStack(K_BETWEEN_CASE_AND_COLON);
903                 break;
904             case TokenNameCOLON:
905                 if(topKnownElementKind(SELECTION_OR_ASSIST_PARSER) == K_BETWEEN_CASE_AND_COLON) {
906                     popElement(K_BETWEEN_CASE_AND_COLON);
907                 }
908                 break;
909         }
910     }
911 }
912 protected void consumeTypeImportOnDemandDeclarationName() {
913     // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
914
/* push an ImportRef build from the last name
915     stored in the identifier stack. */

916
917     int index;
918
919     /* no need to take action if not inside assist identifiers */
920     if ((index = indexOfAssistIdentifier()) < 0) {
921         super.consumeTypeImportOnDemandDeclarationName();
922         return;
923     }
924     /* retrieve identifiers subset and whole positions, the assist node positions
925         should include the entire replaced source. */

926     int length = identifierLengthStack[identifierLengthPtr];
927     char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
928
identifierLengthPtr--;
929     identifierPtr -= length;
930     long[] positions = new long[length];
931     System.arraycopy(
932         identifierPositionStack,
933         identifierPtr + 1,
934         positions,
935         0,
936         length);
937
938     /* build specific assist node on import statement */
939     ImportReference reference = this.createAssistImportReference(subset, positions, ClassFileConstants.AccDefault);
940     reference.bits |= ASTNode.OnDemand;
941     assistNode = reference;
942     this.lastCheckPoint = reference.sourceEnd + 1;
943     
944     pushOnAstStack(reference);
945
946     if (currentToken == TokenNameSEMICOLON){
947         reference.declarationSourceEnd = scanner.currentPosition - 1;
948     } else {
949         reference.declarationSourceEnd = (int) positions[length-1];
950     }
951     //endPosition is just before the ;
952
reference.declarationSourceStart = intStack[intPtr--];
953     // flush comments defined prior to import statements
954
reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
955
956     // recovery
957
if (currentElement != null){
958         lastCheckPoint = reference.declarationSourceEnd+1;
959         currentElement = currentElement.add(reference, 0);
960         lastIgnoredToken = -1;
961         restartRecovery = true; // used to avoid branching back into the regular automaton
962
}
963 }
964 public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
965     return new SelectionOnImportReference(tokens, positions, mod);
966 }
967 public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
968     return new SelectionOnPackageReference(tokens, positions);
969 }
970 protected JavadocParser createJavadocParser() {
971     return new SelectionJavadocParser(this);
972 }
973 protected LocalDeclaration createLocalDeclaration(char[] assistName,int sourceStart,int sourceEnd) {
974     if (this.indexOfAssistIdentifier() < 0) {
975         return super.createLocalDeclaration(assistName, sourceStart, sourceEnd);
976     } else {
977         SelectionOnLocalName local = new SelectionOnLocalName(assistName, sourceStart, sourceEnd);
978         this.assistNode = local;
979         this.lastCheckPoint = sourceEnd + 1;
980         return local;
981     }
982 }
983 public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
984     return new SelectionOnQualifiedNameReference(
985                     previousIdentifiers,
986                     assistName,
987                     positions);
988 }
989 public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
990     return new SelectionOnQualifiedTypeReference(
991                     previousIdentifiers,
992                     assistName,
993                     positions);
994 }
995 public TypeReference createParameterizedQualifiedAssistTypeReference(
996         char[][] tokens, TypeReference[][] typeArguments, char[] assistname, TypeReference[] assistTypeArguments, long[] positions) {
997     return new SelectionOnParameterizedQualifiedTypeReference(tokens, assistname, typeArguments, assistTypeArguments, positions);
998
999 }
1000public NameReference createSingleAssistNameReference(char[] assistName, long position) {
1001    return new SelectionOnSingleNameReference(assistName, position);
1002}
1003public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
1004    return new SelectionOnSingleTypeReference(assistName, position);
1005}
1006public TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position) {
1007    return new SelectionOnParameterizedSingleTypeReference(assistName, typeArguments, position);
1008}
1009public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
1010
1011    this.selectionStart = start;
1012    this.selectionEnd = end;
1013    SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
1014    selectionScanner.selectionIdentifier = null;
1015    selectionScanner.selectionStart = start;
1016    selectionScanner.selectionEnd = end;
1017    return this.dietParse(sourceUnit, compilationResult);
1018}
1019protected NameReference getUnspecifiedReference() {
1020    /* build a (unspecified) NameReference which may be qualified*/
1021
1022    int completionIndex;
1023
1024    /* no need to take action if not inside completed identifiers */
1025    if ((completionIndex = indexOfAssistIdentifier()) < 0) {
1026        return super.getUnspecifiedReference();
1027    }
1028
1029    int length = identifierLengthStack[identifierLengthPtr];
1030    if (CharOperation.equals(assistIdentifier(), SUPER)){
1031        Reference reference;
1032        if (completionIndex > 0){ // qualified super
1033
// discard 'super' from identifier stacks
1034
identifierLengthStack[identifierLengthPtr] = completionIndex;
1035            int ptr = identifierPtr -= (length - completionIndex);
1036            pushOnGenericsLengthStack(0);
1037            pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
1038            reference =
1039                new SelectionOnQualifiedSuperReference(
1040                    getTypeReference(0),
1041                    (int)(identifierPositionStack[ptr+1] >>> 32),
1042                    (int) identifierPositionStack[ptr+1]);
1043        } else { // standard super
1044
identifierPtr -= length;
1045            identifierLengthPtr--;
1046            reference = new SelectionOnSuperReference((int)(identifierPositionStack[identifierPtr+1] >>> 32), (int) identifierPositionStack[identifierPtr+1]);
1047        }
1048        pushOnAstStack(reference);
1049        this.assistNode = reference;
1050        this.lastCheckPoint = reference.sourceEnd + 1;
1051        if (!diet || dietInt != 0){
1052            this.restartRecovery = true; // force to restart in recovery mode
1053
this.lastIgnoredToken = -1;
1054        }
1055        this.isOrphanCompletionNode = true;
1056        return new SingleNameReference(CharOperation.NO_CHAR, 0); // dummy reference
1057
}
1058    NameReference nameReference;
1059    /* retrieve identifiers subset and whole positions, the completion node positions
1060        should include the entire replaced source. */

1061    char[][] subset = identifierSubSet(completionIndex);
1062    identifierLengthPtr--;
1063    identifierPtr -= length;
1064    long[] positions = new long[length];
1065    System.arraycopy(
1066        identifierPositionStack,
1067        identifierPtr + 1,
1068        positions,
1069        0,
1070        length);
1071    /* build specific completion on name reference */
1072    if (completionIndex == 0) {
1073        /* completion inside first identifier */
1074        nameReference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
1075    } else {
1076        /* completion inside subsequent identifier */
1077        nameReference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
1078    }
1079    assistNode = nameReference;
1080    this.lastCheckPoint = nameReference.sourceEnd + 1;
1081    if (!diet){
1082        this.restartRecovery = true; // force to restart in recovery mode
1083
this.lastIgnoredToken = -1;
1084    }
1085    this.isOrphanCompletionNode = true;
1086    return nameReference;
1087}
1088/*
1089 * Copy of code from superclass with the following change:
1090 * In the case of qualified name reference if the cursor location is on the
1091 * qualified name reference, then create a CompletionOnQualifiedNameReference
1092 * instead.
1093 */

1094protected NameReference getUnspecifiedReferenceOptimized() {
1095
1096    int index = indexOfAssistIdentifier();
1097    NameReference reference = super.getUnspecifiedReferenceOptimized();
1098
1099    if (index >= 0){
1100        if (!diet){
1101            this.restartRecovery = true; // force to restart in recovery mode
1102
this.lastIgnoredToken = -1;
1103        }
1104        this.isOrphanCompletionNode = true;
1105    }
1106    return reference;
1107}
1108public void initializeScanner(){
1109    this.scanner = new SelectionScanner(this.options.sourceLevel);
1110}
1111protected MessageSend newMessageSend() {
1112    // '(' ArgumentListopt ')'
1113
// the arguments are on the expression stack
1114

1115    char[] selector = identifierStack[identifierPtr];
1116    if (selector != this.assistIdentifier()){
1117        return super.newMessageSend();
1118    }
1119    MessageSend messageSend = new SelectionOnMessageSend();
1120    int length;
1121    if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
1122        expressionPtr -= length;
1123        System.arraycopy(
1124            expressionStack,
1125            expressionPtr + 1,
1126            messageSend.arguments = new Expression[length],
1127            0,
1128            length);
1129    }
1130    assistNode = messageSend;
1131    if (!diet){
1132        this.restartRecovery = true; // force to restart in recovery mode
1133
this.lastIgnoredToken = -1;
1134    }
1135    
1136    this.isOrphanCompletionNode = true;
1137    return messageSend;
1138}
1139protected MessageSend newMessageSendWithTypeArguments() {
1140    char[] selector = identifierStack[identifierPtr];
1141    if (selector != this.assistIdentifier()){
1142        return super.newMessageSendWithTypeArguments();
1143    }
1144    MessageSend messageSend = new SelectionOnMessageSend();
1145    int length;
1146    if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
1147        this.expressionPtr -= length;
1148        System.arraycopy(
1149            this.expressionStack,
1150            this.expressionPtr + 1,
1151            messageSend.arguments = new Expression[length],
1152            0,
1153            length);
1154    }
1155    assistNode = messageSend;
1156    if (!diet){
1157        this.restartRecovery = true; // force to restart in recovery mode
1158
this.lastIgnoredToken = -1;
1159    }
1160    
1161    this.isOrphanCompletionNode = true;
1162    return messageSend;
1163}
1164public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
1165
1166    if (end == -1) return super.parse(sourceUnit, compilationResult, start, end);
1167    
1168    this.selectionStart = start;
1169    this.selectionEnd = end;
1170    SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
1171    selectionScanner.selectionIdentifier = null;
1172    selectionScanner.selectionStart = start;
1173    selectionScanner.selectionEnd = end;
1174    return super.parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
1175}
1176/*
1177 * Reset context so as to resume to regular parse loop
1178 * If unable to reset for resuming, answers false.
1179 *
1180 * Move checkpoint location, reset internal stacks and
1181 * decide which grammar goal is activated.
1182 */

1183protected boolean resumeAfterRecovery() {
1184
1185    /* if reached assist node inside method body, but still inside nested type,
1186        should continue in diet mode until the end of the method body */

1187    if (this.assistNode != null
1188        && !(referenceContext instanceof CompilationUnitDeclaration)){
1189        currentElement.preserveEnclosingBlocks();
1190        if (currentElement.enclosingType() == null) {
1191            if(!(currentElement instanceof RecoveredType)) {
1192                this.resetStacks();
1193                return false;
1194            }
1195            
1196            RecoveredType recoveredType = (RecoveredType)currentElement;
1197            if(recoveredType.typeDeclaration != null && recoveredType.typeDeclaration.allocation == this.assistNode){
1198                this.resetStacks();
1199                return false;
1200            }
1201        }
1202    }
1203    return super.resumeAfterRecovery();
1204}
1205
1206public void selectionIdentifierCheck(){
1207    if (checkRecoveredType()) return;
1208}
1209public void setAssistIdentifier(char[] assistIdent){
1210    ((SelectionScanner)scanner).selectionIdentifier = assistIdent;
1211}
1212/*
1213 * Update recovery state based on current parser/scanner state
1214 */

1215protected void updateRecoveryState() {
1216
1217    /* expose parser state to recovery state */
1218    currentElement.updateFromParserState();
1219
1220    /* may be able to retrieve completionNode as an orphan, and then attach it */
1221    this.selectionIdentifierCheck();
1222    this.attachOrphanCompletionNode();
1223    
1224    // if an assist node has been found and a recovered element exists,
1225
// mark enclosing blocks as to be preserved
1226
if (this.assistNode != null && this.currentElement != null) {
1227        currentElement.preserveEnclosingBlocks();
1228    }
1229    
1230    /* check and update recovered state based on current token,
1231        this action is also performed when shifting token after recovery
1232        got activated once.
1233    */

1234    this.recoveryTokenCheck();
1235}
1236
1237public String JavaDoc toString() {
1238    String JavaDoc s = Util.EMPTY_STRING;
1239    s = s + "elementKindStack : int[] = {"; //$NON-NLS-1$
1240
for (int i = 0; i <= elementPtr; i++) {
1241        s = s + String.valueOf(elementKindStack[i]) + ","; //$NON-NLS-1$
1242
}
1243    s = s + "}\n"; //$NON-NLS-1$
1244
s = s + "elementInfoStack : int[] = {"; //$NON-NLS-1$
1245
for (int i = 0; i <= elementPtr; i++) {
1246        s = s + String.valueOf(elementInfoStack[i]) + ","; //$NON-NLS-1$
1247
}
1248    s = s + "}\n"; //$NON-NLS-1$
1249
return s + super.toString();
1250}
1251}
1252
Popular Tags