1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.parser;
14 * Internal field structure for parsing recovery
16 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
17 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
18 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
19 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
20 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
21 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
23 public class RecoveredUnit extends RecoveredElement {
25 public CompilationUnitDeclaration unitDeclaration;
27 public RecoveredImport[] imports;
28 public int importCount;
29 public RecoveredType[] types;
31 public RecoveredUnit(CompilationUnitDeclaration unitDeclaration, int bracketBalance, Parser parser){
32 super(null, bracketBalance, parser);
33 this.unitDeclaration = unitDeclaration;
36 * Record a method declaration: should be attached to last type
38 public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
40 /* attach it to last type - if any */
41 if (this.typeCount > 0){
42 RecoveredType type = this.types[this.typeCount -1];
43 type.bodyEnd = 0; // reset position
44 type.typeDeclaration.declarationSourceEnd = 0; // reset position
45 type.typeDeclaration.bodyEnd = 0;
46 return type.add(methodDeclaration, bracketBalanceValue);
48 return this; // ignore
51 * Record a field declaration: should be attached to last type
53 public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
55 /* attach it to last type - if any */
56 if (this.typeCount > 0){
57 RecoveredType type = this.types[this.typeCount -1];
58 type.bodyEnd = 0; // reset position
59 type.typeDeclaration.declarationSourceEnd = 0; // reset position
60 type.typeDeclaration.bodyEnd = 0;
61 return type.add(fieldDeclaration, bracketBalanceValue);
63 return this; // ignore
65 public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) {
66 if (this.imports == null) {
67 this.imports = new RecoveredImport[5];
70 if (this.importCount == this.imports.length) {
74 (this.imports = new RecoveredImport[2 * this.importCount]),
79 RecoveredImport element = new RecoveredImport(importReference, this, bracketBalanceValue);
80 this.imports[this.importCount++] = element;
82 /* if import not finished, then import becomes current */
83 if (importReference.declarationSourceEnd == 0) return element;
86 public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
88 if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0){
89 if (this.typeCount > 0) {
90 // add it to the last type
91 RecoveredType lastType = this.types[this.typeCount-1];
92 lastType.bodyEnd = 0; // reopen type
93 lastType.typeDeclaration.bodyEnd = 0; // reopen type
94 lastType.typeDeclaration.declarationSourceEnd = 0; // reopen type
95 lastType.bracketBalance++; // expect one closing brace
96 return lastType.add(typeDeclaration, bracketBalanceValue);
99 if (this.types == null) {
100 this.types = new RecoveredType[5];
103 if (this.typeCount == this.types.length) {
107 (this.types = new RecoveredType[2 * this.typeCount]),
112 RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
113 this.types[this.typeCount++] = element;
115 /* if type not finished, then type becomes current */
116 if (typeDeclaration.declarationSourceEnd == 0) return element;
120 * Answer the associated parsed structure
122 public ASTNode parseTree(){
123 return this.unitDeclaration;
126 * Answer the very source end of the corresponding parse node
128 public int sourceEnd(){
129 return this.unitDeclaration.sourceEnd;
131 public String toString(int tab) {
132 StringBuffer result = new StringBuffer(tabString(tab));
133 result.append("Recovered unit: [\n"); //$NON-NLS-1$
134 this.unitDeclaration.print(tab + 1, result);
135 result.append(tabString(tab + 1));
136 result.append("]"); //$NON-NLS-1$
137 if (this.imports != null) {
138 for (int i = 0; i < this.importCount; i++) {
139 result.append("\n"); //$NON-NLS-1$
140 result.append(this.imports[i].toString(tab + 1));
143 if (this.types != null) {
144 for (int i = 0; i < this.typeCount; i++) {
145 result.append("\n"); //$NON-NLS-1$
146 result.append(this.types[i].toString(tab + 1));
149 return result.toString();
151 public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){
154 if (this.importCount > 0){
155 ImportReference[] importRefences = new ImportReference[this.importCount];
156 for (int i = 0; i < this.importCount; i++){
157 importRefences[i] = this.imports[i].updatedImportReference();
159 this.unitDeclaration.imports = importRefences;
162 if (this.typeCount > 0){
163 int existingCount = this.unitDeclaration.types == null ? 0 : this.unitDeclaration.types.length;
164 TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + this.typeCount];
165 if (existingCount > 0){
166 System.arraycopy(this.unitDeclaration.types, 0, typeDeclarations, 0, existingCount);
168 // may need to update the declarationSourceEnd of the last type
169 if (this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd == 0){
170 this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd = this.unitDeclaration.sourceEnd;
171 this.types[this.typeCount - 1].typeDeclaration.bodyEnd = this.unitDeclaration.sourceEnd;
173 int actualCount = existingCount;
174 for (int i = 0; i < this.typeCount; i++){
175 TypeDeclaration typeDecl = this.types[i].updatedTypeDeclaration();
176 // filter out local types (12454)
177 if ((typeDecl.bits & ASTNode.IsLocalTypeMASK) == 0){
178 typeDeclarations[actualCount++] = typeDecl;
181 if (actualCount != this.typeCount){
185 typeDeclarations = new TypeDeclaration[existingCount+actualCount],
187 existingCount+actualCount);
189 this.unitDeclaration.types = typeDeclarations;
191 return this.unitDeclaration;
193 public void updateParseTree(){
194 this.updatedCompilationUnitDeclaration();
197 * Update the sourceEnd of the corresponding parse node
199 public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
200 if (this.unitDeclaration.sourceEnd == 0)
201 this.unitDeclaration.sourceEnd = bodyEnd;