blob: a3f3de90d5ae2bc1f0a844960dd90ba4d0cbad2e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 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;
/**
* Internal field structure for parsing recovery
*/
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
public class RecoveredUnit extends RecoveredElement {
public CompilationUnitDeclaration unitDeclaration;
public RecoveredImport[] imports;
public int importCount;
public RecoveredType[] types;
public int typeCount;
public RecoveredUnit(CompilationUnitDeclaration unitDeclaration, int bracketBalance, Parser parser){
super(null, bracketBalance, parser);
this.unitDeclaration = unitDeclaration;
}
/*
* Record a method declaration: should be attached to last type
*/
public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
/* attach it to last type - if any */
if (this.typeCount > 0){
RecoveredType type = this.types[this.typeCount -1];
int start = type.bodyEnd;
int end = type.typeDeclaration.bodyEnd;
type.bodyEnd = 0; // reset position
type.typeDeclaration.declarationSourceEnd = 0; // reset position
type.typeDeclaration.bodyEnd = 0;
if(start > 0 && start < end) {
Initializer initializer = new Initializer(new Block(0), 0);
initializer.bodyStart = end;
initializer.bodyEnd = end;
initializer.declarationSourceStart = end;
initializer.declarationSourceEnd = end;
type.add(initializer, bracketBalanceValue);
}
return type.add(methodDeclaration, bracketBalanceValue);
}
return this; // ignore
}
/*
* Record a field declaration: should be attached to last type
*/
public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
/* attach it to last type - if any */
if (this.typeCount > 0){
RecoveredType type = this.types[this.typeCount -1];
type.bodyEnd = 0; // reset position
type.typeDeclaration.declarationSourceEnd = 0; // reset position
type.typeDeclaration.bodyEnd = 0;
return type.add(fieldDeclaration, bracketBalanceValue);
}
return this; // ignore
}
public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) {
if (this.imports == null) {
this.imports = new RecoveredImport[5];
this.importCount = 0;
} else {
if (this.importCount == this.imports.length) {
System.arraycopy(
this.imports,
0,
(this.imports = new RecoveredImport[2 * this.importCount]),
0,
this.importCount);
}
}
RecoveredImport element = new RecoveredImport(importReference, this, bracketBalanceValue);
this.imports[this.importCount++] = element;
/* if import not finished, then import becomes current */
if (importReference.declarationSourceEnd == 0) return element;
return this;
}
public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0){
if (this.typeCount > 0) {
// add it to the last type
RecoveredType lastType = this.types[this.typeCount-1];
lastType.bodyEnd = 0; // reopen type
lastType.typeDeclaration.bodyEnd = 0; // reopen type
lastType.typeDeclaration.declarationSourceEnd = 0; // reopen type
lastType.bracketBalance++; // expect one closing brace
return lastType.add(typeDeclaration, bracketBalanceValue);
}
}
if (this.types == null) {
this.types = new RecoveredType[5];
this.typeCount = 0;
} else {
if (this.typeCount == this.types.length) {
System.arraycopy(
this.types,
0,
(this.types = new RecoveredType[2 * this.typeCount]),
0,
this.typeCount);
}
}
RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
this.types[this.typeCount++] = element;
/* if type not finished, then type becomes current */
if (typeDeclaration.declarationSourceEnd == 0) return element;
return this;
}
/*
* Answer the associated parsed structure
*/
public ASTNode parseTree(){
return this.unitDeclaration;
}
/*
* Answer the very source end of the corresponding parse node
*/
public int sourceEnd(){
return this.unitDeclaration.sourceEnd;
}
public String toString(int tab) {
StringBuffer result = new StringBuffer(tabString(tab));
result.append("Recovered unit: [\n"); //$NON-NLS-1$
this.unitDeclaration.print(tab + 1, result);
result.append(tabString(tab + 1));
result.append("]"); //$NON-NLS-1$
if (this.imports != null) {
for (int i = 0; i < this.importCount; i++) {
result.append("\n"); //$NON-NLS-1$
result.append(this.imports[i].toString(tab + 1));
}
}
if (this.types != null) {
for (int i = 0; i < this.typeCount; i++) {
result.append("\n"); //$NON-NLS-1$
result.append(this.types[i].toString(tab + 1));
}
}
return result.toString();
}
public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){
/* update imports */
if (this.importCount > 0){
ImportReference[] importRefences = new ImportReference[this.importCount];
for (int i = 0; i < this.importCount; i++){
importRefences[i] = this.imports[i].updatedImportReference();
}
this.unitDeclaration.imports = importRefences;
}
/* update types */
if (this.typeCount > 0){
int existingCount = this.unitDeclaration.types == null ? 0 : this.unitDeclaration.types.length;
TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + this.typeCount];
if (existingCount > 0){
System.arraycopy(this.unitDeclaration.types, 0, typeDeclarations, 0, existingCount);
}
// may need to update the declarationSourceEnd of the last type
if (this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd == 0){
this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd = this.unitDeclaration.sourceEnd;
this.types[this.typeCount - 1].typeDeclaration.bodyEnd = this.unitDeclaration.sourceEnd;
}
int actualCount = existingCount;
for (int i = 0; i < this.typeCount; i++){
TypeDeclaration typeDecl = this.types[i].updatedTypeDeclaration();
// filter out local types (12454)
if ((typeDecl.bits & ASTNode.IsLocalTypeMASK) == 0){
typeDeclarations[actualCount++] = typeDecl;
}
}
if (actualCount != this.typeCount){
System.arraycopy(
typeDeclarations,
0,
typeDeclarations = new TypeDeclaration[existingCount+actualCount],
0,
existingCount+actualCount);
}
this.unitDeclaration.types = typeDeclarations;
}
return this.unitDeclaration;
}
public void updateParseTree(){
this.updatedCompilationUnitDeclaration();
}
/*
* Update the sourceEnd of the corresponding parse node
*/
public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
if (this.unitDeclaration.sourceEnd == 0)
this.unitDeclaration.sourceEnd = bodyEnd;
}
}