1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v0.5 
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v05.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  ******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.compiler;
 
  14  * A source element parser extracts structural and reference information
 
  15  * from a piece of source.
 
  17  * also see @ISourceElementRequestor
 
  19  * The structural investigation includes:
 
  20  * - the package statement
 
  22  * - top-level types: package member, member types (member types of member types...)
 
  26  * If reference information is requested, then all source constructs are
 
  27  * investigated and type, field & method references are provided as well.
 
  29  * Any (parsing) problem encountered is also provided.
 
  32 import net.sourceforge.phpdt.core.compiler.IProblem;
 
  33 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
 
  34 import net.sourceforge.phpdt.internal.compiler.ast.AllocationExpression;
 
  35 import net.sourceforge.phpdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
 
  36 import net.sourceforge.phpdt.internal.compiler.ast.Argument;
 
  37 import net.sourceforge.phpdt.internal.compiler.ast.ArrayQualifiedTypeReference;
 
  38 import net.sourceforge.phpdt.internal.compiler.ast.ArrayTypeReference;
 
  39 import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
 
  40 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
 
  41 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
 
  42 import net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall;
 
  43 import net.sourceforge.phpdt.internal.compiler.ast.Expression;
 
  44 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
 
  45 import net.sourceforge.phpdt.internal.compiler.ast.FieldReference;
 
  46 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
 
  47 import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
 
  48 import net.sourceforge.phpdt.internal.compiler.ast.LocalTypeDeclaration;
 
  49 import net.sourceforge.phpdt.internal.compiler.ast.MemberTypeDeclaration;
 
  50 import net.sourceforge.phpdt.internal.compiler.ast.MessageSend;
 
  51 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
 
  52 import net.sourceforge.phpdt.internal.compiler.ast.NameReference;
 
  53 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedAllocationExpression;
 
  54 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference;
 
  55 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference;
 
  56 import net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference;
 
  57 import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
 
  58 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
 
  59 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
 
  60 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
 
  61 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
 
  62 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
 
  63 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
 
  64 import net.sourceforge.phpdt.internal.compiler.lookup.BindingIds;
 
  65 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
 
  66 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
 
  67 import net.sourceforge.phpdt.internal.compiler.parser.Parser;
 
  68 import net.sourceforge.phpdt.internal.compiler.parser.RecoveredType;
 
  69 import net.sourceforge.phpdt.internal.compiler.parser.SourceConstructorDeclaration;
 
  70 import net.sourceforge.phpdt.internal.compiler.parser.SourceFieldDeclaration;
 
  71 import net.sourceforge.phpdt.internal.compiler.parser.SourceMethodDeclaration;
 
  72 import net.sourceforge.phpdt.internal.compiler.parser.SourceTypeConverter;
 
  73 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
 
  74 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
 
  75 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
 
  77 public class SourceElementParser extends Parser {
 
  79         ISourceElementRequestor requestor;
 
  80         private int fieldCount;
 
  81         private int localIntPtr;
 
  82         private int lastFieldEndPosition;
 
  83         private ISourceType sourceType;
 
  84         private boolean reportReferenceInfo;
 
  85         private char[][] typeNames;
 
  86         private char[][] superTypeNames;
 
  87         private int nestedTypeIndex;
 
  88         private static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
 
  89         private NameReference[] unknownRefs;
 
  90         private int unknownRefsCounter;
 
  91         private LocalDeclarationVisitor localDeclarationVisitor = null;
 
  92         private CompilerOptions options;
 
  95  * An ast visitor that visits local type declarations.
 
  97 public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
 
  99                         AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
 
 101                 notifySourceElementRequestor(anonymousTypeDeclaration, sourceType == null);
 
 102                 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
 
 104         public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
 
 105                 notifySourceElementRequestor(typeDeclaration, sourceType == null);
 
 106                 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
 
 108         public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
 
 109                 notifySourceElementRequestor(typeDeclaration, sourceType == null);
 
 110                 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
 
 115 public SourceElementParser(
 
 116         final ISourceElementRequestor requestor, 
 
 117         IProblemFactory problemFactory,
 
 118         CompilerOptions options) {
 
 119         // we want to notify all syntax error with the acceptProblem API
 
 120         // To do so, we define the record method of the ProblemReporter
 
 121         super(new ProblemReporter(
 
 122                 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
 
 125                 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
 
 126                         unitResult.record(problem, referenceContext);
 
 127                         requestor.acceptProblem(problem);
 
 132         this.requestor = requestor;
 
 133         typeNames = new char[4][];
 
 134         superTypeNames = new char[4][];
 
 136         this.options = options;
 
 139 /** @deprecated use SourceElementParser(ISourceElementRequestor, IProblemFactory, CompilerOptions) */
 
 140 public SourceElementParser(
 
 141         final ISourceElementRequestor requestor, 
 
 142         IProblemFactory problemFactory) {
 
 143                 this(requestor, problemFactory, new CompilerOptions());
 
 146 public SourceElementParser(
 
 147         final ISourceElementRequestor requestor, 
 
 148         IProblemFactory problemFactory,
 
 149         CompilerOptions options,
 
 150         boolean reportLocalDeclarations) {
 
 151                 this(requestor, problemFactory, options);
 
 152                 if (reportLocalDeclarations) {
 
 153                         this.localDeclarationVisitor = new LocalDeclarationVisitor();
 
 157 public void checkAnnotation() {
 
 158         int firstCommentIndex = scanner.commentPtr;
 
 160         super.checkAnnotation();
 
 162         // modify the modifier source start to point at the first comment
 
 163         if (firstCommentIndex >= 0) {
 
 164                 modifiersSourceStart = scanner.commentStarts[0]; 
 
 168 protected void classInstanceCreation(boolean alwaysQualified) {
 
 170         boolean previousFlag = reportReferenceInfo;
 
 171         reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
 
 172         super.classInstanceCreation(alwaysQualified);
 
 173         reportReferenceInfo = previousFlag;
 
 174         if (reportReferenceInfo){
 
 175                 AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
 
 176                 TypeReference typeRef = alloc.type;
 
 177                 requestor.acceptConstructorReference(
 
 178                         typeRef instanceof SingleTypeReference 
 
 179                                 ? ((SingleTypeReference) typeRef).token
 
 180                                 : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
 
 181                         alloc.arguments == null ? 0 : alloc.arguments.length, 
 
 185 protected void consumeConstructorHeaderName() {
 
 186         // ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
 
 188         /* recovering - might be an empty message send */
 
 189         if (currentElement != null){
 
 190                 if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
 
 191                         lastCheckPoint = scanner.startPosition; // force to restart at this exact position                              
 
 192                         restartRecovery = true;
 
 196         SourceConstructorDeclaration cd = new SourceConstructorDeclaration(this.compilationUnit.compilationResult);
 
 198         //name -- this is not really revelant but we do .....
 
 199         cd.selector = identifierStack[identifierPtr];
 
 200         long selectorSourcePositions = identifierPositionStack[identifierPtr--];
 
 201         identifierLengthPtr--;
 
 204         cd.declarationSourceStart = intStack[intPtr--];
 
 205         cd.modifiers = intStack[intPtr--];
 
 207         //highlight starts at the selector starts
 
 208         cd.sourceStart = (int) (selectorSourcePositions >>> 32);
 
 209         cd.selectorSourceEnd = (int) selectorSourcePositions;
 
 212         cd.sourceEnd = lParenPos;
 
 213         cd.bodyStart = lParenPos+1;
 
 214         listLength = 0; // initialize listLength before reading parameters/throws
 
 217         if (currentElement != null){
 
 218                 lastCheckPoint = cd.bodyStart;
 
 219                 if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
 
 220                         || cd.modifiers != 0){
 
 221                         currentElement = currentElement.add(cd, 0);
 
 222                         lastIgnoredToken = -1;
 
 230 protected void consumeExitVariableWithInitialization() {
 
 231         // ExitVariableWithInitialization ::= $empty
 
 232         // the scanner is located after the comma or the semi-colon.
 
 233         // we want to include the comma or the semi-colon
 
 234         super.consumeExitVariableWithInitialization();
 
 235         if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
 
 237         ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
 
 239 protected void consumeExitVariableWithoutInitialization() {
 
 240         // ExitVariableWithoutInitialization ::= $empty
 
 241         // do nothing by default
 
 242         if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
 
 244         ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
 
 250 protected void consumeFieldAccess(boolean isSuperAccess) {
 
 251         // FieldAccess ::= Primary '.' 'Identifier'
 
 252         // FieldAccess ::= 'super' '.' 'Identifier'
 
 253         super.consumeFieldAccess(isSuperAccess);
 
 254         FieldReference fr = (FieldReference) expressionStack[expressionPtr];
 
 255         if (reportReferenceInfo) {
 
 256                 requestor.acceptFieldReference(fr.token, fr.sourceStart);
 
 259 protected void consumeMethodHeaderName() {
 
 260         // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
 
 261         SourceMethodDeclaration md = new SourceMethodDeclaration(this.compilationUnit.compilationResult);
 
 264         md.selector = identifierStack[identifierPtr];
 
 265         long selectorSourcePositions = identifierPositionStack[identifierPtr--];
 
 266         identifierLengthPtr--;
 
 268         md.returnType = getTypeReference(intStack[intPtr--]);
 
 270         md.declarationSourceStart = intStack[intPtr--];
 
 271         md.modifiers = intStack[intPtr--];
 
 273         //highlight starts at selector start
 
 274         md.sourceStart = (int) (selectorSourcePositions >>> 32);
 
 275         md.selectorSourceEnd = (int) selectorSourcePositions;
 
 277         md.sourceEnd = lParenPos;
 
 278         md.bodyStart = lParenPos+1;
 
 279         listLength = 0; // initialize listLength before reading parameters/throws
 
 282         if (currentElement != null){
 
 283                 if (currentElement instanceof RecoveredType 
 
 284                         //|| md.modifiers != 0
 
 285                         || (scanner.getLineNumber(md.returnType.sourceStart)
 
 286                                         == scanner.getLineNumber(md.sourceStart))){
 
 287                         lastCheckPoint = md.bodyStart;
 
 288                         currentElement = currentElement.add(md, 0);
 
 289                         lastIgnoredToken = -1;                  
 
 291                         lastCheckPoint = md.sourceStart;
 
 292                         restartRecovery = true;
 
 300 protected void consumeMethodInvocationName() {
 
 301         // MethodInvocation ::= Name '(' ArgumentListopt ')'
 
 303         // when the name is only an identifier...we have a message send to "this" (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));
 
 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));
 
 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));
 
 345 protected void consumeSingleTypeImportDeclarationName() {
 
 346         // SingleTypeImportDeclarationName ::= 'import' Name
 
 347         /* push an ImportRef build from the last name 
 
 348         stored in the identifier stack. */
 
 350         super.consumeSingleTypeImportDeclarationName();
 
 351         ImportReference impt = (ImportReference)astStack[astPtr];
 
 352         if (reportReferenceInfo) {
 
 353                 requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
 
 356 protected void consumeTypeImportOnDemandDeclarationName() {
 
 357         // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
 
 358         /* push an ImportRef build from the last name 
 
 359         stored in the identifier stack. */
 
 361         super.consumeTypeImportOnDemandDeclarationName();
 
 362         ImportReference impt = (ImportReference)astStack[astPtr];
 
 363         if (reportReferenceInfo) {
 
 364                 requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
 
 367 protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
 
 368         return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
 
 370 protected CompilationUnitDeclaration endParse(int act) {
 
 371         if (sourceType != null) {
 
 372                 if (sourceType.isInterface()) {
 
 373                         consumeInterfaceDeclaration();
 
 375                         consumeClassDeclaration();
 
 378         if (compilationUnit != null) {
 
 379                 CompilationUnitDeclaration result = super.endParse(act);
 
 386  * Flush annotations defined prior to a given positions.
 
 388  * Note: annotations are stacked in syntactical order
 
 390  * Either answer given <position>, or the end position of a comment line 
 
 391  * immediately following the <position> (same line)
 
 395  * } // end of method foo
 
 398 public int flushAnnotationsDefinedPriorTo(int position) {
 
 400         return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
 
 402 public TypeReference getTypeReference(int dim) {
 
 403         /* build a Reference on a variable that may be qualified or not
 
 404          * This variable is a type reference and dim will be its dimensions
 
 407         if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
 
 408                 // single variable reference
 
 410                         SingleTypeReference ref = 
 
 411                                 new SingleTypeReference(
 
 412                                         identifierStack[identifierPtr], 
 
 413                                         identifierPositionStack[identifierPtr--]);
 
 414                         if (reportReferenceInfo) {
 
 415                                 requestor.acceptTypeReference(ref.token, ref.sourceStart);
 
 419                         ArrayTypeReference ref = 
 
 420                                 new ArrayTypeReference(
 
 421                                         identifierStack[identifierPtr], 
 
 423                                         identifierPositionStack[identifierPtr--]); 
 
 424                         ref.sourceEnd = endPosition;
 
 425                         if (reportReferenceInfo) {
 
 426                                 requestor.acceptTypeReference(ref.token, ref.sourceStart);
 
 431                 if (length < 0) { //flag for precompiled type reference on base types
 
 432                         TypeReference ref = TypeReference.baseTypeReference(-length, dim);
 
 433                         ref.sourceStart = intStack[intPtr--];
 
 435                                 ref.sourceEnd = intStack[intPtr--];
 
 437                                 intPtr--; // no need to use this position as it is an array
 
 438                                 ref.sourceEnd = endPosition;
 
 440                         if (reportReferenceInfo){
 
 441                                         requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
 
 444                 } else { //Qualified variable reference
 
 445                         char[][] tokens = new char[length][];
 
 446                         identifierPtr -= length;
 
 447                         long[] positions = new long[length];
 
 448                         System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
 
 450                                 identifierPositionStack, 
 
 456                                 QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
 
 457                                 if (reportReferenceInfo) {
 
 458                                         requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
 
 462                                 ArrayQualifiedTypeReference ref = 
 
 463                                         new ArrayQualifiedTypeReference(tokens, dim, positions); 
 
 464                                 ref.sourceEnd = endPosition;                                    
 
 465                                 if (reportReferenceInfo) {
 
 466                                         requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
 
 473 public NameReference getUnspecifiedReference() {
 
 474         /* build a (unspecified) NameReference which may be qualified*/
 
 477         if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
 
 478                 // single variable reference
 
 479                 SingleNameReference ref = 
 
 480                         new SingleNameReference(
 
 481                                 identifierStack[identifierPtr], 
 
 482                                 identifierPositionStack[identifierPtr--]); 
 
 483                 if (reportReferenceInfo) {
 
 484                         this.addUnknownRef(ref);
 
 488                 //Qualified variable reference
 
 489                 char[][] tokens = new char[length][];
 
 490                 identifierPtr -= length;
 
 491                 System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
 
 492                 QualifiedNameReference ref = 
 
 493                         new QualifiedNameReference(
 
 495                                 (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
 
 496                                 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
 
 497                 if (reportReferenceInfo) {
 
 498                         this.addUnknownRef(ref);
 
 503 public NameReference getUnspecifiedReferenceOptimized() {
 
 504         /* build a (unspecified) NameReference which may be qualified
 
 505         The optimization occurs for qualified reference while we are
 
 506         certain in this case the last item of the qualified name is
 
 507         a field access. This optimization is IMPORTANT while it results
 
 508         that when a NameReference is build, the type checker should always
 
 509         look for that it is not a type reference */
 
 512         if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
 
 513                 // single variable reference
 
 514                 SingleNameReference ref = 
 
 515                         new SingleNameReference(
 
 516                                 identifierStack[identifierPtr], 
 
 517                                 identifierPositionStack[identifierPtr--]); 
 
 518                 ref.bits &= ~AstNode.RestrictiveFlagMASK;
 
 519                 ref.bits |= LOCAL | FIELD;
 
 520                 if (reportReferenceInfo) {
 
 521                         this.addUnknownRef(ref);
 
 526         //Qualified-variable-reference
 
 527         //In fact it is variable-reference DOT field-ref , but it would result in a type
 
 528         //conflict tha can be only reduce by making a superclass (or inetrface ) between
 
 529         //nameReference and FiledReference or putting FieldReference under NameReference
 
 530         //or else..........This optimisation is not really relevant so just leave as it is
 
 532         char[][] tokens = new char[length][];
 
 533         identifierPtr -= length;
 
 534         System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
 
 535         QualifiedNameReference ref = 
 
 536                 new QualifiedNameReference(
 
 538                         (int) (identifierPositionStack[identifierPtr + 1] >> 32), 
 
 540          (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
 
 541         ref.bits &= ~AstNode.RestrictiveFlagMASK;
 
 542         ref.bits |= LOCAL | FIELD;
 
 543         if (reportReferenceInfo) {
 
 544                 this.addUnknownRef(ref);
 
 552 private boolean isLocalDeclaration() {
 
 553         int nestedDepth = nestedType;
 
 554         while (nestedDepth >= 0) {
 
 555                 if (nestedMethod[nestedDepth] != 0) {
 
 563  * Update the bodyStart of the corresponding parse node
 
 565 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
 
 566         if (parsedUnit == null) {
 
 567                 // when we parse a single type member declaration the compilation unit is null, but we still
 
 568                 // want to be able to notify the requestor on the created ast node
 
 569                 if (astStack[0] instanceof AbstractMethodDeclaration) {
 
 570                         notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
 
 577                                 scanner.initialPosition <= parsedUnit.sourceStart
 
 578                                 && scanner.eofPosition >= parsedUnit.sourceEnd;
 
 580         if (reportReferenceInfo) {
 
 581                 notifyAllUnknownReferences();
 
 583         // collect the top level ast nodes
 
 585         AstNode[] nodes = null;
 
 586         if (sourceType == null){
 
 588                         requestor.enterCompilationUnit();
 
 590                 ImportReference currentPackage = parsedUnit.currentPackage;
 
 591                 ImportReference[] imports = parsedUnit.imports;
 
 592                 TypeDeclaration[] types = parsedUnit.types;
 
 594                         (currentPackage == null ? 0 : 1) 
 
 595                         + (imports == null ? 0 : imports.length)
 
 596                         + (types == null ? 0 : types.length);
 
 597                 nodes = new AstNode[length];
 
 599                 if (currentPackage != null) {
 
 600                         nodes[index++] = currentPackage;
 
 602                 if (imports != null) {
 
 603                         for (int i = 0, max = imports.length; i < max; i++) {
 
 604                                 nodes[index++] = imports[i];
 
 608                         for (int i = 0, max = types.length; i < max; i++) {
 
 609                                 nodes[index++] = types[i];
 
 613                 TypeDeclaration[] types = parsedUnit.types;
 
 615                         length = types.length;
 
 616                         nodes = new AstNode[length];
 
 617                         for (int i = 0, max = types.length; i < max; i++) {
 
 623         // notify the nodes in the syntactical order
 
 624         if (nodes != null && length > 0) {
 
 625                 quickSort(nodes, 0, length-1);
 
 626                 for (int i=0;i<length;i++) {
 
 627                         AstNode node = nodes[i];
 
 628                         if (node instanceof ImportReference) {
 
 629                                 ImportReference importRef = (ImportReference)node;
 
 630                                 if (node == parsedUnit.currentPackage) {
 
 631                                         notifySourceElementRequestor(importRef, true);
 
 633                                         notifySourceElementRequestor(importRef, false);
 
 635                         } else { // instanceof TypeDeclaration
 
 636                                 notifySourceElementRequestor((TypeDeclaration)node, sourceType == null);
 
 641         if (sourceType == null){
 
 643                         requestor.exitCompilationUnit(parsedUnit.sourceEnd);
 
 648 private void notifyAllUnknownReferences() {
 
 649         for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
 
 650                 NameReference nameRef = this.unknownRefs[i];
 
 651                 if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
 
 652                         if ((nameRef.bits & BindingIds.TYPE) == 0) { 
 
 653                                 // variable but not type
 
 654                                 if (nameRef instanceof SingleNameReference) { 
 
 655                                         // local var or field
 
 656                                         requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
 
 658                                         // QualifiedNameReference
 
 659                                         // The last token is a field reference and the previous tokens are a type/variable references
 
 660                                         char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
 
 661                                         int tokensLength = tokens.length;
 
 662                                         requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd - tokens[tokensLength - 1].length + 1);
 
 663                                         char[][] typeRef = new char[tokensLength - 1][];
 
 664                                         System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
 
 665                                         requestor.acceptUnknownReference(typeRef, nameRef.sourceStart, nameRef.sourceEnd - tokens[tokensLength - 1].length);
 
 669                                 if (nameRef instanceof SingleNameReference) {
 
 670                                         requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
 
 672                                         //QualifiedNameReference
 
 673                                         requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
 
 676                 } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
 
 677                         if (nameRef instanceof SingleNameReference) {
 
 678                                 requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
 
 680                                 // it is a QualifiedNameReference
 
 681                                 requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
 
 687  * Update the bodyStart of the corresponding parse node
 
 689 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
 
 693                                 scanner.initialPosition <= methodDeclaration.declarationSourceStart
 
 694                                 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
 
 696         if (methodDeclaration.isClinit()) {
 
 697                 this.visitIfNeeded(methodDeclaration);
 
 701         if (methodDeclaration.isDefaultConstructor()) {
 
 702                 if (reportReferenceInfo) {
 
 703                         ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
 
 704                         ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
 
 705                         if (constructorCall != null) {
 
 706                                 switch(constructorCall.accessMode) {
 
 707                                         case ExplicitConstructorCall.This :
 
 708                                                 requestor.acceptConstructorReference(
 
 709                                                         typeNames[nestedTypeIndex-1],
 
 710                                                         constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
 
 711                                                         constructorCall.sourceStart);
 
 713                                         case ExplicitConstructorCall.Super :
 
 714                                         case ExplicitConstructorCall.ImplicitSuper :                                    
 
 715                                                 requestor.acceptConstructorReference(
 
 716                                                         superTypeNames[nestedTypeIndex-1],
 
 717                                                         constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
 
 718                                                         constructorCall.sourceStart);
 
 725         char[][] argumentTypes = null;
 
 726         char[][] argumentNames = null;
 
 727         Argument[] arguments = methodDeclaration.arguments;
 
 728         if (arguments != null) {
 
 729                 int argumentLength = arguments.length;
 
 730                 argumentTypes = new char[argumentLength][];
 
 731                 argumentNames = new char[argumentLength][];
 
 732                 for (int i = 0; i < argumentLength; i++) {
 
 733                         argumentTypes[i] = returnTypeName(arguments[i].type);
 
 734                         argumentNames[i] = arguments[i].name;
 
 737         char[][] thrownExceptionTypes = null;
 
 738         TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
 
 739         if (thrownExceptions != null) {
 
 740                 int thrownExceptionLength = thrownExceptions.length;
 
 741                 thrownExceptionTypes = new char[thrownExceptionLength][];
 
 742                 for (int i = 0; i < thrownExceptionLength; i++) {
 
 743                         thrownExceptionTypes[i] = 
 
 744                                 CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.'); 
 
 747         // by default no selector end position
 
 748         int selectorSourceEnd = -1;
 
 749         if (methodDeclaration.isConstructor()) {
 
 750                 if (methodDeclaration instanceof SourceConstructorDeclaration) {
 
 752                                 ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd; 
 
 755                         requestor.enterConstructor(
 
 756                                 methodDeclaration.declarationSourceStart, 
 
 757                                 methodDeclaration.modifiers, 
 
 758                                 methodDeclaration.selector, 
 
 759                                 methodDeclaration.sourceStart, 
 
 763                                 thrownExceptionTypes);
 
 765                 if (reportReferenceInfo) {
 
 766                         ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
 
 767                         ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
 
 768                         if (constructorCall != null) {
 
 769                                 switch(constructorCall.accessMode) {
 
 770                                         case ExplicitConstructorCall.This :
 
 771                                                 requestor.acceptConstructorReference(
 
 772                                                         typeNames[nestedTypeIndex-1],
 
 773                                                         constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
 
 774                                                         constructorCall.sourceStart);
 
 776                                         case ExplicitConstructorCall.Super :
 
 777                                         case ExplicitConstructorCall.ImplicitSuper :
 
 778                                                 requestor.acceptConstructorReference(
 
 779                                                         superTypeNames[nestedTypeIndex-1],
 
 780                                                         constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
 
 781                                                         constructorCall.sourceStart);
 
 786                 this.visitIfNeeded(methodDeclaration);
 
 788                         requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
 
 792         if (methodDeclaration instanceof SourceMethodDeclaration) {
 
 794                         ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd; 
 
 797                 requestor.enterMethod(
 
 798                         methodDeclaration.declarationSourceStart, 
 
 799                         methodDeclaration.modifiers & AccJustFlag, 
 
 800                         returnTypeName(((MethodDeclaration) methodDeclaration).returnType), 
 
 801                         methodDeclaration.selector, 
 
 802                         methodDeclaration.sourceStart, 
 
 806                         thrownExceptionTypes); 
 
 808         this.visitIfNeeded(methodDeclaration);
 
 811                 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
 
 815 * Update the bodyStart of the corresponding parse node
 
 817 public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
 
 821                                 scanner.initialPosition <= fieldDeclaration.declarationSourceStart
 
 822                                 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
 
 824         if (fieldDeclaration.isField()) {
 
 825                 int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
 
 826                 if (fieldDeclaration instanceof SourceFieldDeclaration) {
 
 827                         fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
 
 828                         if (fieldEndPosition == 0) {
 
 829                                 // use the declaration source end by default
 
 830                                 fieldEndPosition = fieldDeclaration.declarationSourceEnd;
 
 834                         requestor.enterField(
 
 835                                 fieldDeclaration.declarationSourceStart, 
 
 836                                 fieldDeclaration.modifiers & AccJustFlag, 
 
 837                                 returnTypeName(fieldDeclaration.type), 
 
 838                                 fieldDeclaration.name, 
 
 839                                 fieldDeclaration.sourceStart, 
 
 840                                 fieldDeclaration.sourceEnd); 
 
 842                 this.visitIfNeeded(fieldDeclaration);
 
 844                         requestor.exitField(fieldEndPosition);
 
 849                         requestor.enterInitializer(
 
 850                                 fieldDeclaration.declarationSourceStart,
 
 851                                 fieldDeclaration.modifiers); 
 
 853                 this.visitIfNeeded((Initializer)fieldDeclaration);
 
 855                         requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
 
 859 public void notifySourceElementRequestor(
 
 860         ImportReference importReference, 
 
 863                 requestor.acceptPackage(
 
 864                         importReference.declarationSourceStart, 
 
 865                         importReference.declarationSourceEnd, 
 
 866                         CharOperation.concatWith(importReference.getImportName(), '.')); 
 
 868                 requestor.acceptImport(
 
 869                         importReference.declarationSourceStart, 
 
 870                         importReference.declarationSourceEnd, 
 
 871                         CharOperation.concatWith(importReference.getImportName(), '.'), 
 
 872                         importReference.onDemand); 
 
 875 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
 
 879                                 scanner.initialPosition <= typeDeclaration.declarationSourceStart
 
 880                                 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
 
 882         FieldDeclaration[] fields = typeDeclaration.fields;
 
 883         AbstractMethodDeclaration[] methods = typeDeclaration.methods;
 
 884         MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
 
 885         int fieldCount = fields == null ? 0 : fields.length;
 
 886         int methodCount = methods == null ? 0 : methods.length;
 
 887         int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
 
 890         int memberTypeIndex = 0;
 
 891         boolean isInterface = typeDeclaration.isInterface();
 
 893         if (notifyTypePresence){
 
 894                 char[][] interfaceNames = null;
 
 895                 int superInterfacesLength = 0;
 
 896                 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
 
 897                 if (superInterfaces != null) {
 
 898                         superInterfacesLength = superInterfaces.length;
 
 899                         interfaceNames = new char[superInterfacesLength][];
 
 901                         if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
 
 903                                 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation;
 
 904                                 if (alloc != null && alloc.type != null) {
 
 905                                         superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation.type};
 
 906                                         superInterfacesLength = 1;
 
 907                                         interfaceNames = new char[1][];
 
 911                 if (superInterfaces != null) {
 
 912                         for (int i = 0; i < superInterfacesLength; i++) {
 
 914                                         CharOperation.concatWith(superInterfaces[i].getTypeName(), '.'); 
 
 919                                 requestor.enterInterface(
 
 920                                         typeDeclaration.declarationSourceStart, 
 
 921                                         typeDeclaration.modifiers & AccJustFlag, 
 
 922                                         typeDeclaration.name, 
 
 923                                         typeDeclaration.sourceStart, 
 
 924                                         typeDeclaration.sourceEnd, 
 
 927                         if (nestedTypeIndex == typeNames.length) {
 
 929                                 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
 
 930                                 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
 
 932                         typeNames[nestedTypeIndex] = typeDeclaration.name;
 
 933                         superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
 
 935                         TypeReference superclass = typeDeclaration.superclass;
 
 936                         if (superclass == null) {
 
 938                                         requestor.enterClass(
 
 939                                                 typeDeclaration.declarationSourceStart, 
 
 940                                                 typeDeclaration.modifiers, 
 
 941                                                 typeDeclaration.name, 
 
 942                                                 typeDeclaration.sourceStart, 
 
 943                                                 typeDeclaration.sourceEnd, 
 
 949                                         requestor.enterClass(
 
 950                                                 typeDeclaration.declarationSourceStart, 
 
 951                                                 typeDeclaration.modifiers, 
 
 952                                                 typeDeclaration.name, 
 
 953                                                 typeDeclaration.sourceStart, 
 
 954                                                 typeDeclaration.sourceEnd, 
 
 955                                                 CharOperation.concatWith(superclass.getTypeName(), '.'), 
 
 959                         if (nestedTypeIndex == typeNames.length) {
 
 961                                 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
 
 962                                 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
 
 964                         typeNames[nestedTypeIndex] = typeDeclaration.name;
 
 965                         superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
 
 968         while ((fieldIndex < fieldCount)
 
 969                 || (memberTypeIndex < memberTypeCount)
 
 970                 || (methodIndex < methodCount)) {
 
 971                 FieldDeclaration nextFieldDeclaration = null;
 
 972                 AbstractMethodDeclaration nextMethodDeclaration = null;
 
 973                 TypeDeclaration nextMemberDeclaration = null;
 
 975                 int position = Integer.MAX_VALUE;
 
 976                 int nextDeclarationType = -1;
 
 977                 if (fieldIndex < fieldCount) {
 
 978                         nextFieldDeclaration = fields[fieldIndex];
 
 979                         if (nextFieldDeclaration.declarationSourceStart < position) {
 
 980                                 position = nextFieldDeclaration.declarationSourceStart;
 
 981                                 nextDeclarationType = 0; // FIELD
 
 984                 if (methodIndex < methodCount) {
 
 985                         nextMethodDeclaration = methods[methodIndex];
 
 986                         if (nextMethodDeclaration.declarationSourceStart < position) {
 
 987                                 position = nextMethodDeclaration.declarationSourceStart;
 
 988                                 nextDeclarationType = 1; // METHOD
 
 991                 if (memberTypeIndex < memberTypeCount) {
 
 992                         nextMemberDeclaration = memberTypes[memberTypeIndex];
 
 993                         if (nextMemberDeclaration.declarationSourceStart < position) {
 
 994                                 position = nextMemberDeclaration.declarationSourceStart;
 
 995                                 nextDeclarationType = 2; // MEMBER
 
 998                 switch (nextDeclarationType) {
 
1001                                 notifySourceElementRequestor(nextFieldDeclaration);
 
1005                                 notifySourceElementRequestor(nextMethodDeclaration);
 
1009                                 notifySourceElementRequestor(nextMemberDeclaration, true);
 
1012         if (notifyTypePresence){
 
1015                                 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
 
1017                                 requestor.exitClass(typeDeclaration.declarationSourceEnd);
 
1023 public void parseCompilationUnit(
 
1024         ICompilationUnit unit, 
 
1027         boolean needReferenceInfo) {
 
1029         reportReferenceInfo = needReferenceInfo;
 
1031         if (needReferenceInfo) {
 
1032                 unknownRefs = new NameReference[10];
 
1033                 unknownRefsCounter = 0;
 
1037                 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
 
1038                 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
 
1039                 if (needReferenceInfo){
 
1041                         this.getMethodBodies(parsedUnit);
 
1043                 this.scanner.resetTo(start, end);
 
1044                 notifySourceElementRequestor(parsedUnit);
 
1045         } catch (AbortCompilation e) {
 
1047                 if (scanner.recordLineSeparator) {
 
1048                         requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
 
1053 public void parseCompilationUnit(
 
1054         ICompilationUnit unit, 
 
1055         boolean needReferenceInfo) {
 
1057         if (needReferenceInfo) {
 
1058                 unknownRefs = new NameReference[10];
 
1059                 unknownRefsCounter = 0;
 
1063 /*              diet = !needReferenceInfo;
 
1064                 reportReferenceInfo = needReferenceInfo;
 
1065                 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
 
1066                 parse(unit, compilationUnitResult);             
 
1068                 reportReferenceInfo = needReferenceInfo;
 
1069                 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
 
1070                 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult);
 
1071                 int initialStart = this.scanner.initialPosition;
 
1072                 int initialEnd = this.scanner.eofPosition;
 
1073                 if (needReferenceInfo){
 
1075                         this.getMethodBodies(parsedUnit);
 
1077                 this.scanner.resetTo(initialStart, initialEnd);
 
1078                 notifySourceElementRequestor(parsedUnit);
 
1079         } catch (AbortCompilation e) {
 
1081                 if (scanner.recordLineSeparator) {
 
1082                         requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
 
1087 public void parseTypeMemberDeclarations(
 
1088         ISourceType sourceType, 
 
1089         ICompilationUnit sourceUnit, 
 
1092         boolean needReferenceInfo) {
 
1094         if (needReferenceInfo) {
 
1095                 unknownRefs = new NameReference[10];
 
1096                 unknownRefsCounter = 0;
 
1100                 diet = !needReferenceInfo;
 
1101                 reportReferenceInfo = needReferenceInfo;
 
1102                 CompilationResult compilationUnitResult = 
 
1103                         new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit); 
 
1104                 CompilationUnitDeclaration unit = 
 
1105                         SourceTypeConverter.buildCompilationUnit(
 
1106                                 new ISourceType[]{sourceType}, 
 
1110                                 compilationUnitResult); 
 
1111                 if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
 
1113                 this.sourceType = sourceType;
 
1115                         /* automaton initialization */
 
1117                         goForClassBodyDeclarations();
 
1118                         /* scanner initialization */
 
1119                         scanner.setSource(sourceUnit.getContents());
 
1120                         scanner.resetTo(start, end);
 
1122                         referenceContext = compilationUnit = unit;
 
1123                         /* initialize the astStacl */
 
1124                         // the compilationUnitDeclaration should contain exactly one type
 
1125                         pushOnAstStack(unit.types[0]);
 
1128                         notifySourceElementRequestor(unit);
 
1130                         unit = compilationUnit;
 
1131                         compilationUnit = null; // reset parser
 
1133         } catch (AbortCompilation e) {
 
1135                 if (scanner.recordLineSeparator) {
 
1136                         requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
 
1142 public void parseTypeMemberDeclarations(
 
1152                 /* automaton initialization */
 
1154                 goForClassBodyDeclarations();
 
1155                 /* scanner initialization */
 
1156                 scanner.setSource(contents);
 
1157                 scanner.recordLineSeparator = false;
 
1158                 scanner.resetTo(start, end);
 
1161                 referenceContext = null;
 
1163                 /* initialize the astStacl */
 
1164                 // the compilationUnitDeclaration should contain exactly one type
 
1167                 notifySourceElementRequestor((CompilationUnitDeclaration)null);
 
1168         } catch (AbortCompilation e) {
 
1174  * Sort the given ast nodes by their positions.
 
1176 private static void quickSort(AstNode[] sortedCollection, int left, int right) {
 
1177         int original_left = left;
 
1178         int original_right = right;
 
1179         AstNode mid = sortedCollection[ (left + right) / 2];
 
1181                 while (sortedCollection[left].sourceStart < mid.sourceStart) {
 
1184                 while (mid.sourceStart < sortedCollection[right].sourceStart) {
 
1187                 if (left <= right) {
 
1188                         AstNode tmp = sortedCollection[left];
 
1189                         sortedCollection[left] = sortedCollection[right];
 
1190                         sortedCollection[right] = tmp;
 
1194         } while (left <= right);
 
1195         if (original_left < right) {
 
1196                 quickSort(sortedCollection, original_left, right);
 
1198         if (left < original_right) {
 
1199                 quickSort(sortedCollection, left, original_right);
 
1203  * Answer a char array representation of the type name formatted like:
 
1204  * - type name + dimensions
 
1206  * "A[][]".toCharArray()
 
1207  * "java.lang.String".toCharArray()
 
1209 private char[] returnTypeName(TypeReference type) {
 
1212         int dimension = type.dimensions();
 
1213         if (dimension != 0) {
 
1214                 char[] dimensionsArray = new char[dimension * 2];
 
1215                 for (int i = 0; i < dimension; i++) {
 
1216                         dimensionsArray[i * 2] = '[';
 
1217                         dimensionsArray[(i * 2) + 1] = ']';
 
1219                 return CharOperation.concat(
 
1220                         CharOperation.concatWith(type.getTypeName(), '.'), 
 
1223         return CharOperation.concatWith(type.getTypeName(), '.');
 
1226 public void addUnknownRef(NameReference nameRef) {
 
1227         if (this.unknownRefs.length == this.unknownRefsCounter) {
 
1232                         (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
 
1234                         this.unknownRefsCounter);
 
1236         this.unknownRefs[this.unknownRefsCounter++] = nameRef;
 
1238 private TypeReference typeReference(
 
1240         int localIdentifierPtr, 
 
1241         int localIdentifierLengthPtr) {
 
1242         /* build a Reference on a variable that may be qualified or not
 
1243          * This variable is a type reference and dim will be its dimensions.
 
1244          * We don't have any side effect on the stacks' pointers.
 
1249         if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
 
1250                 // single variable reference
 
1253                                 new SingleTypeReference(
 
1254                                         identifierStack[localIdentifierPtr], 
 
1255                                         identifierPositionStack[localIdentifierPtr--]); 
 
1258                                 new ArrayTypeReference(
 
1259                                         identifierStack[localIdentifierPtr], 
 
1261                                         identifierPositionStack[localIdentifierPtr--]);
 
1262                         ref.sourceEnd = endPosition;                     
 
1265                 if (length < 0) { //flag for precompiled type reference on base types
 
1266                         ref = TypeReference.baseTypeReference(-length, dim);
 
1267                         ref.sourceStart = intStack[localIntPtr--];
 
1269                                 ref.sourceEnd = intStack[localIntPtr--];
 
1272                                 ref.sourceEnd = endPosition;
 
1274                 } else { //Qualified variable reference
 
1275                         char[][] tokens = new char[length][];
 
1276                         localIdentifierPtr -= length;
 
1277                         long[] positions = new long[length];
 
1278                         System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
 
1280                                 identifierPositionStack, 
 
1281                                 localIdentifierPtr + 1, 
 
1286                                 ref = new QualifiedTypeReference(tokens, positions);
 
1288                                 ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
 
1289                                 ref.sourceEnd = endPosition;
 
1296 private void visitIfNeeded(AbstractMethodDeclaration method) {
 
1297         if (this.localDeclarationVisitor != null 
 
1298                 && (method.bits & AstNode.HasLocalTypeMASK) != 0) {
 
1299                         if (method.statements != null) {
 
1300                                 int statementsLength = method.statements.length;
 
1301                                 for (int i = 0; i < statementsLength; i++)
 
1302                                         method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
 
1307 private void visitIfNeeded(FieldDeclaration field) {
 
1308         if (this.localDeclarationVisitor != null 
 
1309                 && (field.bits & AstNode.HasLocalTypeMASK) != 0) {
 
1310                         if (field.initialization != null) {
 
1311                                 field.initialization.traverse(this.localDeclarationVisitor, null);
 
1316 private void visitIfNeeded(Initializer initializer) {
 
1317         if (this.localDeclarationVisitor != null 
 
1318                 && (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
 
1319                         if (initializer.block != null) {
 
1320                                 initializer.block.traverse(this.localDeclarationVisitor, null);
 
1325 protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
 
1326         if (compilationUnit == null) return;
 
1327         super.reportSyntaxError(act, currentKind,stateStackTop);