Initial import of the Guide contributed to the project byRobert Kraske. Was originall...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / SourceElementParser.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler;
12
13 import java.util.ArrayList;
14
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.core.compiler.IProblem;
17 import net.sourceforge.phpdt.internal.compiler.ast.ASTNode;
18 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
19 import net.sourceforge.phpdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.Argument;
21 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
22 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
23 import net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall;
24 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
25 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
26 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
27 import net.sourceforge.phpdt.internal.compiler.ast.NameReference;
28 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedAllocationExpression;
29 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
30 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
31 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
32 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
33 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
34 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
35 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
36 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
37 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
38 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
39 import net.sourceforge.phpdt.internal.core.util.CommentRecorderParser;
40
41 /**
42  * A source element parser extracts structural and reference information from a
43  * piece of source.
44  * 
45  * also see
46  * 
47  * @ISourceElementRequestor
48  * 
49  * The structural investigation includes: - the package statement - import
50  * statements - top-level types: package member, member types (member types of
51  * member types...) - fields - methods
52  * 
53  * If reference information is requested, then all source constructs are
54  * investigated and type, field & method references are provided as well.
55  * 
56  * Any (parsing) problem encountered is also provided.
57  */
58
59 public class SourceElementParser extends CommentRecorderParser {// extends
60         // UnitParser {
61
62         ISourceElementRequestor requestor;
63
64         int fieldCount;
65
66         int localIntPtr;
67
68         int lastFieldEndPosition;
69
70         ISourceType sourceType;
71
72         boolean reportReferenceInfo;
73
74         char[][] typeNames;
75
76         char[][] superTypeNames;
77
78         int nestedTypeIndex;
79
80         static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
81
82         NameReference[] unknownRefs;
83
84         int unknownRefsCounter;
85
86         LocalDeclarationVisitor localDeclarationVisitor = null;
87
88         // CompilerOptions options;
89
90         /**
91          * An ast visitor that visits local type declarations.
92          */
93         public class LocalDeclarationVisitor extends ASTVisitor {
94                 public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
95                         notifySourceElementRequestor(typeDeclaration, sourceType == null);
96                         return false; // don't visit members as this was done during
97                                                         // notifySourceElementRequestor(...)
98                 }
99
100                 public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
101                         notifySourceElementRequestor(typeDeclaration, sourceType == null);
102                         return false; // don't visit members as this was done during
103                                                         // notifySourceElementRequestor(...)
104                 }
105
106         }
107
108         public SourceElementParser(final ISourceElementRequestor requestor,
109                         IProblemFactory problemFactory, CompilerOptions options) {
110                 // we want to notify all syntax error with the acceptProblem API
111                 // To do so, we define the record method of the ProblemReporter
112                 super(new ProblemReporter(DefaultErrorHandlingPolicies
113                                 .exitAfterAllProblems(), options, problemFactory) {
114                         public void record(IProblem problem, CompilationResult unitResult,
115                                         ReferenceContext referenceContext) {
116                                 unitResult.record(problem, referenceContext);
117                                 if (requestor != null) {
118                                         requestor.acceptProblem(problem);
119                                 }
120                         }
121                 });
122                 // true);
123                 // options.sourceLevel >= CompilerOptions.JDK1_4);
124                 this.requestor = requestor;
125                 typeNames = new char[4][];
126                 superTypeNames = new char[4][];
127                 nestedTypeIndex = 0;
128                 this.options = options;
129         }
130
131         /**
132          * @deprecated use SourceElementParser(ISourceElementRequestor,
133          *             IProblemFactory, CompilerOptions)
134          */
135         public SourceElementParser(final ISourceElementRequestor requestor,
136                         IProblemFactory problemFactory) {
137                 this(requestor, problemFactory, new CompilerOptions());
138         }
139
140         public SourceElementParser(final ISourceElementRequestor requestor,
141                         IProblemFactory problemFactory, CompilerOptions options,
142                         boolean reportLocalDeclarations) {
143                 this(requestor, problemFactory, options);
144                 if (reportLocalDeclarations) {
145                         this.localDeclarationVisitor = new LocalDeclarationVisitor();
146                 }
147         }
148
149         // public void checkAnnotation() {
150         // int firstCommentIndex = scanner.commentPtr;
151         //
152         // super.checkAnnotation();
153         //
154         // // modify the modifier source start to point at the first comment
155         // if (firstCommentIndex >= 0) {
156         // modifiersSourceStart = scanner.commentStarts[0];
157         // }
158         // }
159         // protected void classInstanceCreation(boolean alwaysQualified) {
160         //
161         // boolean previousFlag = reportReferenceInfo;
162         // reportReferenceInfo = false; // not to see the type reference reported in
163         // super call to getTypeReference(...)
164         // super.classInstanceCreation(alwaysQualified);
165         // reportReferenceInfo = previousFlag;
166         // if (reportReferenceInfo){
167         // AllocationExpression alloc =
168         // (AllocationExpression)expressionStack[expressionPtr];
169         // TypeReference typeRef = alloc.type;
170         // requestor.acceptConstructorReference(
171         // typeRef instanceof SingleTypeReference
172         // ? ((SingleTypeReference) typeRef).token
173         // : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
174         // alloc.arguments == null ? 0 : alloc.arguments.length,
175         // alloc.sourceStart);
176         // }
177         // }
178         // protected void consumeConstructorHeaderName() {
179         // // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
180         //
181         // /* recovering - might be an empty message send */
182         // if (currentElement != null){
183         // if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
184         // lastCheckPoint = scanner.startPosition; // force to restart at this exact
185         // position
186         // restartRecovery = true;
187         // return;
188         // }
189         // }
190         // SourceConstructorDeclaration cd = new
191         // SourceConstructorDeclaration(this.compilationUnit.compilationResult);
192         //
193         // //name -- this is not really revelant but we do .....
194         // cd.selector = identifierStack[identifierPtr];
195         // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
196         // identifierLengthPtr--;
197         //
198         // //modifiers
199         // cd.declarationSourceStart = intStack[intPtr--];
200         // cd.modifiers = intStack[intPtr--];
201         //
202         // //highlight starts at the selector starts
203         // cd.sourceStart = (int) (selectorSourcePositions >>> 32);
204         // cd.selectorSourceEnd = (int) selectorSourcePositions;
205         // pushOnAstStack(cd);
206         //
207         // cd.sourceEnd = lParenPos;
208         // cd.bodyStart = lParenPos+1;
209         // listLength = 0; // initialize listLength before reading parameters/throws
210         //
211         // // recovery
212         // if (currentElement != null){
213         // lastCheckPoint = cd.bodyStart;
214         // if ((currentElement instanceof RecoveredType && lastIgnoredToken !=
215         // TokenNameDOT)
216         // || cd.modifiers != 0){
217         // currentElement = currentElement.add(cd, 0);
218         // lastIgnoredToken = -1;
219         // }
220         // }
221         // }
222         // /**
223         // *
224         // * INTERNAL USE-ONLY
225         // */
226         // protected void consumeExitVariableWithInitialization() {
227         // // ExitVariableWithInitialization ::= $empty
228         // // the scanner is located after the comma or the semi-colon.
229         // // we want to include the comma or the semi-colon
230         // super.consumeExitVariableWithInitialization();
231         // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
232         // (currentToken != TokenNameSEMICOLON)))
233         // return;
234         // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
235         // scanner.currentPosition - 1;
236         // }
237         // protected void consumeExitVariableWithoutInitialization() {
238         // // ExitVariableWithoutInitialization ::= $empty
239         // // do nothing by default
240         // super.consumeExitVariableWithoutInitialization();
241         // if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) &&
242         // (currentToken != TokenNameSEMICOLON)))
243         // return;
244         // ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition =
245         // scanner.currentPosition - 1;
246         // }
247         // /**
248         // *
249         // * INTERNAL USE-ONLY
250         // */
251         // protected void consumeFieldAccess(boolean isSuperAccess) {
252         // // FieldAccess ::= Primary '.' 'Identifier'
253         // // FieldAccess ::= 'super' '.' 'Identifier'
254         // super.consumeFieldAccess(isSuperAccess);
255         // FieldReference fr = (FieldReference) expressionStack[expressionPtr];
256         // if (reportReferenceInfo) {
257         // requestor.acceptFieldReference(fr.token, fr.sourceStart);
258         // }
259         // }
260         // protected void consumeMethodHeaderName() {
261         // // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
262         // SourceMethodDeclaration md = new
263         // SourceMethodDeclaration(this.compilationUnit.compilationResult);
264         //
265         // //name
266         // md.selector = identifierStack[identifierPtr];
267         // long selectorSourcePositions = identifierPositionStack[identifierPtr--];
268         // identifierLengthPtr--;
269         // //type
270         // md.returnType = getTypeReference(intStack[intPtr--]);
271         // //modifiers
272         // md.declarationSourceStart = intStack[intPtr--];
273         // md.modifiers = intStack[intPtr--];
274         //
275         // //highlight starts at selector start
276         // md.sourceStart = (int) (selectorSourcePositions >>> 32);
277         // md.selectorSourceEnd = (int) selectorSourcePositions;
278         // pushOnAstStack(md);
279         // md.sourceEnd = lParenPos;
280         // md.bodyStart = lParenPos+1;
281         // listLength = 0; // initialize listLength before reading parameters/throws
282         //      
283         // // recovery
284         // if (currentElement != null){
285         // if (currentElement instanceof RecoveredType
286         // //|| md.modifiers != 0
287         // || (scanner.getLineNumber(md.returnType.sourceStart)
288         // == scanner.getLineNumber(md.sourceStart))){
289         // lastCheckPoint = md.bodyStart;
290         // currentElement = currentElement.add(md, 0);
291         // lastIgnoredToken = -1;
292         // } else {
293         // lastCheckPoint = md.sourceStart;
294         // restartRecovery = true;
295         // }
296         // }
297         // }
298         // /**
299         // *
300         // * INTERNAL USE-ONLY
301         // */
302         // protected void consumeMethodInvocationName() {
303         // // MethodInvocation ::= Name '(' ArgumentListopt ')'
304         //
305         // // when the name is only an identifier...we have a message send to "this"
306         // (implicit)
307         // super.consumeMethodInvocationName();
308         // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
309         // Expression[] args = messageSend.arguments;
310         // if (reportReferenceInfo) {
311         // requestor.acceptMethodReference(
312         // messageSend.selector,
313         // args == null ? 0 : args.length,
314         // (int)(messageSend.nameSourcePosition >>> 32));
315         // }
316         // }
317         // /**
318         // *
319         // * INTERNAL USE-ONLY
320         // */
321         // protected void consumeMethodInvocationPrimary() {
322         // super.consumeMethodInvocationPrimary();
323         // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
324         // Expression[] args = messageSend.arguments;
325         // if (reportReferenceInfo) {
326         // requestor.acceptMethodReference(
327         // messageSend.selector,
328         // args == null ? 0 : args.length,
329         // (int)(messageSend.nameSourcePosition >>> 32));
330         // }
331         // }
332         // /**
333         // *
334         // * INTERNAL USE-ONLY
335         // */
336         // protected void consumeMethodInvocationSuper() {
337         // // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
338         // super.consumeMethodInvocationSuper();
339         // MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
340         // Expression[] args = messageSend.arguments;
341         // if (reportReferenceInfo) {
342         // requestor.acceptMethodReference(
343         // messageSend.selector,
344         // args == null ? 0 : args.length,
345         // (int)(messageSend.nameSourcePosition >>> 32));
346         // }
347         // }
348         // protected void consumeSingleTypeImportDeclarationName() {
349         // // SingleTypeImportDeclarationName ::= 'import' Name
350         // /* push an ImportRef build from the last name
351         // stored in the identifier stack. */
352         //
353         // super.consumeSingleTypeImportDeclarationName();
354         // ImportReference impt = (ImportReference)astStack[astPtr];
355         // if (reportReferenceInfo) {
356         // requestor.acceptTypeReference(impt.tokens, impt.sourceStart,
357         // impt.sourceEnd);
358         // }
359         // }
360         // protected void consumeTypeImportOnDemandDeclarationName() {
361         // // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
362         // /* push an ImportRef build from the last name
363         // stored in the identifier stack. */
364         //
365         // super.consumeTypeImportOnDemandDeclarationName();
366         // ImportReference impt = (ImportReference)astStack[astPtr];
367         // if (reportReferenceInfo) {
368         // requestor.acceptUnknownReference(impt.tokens, impt.sourceStart,
369         // impt.sourceEnd);
370         // }
371         // }
372         // protected FieldDeclaration createFieldDeclaration(Expression
373         // initialization, char[] name, int sourceStart, int sourceEnd) {
374         // return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
375         // }
376         // protected CompilationUnitDeclaration endParse(int act) {
377         // if (sourceType != null) {
378         // if (sourceType.isInterface()) {
379         // consumeInterfaceDeclaration();
380         // } else {
381         // consumeClassDeclaration();
382         // }
383         // }
384         // if (compilationUnit != null) {
385         // CompilationUnitDeclaration result = super.endParse(act);
386         // return result;
387         // } else {
388         // return null;
389         // }
390         // }
391         /*
392          * Flush annotations defined prior to a given positions.
393          * 
394          * Note: annotations are stacked in syntactical order
395          * 
396          * Either answer given <position>, or the end position of a comment line
397          * immediately following the <position> (same line)
398          * 
399          * e.g. void foo(){ } // end of method foo
400          */
401         // 
402         // public int flushAnnotationsDefinedPriorTo(int position) {
403         //
404         // return lastFieldEndPosition =
405         // super.flushAnnotationsDefinedPriorTo(position);
406         // }
407         // public TypeReference getTypeReference(int dim) {
408         // /* build a Reference on a variable that may be qualified or not
409         // * This variable is a type reference and dim will be its dimensions
410         // */
411         // int length;
412         // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
413         // // single variable reference
414         // if (dim == 0) {
415         // SingleTypeReference ref =
416         // new SingleTypeReference(
417         // identifierStack[identifierPtr],
418         // identifierPositionStack[identifierPtr--]);
419         // if (reportReferenceInfo) {
420         // requestor.acceptTypeReference(ref.token, ref.sourceStart);
421         // }
422         // return ref;
423         // } else {
424         // ArrayTypeReference ref =
425         // new ArrayTypeReference(
426         // identifierStack[identifierPtr],
427         // dim,
428         // identifierPositionStack[identifierPtr--]);
429         // ref.sourceEnd = endPosition;
430         // if (reportReferenceInfo) {
431         // requestor.acceptTypeReference(ref.token, ref.sourceStart);
432         // }
433         // return ref;
434         // }
435         // } else {
436         // if (length < 0) { //flag for precompiled type reference on base types
437         // TypeReference ref = TypeReference.baseTypeReference(-length, dim);
438         // ref.sourceStart = intStack[intPtr--];
439         // if (dim == 0) {
440         // ref.sourceEnd = intStack[intPtr--];
441         // } else {
442         // intPtr--; // no need to use this position as it is an array
443         // ref.sourceEnd = endPosition;
444         // }
445         // if (reportReferenceInfo){
446         // requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart,
447         // ref.sourceEnd);
448         // }
449         // return ref;
450         // } else { //Qualified variable reference
451         // char[][] tokens = new char[length][];
452         // identifierPtr -= length;
453         // long[] positions = new long[length];
454         // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
455         // System.arraycopy(
456         // identifierPositionStack,
457         // identifierPtr + 1,
458         // positions,
459         // 0,
460         // length);
461         // if (dim == 0) {
462         // QualifiedTypeReference ref = new QualifiedTypeReference(tokens,
463         // positions);
464         // if (reportReferenceInfo) {
465         // requestor.acceptTypeReference(ref.tokens, ref.sourceStart,
466         // ref.sourceEnd);
467         // }
468         // return ref;
469         // } else {
470         // ArrayQualifiedTypeReference ref =
471         // new ArrayQualifiedTypeReference(tokens, dim, positions);
472         // ref.sourceEnd = endPosition;
473         // if (reportReferenceInfo) {
474         // requestor.acceptTypeReference(ref.tokens, ref.sourceStart,
475         // ref.sourceEnd);
476         // }
477         // return ref;
478         // }
479         // }
480         // }
481         // }
482         // public NameReference getUnspecifiedReference() {
483         // /* build a (unspecified) NameReference which may be qualified*/
484         //
485         // int length;
486         // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
487         // // single variable reference
488         // SingleNameReference ref =
489         // new SingleNameReference(
490         // identifierStack[identifierPtr],
491         // identifierPositionStack[identifierPtr--]);
492         // if (reportReferenceInfo) {
493         // this.addUnknownRef(ref);
494         // }
495         // return ref;
496         // } else {
497         // //Qualified variable reference
498         // char[][] tokens = new char[length][];
499         // identifierPtr -= length;
500         // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
501         // QualifiedNameReference ref =
502         // new QualifiedNameReference(
503         // tokens,
504         // (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
505         // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
506         // if (reportReferenceInfo) {
507         // this.addUnknownRef(ref);
508         // }
509         // return ref;
510         // }
511         // }
512         // public NameReference getUnspecifiedReferenceOptimized() {
513         // /* build a (unspecified) NameReference which may be qualified
514         // The optimization occurs for qualified reference while we are
515         // certain in this case the last item of the qualified name is
516         // a field access. This optimization is IMPORTANT while it results
517         // that when a NameReference is build, the type checker should always
518         // look for that it is not a type reference */
519         //
520         // int length;
521         // if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
522         // // single variable reference
523         // SingleNameReference ref =
524         // new SingleNameReference(
525         // identifierStack[identifierPtr],
526         // identifierPositionStack[identifierPtr--]);
527         // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
528         // ref.bits |= LOCAL | FIELD;
529         // if (reportReferenceInfo) {
530         // this.addUnknownRef(ref);
531         // }
532         // return ref;
533         // }
534         //
535         // //Qualified-variable-reference
536         // //In fact it is variable-reference DOT field-ref , but it would result in
537         // a
538         // type
539         // //conflict tha can be only reduce by making a superclass (or inetrface )
540         // between
541         // //nameReference and FiledReference or putting FieldReference under
542         // NameReference
543         // //or else..........This optimisation is not really relevant so just leave
544         // as it is
545         //
546         // char[][] tokens = new char[length][];
547         // identifierPtr -= length;
548         // System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
549         // QualifiedNameReference ref =
550         // new QualifiedNameReference(
551         // tokens,
552         // (int) (identifierPositionStack[identifierPtr + 1] >> 32),
553         // // sourceStart
554         // (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
555         // ref.bits &= ~ASTNode.RestrictiveFlagMASK;
556         // ref.bits |= LOCAL | FIELD;
557         // if (reportReferenceInfo) {
558         // this.addUnknownRef(ref);
559         // }
560         // return ref;
561         // }
562         // /**
563         // *
564         // * INTERNAL USE-ONLY
565         // */
566         // private boolean isLocalDeclaration() {
567         // int nestedDepth = nestedType;
568         // while (nestedDepth >= 0) {
569         // if (nestedMethod[nestedDepth] != 0) {
570         // return true;
571         // }
572         // nestedDepth--;
573         // }
574         // return false;
575         // }
576         /*
577          * Update the bodyStart of the corresponding parse node
578          */
579         public void notifySourceElementRequestor(
580                         CompilationUnitDeclaration parsedUnit) {
581                 if (parsedUnit == null) {
582                         // when we parse a single type member declaration the compilation
583                         // unit is
584                         // null, but we still
585                         // want to be able to notify the requestor on the created ast node
586                         if (astStack[0] instanceof AbstractMethodDeclaration) {
587                                 notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
588                                 return;
589                         }
590                         return;
591                 }
592                 // range check
593                 boolean isInRange = scanner.initialPosition <= parsedUnit.sourceStart
594                                 && scanner.eofPosition >= parsedUnit.sourceEnd;
595
596                 // if (reportReferenceInfo) {
597                 // notifyAllUnknownReferences();
598                 // }
599                 // collect the top level ast nodes
600                 int length = 0;
601                 ASTNode[] nodes = null;
602                 if (sourceType == null) {
603                         if (isInRange) {
604                                 requestor.enterCompilationUnit();
605                         }
606                         // ImportReference currentPackage = parsedUnit.currentPackage;
607                         ImportReference[] imports = parsedUnit.imports;
608                         // TypeDeclaration[] types = parsedUnit.types;
609                         ArrayList types = parsedUnit.types;
610                         if (types != null) {
611                                 // length =
612                                 // (currentPackage == null ? 0 : 1)
613                                 // + (imports == null ? 0 : imports.length)
614                                 // + (types == null ? 0 : types.length);
615                                 // nodes = new ASTNode[length];
616                                 length = (imports == null ? 0 : imports.length) + types.size();
617                                 nodes = new ASTNode[length];
618                                 int index = 0;
619                                 // if (currentPackage != null) {
620                                 // nodes[index++] = currentPackage;
621                                 // }
622                                 if (imports != null) {
623                                         for (int i = 0, max = imports.length; i < max; i++) {
624                                                 nodes[index++] = imports[i];
625                                         }
626                                 }
627
628                                 for (int i = 0, max = types.size(); i < max; i++) {
629                                         nodes[index++] = (ASTNode) types.get(i);
630                                 }
631                         }
632                 } else {
633                         // TypeDeclaration[] types = parsedUnit.types;
634                         ArrayList types = parsedUnit.types;
635                         if (types != null) {
636                                 length = types.size();
637                                 nodes = new ASTNode[length];
638                                 for (int i = 0, max = types.size(); i < max; i++) {
639                                         nodes[i] = (ASTNode) types.get(i);
640                                 }
641                         }
642                 }
643
644                 // notify the nodes in the syntactical order
645                 if (nodes != null && length > 0) {
646                         quickSort(nodes, 0, length - 1);
647                         for (int i = 0; i < length; i++) {
648                                 ASTNode node = nodes[i];
649                                 if (node instanceof ImportReference) {
650                                         ImportReference importRef = (ImportReference) node;
651                                         // if (node == parsedUnit.currentPackage) {
652                                         // notifySourceElementRequestor(importRef, true);
653                                         // } else {
654                                         notifySourceElementRequestor(importRef, false);
655                                         // }
656                                 } // else { instanceof TypeDeclaration
657                                 if (node instanceof TypeDeclaration) {
658                                         notifySourceElementRequestor((TypeDeclaration) node,
659                                                         sourceType == null);
660                                         // notifySourceElementRequestor((CompilationUnitDeclaration)node,
661                                         // sourceType == null);
662                                 }
663                                 // jsurfer - INSERT start
664                                 if (node instanceof AbstractMethodDeclaration) {
665                                         notifySourceElementRequestor((AbstractMethodDeclaration) node);
666                                 }
667                                 // jsurfer - INSERT end
668                         }
669                 }
670
671                 if (sourceType == null) {
672                         if (isInRange) {
673                                 requestor.exitCompilationUnit(parsedUnit.sourceEnd);
674                         }
675                 }
676         }
677
678         // private void notifyAllUnknownReferences() {
679         // for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
680         // NameReference nameRef = this.unknownRefs[i];
681         // if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
682         // if ((nameRef.bits & BindingIds.TYPE) == 0) {
683         // // variable but not type
684         // if (nameRef instanceof SingleNameReference) {
685         // // local var or field
686         // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
687         // nameRef.sourceStart);
688         // } else {
689         // // QualifiedNameReference
690         // // The last token is a field reference and the previous tokens are a
691         // type/variable references
692         // char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
693         // int tokensLength = tokens.length;
694         // requestor.acceptFieldReference(tokens[tokensLength - 1],
695         // nameRef.sourceEnd
696         // - tokens[tokensLength - 1].length + 1);
697         // char[][] typeRef = new char[tokensLength - 1][];
698         // System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
699         // requestor.acceptUnknownReference(typeRef, nameRef.sourceStart,
700         // nameRef.sourceEnd - tokens[tokensLength - 1].length);
701         // }
702         // } else {
703         // // variable or type
704         // if (nameRef instanceof SingleNameReference) {
705         // requestor.acceptUnknownReference(((SingleNameReference) nameRef).token,
706         // nameRef.sourceStart);
707         // } else {
708         // //QualifiedNameReference
709         // requestor.acceptUnknownReference(((QualifiedNameReference)
710         // nameRef).tokens,
711         // nameRef.sourceStart, nameRef.sourceEnd);
712         // }
713         // }
714         // } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
715         // if (nameRef instanceof SingleNameReference) {
716         // requestor.acceptTypeReference(((SingleNameReference) nameRef).token,
717         // nameRef.sourceStart);
718         // } else {
719         // // it is a QualifiedNameReference
720         // requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens,
721         // nameRef.sourceStart, nameRef.sourceEnd);
722         // }
723         // }
724         // }
725         // }
726         /*
727          * Update the bodyStart of the corresponding parse node
728          */
729         public void notifySourceElementRequestor(
730                         AbstractMethodDeclaration methodDeclaration) {
731
732                 // range check
733                 boolean isInRange = scanner.initialPosition <= methodDeclaration.declarationSourceStart
734                                 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
735
736                 if (methodDeclaration.isClinit()) {
737                         this.visitIfNeeded(methodDeclaration);
738                         return;
739                 }
740
741                 if (methodDeclaration.isDefaultConstructor()) {
742                         if (reportReferenceInfo) {
743                                 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
744                                 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
745                                 if (constructorCall != null) {
746                                         switch (constructorCall.accessMode) {
747                                         case ExplicitConstructorCall.This:
748                                                 requestor.acceptConstructorReference(
749                                                                 typeNames[nestedTypeIndex - 1],
750                                                                 constructorCall.arguments == null ? 0
751                                                                                 : constructorCall.arguments.length,
752                                                                 constructorCall.sourceStart);
753                                                 break;
754                                         case ExplicitConstructorCall.Super:
755                                         case ExplicitConstructorCall.ImplicitSuper:
756                                                 requestor.acceptConstructorReference(
757                                                                 superTypeNames[nestedTypeIndex - 1],
758                                                                 constructorCall.arguments == null ? 0
759                                                                                 : constructorCall.arguments.length,
760                                                                 constructorCall.sourceStart);
761                                                 break;
762                                         }
763                                 }
764                         }
765                         return;
766                 }
767                 char[][] argumentTypes = null;
768                 char[][] argumentNames = null;
769                 Argument[] arguments = methodDeclaration.arguments;
770                 if (arguments != null) {
771                         int argumentLength = arguments.length;
772                         argumentTypes = new char[argumentLength][];
773                         argumentNames = new char[argumentLength][];
774                         for (int i = 0; i < argumentLength; i++) {
775                                 argumentTypes[i] = returnTypeName(arguments[i].type);
776                                 argumentNames[i] = arguments[i].name;
777                         }
778                 }
779                 char[][] thrownExceptionTypes = null;
780                 TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
781                 if (thrownExceptions != null) {
782                         int thrownExceptionLength = thrownExceptions.length;
783                         thrownExceptionTypes = new char[thrownExceptionLength][];
784                         for (int i = 0; i < thrownExceptionLength; i++) {
785                                 thrownExceptionTypes[i] = CharOperation.concatWith(
786                                                 thrownExceptions[i].getTypeName(), '.');
787                         }
788                 }
789                 // by default no selector end position
790                 int selectorSourceEnd = -1;
791                 if (methodDeclaration.isConstructor()) {
792                         // if (methodDeclaration instanceof SourceConstructorDeclaration) {
793                         // selectorSourceEnd =
794                         // ((SourceConstructorDeclaration)
795                         // methodDeclaration).selectorSourceEnd;
796                         // }
797                         if (isInRange) {
798                                 requestor.enterConstructor(
799                                                 methodDeclaration.declarationSourceStart,
800                                                 methodDeclaration.modifiers,
801                                                 methodDeclaration.selector,
802                                                 methodDeclaration.sourceStart, selectorSourceEnd,
803                                                 argumentTypes, argumentNames, thrownExceptionTypes);
804                         }
805                         if (reportReferenceInfo) {
806                                 ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
807                                 ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
808                                 if (constructorCall != null) {
809                                         switch (constructorCall.accessMode) {
810                                         case ExplicitConstructorCall.This:
811                                                 requestor.acceptConstructorReference(
812                                                                 typeNames[nestedTypeIndex - 1],
813                                                                 constructorCall.arguments == null ? 0
814                                                                                 : constructorCall.arguments.length,
815                                                                 constructorCall.sourceStart);
816                                                 break;
817                                         case ExplicitConstructorCall.Super:
818                                         case ExplicitConstructorCall.ImplicitSuper:
819                                                 requestor.acceptConstructorReference(
820                                                                 superTypeNames[nestedTypeIndex - 1],
821                                                                 constructorCall.arguments == null ? 0
822                                                                                 : constructorCall.arguments.length,
823                                                                 constructorCall.sourceStart);
824                                                 break;
825                                         }
826                                 }
827                         }
828                         this.visitIfNeeded(methodDeclaration);
829                         if (isInRange) {
830                                 requestor
831                                                 .exitConstructor(methodDeclaration.declarationSourceEnd);
832                         }
833                         return;
834                 }
835                 // if (methodDeclaration instanceof SourceMethodDeclaration) {
836                 // selectorSourceEnd =
837                 // ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
838                 // }
839                 if (isInRange) {
840                         int modifiers = methodDeclaration.modifiers;
841                         // boolean deprecated = (modifiers & AccDeprecated) != 0; //
842                         // remember
843                         // deprecation so as to not lose it below
844                         requestor
845                                         .enterMethod(
846                                                         methodDeclaration.declarationSourceStart,
847                                                         modifiers, // deprecated
848                                                         // ?
849                                                         // (modifiers
850                                                         // &
851                                                         // AccJustFlag)
852                                                         // |
853                                                         // AccDeprecated
854                                                         // :
855                                                         // modifiers
856                                                         // &
857                                                         // AccJustFlag,
858                                                         returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
859                                                         methodDeclaration.selector,
860                                                         methodDeclaration.sourceStart, selectorSourceEnd,
861                                                         argumentTypes, argumentNames, thrownExceptionTypes);
862                 }
863                 this.visitIfNeeded(methodDeclaration);
864
865                 if (isInRange) {
866                         requestor.exitMethod(methodDeclaration.declarationSourceEnd);
867                 }
868         }
869
870         /*
871          * Update the bodyStart of the corresponding parse node
872          */
873         public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
874
875                 // range check
876                 boolean isInRange = scanner.initialPosition <= fieldDeclaration.declarationSourceStart
877                                 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
878
879                 if (fieldDeclaration.isField()) {
880                         int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
881                         // if (fieldDeclaration instanceof SourceFieldDeclaration) {
882                         // fieldEndPosition = ((SourceFieldDeclaration)
883                         // fieldDeclaration).fieldEndPosition;
884                         // if (fieldEndPosition == 0) {
885                         // // use the declaration source end by default
886                         // fieldEndPosition = fieldDeclaration.declarationSourceEnd;
887                         // }
888                         // }
889                         if (isInRange) {
890                                 int modifiers = fieldDeclaration.modifiers;
891                                 boolean deprecated = (modifiers & AccDeprecated) != 0; // remember
892                                 // deprecation so
893                                 // as to not lose
894                                 // it below
895                                 requestor.enterField(fieldDeclaration.declarationSourceStart,
896                                                 deprecated ? (modifiers & AccJustFlag) | AccDeprecated
897                                                                 : modifiers & AccJustFlag,
898                                                 returnTypeName(fieldDeclaration.type),
899                                                 fieldDeclaration.name, fieldDeclaration.sourceStart,
900                                                 fieldDeclaration.sourceEnd);
901                         }
902                         // this.visitIfNeeded(fieldDeclaration);
903                         if (isInRange) {
904                                 // requestor.exitField(
905                                 // // filter out initializations that are not a constant (simple
906                                 // check)
907                                 // (fieldDeclaration.initialization == null
908                                 // || fieldDeclaration.initialization instanceof
909                                 // ArrayInitializer
910                                 // || fieldDeclaration.initialization instanceof
911                                 // AllocationExpression
912                                 // || fieldDeclaration.initialization instanceof
913                                 // ArrayAllocationExpression
914                                 // || fieldDeclaration.initialization instanceof Assignment
915                                 // || fieldDeclaration.initialization instanceof
916                                 // ClassLiteralAccess
917                                 // || fieldDeclaration.initialization instanceof MessageSend
918                                 // || fieldDeclaration.initialization instanceof ArrayReference
919                                 // || fieldDeclaration.initialization instanceof ThisReference)
920                                 // ?
921                                 // -1 :
922                                 // fieldDeclaration.initialization.sourceStart,
923                                 // fieldEndPosition,
924                                 // fieldDeclaration.declarationSourceEnd);
925                                 requestor.exitField(
926                                                 // filter out initializations that are not a constant
927                                                 // (simple check)
928                                                 -1, fieldEndPosition,
929                                                 fieldDeclaration.declarationSourceEnd);
930                         }
931
932                 } else {
933                         // if (isInRange){
934                         // requestor.enterInitializer(
935                         // fieldDeclaration.declarationSourceStart,
936                         // fieldDeclaration.modifiers);
937                         // }
938                         // this.visitIfNeeded((Initializer)fieldDeclaration);
939                         // if (isInRange){
940                         // requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
941                         // }
942                 }
943         }
944
945         public void notifySourceElementRequestor(ImportReference importReference,
946                         boolean isPackage) {
947                 // if (isPackage) {
948                 // requestor.acceptPackage(
949                 // importReference.declarationSourceStart,
950                 // importReference.declarationSourceEnd,
951                 // CharOperation.concatWith(importReference.getImportName(), '.'));
952                 // } else {
953                 requestor.acceptImport(importReference.declarationSourceStart,
954                                 importReference.declarationSourceEnd, importReference
955                                                 .getIncludeName(), // CharOperation.concatWith(importReference.getImportName(),
956                                                                                         // '.'),
957                                 importReference.onDemand);
958                 // }
959         }
960
961         public void notifySourceElementRequestor(TypeDeclaration typeDeclaration,
962                         boolean notifyTypePresence) {
963                 // // public void notifySourceElementRequestor(ASTNode typeDeclaration,
964                 // boolean notifyTypePresence) {
965
966                 // range check
967                 boolean isInRange = scanner.initialPosition <= typeDeclaration.declarationSourceStart
968                                 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
969
970                 FieldDeclaration[] fields = typeDeclaration.fields;
971                 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
972                 TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
973                 int fieldCount = fields == null ? 0 : fields.length;
974                 int methodCount = methods == null ? 0 : methods.length;
975                 int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
976                 int fieldIndex = 0;
977                 int methodIndex = 0;
978                 int memberTypeIndex = 0;
979                 boolean isInterface = typeDeclaration.isInterface();
980
981                 if (notifyTypePresence) {
982                         char[][] interfaceNames = null;
983                         int superInterfacesLength = 0;
984                         TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
985                         if (superInterfaces != null) {
986                                 superInterfacesLength = superInterfaces.length;
987                                 interfaceNames = new char[superInterfacesLength][];
988                         } else {
989                                 if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
990                                         // see PR 3442
991                                         QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration) typeDeclaration).allocation;
992                                         if (alloc != null && alloc.type != null) {
993                                                 superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration) typeDeclaration).allocation.type };
994                                                 superInterfacesLength = 1;
995                                                 interfaceNames = new char[1][];
996                                         }
997                                 }
998                         }
999                         if (superInterfaces != null) {
1000                                 for (int i = 0; i < superInterfacesLength; i++) {
1001                                         interfaceNames[i] = CharOperation.concatWith(
1002                                                         superInterfaces[i].getTypeName(), '.');
1003                                 }
1004                         }
1005                         if (isInterface) {
1006                                 if (isInRange) {
1007                                         int modifiers = typeDeclaration.modifiers;
1008                                         boolean deprecated = false; // (modifiers & AccDeprecated)
1009                                                                                                 // != 0; //
1010                                         // remember deprecation so as to not lose
1011                                         // it below
1012                                         requestor.enterInterface(
1013                                                         typeDeclaration.declarationSourceStart,
1014                                                         modifiers, // deprecated
1015                                                         // ?
1016                                                         // (modifiers
1017                                                         // &
1018                                                         // AccJustFlag)
1019                                                         // |
1020                                                         // AccDeprecated
1021                                                         // :
1022                                                         // modifiers
1023                                                         // &
1024                                                         // AccJustFlag,
1025                                                         typeDeclaration.name, typeDeclaration.sourceStart,
1026                                                         typeDeclaration.sourceEnd, interfaceNames);
1027                                 }
1028                                 if (nestedTypeIndex == typeNames.length) {
1029                                         // need a resize
1030                                         System.arraycopy(typeNames, 0,
1031                                                         (typeNames = new char[nestedTypeIndex * 2][]), 0,
1032                                                         nestedTypeIndex);
1033                                         System.arraycopy(superTypeNames, 0,
1034                                                         (superTypeNames = new char[nestedTypeIndex * 2][]),
1035                                                         0, nestedTypeIndex);
1036                                 }
1037                                 typeNames[nestedTypeIndex] = typeDeclaration.name;
1038                                 superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
1039                         } else {
1040                                 TypeReference superclass = typeDeclaration.superclass;
1041                                 if (superclass == null) {
1042                                         if (isInRange) {
1043                                                 requestor
1044                                                                 .enterClass(
1045                                                                                 typeDeclaration.declarationSourceStart,
1046                                                                                 typeDeclaration.modifiers,
1047                                                                                 typeDeclaration.name,
1048                                                                                 typeDeclaration.sourceStart,
1049                                                                                 typeDeclaration.sourceEnd, null,
1050                                                                                 interfaceNames);
1051                                         }
1052                                 } else {
1053                                         if (isInRange) {
1054                                                 requestor.enterClass(
1055                                                                 typeDeclaration.declarationSourceStart,
1056                                                                 typeDeclaration.modifiers,
1057                                                                 typeDeclaration.name,
1058                                                                 typeDeclaration.sourceStart,
1059                                                                 typeDeclaration.sourceEnd, CharOperation
1060                                                                                 .concatWith(superclass.getTypeName(),
1061                                                                                                 '.'), interfaceNames);
1062                                         }
1063                                 }
1064                                 if (nestedTypeIndex == typeNames.length) {
1065                                         // need a resize
1066                                         System.arraycopy(typeNames, 0,
1067                                                         (typeNames = new char[nestedTypeIndex * 2][]), 0,
1068                                                         nestedTypeIndex);
1069                                         System.arraycopy(superTypeNames, 0,
1070                                                         (superTypeNames = new char[nestedTypeIndex * 2][]),
1071                                                         0, nestedTypeIndex);
1072                                 }
1073                                 typeNames[nestedTypeIndex] = typeDeclaration.name;
1074                                 superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT
1075                                                 : CharOperation.concatWith(superclass.getTypeName(),
1076                                                                 '.');
1077                         }
1078                 }
1079                 while ((fieldIndex < fieldCount) || (memberTypeIndex < memberTypeCount)
1080                                 || (methodIndex < methodCount)) {
1081                         FieldDeclaration nextFieldDeclaration = null;
1082                         AbstractMethodDeclaration nextMethodDeclaration = null;
1083                         TypeDeclaration nextMemberDeclaration = null;
1084
1085                         int position = Integer.MAX_VALUE;
1086                         int nextDeclarationType = -1;
1087                         if (fieldIndex < fieldCount) {
1088                                 nextFieldDeclaration = fields[fieldIndex];
1089                                 if (nextFieldDeclaration.declarationSourceStart < position) {
1090                                         position = nextFieldDeclaration.declarationSourceStart;
1091                                         nextDeclarationType = 0; // FIELD
1092                                 }
1093                         }
1094                         if (methodIndex < methodCount) {
1095                                 nextMethodDeclaration = methods[methodIndex];
1096                                 if (nextMethodDeclaration.declarationSourceStart < position) {
1097                                         position = nextMethodDeclaration.declarationSourceStart;
1098                                         nextDeclarationType = 1; // METHOD
1099                                 }
1100                         }
1101                         if (memberTypeIndex < memberTypeCount) {
1102                                 nextMemberDeclaration = memberTypes[memberTypeIndex];
1103                                 if (nextMemberDeclaration.declarationSourceStart < position) {
1104                                         position = nextMemberDeclaration.declarationSourceStart;
1105                                         nextDeclarationType = 2; // MEMBER
1106                                 }
1107                         }
1108                         switch (nextDeclarationType) {
1109                         case 0:
1110                                 fieldIndex++;
1111                                 notifySourceElementRequestor(nextFieldDeclaration);
1112                                 break;
1113                         case 1:
1114                                 methodIndex++;
1115                                 notifySourceElementRequestor(nextMethodDeclaration);
1116                                 break;
1117                         case 2:
1118                                 memberTypeIndex++;
1119                                 notifySourceElementRequestor(nextMemberDeclaration, true);
1120                         }
1121                 }
1122                 if (notifyTypePresence) {
1123                         if (isInRange) {
1124                                 if (isInterface) {
1125                                         requestor
1126                                                         .exitInterface(typeDeclaration.declarationSourceEnd);
1127                                 } else {
1128                                         requestor.exitClass(typeDeclaration.declarationSourceEnd);
1129                                 }
1130                         }
1131                         nestedTypeIndex--;
1132                 }
1133         }
1134
1135         public void parseCompilationUnit(ICompilationUnit unit, int start, int end) {
1136                 // boolean needReferenceInfo) {
1137
1138                 // reportReferenceInfo = needReferenceInfo;
1139                 // boolean old = diet;
1140                 // if (needReferenceInfo) {
1141                 // unknownRefs = new NameReference[10];
1142                 // unknownRefsCounter = 0;
1143                 // }
1144
1145                 try {
1146                         // diet = true;
1147                         CompilationResult compilationUnitResult = new CompilationResult(
1148                                         unit, 0, 0, 10); // this.options.maxProblemsPerUnit);
1149                         CompilationUnitDeclaration parsedUnit = parse(unit,
1150                                         compilationUnitResult, start, end);
1151                         // if (scanner.recordLineSeparator) {
1152                         // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1153                         // }
1154                         // if (this.localDeclarationVisitor != null || needReferenceInfo){
1155                         // diet = false;
1156                         // this.getMethodBodies(parsedUnit);
1157                         // }
1158                         // this.scanner.resetTo(start, end);
1159                         // notifySourceElementRequestor(parsedUnit);
1160                 } catch (AbortCompilation e) {
1161                 } finally {
1162                         // diet = old;
1163                 }
1164         }
1165
1166         public CompilationUnitDeclaration parseCompilationUnit(
1167                         ICompilationUnit unit, boolean fullParse) {
1168
1169                 // boolean old = diet;
1170                 // if (fullParse) {
1171                 // unknownRefs = new NameReference[10];
1172                 // unknownRefsCounter = 0;
1173                 // }
1174
1175                 try {
1176                         // diet = true;
1177                         this.reportReferenceInfo = fullParse;
1178                         CompilationResult compilationUnitResult = new CompilationResult(
1179                                         unit, 0, 0, this.options.maxProblemsPerUnit);
1180                         CompilationUnitDeclaration parsedUnit = parse(unit,
1181                                         compilationUnitResult, false);
1182                         if (scanner.recordLineSeparator) {
1183                                 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1184                         }
1185                         int initialStart = this.scanner.initialPosition;
1186                         int initialEnd = this.scanner.eofPosition;
1187                         // if (this.localDeclarationVisitor != null || fullParse){
1188                         // diet = false;
1189                         // this.getMethodBodies(parsedUnit);
1190                         // }
1191                         this.scanner.resetTo(initialStart, initialEnd);
1192                         notifySourceElementRequestor(parsedUnit);
1193                         return parsedUnit;
1194                 } catch (AbortCompilation e) {
1195                         // ignore this exception
1196                 } finally {
1197                         // diet = old;
1198                 }
1199                 return null;
1200         }
1201
1202         public CompilationUnitDeclaration parseCompletionUnit(
1203                         ICompilationUnit unit, boolean fullParse) {
1204
1205                 // boolean old = diet;
1206                 // if (fullParse) {
1207                 // unknownRefs = new NameReference[10];
1208                 // unknownRefsCounter = 0;
1209                 // }
1210
1211                 try {
1212                         // diet = true;
1213                         this.reportReferenceInfo = fullParse;
1214                         CompilationResult compilationUnitResult = new CompilationResult(
1215                                         unit, 0, 0, this.options.maxProblemsPerUnit);
1216                         CompilationUnitDeclaration parsedUnit = parse(unit,
1217                                         compilationUnitResult, false);
1218                         // if (scanner.recordLineSeparator) {
1219                         // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1220                         // }
1221                         // int initialStart = this.scanner.initialPosition;
1222                         // int initialEnd = this.scanner.eofPosition;
1223                         // // if (this.localDeclarationVisitor != null || fullParse){
1224                         // // diet = false;
1225                         // // this.getMethodBodies(parsedUnit);
1226                         // // }
1227                         // this.scanner.resetTo(initialStart, initialEnd);
1228                         // notifySourceElementRequestor(parsedUnit);
1229                         return parsedUnit;
1230                 } catch (AbortCompilation e) {
1231                         // ignore this exception
1232                 } finally {
1233                         // diet = old;
1234                 }
1235                 return null;
1236         }
1237
1238         // public void parseTypeMemberDeclarations(
1239         // ISourceType sourceType,
1240         // ICompilationUnit sourceUnit,
1241         // int start,
1242         // int end,
1243         // boolean needReferenceInfo) {
1244         // boolean old = diet;
1245         // if (needReferenceInfo) {
1246         // unknownRefs = new NameReference[10];
1247         // unknownRefsCounter = 0;
1248         // }
1249         //      
1250         // try {
1251         // diet = !needReferenceInfo;
1252         // reportReferenceInfo = needReferenceInfo;
1253         // CompilationResult compilationUnitResult =
1254         // new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
1255         // CompilationUnitDeclaration unit =
1256         // SourceTypeConverter.buildCompilationUnit(
1257         // new ISourceType[]{sourceType},
1258         // false, // no need for field and methods
1259         // false, // no need for member types
1260         // false, // no need for field initialization
1261         // problemReporter(),
1262         // compilationUnitResult);
1263         // if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
1264         // return;
1265         // this.sourceType = sourceType;
1266         // try {
1267         // /* automaton initialization */
1268         // initialize();
1269         // goForClassBodyDeclarations();
1270         // /* scanner initialization */
1271         // scanner.setSource(sourceUnit.getContents());
1272         // scanner.resetTo(start, end);
1273         // /* unit creation */
1274         // referenceContext = compilationUnit = unit;
1275         // /* initialize the astStacl */
1276         // // the compilationUnitDeclaration should contain exactly one type
1277         // pushOnAstStack(unit.types[0]);
1278         // /* run automaton */
1279         // parse();
1280         // notifySourceElementRequestor(unit);
1281         // } finally {
1282         // unit = compilationUnit;
1283         // compilationUnit = null; // reset parser
1284         // }
1285         // } catch (AbortCompilation e) {
1286         // } finally {
1287         // if (scanner.recordLineSeparator) {
1288         // requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
1289         // }
1290         // diet = old;
1291         // }
1292         // }
1293         //
1294         // public void parseTypeMemberDeclarations(
1295         // char[] contents,
1296         // int start,
1297         // int end) {
1298         //
1299         // boolean old = diet;
1300         //      
1301         // try {
1302         // diet = true;
1303         //
1304         // /* automaton initialization */
1305         // initialize();
1306         // goForClassBodyDeclarations();
1307         // /* scanner initialization */
1308         // scanner.setSource(contents);
1309         // scanner.recordLineSeparator = false;
1310         // scanner.taskTags = null;
1311         // scanner.taskPriorities = null;
1312         // scanner.resetTo(start, end);
1313         //
1314         // /* unit creation */
1315         // referenceContext = null;
1316         //
1317         // /* initialize the astStacl */
1318         // // the compilationUnitDeclaration should contain exactly one type
1319         // /* run automaton */
1320         // parse();
1321         // notifySourceElementRequestor((CompilationUnitDeclaration)null);
1322         // } catch (AbortCompilation e) {
1323         // } finally {
1324         // diet = old;
1325         // }
1326         // }
1327         /**
1328          * Sort the given ast nodes by their positions.
1329          */
1330         private static void quickSort(ASTNode[] sortedCollection, int left,
1331                         int right) {
1332                 int original_left = left;
1333                 int original_right = right;
1334                 ASTNode mid = sortedCollection[(left + right) / 2];
1335                 do {
1336                         while (sortedCollection[left].sourceStart < mid.sourceStart) {
1337                                 left++;
1338                         }
1339                         while (mid.sourceStart < sortedCollection[right].sourceStart) {
1340                                 right--;
1341                         }
1342                         if (left <= right) {
1343                                 ASTNode tmp = sortedCollection[left];
1344                                 sortedCollection[left] = sortedCollection[right];
1345                                 sortedCollection[right] = tmp;
1346                                 left++;
1347                                 right--;
1348                         }
1349                 } while (left <= right);
1350                 if (original_left < right) {
1351                         quickSort(sortedCollection, original_left, right);
1352                 }
1353                 if (left < original_right) {
1354                         quickSort(sortedCollection, left, original_right);
1355                 }
1356         }
1357
1358         /*
1359          * Answer a char array representation of the type name formatted like: -
1360          * type name + dimensions Example: "A[][]".toCharArray()
1361          * "java.lang.String".toCharArray()
1362          */
1363         private char[] returnTypeName(TypeReference type) {
1364                 if (type == null)
1365                         return null;
1366                 int dimension = type.dimensions();
1367                 if (dimension != 0) {
1368                         char[] dimensionsArray = new char[dimension * 2];
1369                         for (int i = 0; i < dimension; i++) {
1370                                 dimensionsArray[i * 2] = '[';
1371                                 dimensionsArray[(i * 2) + 1] = ']';
1372                         }
1373                         return CharOperation.concat(CharOperation.concatWith(type
1374                                         .getTypeName(), '.'), dimensionsArray);
1375                 }
1376                 return CharOperation.concatWith(type.getTypeName(), '.');
1377         }
1378
1379         public void addUnknownRef(NameReference nameRef) {
1380                 if (this.unknownRefs.length == this.unknownRefsCounter) {
1381                         // resize
1382                         System
1383                                         .arraycopy(
1384                                                         this.unknownRefs,
1385                                                         0,
1386                                                         (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
1387                                                         0, this.unknownRefsCounter);
1388                 }
1389                 this.unknownRefs[this.unknownRefsCounter++] = nameRef;
1390         }
1391
1392         private void visitIfNeeded(AbstractMethodDeclaration method) {
1393                 if (this.localDeclarationVisitor != null
1394                                 && (method.bits & ASTNode.HasLocalTypeMASK) != 0) {
1395                         if (method.statements != null) {
1396                                 int statementsLength = method.statements.length;
1397                                 for (int i = 0; i < statementsLength; i++)
1398                                         method.statements[i].traverse(this.localDeclarationVisitor,
1399                                                         method.scope);
1400                         }
1401                 }
1402         }
1403
1404         // private void visitIfNeeded(FieldDeclaration field) {
1405         // if (this.localDeclarationVisitor != null
1406         // && (field.bits & ASTNode.HasLocalTypeMASK) != 0) {
1407         // if (field.initialization != null) {
1408         // field.initialization.traverse(this.localDeclarationVisitor, null);
1409         // }
1410         // }
1411         // }
1412         //
1413         // private void visitIfNeeded(Initializer initializer) {
1414         // if (this.localDeclarationVisitor != null
1415         // && (initializer.bits & ASTNode.HasLocalTypeMASK) != 0) {
1416         // if (initializer.block != null) {
1417         // initializer.block.traverse(this.localDeclarationVisitor, null);
1418         // }
1419         // }
1420         // }
1421         //
1422         // protected void reportSyntaxError(int act, int currentKind, int
1423         // stateStackTop) {
1424         // if (compilationUnit == null) return;
1425         // super.reportSyntaxError(act, currentKind,stateStackTop);
1426         // }
1427         protected CompilationUnitDeclaration endParse(int act) {
1428                 // if (sourceType != null) {
1429                 // if (sourceType.isInterface()) {
1430                 // consumeInterfaceDeclaration();
1431                 // } else {
1432                 // consumeClassDeclaration();
1433                 // }
1434                 // }
1435                 if (compilationUnit != null) {
1436                         CompilationUnitDeclaration result = super.endParse(act);
1437                         return result;
1438                 } else {
1439                         return null;
1440                 }
1441         }
1442 }