Package org.eclipse.jdt.internal.compiler

Source Code of org.eclipse.jdt.internal.compiler.SourceElementParser

/*******************************************************************************
* Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler;

import java.util.HashMap;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
import org.eclipse.jdt.internal.core.util.Messages;

/**
* A source element parser extracts structural and reference information
* from a piece of source.
*
* also see @ISourceElementRequestor
*
* The structural investigation includes:
* - the package statement
* - import statements
* - top-level types: package member, member types (member types of member types...)
* - fields
* - methods
*
* If reference information is requested, then all source constructs are
* investigated and type, field & method references are provided as well.
*
* Any (parsing) problem encountered is also provided.
*/
public class SourceElementParser extends CommentRecorderParser {

  ISourceElementRequestor requestor;
  boolean reportReferenceInfo;
  boolean reportLocalDeclarations;
  HashtableOfObjectToInt sourceEnds = new HashtableOfObjectToInt();
  HashMap nodesToCategories = new HashMap(); // a map from ASTNode to char[][]
  boolean useSourceJavadocParser = true;

  SourceElementNotifier notifier;

public SourceElementParser(
    final ISourceElementRequestor requestor,
    IProblemFactory problemFactory,
    CompilerOptions options,
    boolean reportLocalDeclarations,
    boolean optimizeStringLiterals) {
  this(requestor, problemFactory, options, reportLocalDeclarations, optimizeStringLiterals, true/* use SourceJavadocParser */);
}

public SourceElementParser(
    ISourceElementRequestor requestor,
    IProblemFactory problemFactory,
    CompilerOptions options,
    boolean reportLocalDeclarations,
    boolean optimizeStringLiterals,
    boolean useSourceJavadocParser) {

  super(
    new ProblemReporter(
      DefaultErrorHandlingPolicies.exitAfterAllProblems(),
      options,
      problemFactory),
    optimizeStringLiterals);

  this.reportLocalDeclarations = reportLocalDeclarations;

  // we want to notify all syntax error with the acceptProblem API
  // To do so, we define the record method of the ProblemReporter
  this.problemReporter = new ProblemReporter(
    DefaultErrorHandlingPolicies.exitAfterAllProblems(),
    options,
    problemFactory) {
    public void record(CategorizedProblem problem, CompilationResult unitResult, ReferenceContext context) {
      unitResult.record(problem, context); // TODO (jerome) clients are trapping problems either through factory or requestor... is result storing needed?
      SourceElementParser.this.requestor.acceptProblem(problem);
    }
  };
  this.requestor = requestor;
  this.options = options;

  this.notifier = new SourceElementNotifier(this.requestor, reportLocalDeclarations);

  // set specific javadoc parser
  this.useSourceJavadocParser = useSourceJavadocParser;
  if (useSourceJavadocParser) {
    this.javadocParser = new SourceJavadocParser(this);
  }
}
private void acceptJavadocTypeReference(Expression expression) {
  if (expression instanceof JavadocSingleTypeReference) {
    JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) expression;
    this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
  } else if (expression instanceof JavadocQualifiedTypeReference) {
    JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) expression;
    this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
  }
}
public void addUnknownRef(NameReference nameRef) {
  // Note that:
  // - the only requestor interested in references is the SourceIndexerRequestor
  // - a name reference can become a type reference only during the cast case, it is then tagged later with the Binding.TYPE bit
  // However since the indexer doesn't make the distinction between name reference and type reference, there is no need
  // to report a type reference in the SourceElementParser.
  // This gained 3.7% in the indexing performance test.
  if (nameRef instanceof SingleNameReference) {
    this.requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
  } else {
    //QualifiedNameReference
    this.requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
  }
}
public void checkComment() {
  // discard obsolete comments while inside methods or fields initializer (see bug 74369)
  if (!(this.diet && this.dietInt==0) && this.scanner.commentPtr >= 0) {
    flushCommentsDefinedPriorTo(this.endStatementPosition);
  }

  int lastComment = this.scanner.commentPtr;

  if (this.modifiersSourceStart >= 0) {
    // eliminate comments located after modifierSourceStart if positionned
    while (lastComment >= 0) {
      int commentSourceStart = this.scanner.commentStarts[lastComment];
      if (commentSourceStart < 0) commentSourceStart = -commentSourceStart;
      if (commentSourceStart <= this.modifiersSourceStart) break;
      lastComment--;
    }
  }
  if (lastComment >= 0) {
    // consider all remaining leading comments to be part of current declaration
    this.modifiersSourceStart = this.scanner.commentStarts[0];
    if (this.modifiersSourceStart < 0) this.modifiersSourceStart = -this.modifiersSourceStart;

    // check deprecation in last comment if javadoc (can be followed by non-javadoc comments which are simply ignored)
    while (lastComment >= 0 && this.scanner.commentStops[lastComment] < 0) lastComment--; // non javadoc comment have negative end positions
    if (lastComment >= 0 && this.javadocParser != null) {
      int commentEnd = this.scanner.commentStops[lastComment] - 1; //stop is one over
      // do not report problem before last parsed comment while recovering code...
      if (this.javadocParser.shouldReportProblems) {
        this.javadocParser.reportProblems = this.currentElement == null || commentEnd > this.lastJavadocEnd;
      } else {
        this.javadocParser.reportProblems = false;
      }
      if (this.javadocParser.checkDeprecation(lastComment)) {
        checkAndSetModifiers(ClassFileConstants.AccDeprecated);
      }
      this.javadoc = this.javadocParser.docComment;  // null if check javadoc is not activated
      if (this.currentElement == null) this.lastJavadocEnd = commentEnd;
    }
  }

  if (this.reportReferenceInfo && this.javadocParser.checkDocComment && this.javadoc != null) {
    // Report reference info in javadoc comment @throws/@exception tags
    TypeReference[] thrownExceptions = this.javadoc.exceptionReferences;
    if (thrownExceptions != null) {
      for (int i = 0, max=thrownExceptions.length; i < max; i++) {
        TypeReference typeRef = thrownExceptions[i];
        if (typeRef instanceof JavadocSingleTypeReference) {
          JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
          this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
        } else if (typeRef instanceof JavadocQualifiedTypeReference) {
          JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) typeRef;
          this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
        }
      }
    }

    // Report reference info in javadoc comment @see tags
    Expression[] references = this.javadoc.seeReferences;
    if (references != null) {
      for (int i = 0, max=references.length; i < max; i++) {
        Expression reference = references[i];
        acceptJavadocTypeReference(reference);
        if (reference instanceof JavadocFieldReference) {
          JavadocFieldReference fieldRef = (JavadocFieldReference) reference;
          this.requestor.acceptFieldReference(fieldRef.token, fieldRef.sourceStart);
          if (fieldRef.receiver != null && !fieldRef.receiver.isThis()) {
            acceptJavadocTypeReference(fieldRef.receiver);
          }
        } else if (reference instanceof JavadocMessageSend) {
          JavadocMessageSend messageSend = (JavadocMessageSend) reference;
          int argCount = messageSend.arguments == null ? 0 : messageSend.arguments.length;
          this.requestor.acceptMethodReference(messageSend.selector, argCount, messageSend.sourceStart);
          this.requestor.acceptConstructorReference(messageSend.selector, argCount, messageSend.sourceStart);
          if (messageSend.receiver != null && !messageSend.receiver.isThis()) {
            acceptJavadocTypeReference(messageSend.receiver);
          }
        } else if (reference instanceof JavadocAllocationExpression) {
          JavadocAllocationExpression constructor = (JavadocAllocationExpression) reference;
          int argCount = constructor.arguments == null ? 0 : constructor.arguments.length;
          if (constructor.type != null) {
            char[][] compoundName = constructor.type.getParameterizedTypeName();
            this.requestor.acceptConstructorReference(compoundName[compoundName.length-1], argCount, constructor.sourceStart);
            if (!constructor.type.isThis()) {
              acceptJavadocTypeReference(constructor.type);
            }
          }
        }
      }
    }
  }
}
protected void classInstanceCreation(boolean alwaysQualified) {

  boolean previousFlag = this.reportReferenceInfo;
  this.reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
  super.classInstanceCreation(alwaysQualified);
  this.reportReferenceInfo = previousFlag;
  if (this.reportReferenceInfo){
    AllocationExpression alloc = (AllocationExpression)this.expressionStack[this.expressionPtr];
    TypeReference typeRef = alloc.type;
    this.requestor.acceptConstructorReference(
      typeRef instanceof SingleTypeReference
        ? ((SingleTypeReference) typeRef).token
        : CharOperation.concatWith(alloc.type.getParameterizedTypeName(), '.'),
      alloc.arguments == null ? 0 : alloc.arguments.length,
      alloc.sourceStart);
  }
}
protected void consumeAnnotationAsModifier() {
  super.consumeAnnotationAsModifier();
  Annotation annotation = (Annotation)this.expressionStack[this.expressionPtr];
  if (this.reportReferenceInfo) { // accept annotation type reference
    this.requestor.acceptAnnotationTypeReference(annotation.type.getTypeName(), annotation.sourceStart, annotation.sourceEnd);
  }
}
protected void consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() {
  boolean previousFlag = this.reportReferenceInfo;
  this.reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
  super.consumeClassInstanceCreationExpressionQualifiedWithTypeArguments();
  this.reportReferenceInfo = previousFlag;
  if (this.reportReferenceInfo){
    AllocationExpression alloc = (AllocationExpression)this.expressionStack[this.expressionPtr];
    TypeReference typeRef = alloc.type;
    this.requestor.acceptConstructorReference(
      typeRef instanceof SingleTypeReference
        ? ((SingleTypeReference) typeRef).token
        : CharOperation.concatWith(alloc.type.getParameterizedTypeName(), '.'),
      alloc.arguments == null ? 0 : alloc.arguments.length,
      alloc.sourceStart);
  }
}
protected void consumeAnnotationTypeDeclarationHeaderName() {
  int currentAstPtr = this.astPtr;
  super.consumeAnnotationTypeDeclarationHeaderName();
  if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
    rememberCategories();
}
protected void consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters() {
  int currentAstPtr = this.astPtr;
  super.consumeAnnotationTypeDeclarationHeaderNameWithTypeParameters();
  if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
    rememberCategories();
}
protected void consumeCatchFormalParameter() {
  super.consumeCatchFormalParameter();

  // Flush comments prior to this formal parameter so the declarationSourceStart of the following parameter
  // is correctly set (see bug 80904)
  // Note that this could be done in the Parser itself, but this would slow down all parsers, when they don't need
  // the declarationSourceStart to be set
  flushCommentsDefinedPriorTo(this.scanner.currentPosition);
}
protected void consumeClassHeaderName1() {
  int currentAstPtr = this.astPtr;
  super.consumeClassHeaderName1();
  if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
    rememberCategories();
}
protected void consumeClassInstanceCreationExpressionWithTypeArguments() {
  boolean previousFlag = this.reportReferenceInfo;
  this.reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
  super.consumeClassInstanceCreationExpressionWithTypeArguments();
  this.reportReferenceInfo = previousFlag;
  if (this.reportReferenceInfo){
    AllocationExpression alloc = (AllocationExpression)this.expressionStack[this.expressionPtr];
    TypeReference typeRef = alloc.type;
    this.requestor.acceptConstructorReference(
      typeRef instanceof SingleTypeReference
        ? ((SingleTypeReference) typeRef).token
        : CharOperation.concatWith(alloc.type.getParameterizedTypeName(), '.'),
      alloc.arguments == null ? 0 : alloc.arguments.length,
      alloc.sourceStart);
  }
}
protected void consumeConstructorHeaderName() {
  long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
  int selectorSourceEnd = (int) selectorSourcePositions;
  int currentAstPtr = this.astPtr;
  super.consumeConstructorHeaderName();
  if (this.astPtr > currentAstPtr) { // if ast node was pushed on the ast stack
    this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
    rememberCategories();
  }
}
protected void consumeConstructorHeaderNameWithTypeParameters() {
  long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
  int selectorSourceEnd = (int) selectorSourcePositions;
  int currentAstPtr = this.astPtr;
  super.consumeConstructorHeaderNameWithTypeParameters();
  if (this.astPtr > currentAstPtr) { // if ast node was pushed on the ast stack
    this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
    rememberCategories();
  }
}
protected void consumeEnumConstantWithClassBody() {
  super.consumeEnumConstantWithClassBody();
  if ((this.currentToken == TokenNameCOMMA || this.currentToken == TokenNameSEMICOLON)
      && this.astStack[this.astPtr] instanceof FieldDeclaration) {
    this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
    rememberCategories();
  }
}
protected void consumeEnumConstantNoClassBody() {
  super.consumeEnumConstantNoClassBody();
  if ((this.currentToken == TokenNameCOMMA || this.currentToken == TokenNameSEMICOLON)
      && this.astStack[this.astPtr] instanceof FieldDeclaration) {
    this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
    rememberCategories();
  }
}
protected void consumeEnumHeaderName() {
  int currentAstPtr = this.astPtr;
  super.consumeEnumHeaderName();
  if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
    rememberCategories();
}
protected void consumeEnumHeaderNameWithTypeParameters() {
  int currentAstPtr = this.astPtr;
  super.consumeEnumHeaderNameWithTypeParameters();
  if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
    rememberCategories();
}
protected void consumeExitVariableWithInitialization() {
  // ExitVariableWithInitialization ::= $empty
  // the scanner is located after the comma or the semi-colon.
  // we want to include the comma or the semi-colon
  super.consumeExitVariableWithInitialization();
  if ((this.currentToken == TokenNameCOMMA || this.currentToken == TokenNameSEMICOLON)
      && this.astStack[this.astPtr] instanceof FieldDeclaration) {
    this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
    rememberCategories();
  }
}
protected void consumeExitVariableWithoutInitialization() {
  // ExitVariableWithoutInitialization ::= $empty
  // do nothing by default
  super.consumeExitVariableWithoutInitialization();
  if ((this.currentToken == TokenNameCOMMA || this.currentToken == TokenNameSEMICOLON)
      && this.astStack[this.astPtr] instanceof FieldDeclaration) {
    this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
    rememberCategories();
  }
}
/*
*
* INTERNAL USE-ONLY
*/
protected void consumeFieldAccess(boolean isSuperAccess) {
  // FieldAccess ::= Primary '.' 'Identifier'
  // FieldAccess ::= 'super' '.' 'Identifier'
  super.consumeFieldAccess(isSuperAccess);
  FieldReference fr = (FieldReference) this.expressionStack[this.expressionPtr];
  if (this.reportReferenceInfo) {
    this.requestor.acceptFieldReference(fr.token, fr.sourceStart);
  }
}
protected void consumeFormalParameter(boolean isVarArgs) {
  super.consumeFormalParameter(isVarArgs);

  // Flush comments prior to this formal parameter so the declarationSourceStart of the following parameter
  // is correctly set (see bug 80904)
  // Note that this could be done in the Parser itself, but this would slow down all parsers, when they don't need
  // the declarationSourceStart to be set
  flushCommentsDefinedPriorTo(this.scanner.currentPosition);
}
protected void consumeInterfaceHeaderName1() {
  int currentAstPtr = this.astPtr;
  super.consumeInterfaceHeaderName1();
  if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
    rememberCategories();
}
protected void consumeMemberValuePair() {
  super.consumeMemberValuePair();
  MemberValuePair memberValuepair = (MemberValuePair) this.astStack[this.astPtr];
  if (this.reportReferenceInfo) {
    this.requestor.acceptMethodReference(memberValuepair.name, 0, memberValuepair.sourceStart);
  }
}
protected void consumeMarkerAnnotation() {
  super.consumeMarkerAnnotation();
  Annotation annotation = (Annotation)this.expressionStack[this.expressionPtr];
  if (this.reportReferenceInfo) { // accept annotation type reference
    this.requestor.acceptAnnotationTypeReference(annotation.type.getTypeName(), annotation.sourceStart, annotation.sourceEnd);
  }
}
protected void consumeMethodHeaderName(boolean isAnnotationMethod) {
  long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
  int selectorSourceEnd = (int) selectorSourcePositions;
  int currentAstPtr = this.astPtr;
  super.consumeMethodHeaderName(isAnnotationMethod);
  if (this.astPtr > currentAstPtr) { // if ast node was pushed on the ast stack
    this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
    rememberCategories();
  }
}

