Package org.eclipse.jdt.internal.compiler.parser

Source Code of org.eclipse.jdt.internal.compiler.parser.RecoveredType

/*******************************************************************************
* Copyright (c) 2000, 2009 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.parser;

import java.util.HashSet;
import java.util.Set;

import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;

/**
* Internal type structure for parsing recovery
*/

public class RecoveredType extends RecoveredStatement implements TerminalTokens {
  public static final int MAX_TYPE_DEPTH = 256;
 
  public TypeDeclaration typeDeclaration;

  public RecoveredAnnotation[] annotations;
  public int annotationCount;

  public int modifiers;
  public int modifiersStart;

  public RecoveredType[] memberTypes;
  public int memberTypeCount;
  public RecoveredField[] fields;
  public int fieldCount;
  public RecoveredMethod[] methods;
  public int methodCount;

  public boolean preserveContent = false// only used for anonymous types
  public int bodyEnd;

  public boolean insideEnumConstantPart = false;

  public TypeParameter[] pendingTypeParameters;
  public int pendingTypeParametersStart;

  int pendingModifiers;
  int pendingModifersSourceStart = -1;
  RecoveredAnnotation[] pendingAnnotations;
  int pendingAnnotationCount;

public RecoveredType(TypeDeclaration typeDeclaration, RecoveredElement parent, int bracketBalance){
  super(typeDeclaration, parent, bracketBalance);
  this.typeDeclaration = typeDeclaration;
  if(typeDeclaration.allocation != null && typeDeclaration.allocation.type == null) {
    // an enum constant body can not exist if there is no opening brace
    this.foundOpeningBrace = true;
  } else {
    this.foundOpeningBrace = !bodyStartsAtHeaderEnd();
  }
  this.insideEnumConstantPart = TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL;
  if(this.foundOpeningBrace) {
    this.bracketBalance++;
  }

  this.preserveContent = parser().methodRecoveryActivated || parser().statementRecoveryActivated;
}
public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {

  /* do not consider a method starting passed the type end (if set)
    it must be belonging to an enclosing type */
  if (this.typeDeclaration.declarationSourceEnd != 0
    && methodDeclaration.declarationSourceStart > this.typeDeclaration.declarationSourceEnd){
    this.pendingTypeParameters = null;
    resetPendingModifiers();

    return this.parent.add(methodDeclaration, bracketBalanceValue);
  }

  if (this.methods == null) {
    this.methods = new RecoveredMethod[5];
    this.methodCount = 0;
  } else {
    if (this.methodCount == this.methods.length) {
      System.arraycopy(
        this.methods,
        0,
        (this.methods = new RecoveredMethod[2 * this.methodCount]),
        0,
        this.methodCount);
    }
  }
  RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalanceValue, this.recoveringParser);
  this.methods[this.methodCount++] = element;

  if(this.pendingTypeParameters != null) {
    element.attach(this.pendingTypeParameters, this.pendingTypeParametersStart);
    this.pendingTypeParameters = null;
  }

  if(this.pendingAnnotationCount > 0) {
    element.attach(
        this.pendingAnnotations,
        this.pendingAnnotationCount,
        this.pendingModifiers,
        this.pendingModifersSourceStart);
  }
  resetPendingModifiers();

  this.insideEnumConstantPart = false;

