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