protected void consumeMethodHeaderNameWithTypeParameters(boolean isAnnotationMethod) {
  long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
  int selectorSourceEnd = (int) selectorSourcePositions;
  int currentAstPtr = this.astPtr;
  super.consumeMethodHeaderNameWithTypeParameters(isAnnotationMethod);
  if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
    this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
    rememberCategories();
}
/*
*
* INTERNAL USE-ONLY
*/
protected void consumeMethodInvocationName() {
  // MethodInvocation ::= Name '(' ArgumentListopt ')'
  super.consumeMethodInvocationName();

  // when the name is only an identifier...we have a message send to "this" (implicit)
  MessageSend messageSend = (MessageSend) this.expressionStack[this.expressionPtr];
  Expression[] args = messageSend.arguments;
  if (this.reportReferenceInfo) {
    this.requestor.acceptMethodReference(
      messageSend.selector,
      args == null ? 0 : args.length,
      (int)(messageSend.nameSourcePosition >>> 32));
  }
}
protected void consumeMethodInvocationNameWithTypeArguments() {
  // MethodInvocation ::= Name '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
  super.consumeMethodInvocationNameWithTypeArguments();

  // when the name is only an identifier...we have a message send to "this" (implicit)
  MessageSend messageSend = (MessageSend) this.expressionStack[this.expressionPtr];
  Expression[] args = messageSend.arguments;
  if (this.reportReferenceInfo) {
    this.requestor.acceptMethodReference(
      messageSend.selector,
      args == null ? 0 : args.length,
      (int)(messageSend.nameSourcePosition >>> 32));
  }
}
/*
*
* INTERNAL USE-ONLY
*/
protected void consumeMethodInvocationPrimary() {
  super.consumeMethodInvocationPrimary();
  MessageSend messageSend = (MessageSend) this.expressionStack[this.expressionPtr];
  Expression[] args = messageSend.arguments;
  if (this.reportReferenceInfo) {
    this.requestor.acceptMethodReference(
      messageSend.selector,
      args == null ? 0 : args.length,
      (int)(messageSend.nameSourcePosition >>> 32));
  }
}
/*
*
* INTERNAL USE-ONLY
*/
protected void consumeMethodInvocationPrimaryWithTypeArguments() {
  super.consumeMethodInvocationPrimaryWithTypeArguments();
  MessageSend messageSend = (MessageSend) this.expressionStack[this.expressionPtr];
  Expression[] args = messageSend.arguments;
  if (this.reportReferenceInfo) {
    this.requestor.acceptMethodReference(
      messageSend.selector,
      args == null ? 0 : args.length,
      (int)(messageSend.nameSourcePosition >>> 32));
  }
}
/*
*
* INTERNAL USE-ONLY
*/
protected void consumeMethodInvocationSuper() {
  // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
  super.consumeMethodInvocationSuper();
  MessageSend messageSend = (MessageSend) this.expressionStack[this.expressionPtr];
  Expression[] args = messageSend.arguments;
  if (this.reportReferenceInfo) {
    this.requestor.acceptMethodReference(
      messageSend.selector,
      args == null ? 0 : args.length,
      (int)(messageSend.nameSourcePosition >>> 32));
  }
}
protected void consumeMethodInvocationSuperWithTypeArguments() {
  // MethodInvocation ::= 'super' '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
  super.consumeMethodInvocationSuperWithTypeArguments();
  MessageSend messageSend = (MessageSend) this.expressionStack[this.expressionPtr];
  Expression[] args = messageSend.arguments;
  if (this.reportReferenceInfo) {
    this.requestor.acceptMethodReference(
      messageSend.selector,
      args == null ? 0 : args.length,
      (int)(messageSend.nameSourcePosition >>> 32));
  }
}
protected void consumeNormalAnnotation() {
  super.consumeNormalAnnotation();
  Annotation annotation = (Annotation)this.expressionStack[this.expressionPtr];
  if (this.reportReferenceInfo) { // accept annotation type reference
    this.requestor.acceptAnnotationTypeReference(annotation.type.getTypeName(), annotation.sourceStart, annotation.sourceEnd);
  }
}
protected void consumeSingleMemberAnnotation() {
  super.consumeSingleMemberAnnotation();
  SingleMemberAnnotation member = (SingleMemberAnnotation) this.expressionStack[this.expressionPtr];
  if (this.reportReferenceInfo) {
    this.requestor.acceptMethodReference(TypeConstants.VALUE, 0, member.sourceStart);
  }
}
protected void consumeSingleStaticImportDeclarationName() {
  // SingleTypeImportDeclarationName ::= 'import' 'static' Name
  ImportReference impt;
  int length;
  char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
  this.identifierPtr -= length;
  long[] positions = new long[length];
  System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
  System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
  pushOnAstStack(impt = newImportReference(tokens, positions, false, ClassFileConstants.AccStatic));

  this.modifiers = ClassFileConstants.AccDefault;
  this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)

  if (this.currentToken == TokenNameSEMICOLON){
    impt.declarationSourceEnd = this.scanner.currentPosition - 1;
  } else {
    impt.declarationSourceEnd = impt.sourceEnd;
  }
  impt.declarationEnd = impt.declarationSourceEnd;
  //this.endPosition is just before the ;
  impt.declarationSourceStart = this.intStack[this.intPtr--];

  if(!this.statementRecoveryActivated &&
      this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
      this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
    impt.modifiers = ClassFileConstants.AccDefault; // convert the static import reference to a non-static importe reference
    problemReporter().invalidUsageOfStaticImports(impt);
  }

  // recovery
  if (this.currentElement != null){
    this.lastCheckPoint = impt.declarationSourceEnd+1;
    this.currentElement = this.currentElement.add(impt, 0);
    this.lastIgnoredToken = -1;
    this.restartRecovery = true; // used to avoid branching back into the regular automaton
  }
  if (this.reportReferenceInfo) {
    // Name for static import is TypeName '.' Identifier
    // => accept unknown ref on identifier
    int tokensLength = impt.tokens.length-1;
    int start = (int) (impt.sourcePositions[tokensLength] >>> 32);
    char[] last = impt.tokens[tokensLength];
    // accept all possible kind for last name, index users will have to select the right one...
    // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=86901
    this.requestor.acceptFieldReference(last, start);
    this.requestor.acceptMethodReference(last, 0,start);
    this.requestor.acceptTypeReference(last, start);
    // accept type name
    if (tokensLength > 0) {
      char[][] compoundName = new char[tokensLength][];
      System.arraycopy(impt.tokens, 0, compoundName, 0, tokensLength);
      int end = (int) impt.sourcePositions[tokensLength-1];
      this.requestor.acceptTypeReference(compoundName, impt.sourceStart, end);
    }
  }
}