  /* consider that if the opening brace was not found, it is there */
  if (!this.foundOpeningBrace){
    this.foundOpeningBrace = true;
    this.bracketBalance++;
  }
  /* if method not finished, then method becomes current */
  if (methodDeclaration.declarationSourceEnd == 0) return element;
  return this;
}
public RecoveredElement add(Block nestedBlockDeclaration,int bracketBalanceValue) {
  this.pendingTypeParameters = null;
  resetPendingModifiers();

  int mods = ClassFileConstants.AccDefault;
  if(parser().recoveredStaticInitializerStart != 0) {
    mods = ClassFileConstants.AccStatic;
  }
  return this.add(new Initializer(nestedBlockDeclaration, mods), bracketBalanceValue);
}
public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
  this.pendingTypeParameters = null;

  /* do not consider a field starting passed the type end (if set)
  it must be belonging to an enclosing type */
  if (this.typeDeclaration.declarationSourceEnd != 0
    && fieldDeclaration.declarationSourceStart > this.typeDeclaration.declarationSourceEnd) {

    resetPendingModifiers();

    return this.parent.add(fieldDeclaration, bracketBalanceValue);
  }
  if (this.fields == null) {
    this.fields = new RecoveredField[5];
    this.fieldCount = 0;
  } else {
    if (this.fieldCount == this.fields.length) {
      System.arraycopy(
        this.fields,
        0,
        (this.fields = new RecoveredField[2 * this.fieldCount]),
        0,
        this.fieldCount);
    }
  }
  RecoveredField element;
  switch (fieldDeclaration.getKind()) {
    case AbstractVariableDeclaration.FIELD:
    case AbstractVariableDeclaration.ENUM_CONSTANT:
      element = new RecoveredField(fieldDeclaration, this, bracketBalanceValue);
      break;
    case AbstractVariableDeclaration.INITIALIZER:
      element = new RecoveredInitializer(fieldDeclaration, this, bracketBalanceValue);
      break;
    default:
      // never happens, as field is always identified
      return this;
  }
  this.fields[this.fieldCount++] = element;

  if(this.pendingAnnotationCount > 0) {
    element.attach(
        this.pendingAnnotations,
        this.pendingAnnotationCount,
        this.pendingModifiers,
        this.pendingModifersSourceStart);
  }
  resetPendingModifiers();

  /* consider that if the opening brace was not found, it is there */
  if (!this.foundOpeningBrace){
    this.foundOpeningBrace = true;
    this.bracketBalance++;
  }
  /* if field not finished, then field becomes current */
  if (fieldDeclaration.declarationSourceEnd == 0) return element;
  return this;
}
public RecoveredElement add(TypeDeclaration memberTypeDeclaration, int bracketBalanceValue) {
  this.pendingTypeParameters = null;

  /* do not consider a type starting passed the type end (if set)
    it must be belonging to an enclosing type */
  if (this.typeDeclaration.declarationSourceEnd != 0
    && memberTypeDeclaration.declarationSourceStart > this.typeDeclaration.declarationSourceEnd){

    resetPendingModifiers();

    return this.parent.add(memberTypeDeclaration, bracketBalanceValue);
  }

  this.insideEnumConstantPart = false;

  if ((memberTypeDeclaration.bits & ASTNode.IsAnonymousType) != 0){
    if (this.methodCount > 0) {
      // add it to the last method body
      RecoveredMethod lastMethod = this.methods[this.methodCount-1];
      lastMethod.methodDeclaration.bodyEnd = 0; // reopen method
      lastMethod.methodDeclaration.declarationSourceEnd = 0; // reopen method
      lastMethod.bracketBalance++; // expect one closing brace

      resetPendingModifiers();

      return lastMethod.add(memberTypeDeclaration, bracketBalanceValue);
    } else {
      // ignore
      return this;
    }
  }

  if (this.memberTypes == null) {
    this.memberTypes = new RecoveredType[5];
    this.memberTypeCount = 0;
  } else {
    if (this.memberTypeCount == this.memberTypes.length) {
      System.arraycopy(
        this.memberTypes,
        0,
        (this.memberTypes = new RecoveredType[2 * this.memberTypeCount]),
        0,
        this.memberTypeCount);
    }
  }
  RecoveredType element = new RecoveredType(memberTypeDeclaration, this, bracketBalanceValue);
  this.memberTypes[this.memberTypeCount++] = element;

  if(this.pendingAnnotationCount > 0) {
    element.attach(
        this.pendingAnnotations,
        this.pendingAnnotationCount,
        this.pendingModifiers,
        this.pendingModifersSourceStart);
  }
  resetPendingModifiers();

  /* consider that if the opening brace was not found, it is there */
  if (!this.foundOpeningBrace){
    this.foundOpeningBrace = true;
    this.bracketBalance++;
  }
  /* if member type not finished, then member type becomes current */
  if (memberTypeDeclaration.declarationSourceEnd == 0) return element;
  return this;
}
public void add(TypeParameter[] parameters, int startPos) {
  this.pendingTypeParameters = parameters;
  this.pendingTypeParametersStart = startPos;
}
public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengthPtr, int annotationStart, int bracketBalanceValue) {
  if (this.pendingAnnotations == null) {
    this.pendingAnnotations = new RecoveredAnnotation[5];
    this.pendingAnnotationCount = 0;
  } else {
    if (this.pendingAnnotationCount == this.pendingAnnotations.length) {
      System.arraycopy(
        this.pendingAnnotations,
        0,
        (this.pendingAnnotations = new RecoveredAnnotation[2 * this.pendingAnnotationCount]),
        0,
        this.pendingAnnotationCount);
    }
  }

  RecoveredAnnotation element = new RecoveredAnnotation(identifierPtr, identifierLengthPtr, annotationStart, this, bracketBalanceValue);

  this.pendingAnnotations[this.pendingAnnotationCount++] = element;

  return element;
}
public void addModifier(int flag, int modifiersSourceStart) {
  this.pendingModifiers |= flag;

  if (this.pendingModifersSourceStart < 0) {
    this.pendingModifersSourceStart = modifiersSourceStart;
  }
}
public void attach(RecoveredAnnotation[] annots, int annotCount, int mods, int modsSourceStart) {
  if (annotCount > 0) {
    Annotation[] existingAnnotations = this.typeDeclaration.annotations;
    if (existingAnnotations != null) {
      this.annotations = new RecoveredAnnotation[annotCount];
      this.annotationCount = 0;
      next : for (int i = 0; i < annotCount; i++) {
        for (int j = 0; j < existingAnnotations.length; j++) {
          if (annots[i].annotation == existingAnnotations[j]) continue next;
        }
        this.annotations[this.annotationCount++] = annots[i];
      }
    } else {
      this.annotations = annots;
      this.annotationCount = annotCount;
    }
  }

  if (mods != 0) {
    this.modifiers = mods;
    this.modifiersStart = modsSourceStart;
  }
}
/*
* Answer the body end of the corresponding parse node
*/
public int bodyEnd(){
  if (this.bodyEnd == 0) return this.typeDeclaration.declarationSourceEnd;
  return this.bodyEnd;
}
public boolean bodyStartsAtHeaderEnd(){
  if (this.typeDeclaration.superInterfaces == null){
    if (this.typeDeclaration.superclass == null){
      if(this.typeDeclaration.typeParameters == null) {
        return this.typeDeclaration.bodyStart == this.typeDeclaration.sourceEnd+1;
      } else {
        return this.typeDeclaration.bodyStart == this.typeDeclaration.typeParameters[this.typeDeclaration.typeParameters.length-1].sourceEnd+1;
      }
    } else {
      return this.typeDeclaration.bodyStart == this.typeDeclaration.superclass.sourceEnd+1;
    }
  } else {
    return this.typeDeclaration.bodyStart
        == this.typeDeclaration.superInterfaces[this.typeDeclaration.superInterfaces.length-1].sourceEnd+1;
  }
}
/*
* Answer the enclosing type node, or null if none
*/
public RecoveredType enclosingType(){
  RecoveredElement current = this.parent;
  while (current != null){
    if (current instanceof RecoveredType){
      return (RecoveredType) current;
    }
    current = current.parent;
  }
  return null;
}
public int lastMemberEnd() {
  int lastMemberEnd = this.typeDeclaration.bodyStart;

  if (this.fieldCount > 0) {
    FieldDeclaration lastField = this.fields[this.fieldCount - 1].fieldDeclaration;
    if (lastMemberEnd < lastField.declarationSourceEnd && lastField.declarationSourceEnd != 0) {
      lastMemberEnd = lastField.declarationSourceEnd;
    }
  }

  if (this.methodCount > 0) {
    AbstractMethodDeclaration lastMethod = this.methods[this.methodCount - 1].methodDeclaration;
    if (lastMemberEnd < lastMethod.declarationSourceEnd && lastMethod.declarationSourceEnd != 0) {
      lastMemberEnd = lastMethod.declarationSourceEnd;
    }
  }

  if (this.memberTypeCount > 0) {
    TypeDeclaration lastType = this.memberTypes[this.memberTypeCount - 1].typeDeclaration;
    if (lastMemberEnd < lastType.declarationSourceEnd && lastType.declarationSourceEnd != 0) {
      lastMemberEnd = lastType.declarationSourceEnd;
    }
  }

  return lastMemberEnd;
}
public char[] name(){
  return this.typeDeclaration.name;
}
/*
* Answer the associated parsed structure
*/
public ASTNode parseTree(){
  return this.typeDeclaration;
}
public void resetPendingModifiers() {
  this.pendingAnnotations = null;
  this.pendingAnnotationCount = 0;
  this.pendingModifiers = 0;
  this.pendingModifersSourceStart = -1;
}
/*
* Answer the very source end of the corresponding parse node
*/
public int sourceEnd(){
  return this.typeDeclaration.declarationSourceEnd;
}
public String toString(int tab) {
  StringBuffer result = new StringBuffer(tabString(tab));
  result.append("Recovered type:\n"); //$NON-NLS-1$
  if ((this.typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
    result.append(tabString(tab));
    result.append(" "); //$NON-NLS-1$
  }
  this.typeDeclaration.print(tab + 1, result);
  if (this.annotations != null) {
    for (int i = 0; i < this.annotationCount; i++) {
      result.append("\n"); //$NON-NLS-1$
      result.append(this.annotations[i].toString(tab + 1));
    }
  }
  if (this.memberTypes != null) {
    for (int i = 0; i < this.memberTypeCount; i++) {
      result.append("\n"); //$NON-NLS-1$
      result.append(this.memberTypes[i].toString(tab + 1));
    }
  }
  if (this.fields != null) {
    for (int i = 0; i < this.fieldCount; i++) {
      result.append("\n"); //$NON-NLS-1$
      result.append(this.fields[i].toString(tab + 1));
    }
  }
  if (this.methods != null) {
    for (int i = 0; i < this.methodCount; i++) {
      result.append("\n"); //$NON-NLS-1$
      result.append(this.methods[i].toString(tab + 1));
    }
  }
  return result.toString();
}
/*
* Update the bodyStart of the corresponding parse node
*/
public void updateBodyStart(int bodyStart){
  this.foundOpeningBrace = true;
  this.typeDeclaration.bodyStart = bodyStart;
}
public Statement updatedStatement(int depth, Set knownTypes){

  // ignore closed anonymous type
  if ((this.typeDeclaration.bits & ASTNode.IsAnonymousType) != 0 && !this.preserveContent){
    return null;
  }

  TypeDeclaration updatedType = updatedTypeDeclaration(depth + 1, knownTypes);
  if (updatedType != null && (updatedType.bits & ASTNode.IsAnonymousType) != 0){
    /* in presence of an anonymous type, we want the full allocation expression */
    QualifiedAllocationExpression allocation = updatedType.allocation;

    if (allocation.statementEnd == -1) {
      allocation.statementEnd = updatedType.declarationSourceEnd;
    }
    return allocation;
  }
  return updatedType;
}
public TypeDeclaration updatedTypeDeclaration(int depth, Set knownTypes){
  if (depth >= MAX_TYPE_DEPTH) return null;

  if(knownTypes.contains(this.typeDeclaration)) return null;
  knownTypes.add(this.typeDeclaration);
 
  int lastEnd = this.typeDeclaration.bodyStart;
  /* update annotations */
  if (this.modifiers != 0) {
    this.typeDeclaration.modifiers |= this.modifiers;
    if (this.modifiersStart < this.typeDeclaration.declarationSourceStart) {
      this.typeDeclaration.declarationSourceStart = this.modifiersStart;
    }
  }
  /* update annotations */
  if (this.annotationCount > 0){
    int existingCount = this.typeDeclaration.annotations == null ? 0 : this.typeDeclaration.annotations.length;
    Annotation[] annotationReferences = new Annotation[existingCount + this.annotationCount];
    if (existingCount > 0){
      System.arraycopy(this.typeDeclaration.annotations, 0, annotationReferences, this.annotationCount, existingCount);
    }
    for (int i = 0; i < this.annotationCount; i++){
      annotationReferences[i] = this.annotations[i].updatedAnnotationReference();
    }
    this.typeDeclaration.annotations = annotationReferences;

    int start = this.annotations[0].annotation.sourceStart;
    if (start < this.typeDeclaration.declarationSourceStart) {
      this.typeDeclaration.declarationSourceStart = start;
    }
  }
  /* update member types */
  if (this.memberTypeCount > 0){
    int existingCount = this.typeDeclaration.memberTypes == null ? 0 : this.typeDeclaration.memberTypes.length;
    TypeDeclaration[] memberTypeDeclarations = new TypeDeclaration[existingCount + this.memberTypeCount];
    if (existingCount > 0){
      System.arraycopy(this.typeDeclaration.memberTypes, 0, memberTypeDeclarations, 0, existingCount);
    }
    // may need to update the declarationSourceEnd of the last type
    if (this.memberTypes[this.memberTypeCount - 1].typeDeclaration.declarationSourceEnd == 0){
      int bodyEndValue = bodyEnd();
      this.memberTypes[this.memberTypeCount - 1].typeDeclaration.declarationSourceEnd = bodyEndValue;
      this.memberTypes[this.memberTypeCount - 1].typeDeclaration.bodyEnd =  bodyEndValue;
    }
   
    int updatedCount = 0;
    for (int i = 0; i < this.memberTypeCount; i++){
      TypeDeclaration updatedTypeDeclaration = this.memberTypes[i].updatedTypeDeclaration(depth + 1, knownTypes);
      if (updatedTypeDeclaration != null) {
        memberTypeDeclarations[existingCount + (updatedCount++)] = updatedTypeDeclaration;
      }
    }
    if (updatedCount < this.memberTypeCount) {
      int length = existingCount + updatedCount;
      System.arraycopy(memberTypeDeclarations, 0, memberTypeDeclarations = new TypeDeclaration[length], 0, length);
    }
   
    if (memberTypeDeclarations.length > 0) {
      this.typeDeclaration.memberTypes = memberTypeDeclarations;
      if(memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd > lastEnd) {
        lastEnd = memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd;
      }
    }
  }
  /* update fields */
  if (this.fieldCount > 0){
    int existingCount = this.typeDeclaration.fields == null ? 0 : this.typeDeclaration.fields.length;
    FieldDeclaration[] fieldDeclarations = new FieldDeclaration[existingCount + this.fieldCount];
    if (existingCount > 0){
      System.arraycopy(this.typeDeclaration.fields, 0, fieldDeclarations, 0, existingCount);
    }
    // may need to update the declarationSourceEnd of the last field
    if (this.fields[this.fieldCount - 1].fieldDeclaration.declarationSourceEnd == 0){
      int temp = bodyEnd();
      this.fields[this.fieldCount - 1].fieldDeclaration.declarationSourceEnd = temp;
      this.fields[this.fieldCount - 1].fieldDeclaration.declarationEnd = temp;
    }
    for (int i = 0; i < this.fieldCount; i++){
      fieldDeclarations[existingCount + i] = this.fields[i].updatedFieldDeclaration(depth, knownTypes);
    }
   
    for (int i = this.fieldCount - 1; 0 < i; i--) {
      if (fieldDeclarations[existingCount + i - 1].declarationSourceStart == fieldDeclarations[existingCount + i].declarationSourceStart) {
        fieldDeclarations[existingCount + i - 1].declarationSourceEnd = fieldDeclarations[existingCount + i].declarationSourceEnd;
        fieldDeclarations[existingCount + i - 1].declarationEnd = fieldDeclarations[existingCount + i].declarationEnd;
      }
    }
   
    this.typeDeclaration.fields = fieldDeclarations;
    if(fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd > lastEnd) {
      lastEnd = fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd;
    }
  }
  /* update methods */
  int existingCount = this.typeDeclaration.methods == null ? 0 : this.typeDeclaration.methods.length;
  boolean hasConstructor = false, hasRecoveredConstructor = false;
  boolean hasAbstractMethods = false;
  int defaultConstructorIndex = -1;
  if (this.methodCount > 0){
    AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[existingCount + this.methodCount];
    for (int i = 0; i < existingCount; i++){
      AbstractMethodDeclaration m = this.typeDeclaration.methods[i];
      if (m.isDefaultConstructor()) defaultConstructorIndex = i;
      if (m.isAbstract()) hasAbstractMethods = true;
      methodDeclarations[i] = m;
    }
    // may need to update the declarationSourceEnd of the last method
    if (this.methods[this.methodCount - 1].methodDeclaration.declarationSourceEnd == 0){
      int bodyEndValue = bodyEnd();
      this.methods[this.methodCount - 1].methodDeclaration.declarationSourceEnd = bodyEndValue;
      this.methods[this.methodCount - 1].methodDeclaration.bodyEnd = bodyEndValue;
    }
    for (int i = 0; i < this.methodCount; i++){
      AbstractMethodDeclaration updatedMethod = this.methods[i].updatedMethodDeclaration(depth, knownTypes);
      if (updatedMethod.isConstructor()) hasRecoveredConstructor = true;
      if (updatedMethod.isAbstract()) hasAbstractMethods = true;
      methodDeclarations[existingCount + i] = updatedMethod;
    }
    this.typeDeclaration.methods = methodDeclarations;
    if(methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd > lastEnd) {
      lastEnd = methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd;
    }
    if (hasAbstractMethods) this.typeDeclaration.bits |= ASTNode.HasAbstractMethods;
    hasConstructor = this.typeDeclaration.checkConstructors(parser());
  } else {
    for (int i = 0; i < existingCount; i++){
      if (this.typeDeclaration.methods[i].isConstructor()) hasConstructor = true;
    }
  }
  /* add clinit ? */
  if (this.typeDeclaration.needClassInitMethod()){
    boolean alreadyHasClinit = false;
    for (int i = 0; i < existingCount; i++){
      if (this.typeDeclaration.methods[i].isClinit()){
        alreadyHasClinit = true;
        break;
      }
    }
    if (!alreadyHasClinit) this.typeDeclaration.addClinit();
  }
  /* add default constructor ? */
  if (defaultConstructorIndex >= 0 && hasRecoveredConstructor){
    /* should discard previous default construtor */
    AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[this.typeDeclaration.methods.length - 1];
    if (defaultConstructorIndex != 0){
      System.arraycopy(this.typeDeclaration.methods, 0, methodDeclarations, 0, defaultConstructorIndex);
    }
    if (defaultConstructorIndex != this.typeDeclaration.methods.length-1){
      System.arraycopy(
        this.typeDeclaration.methods,
        defaultConstructorIndex+1,
        methodDeclarations,
        defaultConstructorIndex,
        this.typeDeclaration.methods.length - defaultConstructorIndex - 1);
    }
    this.typeDeclaration.methods = methodDeclarations;
  } else {
    int kind = TypeDeclaration.kind(this.typeDeclaration.modifiers);
    if (!hasConstructor &&
        kind != TypeDeclaration.INTERFACE_DECL &&
        kind != TypeDeclaration.ANNOTATION_TYPE_DECL &&
        this.typeDeclaration.allocation == null) {// if was already reduced, then constructor
      boolean insideFieldInitializer = false;
      RecoveredElement parentElement = this.parent;
      while (parentElement != null){
        if (parentElement instanceof RecoveredField){
            insideFieldInitializer = true;
            break;
        }
        parentElement = parentElement.parent;
      }
      this.typeDeclaration.createDefaultConstructor(!parser().diet || insideFieldInitializer, true);
    }
  }
  if (this.parent instanceof RecoveredType){
    this.typeDeclaration.bits |= ASTNode.IsMemberType;
  } else if (this.parent instanceof RecoveredMethod){
    this.typeDeclaration.bits |= ASTNode.IsLocalType;
  }
  if(this.typeDeclaration.declarationSourceEnd == 0) {
    this.typeDeclaration.declarationSourceEnd = lastEnd;
    this.typeDeclaration.bodyEnd = lastEnd;
  }
  return this.typeDeclaration;
}
/*
* Update the corresponding parse node from parser state which
* is about to disappear because of restarting recovery
*/
public void updateFromParserState(){

  // anymous type and enum constant doesn't need to be updated
  if(bodyStartsAtHeaderEnd() && this.typeDeclaration.allocation == null){
    Parser parser = parser();
    /* might want to recover implemented interfaces */
    // protection for bugs 15142
    if (parser.listLength > 0 && parser.astLengthPtr > 0){ // awaiting interface type references
      int length = parser.astLengthStack[parser.astLengthPtr];
      int astPtr = parser.astPtr - length;
      boolean canConsume = astPtr >= 0;
      if(canConsume) {
        if((!(parser.astStack[astPtr] instanceof TypeDeclaration))) {
          canConsume = false;
        }
        for (int i = 1, max = length + 1; i < max; i++) {
          if(!(parser.astStack[astPtr + i ] instanceof TypeReference)) {
            canConsume = false;
          }
        }
      }
      if(canConsume) {
        parser.consumeClassHeaderImplements();
        // will reset typeListLength to zero
        // thus this check will only be performed on first errorCheck after class X implements Y,Z,
      }
    } else if (parser.listTypeParameterLength > 0) {
      int length = parser.listTypeParameterLength;
      int genericsPtr = parser.genericsPtr;
      boolean canConsume = genericsPtr + 1 >= length && parser.astPtr > -1;
      if(canConsume) {
        if (!(parser.astStack[parser.astPtr] instanceof TypeDeclaration)) {
          canConsume = false;
        }
        while(genericsPtr + 1 > length && !(parser.genericsStack[genericsPtr] instanceof TypeParameter)) {
          genericsPtr--;
        }
        for (int i = 0; i < length; i++) {
          if(!(parser.genericsStack[genericsPtr - i] instanceof TypeParameter)) {
            canConsume = false;
          }
        }
      }
      if(canConsume) {
        TypeDeclaration typeDecl = (TypeDeclaration)parser.astStack[parser.astPtr];
        System.arraycopy(parser.genericsStack, genericsPtr - length + 1, typeDecl.typeParameters = new TypeParameter[length], 0, length);
        typeDecl.bodyStart = typeDecl.typeParameters[length-1].declarationSourceEnd + 1;
        parser.listTypeParameterLength = 0;
        parser.lastCheckPoint = typeDecl.bodyStart;
      }
    }
  }
}
/*
* A closing brace got consumed, might have closed the current element,
* in which case both the currentElement is exited
*/
public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
  if ((--this.bracketBalance <= 0) && (this.parent != null)){
    this.updateSourceEndIfNecessary(braceStart, braceEnd);
    this.bodyEnd = braceStart - 1;
    return this.parent;
  }
  return this;
}
/*
* An opening brace got consumed, might be the expected opening one of the current element,
* in which case the bodyStart is updated.
*/
public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
  /* in case the opening brace is not close enough to the signature, ignore it */
  if (this.bracketBalance == 0){
    /*
      if (parser.scanner.searchLineNumber(typeDeclaration.sourceEnd)
        != parser.scanner.searchLineNumber(braceEnd)){
     */
    Parser parser = parser();
    switch(parser.lastIgnoredToken){
      case -1 :
      case TokenNameextends :
      case TokenNameimplements :
      case TokenNameGREATER :
      case TokenNameRIGHT_SHIFT :
      case TokenNameUNSIGNED_RIGHT_SHIFT :
        if (parser.recoveredStaticInitializerStart == 0) break;
      //$FALL-THROUGH$
      default:
        this.foundOpeningBrace = true;
        this.bracketBalance = 1; // pretend the brace was already there
    }
  }
  // might be an initializer
  if (this.bracketBalance == 1){
    Block block = new Block(0);
    Parser parser = parser();
    block.sourceStart = parser.scanner.startPosition;
    Initializer init;
    if (parser.recoveredStaticInitializerStart == 0){
      init = new Initializer(block, ClassFileConstants.AccDefault);
    } else {
      init = new Initializer(block, ClassFileConstants.AccStatic);
      init.declarationSourceStart = parser.recoveredStaticInitializerStart;
    }
    init.bodyStart = parser.scanner.currentPosition;
    return this.add(init, 1);
  }
  return super.updateOnOpeningBrace(braceStart, braceEnd);
}
public void updateParseTree(){
  updatedTypeDeclaration(0, new HashSet());
}
/*
* Update the declarationSourceEnd of the corresponding parse node
*/
public void updateSourceEndIfNecessary(int start, int end){
  if (this.typeDeclaration.declarationSourceEnd == 0){
    this.bodyEnd = 0;
    this.typeDeclaration.declarationSourceEnd = end;
    this.typeDeclaration.bodyEnd = end;
  }
}
}
TOP

Related Classes of org.eclipse.jdt.internal.compiler.parser.RecoveredType

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.