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