protected void consumeSingleTypeImportDeclarationName() {
  // SingleTypeImportDeclarationName ::= 'import' Name
  /* push an ImportRef build from the last name
  stored in the identifier stack. */

  ImportReference impt;
  int length;
  char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
  this.identifierPtr -= length;
  long[] positions = new long[length];
  System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
  System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
  pushOnAstStack(impt = newImportReference(tokens, positions, false, ClassFileConstants.AccDefault));

  if (this.currentToken == TokenNameSEMICOLON){
    impt.declarationSourceEnd = this.scanner.currentPosition - 1;
  } else {
    impt.declarationSourceEnd = impt.sourceEnd;
  }
  impt.declarationEnd = impt.declarationSourceEnd;
  //this.endPosition is just before the ;
  impt.declarationSourceStart = this.intStack[this.intPtr--];

  // recovery
  if (this.currentElement != null){
    this.lastCheckPoint = impt.declarationSourceEnd+1;
    this.currentElement = this.currentElement.add(impt, 0);
    this.lastIgnoredToken = -1;
    this.restartRecovery = true; // used to avoid branching back into the regular automaton
  }
  if (this.reportReferenceInfo) {
    this.requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
  }
}
protected void consumeStaticImportOnDemandDeclarationName() {
  // TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
  /* push an ImportRef build from the last name
  stored in the identifier stack. */

  ImportReference impt;
  int length;
  char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
  this.identifierPtr -= length;
  long[] positions = new long[length];
  System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
  System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
  pushOnAstStack(impt = new ImportReference(tokens, positions, true, ClassFileConstants.AccStatic));

  // star end position
  impt.trailingStarPosition = this.intStack[this.intPtr--];
  this.modifiers = ClassFileConstants.AccDefault;
  this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)

  if (this.currentToken == TokenNameSEMICOLON){
    impt.declarationSourceEnd = this.scanner.currentPosition - 1;
  } else {
    impt.declarationSourceEnd = impt.sourceEnd;
  }
  impt.declarationEnd = impt.declarationSourceEnd;
  //this.endPosition is just before the ;
  impt.declarationSourceStart = this.intStack[this.intPtr--];

  if(!this.statementRecoveryActivated &&
      this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
      this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
    impt.modifiers = ClassFileConstants.AccDefault; // convert the static import reference to a non-static importe reference
    problemReporter().invalidUsageOfStaticImports(impt);
  }

  // recovery
  if (this.currentElement != null){
    this.lastCheckPoint = impt.declarationSourceEnd+1;
    this.currentElement = this.currentElement.add(impt, 0);
    this.lastIgnoredToken = -1;
    this.restartRecovery = true; // used to avoid branching back into the regular automaton
  }
  if (this.reportReferenceInfo) {
    this.requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
  }
}
protected void consumeTypeImportOnDemandDeclarationName() {
  // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
  /* push an ImportRef build from the last name
  stored in the identifier stack. */

  ImportReference impt;
  int length;
  char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
  this.identifierPtr -= length;
  long[] positions = new long[length];
  System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
  System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
  pushOnAstStack(impt = new ImportReference(tokens, positions, true, ClassFileConstants.AccDefault));

  // star end position
  impt.trailingStarPosition = this.intStack[this.intPtr--];
  if (this.currentToken == TokenNameSEMICOLON){
    impt.declarationSourceEnd = this.scanner.currentPosition - 1;
  } else {
    impt.declarationSourceEnd = impt.sourceEnd;
  }
  impt.declarationEnd = impt.declarationSourceEnd;
  //this.endPosition is just before the ;
  impt.declarationSourceStart = this.intStack[this.intPtr--];

  // recovery
  if (this.currentElement != null){
    this.lastCheckPoint = impt.declarationSourceEnd+1;
    this.currentElement = this.currentElement.add(impt, 0);
    this.lastIgnoredToken = -1;
    this.restartRecovery = true; // used to avoid branching back into the regular automaton
  }
  if (this.reportReferenceInfo) {
    this.requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
  }
}
public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
  MethodDeclaration methodDeclaration = super.convertToMethodDeclaration(c, compilationResult);
  int selectorSourceEnd = this.sourceEnds.removeKey(c);
  if (selectorSourceEnd != -1)
    this.sourceEnds.put(methodDeclaration, selectorSourceEnd);
  char[][] categories =  (char[][]) this.nodesToCategories.remove(c);
  if (categories != null)
    this.nodesToCategories.put(methodDeclaration, categories);

  return methodDeclaration;
}
protected CompilationUnitDeclaration endParse(int act) {
  if (this.scanner.recordLineSeparator) {
    this.requestor.acceptLineSeparatorPositions(this.scanner.getLineEnds());
  }
  if (this.compilationUnit != null) {
    CompilationUnitDeclaration result = super.endParse(act);
    return result;
  } else {
    return null;
  }
}
public TypeReference getTypeReference(int dim) {
  /* build a Reference on a variable that may be qualified or not
   * This variable is a type reference and dim will be its dimensions
   */
  int length = this.identifierLengthStack[this.identifierLengthPtr--];
  if (length < 0) { //flag for precompiled type reference on base types
    TypeReference ref = TypeReference.baseTypeReference(-length, dim);
    ref.sourceStart = this.intStack[this.intPtr--];
    if (dim == 0) {
      ref.sourceEnd = this.intStack[this.intPtr--];
    } else {
      this.intPtr--; // no need to use this position as it is an array
      ref.sourceEnd = this.endPosition;
    }
    if (this.reportReferenceInfo){
        this.requestor.acceptTypeReference(ref.getParameterizedTypeName(), ref.sourceStart, ref.sourceEnd);
    }
    return ref;
  } else {
    int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
    if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
      // generic type
      TypeReference ref = getTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
      if (this.reportReferenceInfo) {
        if (length == 1 && numberOfIdentifiers == 1) {
          ParameterizedSingleTypeReference parameterizedSingleTypeReference = (ParameterizedSingleTypeReference) ref;
          this.requestor.acceptTypeReference(parameterizedSingleTypeReference.token, parameterizedSingleTypeReference.sourceStart);
        } else {
          ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference = (ParameterizedQualifiedTypeReference) ref;
          this.requestor.acceptTypeReference(parameterizedQualifiedTypeReference.tokens, parameterizedQualifiedTypeReference.sourceStart, parameterizedQualifiedTypeReference.sourceEnd);
        }
      }
      return ref;
    } else if (length == 1) {
      // single variable reference
      this.genericsLengthPtr--; // pop the 0
      if (dim == 0) {
        SingleTypeReference ref =
          new SingleTypeReference(
            this.identifierStack[this.identifierPtr],
            this.identifierPositionStack[this.identifierPtr--]);
        if (this.reportReferenceInfo) {
          this.requestor.acceptTypeReference(ref.token, ref.sourceStart);
        }
        return ref;
      } else {
        ArrayTypeReference ref =
          new ArrayTypeReference(
            this.identifierStack[this.identifierPtr],
            dim,
            this.identifierPositionStack[this.identifierPtr--]);
        ref.sourceEnd = this.endPosition;
        if (this.reportReferenceInfo) {
          this.requestor.acceptTypeReference(ref.token, ref.sourceStart);
        }
        return ref;
      }
    } else {//Qualified variable reference
      this.genericsLengthPtr--;
      char[][] tokens = new char[length][];
      this.identifierPtr -= length;
      long[] positions = new long[length];
      System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
      System.arraycopy(
        this.identifierPositionStack,
        this.identifierPtr + 1,
        positions,
        0,
        length);
      if (dim == 0) {
        QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
        if (this.reportReferenceInfo) {
          this.requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
        }
        return ref;
      } else {
        ArrayQualifiedTypeReference ref =
          new ArrayQualifiedTypeReference(tokens, dim, positions);
        ref.sourceEnd = this.endPosition;
        if (this.reportReferenceInfo) {
          this.requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
        }
        return ref;
      }
    }
  }
}
public NameReference getUnspecifiedReference() {
  /* build a (unspecified) NameReference which may be qualified*/

  int length;
  if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
    // single variable reference
    SingleNameReference ref =
      newSingleNameReference(
        this.identifierStack[this.identifierPtr],
        this.identifierPositionStack[this.identifierPtr--]);
    if (this.reportReferenceInfo) {
      addUnknownRef(ref);
    }
    return ref;
  } else {
    //Qualified variable reference
    char[][] tokens = new char[length][];
    this.identifierPtr -= length;
    System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
    long[] positions = new long[length];
    System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
    QualifiedNameReference ref =
      newQualifiedNameReference(
        tokens,
        positions,
        (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
        (int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd
    if (this.reportReferenceInfo) {
      addUnknownRef(ref);
    }
    return ref;
  }
}
public NameReference getUnspecifiedReferenceOptimized() {
  /* build a (unspecified) NameReference which may be qualified
  The optimization occurs for qualified reference while we are
  certain in this case the last item of the qualified name is
  a field access. This optimization is IMPORTANT while it results
  that when a NameReference is build, the type checker should always
  look for that it is not a type reference */

  int length;
  if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
    // single variable reference
    SingleNameReference ref =
      newSingleNameReference(
        this.identifierStack[this.identifierPtr],
        this.identifierPositionStack[this.identifierPtr--]);
    ref.bits &= ~ASTNode.RestrictiveFlagMASK;
    ref.bits |= Binding.LOCAL | Binding.FIELD;
    if (this.reportReferenceInfo) {
      addUnknownRef(ref);
    }
    return ref;
  }

  //Qualified-variable-reference
  //In fact it is variable-reference DOT field-ref , but it would result in a type
  //conflict tha can be only reduce by making a superclass (or inetrface ) between
  //nameReference and FiledReference or putting FieldReference under NameReference
  //or else..........This optimisation is not really relevant so just leave as it is

  char[][] tokens = new char[length][];
  this.identifierPtr -= length;
  System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
  long[] positions = new long[length];
  System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
  QualifiedNameReference ref =
    newQualifiedNameReference(
      tokens,
      positions,
      (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32),
  // sourceStart
   (int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd
  ref.bits &= ~ASTNode.RestrictiveFlagMASK;
  ref.bits |= Binding.LOCAL | Binding.FIELD;
  if (this.reportReferenceInfo) {
    addUnknownRef(ref);
  }
  return ref;
}
protected ImportReference newImportReference(char[][] tokens, long[] positions, boolean onDemand, int mod) {
  return new ImportReference(tokens, positions, onDemand, mod);
}
protected QualifiedNameReference newQualifiedNameReference(char[][] tokens, long[] positions, int sourceStart, int sourceEnd) {
  return new QualifiedNameReference(tokens, positions, sourceStart, sourceEnd);
}
protected SingleNameReference newSingleNameReference(char[] source, long positions) {
  return new SingleNameReference(source, positions);
}
public CompilationUnitDeclaration parseCompilationUnit(
  ICompilationUnit unit,
  boolean fullParse,
  IProgressMonitor pm) {

  boolean old = this.diet;
  CompilationUnitDeclaration parsedUnit = null;
  try {
    this.diet = true;
    this.reportReferenceInfo = fullParse;
    CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
    parsedUnit = parse(unit, compilationUnitResult);
    if (pm != null && pm.isCanceled())
      throw new OperationCanceledException(Messages.operation_cancelled);
    if (this.scanner.recordLineSeparator) {
      this.requestor.acceptLineSeparatorPositions(compilationUnitResult.getLineSeparatorPositions());
    }
    int initialStart = this.scanner.initialPosition;
    int initialEnd = this.scanner.eofPosition;
    if (this.reportLocalDeclarations || fullParse){
      this.diet = false;
      getMethodBodies(parsedUnit);
    }
    this.scanner.resetTo(initialStart, initialEnd);
    this.notifier.notifySourceElementRequestor(
        parsedUnit,
        this.scanner.initialPosition,
        this.scanner.eofPosition,
        this.reportReferenceInfo,
        this.sourceEnds,
        this.nodesToCategories);
    return parsedUnit;
  } catch (AbortCompilation e) {
    // ignore this exception
  } finally {
    this.diet = old;
    reset();
  }
  return parsedUnit;
}
private void rememberCategories() {
  if (this.useSourceJavadocParser) {
    SourceJavadocParser sourceJavadocParser = (SourceJavadocParser) this.javadocParser;
    char[][] categories =  sourceJavadocParser.categories;
    if (categories.length > 0) {
      this.nodesToCategories.put(this.astStack[this.astPtr], categories);
      sourceJavadocParser.categories = CharOperation.NO_CHAR_CHAR;
    }
  }
}
private void reset() {
  this.sourceEnds = new HashtableOfObjectToInt();
  this.nodesToCategories = new HashMap();
}
public void setRequestor(ISourceElementRequestor requestor) {
  this.requestor = requestor;
  this.notifier.requestor = requestor;
}
}
TOP

Related Classes of org.eclipse.jdt.internal.compiler.SourceElementParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.