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