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.internal.compiler.env.*;
 
  33 import net.sourceforge.phpdt.internal.compiler.impl.*;
 
  34 import net.sourceforge.phpdt.core.compiler.*;
 
  35 import net.sourceforge.phpdt.internal.compiler.ast.*;
 
  36 import net.sourceforge.phpdt.internal.compiler.lookup.*;
 
  37 import net.sourceforge.phpdt.internal.compiler.parser.*;
 
  38 import net.sourceforge.phpdt.internal.compiler.problem.*;
 
  39 import net.sourceforge.phpdt.internal.compiler.util.*;
 
  41 public class SourceElementParser extends Parser {
 
  43         ISourceElementRequestor requestor;
 
  44         private int fieldCount;
 
  45         private int localIntPtr;
 
  46         private int lastFieldEndPosition;
 
  47         private ISourceType sourceType;
 
  48         private boolean reportReferenceInfo;
 
  49         private char[][] typeNames;
 
  50         private char[][] superTypeNames;
 
  51         private int nestedTypeIndex;
 
  52         private static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
 
  53         private NameReference[] unknownRefs;
 
  54         private int unknownRefsCounter;
 
  55         private LocalDeclarationVisitor localDeclarationVisitor = null;
 
  56         private CompilerOptions options;
 
  59  * An ast visitor that visits local type declarations.
 
  61 public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
 
  63                         AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
 
  65                 notifySourceElementRequestor(anonymousTypeDeclaration, sourceType == null);
 
  66                 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
 
  68         public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
 
  69                 notifySourceElementRequestor(typeDeclaration, sourceType == null);
 
  70                 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
 
  72         public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
 
  73                 notifySourceElementRequestor(typeDeclaration, sourceType == null);
 
  74                 return false; // don't visit members as this was done during notifySourceElementRequestor(...)
 
  79 public SourceElementParser(
 
  80         final ISourceElementRequestor requestor, 
 
  81         IProblemFactory problemFactory,
 
  82         CompilerOptions options) {
 
  83         // we want to notify all syntax error with the acceptProblem API
 
  84         // To do so, we define the record method of the ProblemReporter
 
  85         super(new ProblemReporter(
 
  86                 DefaultErrorHandlingPolicies.exitAfterAllProblems(),
 
  89                 public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
 
  90                         unitResult.record(problem, referenceContext);
 
  91                         requestor.acceptProblem(problem);
 
  96         this.requestor = requestor;
 
  97         typeNames = new char[4][];
 
  98         superTypeNames = new char[4][];
 
 100         this.options = options;
 
 103 /** @deprecated use SourceElementParser(ISourceElementRequestor, IProblemFactory, CompilerOptions) */
 
 104 public SourceElementParser(
 
 105         final ISourceElementRequestor requestor, 
 
 106         IProblemFactory problemFactory) {
 
 107                 this(requestor, problemFactory, new CompilerOptions());
 
 110 public SourceElementParser(
 
 111         final ISourceElementRequestor requestor, 
 
 112         IProblemFactory problemFactory,
 
 113         CompilerOptions options,
 
 114         boolean reportLocalDeclarations) {
 
 115                 this(requestor, problemFactory, options);
 
 116                 if (reportLocalDeclarations) {
 
 117                         this.localDeclarationVisitor = new LocalDeclarationVisitor();
 
 121 public void checkAnnotation() {
 
 122         int firstCommentIndex = scanner.commentPtr;
 
 124         super.checkAnnotation();
 
 126         // modify the modifier source start to point at the first comment
 
 127         if (firstCommentIndex >= 0) {
 
 128                 modifiersSourceStart = scanner.commentStarts[0]; 
 
 132 protected void classInstanceCreation(boolean alwaysQualified) {
 
 134         boolean previousFlag = reportReferenceInfo;
 
 135         reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
 
 136         super.classInstanceCreation(alwaysQualified);
 
 137         reportReferenceInfo = previousFlag;
 
 138         if (reportReferenceInfo){
 
 139                 AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
 
 140                 TypeReference typeRef = alloc.type;
 
 141                 requestor.acceptConstructorReference(
 
 142                         typeRef instanceof SingleTypeReference 
 
 143                                 ? ((SingleTypeReference) typeRef).token
 
 144                                 : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
 
 145                         alloc.arguments == null ? 0 : alloc.arguments.length, 
 
 149 protected void consumeConstructorHeaderName() {
 
 150         // ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
 
 152         /* recovering - might be an empty message send */
 
 153         if (currentElement != null){
 
 154                 if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
 
 155                         lastCheckPoint = scanner.startPosition; // force to restart at this exact position                              
 
 156                         restartRecovery = true;
 
 160         SourceConstructorDeclaration cd = new SourceConstructorDeclaration(this.compilationUnit.compilationResult);
 
 162         //name -- this is not really revelant but we do .....
 
 163         cd.selector = identifierStack[identifierPtr];
 
 164         long selectorSourcePositions = identifierPositionStack[identifierPtr--];
 
 165         identifierLengthPtr--;
 
 168         cd.declarationSourceStart = intStack[intPtr--];
 
 169         cd.modifiers = intStack[intPtr--];
 
 171         //highlight starts at the selector starts
 
 172         cd.sourceStart = (int) (selectorSourcePositions >>> 32);
 
 173         cd.selectorSourceEnd = (int) selectorSourcePositions;
 
 176         cd.sourceEnd = lParenPos;
 
 177         cd.bodyStart = lParenPos+1;
 
 178         listLength = 0; // initialize listLength before reading parameters/throws
 
 181         if (currentElement != null){
 
 182                 lastCheckPoint = cd.bodyStart;
 
 183                 if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
 
 184                         || cd.modifiers != 0){
 
 185                         currentElement = currentElement.add(cd, 0);
 
 186                         lastIgnoredToken = -1;
 
 194 protected void consumeExitVariableWithInitialization() {
 
 195         // ExitVariableWithInitialization ::= $empty
 
 196         // the scanner is located after the comma or the semi-colon.
 
 197         // we want to include the comma or the semi-colon
 
 198         super.consumeExitVariableWithInitialization();
 
 199         if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
 
 201         ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
 
 203 protected void consumeExitVariableWithoutInitialization() {
 
 204         // ExitVariableWithoutInitialization ::= $empty
 
 205         // do nothing by default
 
 206         if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
 
 208         ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
 
 214 protected void consumeFieldAccess(boolean isSuperAccess) {
 
 215         // FieldAccess ::= Primary '.' 'Identifier'
 
 216         // FieldAccess ::= 'super' '.' 'Identifier'
 
 217         super.consumeFieldAccess(isSuperAccess);
 
 218         FieldReference fr = (FieldReference) expressionStack[expressionPtr];
 
 219         if (reportReferenceInfo) {
 
 220                 requestor.acceptFieldReference(fr.token, fr.sourceStart);
 
 223 protected void consumeMethodHeaderName() {
 
 224         // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
 
 225         SourceMethodDeclaration md = new SourceMethodDeclaration(this.compilationUnit.compilationResult);
 
 228         md.selector = identifierStack[identifierPtr];
 
 229         long selectorSourcePositions = identifierPositionStack[identifierPtr--];
 
 230         identifierLengthPtr--;
 
 232         md.returnType = getTypeReference(intStack[intPtr--]);
 
 234         md.declarationSourceStart = intStack[intPtr--];
 
 235         md.modifiers = intStack[intPtr--];
 
 237         //highlight starts at selector start
 
 238         md.sourceStart = (int) (selectorSourcePositions >>> 32);
 
 239         md.selectorSourceEnd = (int) selectorSourcePositions;
 
 241         md.sourceEnd = lParenPos;
 
 242         md.bodyStart = lParenPos+1;
 
 243         listLength = 0; // initialize listLength before reading parameters/throws
 
 246         if (currentElement != null){
 
 247                 if (currentElement instanceof RecoveredType 
 
 248                         //|| md.modifiers != 0
 
 249                         || (scanner.getLineNumber(md.returnType.sourceStart)
 
 250                                         == scanner.getLineNumber(md.sourceStart))){
 
 251                         lastCheckPoint = md.bodyStart;
 
 252                         currentElement = currentElement.add(md, 0);
 
 253                         lastIgnoredToken = -1;                  
 
 255                         lastCheckPoint = md.sourceStart;
 
 256                         restartRecovery = true;
 
 264 protected void consumeMethodInvocationName() {
 
 265         // MethodInvocation ::= Name '(' ArgumentListopt ')'
 
 267         // when the name is only an identifier...we have a message send to "this" (implicit)
 
 268         super.consumeMethodInvocationName();
 
 269         MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
 
 270         Expression[] args = messageSend.arguments;
 
 271         if (reportReferenceInfo) {
 
 272                 requestor.acceptMethodReference(
 
 273                         messageSend.selector, 
 
 274                         args == null ? 0 : args.length, 
 
 275                         (int)(messageSend.nameSourcePosition >>> 32));
 
 282 protected void consumeMethodInvocationPrimary() {
 
 283         super.consumeMethodInvocationPrimary();
 
 284         MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
 
 285         Expression[] args = messageSend.arguments;
 
 286         if (reportReferenceInfo) {
 
 287                 requestor.acceptMethodReference(
 
 288                         messageSend.selector, 
 
 289                         args == null ? 0 : args.length, 
 
 290                         (int)(messageSend.nameSourcePosition >>> 32));
 
 297 protected void consumeMethodInvocationSuper() {
 
 298         // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
 
 299         super.consumeMethodInvocationSuper();
 
 300         MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
 
 301         Expression[] args = messageSend.arguments;
 
 302         if (reportReferenceInfo) {
 
 303                 requestor.acceptMethodReference(
 
 304                         messageSend.selector, 
 
 305                         args == null ? 0 : args.length, 
 
 306                         (int)(messageSend.nameSourcePosition >>> 32));
 
 309 protected void consumeSingleTypeImportDeclarationName() {
 
 310         // SingleTypeImportDeclarationName ::= 'import' Name
 
 311         /* push an ImportRef build from the last name 
 
 312         stored in the identifier stack. */
 
 314         super.consumeSingleTypeImportDeclarationName();
 
 315         ImportReference impt = (ImportReference)astStack[astPtr];
 
 316         if (reportReferenceInfo) {
 
 317                 requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
 
 320 protected void consumeTypeImportOnDemandDeclarationName() {
 
 321         // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
 
 322         /* push an ImportRef build from the last name 
 
 323         stored in the identifier stack. */
 
 325         super.consumeTypeImportOnDemandDeclarationName();
 
 326         ImportReference impt = (ImportReference)astStack[astPtr];
 
 327         if (reportReferenceInfo) {
 
 328                 requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
 
 331 protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
 
 332         return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
 
 334 protected CompilationUnitDeclaration endParse(int act) {
 
 335         if (sourceType != null) {
 
 336                 if (sourceType.isInterface()) {
 
 337                         consumeInterfaceDeclaration();
 
 339                         consumeClassDeclaration();
 
 342         if (compilationUnit != null) {
 
 343                 CompilationUnitDeclaration result = super.endParse(act);
 
 350  * Flush annotations defined prior to a given positions.
 
 352  * Note: annotations are stacked in syntactical order
 
 354  * Either answer given <position>, or the end position of a comment line 
 
 355  * immediately following the <position> (same line)
 
 359  * } // end of method foo
 
 362 public int flushAnnotationsDefinedPriorTo(int position) {
 
 364         return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
 
 366 public TypeReference getTypeReference(int dim) {
 
 367         /* build a Reference on a variable that may be qualified or not
 
 368          * This variable is a type reference and dim will be its dimensions
 
 371         if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
 
 372                 // single variable reference
 
 374                         SingleTypeReference ref = 
 
 375                                 new SingleTypeReference(
 
 376                                         identifierStack[identifierPtr], 
 
 377                                         identifierPositionStack[identifierPtr--]);
 
 378                         if (reportReferenceInfo) {
 
 379                                 requestor.acceptTypeReference(ref.token, ref.sourceStart);
 
 383                         ArrayTypeReference ref = 
 
 384                                 new ArrayTypeReference(
 
 385                                         identifierStack[identifierPtr], 
 
 387                                         identifierPositionStack[identifierPtr--]); 
 
 388                         ref.sourceEnd = endPosition;
 
 389                         if (reportReferenceInfo) {
 
 390                                 requestor.acceptTypeReference(ref.token, ref.sourceStart);
 
 395                 if (length < 0) { //flag for precompiled type reference on base types
 
 396                         TypeReference ref = TypeReference.baseTypeReference(-length, dim);
 
 397                         ref.sourceStart = intStack[intPtr--];
 
 399                                 ref.sourceEnd = intStack[intPtr--];
 
 401                                 intPtr--; // no need to use this position as it is an array
 
 402                                 ref.sourceEnd = endPosition;
 
 404                         if (reportReferenceInfo){
 
 405                                         requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
 
 408                 } else { //Qualified variable reference
 
 409                         char[][] tokens = new char[length][];
 
 410                         identifierPtr -= length;
 
 411                         long[] positions = new long[length];
 
 412                         System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
 
 414                                 identifierPositionStack, 
 
 420                                 QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
 
 421                                 if (reportReferenceInfo) {
 
 422                                         requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
 
 426                                 ArrayQualifiedTypeReference ref = 
 
 427                                         new ArrayQualifiedTypeReference(tokens, dim, positions); 
 
 428                                 ref.sourceEnd = endPosition;                                    
 
 429                                 if (reportReferenceInfo) {
 
 430                                         requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
 
 437 public NameReference getUnspecifiedReference() {
 
 438         /* build a (unspecified) NameReference which may be qualified*/
 
 441         if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
 
 442                 // single variable reference
 
 443                 SingleNameReference ref = 
 
 444                         new SingleNameReference(
 
 445                                 identifierStack[identifierPtr], 
 
 446                                 identifierPositionStack[identifierPtr--]); 
 
 447                 if (reportReferenceInfo) {
 
 448                         this.addUnknownRef(ref);
 
 452                 //Qualified variable reference
 
 453                 char[][] tokens = new char[length][];
 
 454                 identifierPtr -= length;
 
 455                 System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
 
 456                 QualifiedNameReference ref = 
 
 457                         new QualifiedNameReference(
 
 459                                 (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
 
 460                                 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
 
 461                 if (reportReferenceInfo) {
 
 462                         this.addUnknownRef(ref);
 
 467 public NameReference getUnspecifiedReferenceOptimized() {
 
 468         /* build a (unspecified) NameReference which may be qualified
 
 469         The optimization occurs for qualified reference while we are
 
 470         certain in this case the last item of the qualified name is
 
 471         a field access. This optimization is IMPORTANT while it results
 
 472         that when a NameReference is build, the type checker should always
 
 473         look for that it is not a type reference */
 
 476         if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
 
 477                 // single variable reference
 
 478                 SingleNameReference ref = 
 
 479                         new SingleNameReference(
 
 480                                 identifierStack[identifierPtr], 
 
 481                                 identifierPositionStack[identifierPtr--]); 
 
 482                 ref.bits &= ~AstNode.RestrictiveFlagMASK;
 
 483                 ref.bits |= LOCAL | FIELD;
 
 484                 if (reportReferenceInfo) {
 
 485                         this.addUnknownRef(ref);
 
 490         //Qualified-variable-reference
 
 491         //In fact it is variable-reference DOT field-ref , but it would result in a type
 
 492         //conflict tha can be only reduce by making a superclass (or inetrface ) between
 
 493         //nameReference and FiledReference or putting FieldReference under NameReference
 
 494         //or else..........This optimisation is not really relevant so just leave as it is
 
 496         char[][] tokens = new char[length][];
 
 497         identifierPtr -= length;
 
 498         System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
 
 499         QualifiedNameReference ref = 
 
 500                 new QualifiedNameReference(
 
 502                         (int) (identifierPositionStack[identifierPtr + 1] >> 32), 
 
 504          (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
 
 505         ref.bits &= ~AstNode.RestrictiveFlagMASK;
 
 506         ref.bits |= LOCAL | FIELD;
 
 507         if (reportReferenceInfo) {
 
 508                 this.addUnknownRef(ref);
 
 516 private boolean isLocalDeclaration() {
 
 517         int nestedDepth = nestedType;
 
 518         while (nestedDepth >= 0) {
 
 519                 if (nestedMethod[nestedDepth] != 0) {
 
 527  * Update the bodyStart of the corresponding parse node
 
 529 public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
 
 530         if (parsedUnit == null) {
 
 531                 // when we parse a single type member declaration the compilation unit is null, but we still
 
 532                 // want to be able to notify the requestor on the created ast node
 
 533                 if (astStack[0] instanceof AbstractMethodDeclaration) {
 
 534                         notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
 
 541                                 scanner.initialPosition <= parsedUnit.sourceStart
 
 542                                 && scanner.eofPosition >= parsedUnit.sourceEnd;
 
 544         if (reportReferenceInfo) {
 
 545                 notifyAllUnknownReferences();
 
 547         // collect the top level ast nodes
 
 549         AstNode[] nodes = null;
 
 550         if (sourceType == null){
 
 552                         requestor.enterCompilationUnit();
 
 554                 ImportReference currentPackage = parsedUnit.currentPackage;
 
 555                 ImportReference[] imports = parsedUnit.imports;
 
 556                 TypeDeclaration[] types = parsedUnit.types;
 
 558                         (currentPackage == null ? 0 : 1) 
 
 559                         + (imports == null ? 0 : imports.length)
 
 560                         + (types == null ? 0 : types.length);
 
 561                 nodes = new AstNode[length];
 
 563                 if (currentPackage != null) {
 
 564                         nodes[index++] = currentPackage;
 
 566                 if (imports != null) {
 
 567                         for (int i = 0, max = imports.length; i < max; i++) {
 
 568                                 nodes[index++] = imports[i];
 
 572                         for (int i = 0, max = types.length; i < max; i++) {
 
 573                                 nodes[index++] = types[i];
 
 577                 TypeDeclaration[] types = parsedUnit.types;
 
 579                         length = types.length;
 
 580                         nodes = new AstNode[length];
 
 581                         for (int i = 0, max = types.length; i < max; i++) {
 
 587         // notify the nodes in the syntactical order
 
 588         if (nodes != null && length > 0) {
 
 589                 quickSort(nodes, 0, length-1);
 
 590                 for (int i=0;i<length;i++) {
 
 591                         AstNode node = nodes[i];
 
 592                         if (node instanceof ImportReference) {
 
 593                                 ImportReference importRef = (ImportReference)node;
 
 594                                 if (node == parsedUnit.currentPackage) {
 
 595                                         notifySourceElementRequestor(importRef, true);
 
 597                                         notifySourceElementRequestor(importRef, false);
 
 599                         } else { // instanceof TypeDeclaration
 
 600                                 notifySourceElementRequestor((TypeDeclaration)node, sourceType == null);
 
 605         if (sourceType == null){
 
 607                         requestor.exitCompilationUnit(parsedUnit.sourceEnd);
 
 612 private void notifyAllUnknownReferences() {
 
 613         for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
 
 614                 NameReference nameRef = this.unknownRefs[i];
 
 615                 if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
 
 616                         if ((nameRef.bits & BindingIds.TYPE) == 0) { 
 
 617                                 // variable but not type
 
 618                                 if (nameRef instanceof SingleNameReference) { 
 
 619                                         // local var or field
 
 620                                         requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
 
 622                                         // QualifiedNameReference
 
 623                                         // The last token is a field reference and the previous tokens are a type/variable references
 
 624                                         char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
 
 625                                         int tokensLength = tokens.length;
 
 626                                         requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd - tokens[tokensLength - 1].length + 1);
 
 627                                         char[][] typeRef = new char[tokensLength - 1][];
 
 628                                         System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
 
 629                                         requestor.acceptUnknownReference(typeRef, nameRef.sourceStart, nameRef.sourceEnd - tokens[tokensLength - 1].length);
 
 633                                 if (nameRef instanceof SingleNameReference) {
 
 634                                         requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
 
 636                                         //QualifiedNameReference
 
 637                                         requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
 
 640                 } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
 
 641                         if (nameRef instanceof SingleNameReference) {
 
 642                                 requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
 
 644                                 // it is a QualifiedNameReference
 
 645                                 requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
 
 651  * Update the bodyStart of the corresponding parse node
 
 653 public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
 
 657                                 scanner.initialPosition <= methodDeclaration.declarationSourceStart
 
 658                                 && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
 
 660         if (methodDeclaration.isClinit()) {
 
 661                 this.visitIfNeeded(methodDeclaration);
 
 665         if (methodDeclaration.isDefaultConstructor()) {
 
 666                 if (reportReferenceInfo) {
 
 667                         ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
 
 668                         ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
 
 669                         if (constructorCall != null) {
 
 670                                 switch(constructorCall.accessMode) {
 
 671                                         case ExplicitConstructorCall.This :
 
 672                                                 requestor.acceptConstructorReference(
 
 673                                                         typeNames[nestedTypeIndex-1],
 
 674                                                         constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
 
 675                                                         constructorCall.sourceStart);
 
 677                                         case ExplicitConstructorCall.Super :
 
 678                                         case ExplicitConstructorCall.ImplicitSuper :                                    
 
 679                                                 requestor.acceptConstructorReference(
 
 680                                                         superTypeNames[nestedTypeIndex-1],
 
 681                                                         constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
 
 682                                                         constructorCall.sourceStart);
 
 689         char[][] argumentTypes = null;
 
 690         char[][] argumentNames = null;
 
 691         Argument[] arguments = methodDeclaration.arguments;
 
 692         if (arguments != null) {
 
 693                 int argumentLength = arguments.length;
 
 694                 argumentTypes = new char[argumentLength][];
 
 695                 argumentNames = new char[argumentLength][];
 
 696                 for (int i = 0; i < argumentLength; i++) {
 
 697                         argumentTypes[i] = returnTypeName(arguments[i].type);
 
 698                         argumentNames[i] = arguments[i].name;
 
 701         char[][] thrownExceptionTypes = null;
 
 702         TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
 
 703         if (thrownExceptions != null) {
 
 704                 int thrownExceptionLength = thrownExceptions.length;
 
 705                 thrownExceptionTypes = new char[thrownExceptionLength][];
 
 706                 for (int i = 0; i < thrownExceptionLength; i++) {
 
 707                         thrownExceptionTypes[i] = 
 
 708                                 CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.'); 
 
 711         // by default no selector end position
 
 712         int selectorSourceEnd = -1;
 
 713         if (methodDeclaration.isConstructor()) {
 
 714                 if (methodDeclaration instanceof SourceConstructorDeclaration) {
 
 716                                 ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd; 
 
 719                         requestor.enterConstructor(
 
 720                                 methodDeclaration.declarationSourceStart, 
 
 721                                 methodDeclaration.modifiers, 
 
 722                                 methodDeclaration.selector, 
 
 723                                 methodDeclaration.sourceStart, 
 
 727                                 thrownExceptionTypes);
 
 729                 if (reportReferenceInfo) {
 
 730                         ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
 
 731                         ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
 
 732                         if (constructorCall != null) {
 
 733                                 switch(constructorCall.accessMode) {
 
 734                                         case ExplicitConstructorCall.This :
 
 735                                                 requestor.acceptConstructorReference(
 
 736                                                         typeNames[nestedTypeIndex-1],
 
 737                                                         constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
 
 738                                                         constructorCall.sourceStart);
 
 740                                         case ExplicitConstructorCall.Super :
 
 741                                         case ExplicitConstructorCall.ImplicitSuper :
 
 742                                                 requestor.acceptConstructorReference(
 
 743                                                         superTypeNames[nestedTypeIndex-1],
 
 744                                                         constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
 
 745                                                         constructorCall.sourceStart);
 
 750                 this.visitIfNeeded(methodDeclaration);
 
 752                         requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
 
 756         if (methodDeclaration instanceof SourceMethodDeclaration) {
 
 758                         ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd; 
 
 761                 requestor.enterMethod(
 
 762                         methodDeclaration.declarationSourceStart, 
 
 763                         methodDeclaration.modifiers & AccJustFlag, 
 
 764                         returnTypeName(((MethodDeclaration) methodDeclaration).returnType), 
 
 765                         methodDeclaration.selector, 
 
 766                         methodDeclaration.sourceStart, 
 
 770                         thrownExceptionTypes); 
 
 772         this.visitIfNeeded(methodDeclaration);
 
 775                 requestor.exitMethod(methodDeclaration.declarationSourceEnd);
 
 779 * Update the bodyStart of the corresponding parse node
 
 781 public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
 
 785                                 scanner.initialPosition <= fieldDeclaration.declarationSourceStart
 
 786                                 && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
 
 788         if (fieldDeclaration.isField()) {
 
 789                 int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
 
 790                 if (fieldDeclaration instanceof SourceFieldDeclaration) {
 
 791                         fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
 
 792                         if (fieldEndPosition == 0) {
 
 793                                 // use the declaration source end by default
 
 794                                 fieldEndPosition = fieldDeclaration.declarationSourceEnd;
 
 798                         requestor.enterField(
 
 799                                 fieldDeclaration.declarationSourceStart, 
 
 800                                 fieldDeclaration.modifiers & AccJustFlag, 
 
 801                                 returnTypeName(fieldDeclaration.type), 
 
 802                                 fieldDeclaration.name, 
 
 803                                 fieldDeclaration.sourceStart, 
 
 804                                 fieldDeclaration.sourceEnd); 
 
 806                 this.visitIfNeeded(fieldDeclaration);
 
 808                         requestor.exitField(fieldEndPosition);
 
 813                         requestor.enterInitializer(
 
 814                                 fieldDeclaration.declarationSourceStart,
 
 815                                 fieldDeclaration.modifiers); 
 
 817                 this.visitIfNeeded((Initializer)fieldDeclaration);
 
 819                         requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
 
 823 public void notifySourceElementRequestor(
 
 824         ImportReference importReference, 
 
 827                 requestor.acceptPackage(
 
 828                         importReference.declarationSourceStart, 
 
 829                         importReference.declarationSourceEnd, 
 
 830                         CharOperation.concatWith(importReference.getImportName(), '.')); 
 
 832                 requestor.acceptImport(
 
 833                         importReference.declarationSourceStart, 
 
 834                         importReference.declarationSourceEnd, 
 
 835                         CharOperation.concatWith(importReference.getImportName(), '.'), 
 
 836                         importReference.onDemand); 
 
 839 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
 
 843                                 scanner.initialPosition <= typeDeclaration.declarationSourceStart
 
 844                                 && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
 
 846         FieldDeclaration[] fields = typeDeclaration.fields;
 
 847         AbstractMethodDeclaration[] methods = typeDeclaration.methods;
 
 848         MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
 
 849         int fieldCount = fields == null ? 0 : fields.length;
 
 850         int methodCount = methods == null ? 0 : methods.length;
 
 851         int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
 
 854         int memberTypeIndex = 0;
 
 855         boolean isInterface = typeDeclaration.isInterface();
 
 857         if (notifyTypePresence){
 
 858                 char[][] interfaceNames = null;
 
 859                 int superInterfacesLength = 0;
 
 860                 TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
 
 861                 if (superInterfaces != null) {
 
 862                         superInterfacesLength = superInterfaces.length;
 
 863                         interfaceNames = new char[superInterfacesLength][];
 
 865                         if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
 
 867                                 QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation;
 
 868                                 if (alloc != null && alloc.type != null) {
 
 869                                         superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation.type};
 
 870                                         superInterfacesLength = 1;
 
 871                                         interfaceNames = new char[1][];
 
 875                 if (superInterfaces != null) {
 
 876                         for (int i = 0; i < superInterfacesLength; i++) {
 
 878                                         CharOperation.concatWith(superInterfaces[i].getTypeName(), '.'); 
 
 883                                 requestor.enterInterface(
 
 884                                         typeDeclaration.declarationSourceStart, 
 
 885                                         typeDeclaration.modifiers & AccJustFlag, 
 
 886                                         typeDeclaration.name, 
 
 887                                         typeDeclaration.sourceStart, 
 
 888                                         typeDeclaration.sourceEnd, 
 
 891                         if (nestedTypeIndex == typeNames.length) {
 
 893                                 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
 
 894                                 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
 
 896                         typeNames[nestedTypeIndex] = typeDeclaration.name;
 
 897                         superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
 
 899                         TypeReference superclass = typeDeclaration.superclass;
 
 900                         if (superclass == null) {
 
 902                                         requestor.enterClass(
 
 903                                                 typeDeclaration.declarationSourceStart, 
 
 904                                                 typeDeclaration.modifiers, 
 
 905                                                 typeDeclaration.name, 
 
 906                                                 typeDeclaration.sourceStart, 
 
 907                                                 typeDeclaration.sourceEnd, 
 
 913                                         requestor.enterClass(
 
 914                                                 typeDeclaration.declarationSourceStart, 
 
 915                                                 typeDeclaration.modifiers, 
 
 916                                                 typeDeclaration.name, 
 
 917                                                 typeDeclaration.sourceStart, 
 
 918                                                 typeDeclaration.sourceEnd, 
 
 919                                                 CharOperation.concatWith(superclass.getTypeName(), '.'), 
 
 923                         if (nestedTypeIndex == typeNames.length) {
 
 925                                 System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
 
 926                                 System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
 
 928                         typeNames[nestedTypeIndex] = typeDeclaration.name;
 
 929                         superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
 
 932         while ((fieldIndex < fieldCount)
 
 933                 || (memberTypeIndex < memberTypeCount)
 
 934                 || (methodIndex < methodCount)) {
 
 935                 FieldDeclaration nextFieldDeclaration = null;
 
 936                 AbstractMethodDeclaration nextMethodDeclaration = null;
 
 937                 TypeDeclaration nextMemberDeclaration = null;
 
 939                 int position = Integer.MAX_VALUE;
 
 940                 int nextDeclarationType = -1;
 
 941                 if (fieldIndex < fieldCount) {
 
 942                         nextFieldDeclaration = fields[fieldIndex];
 
 943                         if (nextFieldDeclaration.declarationSourceStart < position) {
 
 944                                 position = nextFieldDeclaration.declarationSourceStart;
 
 945                                 nextDeclarationType = 0; // FIELD
 
 948                 if (methodIndex < methodCount) {
 
 949                         nextMethodDeclaration = methods[methodIndex];
 
 950                         if (nextMethodDeclaration.declarationSourceStart < position) {
 
 951                                 position = nextMethodDeclaration.declarationSourceStart;
 
 952                                 nextDeclarationType = 1; // METHOD
 
 955                 if (memberTypeIndex < memberTypeCount) {
 
 956                         nextMemberDeclaration = memberTypes[memberTypeIndex];
 
 957                         if (nextMemberDeclaration.declarationSourceStart < position) {
 
 958                                 position = nextMemberDeclaration.declarationSourceStart;
 
 959                                 nextDeclarationType = 2; // MEMBER
 
 962                 switch (nextDeclarationType) {
 
 965                                 notifySourceElementRequestor(nextFieldDeclaration);
 
 969                                 notifySourceElementRequestor(nextMethodDeclaration);
 
 973                                 notifySourceElementRequestor(nextMemberDeclaration, true);
 
 976         if (notifyTypePresence){
 
 979                                 requestor.exitInterface(typeDeclaration.declarationSourceEnd);
 
 981                                 requestor.exitClass(typeDeclaration.declarationSourceEnd);
 
 987 public void parseCompilationUnit(
 
 988         ICompilationUnit unit, 
 
 991         boolean needReferenceInfo) {
 
 993         reportReferenceInfo = needReferenceInfo;
 
 995         if (needReferenceInfo) {
 
 996                 unknownRefs = new NameReference[10];
 
 997                 unknownRefsCounter = 0;
 
1001                 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
 
1002                 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
 
1003                 if (needReferenceInfo){
 
1005                         this.getMethodBodies(parsedUnit);
 
1007                 this.scanner.resetTo(start, end);
 
1008                 notifySourceElementRequestor(parsedUnit);
 
1009         } catch (AbortCompilation e) {
 
1011                 if (scanner.recordLineSeparator) {
 
1012                         requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
 
1017 public void parseCompilationUnit(
 
1018         ICompilationUnit unit, 
 
1019         boolean needReferenceInfo) {
 
1021         if (needReferenceInfo) {
 
1022                 unknownRefs = new NameReference[10];
 
1023                 unknownRefsCounter = 0;
 
1027 /*              diet = !needReferenceInfo;
 
1028                 reportReferenceInfo = needReferenceInfo;
 
1029                 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
 
1030                 parse(unit, compilationUnitResult);             
 
1032                 reportReferenceInfo = needReferenceInfo;
 
1033                 CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
 
1034                 CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult);
 
1035                 int initialStart = this.scanner.initialPosition;
 
1036                 int initialEnd = this.scanner.eofPosition;
 
1037                 if (needReferenceInfo){
 
1039                         this.getMethodBodies(parsedUnit);
 
1041                 this.scanner.resetTo(initialStart, initialEnd);
 
1042                 notifySourceElementRequestor(parsedUnit);
 
1043         } catch (AbortCompilation e) {
 
1045                 if (scanner.recordLineSeparator) {
 
1046                         requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
 
1051 public void parseTypeMemberDeclarations(
 
1052         ISourceType sourceType, 
 
1053         ICompilationUnit sourceUnit, 
 
1056         boolean needReferenceInfo) {
 
1058         if (needReferenceInfo) {
 
1059                 unknownRefs = new NameReference[10];
 
1060                 unknownRefsCounter = 0;
 
1064                 diet = !needReferenceInfo;
 
1065                 reportReferenceInfo = needReferenceInfo;
 
1066                 CompilationResult compilationUnitResult = 
 
1067                         new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit); 
 
1068                 CompilationUnitDeclaration unit = 
 
1069                         SourceTypeConverter.buildCompilationUnit(
 
1070                                 new ISourceType[]{sourceType}, 
 
1074                                 compilationUnitResult); 
 
1075                 if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
 
1077                 this.sourceType = sourceType;
 
1079                         /* automaton initialization */
 
1081                         goForClassBodyDeclarations();
 
1082                         /* scanner initialization */
 
1083                         scanner.setSource(sourceUnit.getContents());
 
1084                         scanner.resetTo(start, end);
 
1086                         referenceContext = compilationUnit = unit;
 
1087                         /* initialize the astStacl */
 
1088                         // the compilationUnitDeclaration should contain exactly one type
 
1089                         pushOnAstStack(unit.types[0]);
 
1092                         notifySourceElementRequestor(unit);
 
1094                         unit = compilationUnit;
 
1095                         compilationUnit = null; // reset parser
 
1097         } catch (AbortCompilation e) {
 
1099                 if (scanner.recordLineSeparator) {
 
1100                         requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
 
1106 public void parseTypeMemberDeclarations(
 
1116                 /* automaton initialization */
 
1118                 goForClassBodyDeclarations();
 
1119                 /* scanner initialization */
 
1120                 scanner.setSource(contents);
 
1121                 scanner.recordLineSeparator = false;
 
1122                 scanner.resetTo(start, end);
 
1125                 referenceContext = null;
 
1127                 /* initialize the astStacl */
 
1128                 // the compilationUnitDeclaration should contain exactly one type
 
1131                 notifySourceElementRequestor((CompilationUnitDeclaration)null);
 
1132         } catch (AbortCompilation e) {
 
1138  * Sort the given ast nodes by their positions.
 
1140 private static void quickSort(AstNode[] sortedCollection, int left, int right) {
 
1141         int original_left = left;
 
1142         int original_right = right;
 
1143         AstNode mid = sortedCollection[ (left + right) / 2];
 
1145                 while (sortedCollection[left].sourceStart < mid.sourceStart) {
 
1148                 while (mid.sourceStart < sortedCollection[right].sourceStart) {
 
1151                 if (left <= right) {
 
1152                         AstNode tmp = sortedCollection[left];
 
1153                         sortedCollection[left] = sortedCollection[right];
 
1154                         sortedCollection[right] = tmp;
 
1158         } while (left <= right);
 
1159         if (original_left < right) {
 
1160                 quickSort(sortedCollection, original_left, right);
 
1162         if (left < original_right) {
 
1163                 quickSort(sortedCollection, left, original_right);
 
1167  * Answer a char array representation of the type name formatted like:
 
1168  * - type name + dimensions
 
1170  * "A[][]".toCharArray()
 
1171  * "java.lang.String".toCharArray()
 
1173 private char[] returnTypeName(TypeReference type) {
 
1176         int dimension = type.dimensions();
 
1177         if (dimension != 0) {
 
1178                 char[] dimensionsArray = new char[dimension * 2];
 
1179                 for (int i = 0; i < dimension; i++) {
 
1180                         dimensionsArray[i * 2] = '[';
 
1181                         dimensionsArray[(i * 2) + 1] = ']';
 
1183                 return CharOperation.concat(
 
1184                         CharOperation.concatWith(type.getTypeName(), '.'), 
 
1187         return CharOperation.concatWith(type.getTypeName(), '.');
 
1190 public void addUnknownRef(NameReference nameRef) {
 
1191         if (this.unknownRefs.length == this.unknownRefsCounter) {
 
1196                         (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
 
1198                         this.unknownRefsCounter);
 
1200         this.unknownRefs[this.unknownRefsCounter++] = nameRef;
 
1202 private TypeReference typeReference(
 
1204         int localIdentifierPtr, 
 
1205         int localIdentifierLengthPtr) {
 
1206         /* build a Reference on a variable that may be qualified or not
 
1207          * This variable is a type reference and dim will be its dimensions.
 
1208          * We don't have any side effect on the stacks' pointers.
 
1213         if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
 
1214                 // single variable reference
 
1217                                 new SingleTypeReference(
 
1218                                         identifierStack[localIdentifierPtr], 
 
1219                                         identifierPositionStack[localIdentifierPtr--]); 
 
1222                                 new ArrayTypeReference(
 
1223                                         identifierStack[localIdentifierPtr], 
 
1225                                         identifierPositionStack[localIdentifierPtr--]);
 
1226                         ref.sourceEnd = endPosition;                     
 
1229                 if (length < 0) { //flag for precompiled type reference on base types
 
1230                         ref = TypeReference.baseTypeReference(-length, dim);
 
1231                         ref.sourceStart = intStack[localIntPtr--];
 
1233                                 ref.sourceEnd = intStack[localIntPtr--];
 
1236                                 ref.sourceEnd = endPosition;
 
1238                 } else { //Qualified variable reference
 
1239                         char[][] tokens = new char[length][];
 
1240                         localIdentifierPtr -= length;
 
1241                         long[] positions = new long[length];
 
1242                         System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
 
1244                                 identifierPositionStack, 
 
1245                                 localIdentifierPtr + 1, 
 
1250                                 ref = new QualifiedTypeReference(tokens, positions);
 
1252                                 ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
 
1253                                 ref.sourceEnd = endPosition;
 
1260 private void visitIfNeeded(AbstractMethodDeclaration method) {
 
1261         if (this.localDeclarationVisitor != null 
 
1262                 && (method.bits & AstNode.HasLocalTypeMASK) != 0) {
 
1263                         if (method.statements != null) {
 
1264                                 int statementsLength = method.statements.length;
 
1265                                 for (int i = 0; i < statementsLength; i++)
 
1266                                         method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
 
1271 private void visitIfNeeded(FieldDeclaration field) {
 
1272         if (this.localDeclarationVisitor != null 
 
1273                 && (field.bits & AstNode.HasLocalTypeMASK) != 0) {
 
1274                         if (field.initialization != null) {
 
1275                                 field.initialization.traverse(this.localDeclarationVisitor, null);
 
1280 private void visitIfNeeded(Initializer initializer) {
 
1281         if (this.localDeclarationVisitor != null 
 
1282                 && (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
 
1283                         if (initializer.block != null) {
 
1284                                 initializer.block.traverse(this.localDeclarationVisitor, null);
 
1289 protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
 
1290         if (compilationUnit == null) return;
 
1291         super.reportSyntaxError(act, currentKind,stateStackTop);