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