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.Block;
19 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
20 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
21 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
22 import org.eclipse.jdt.internal.compiler.ast.Initializer;
23 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
25 public class RecoveredUnit extends RecoveredElement {
27 public CompilationUnitDeclaration unitDeclaration;
29 public RecoveredImport[] imports;
30 public int importCount;
31 public RecoveredType[] types;
33 public RecoveredUnit(CompilationUnitDeclaration unitDeclaration, int bracketBalance, Parser parser){
34 super(null, bracketBalance, parser);
35 this.unitDeclaration = unitDeclaration;
38 * Record a method declaration: should be attached to last type
40 public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
42 /* attach it to last type - if any */
43 if (this.typeCount > 0){
44 RecoveredType type = this.types[this.typeCount -1];
45 int start = type.bodyEnd;
46 int end = type.typeDeclaration.bodyEnd;
47 type.bodyEnd = 0; // reset position
48 type.typeDeclaration.declarationSourceEnd = 0; // reset position
49 type.typeDeclaration.bodyEnd = 0;
51 if(start > 0 && start < end) {
52 Initializer initializer = new Initializer(new Block(0), 0);
53 initializer.bodyStart = end;
54 initializer.bodyEnd = end;
55 initializer.declarationSourceStart = end;
56 initializer.declarationSourceEnd = end;
57 type.add(initializer, bracketBalanceValue);
60 return type.add(methodDeclaration, bracketBalanceValue);
62 return this; // ignore
65 * Record a field declaration: should be attached to last type
67 public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
69 /* attach it to last type - if any */
70 if (this.typeCount > 0){
71 RecoveredType type = this.types[this.typeCount -1];
72 type.bodyEnd = 0; // reset position
73 type.typeDeclaration.declarationSourceEnd = 0; // reset position
74 type.typeDeclaration.bodyEnd = 0;
75 return type.add(fieldDeclaration, bracketBalanceValue);
77 return this; // ignore
79 public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) {
80 if (this.imports == null) {
81 this.imports = new RecoveredImport[5];
84 if (this.importCount == this.imports.length) {
88 (this.imports = new RecoveredImport[2 * this.importCount]),
93 RecoveredImport element = new RecoveredImport(importReference, this, bracketBalanceValue);
94 this.imports[this.importCount++] = element;
96 /* if import not finished, then import becomes current */
97 if (importReference.declarationSourceEnd == 0) return element;
100 public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
102 if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0){
103 if (this.typeCount > 0) {
104 // add it to the last type
105 RecoveredType lastType = this.types[this.typeCount-1];
106 lastType.bodyEnd = 0; // reopen type
107 lastType.typeDeclaration.bodyEnd = 0; // reopen type
108 lastType.typeDeclaration.declarationSourceEnd = 0; // reopen type
109 lastType.bracketBalance++; // expect one closing brace
110 return lastType.add(typeDeclaration, bracketBalanceValue);
113 if (this.types == null) {
114 this.types = new RecoveredType[5];
117 if (this.typeCount == this.types.length) {
121 (this.types = new RecoveredType[2 * this.typeCount]),
126 RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
127 this.types[this.typeCount++] = element;
129 /* if type not finished, then type becomes current */
130 if (typeDeclaration.declarationSourceEnd == 0) return element;
134 * Answer the associated parsed structure
136 public ASTNode parseTree(){
137 return this.unitDeclaration;
140 * Answer the very source end of the corresponding parse node
142 public int sourceEnd(){
143 return this.unitDeclaration.sourceEnd;
145 public String toString(int tab) {
146 StringBuffer result = new StringBuffer(tabString(tab));
147 result.append("Recovered unit: [\n"); //$NON-NLS-1$
148 this.unitDeclaration.print(tab + 1, result);
149 result.append(tabString(tab + 1));
150 result.append("]"); //$NON-NLS-1$
151 if (this.imports != null) {
152 for (int i = 0; i < this.importCount; i++) {
153 result.append("\n"); //$NON-NLS-1$
154 result.append(this.imports[i].toString(tab + 1));
157 if (this.types != null) {
158 for (int i = 0; i < this.typeCount; i++) {
159 result.append("\n"); //$NON-NLS-1$
160 result.append(this.types[i].toString(tab + 1));
163 return result.toString();
165 public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){
168 if (this.importCount > 0){
169 ImportReference[] importRefences = new ImportReference[this.importCount];
170 for (int i = 0; i < this.importCount; i++){
171 importRefences[i] = this.imports[i].updatedImportReference();
173 this.unitDeclaration.imports = importRefences;
176 if (this.typeCount > 0){
177 int existingCount = this.unitDeclaration.types == null ? 0 : this.unitDeclaration.types.length;
178 TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + this.typeCount];
179 if (existingCount > 0){
180 System.arraycopy(this.unitDeclaration.types, 0, typeDeclarations, 0, existingCount);
182 // may need to update the declarationSourceEnd of the last type
183 if (this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd == 0){
184 this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd = this.unitDeclaration.sourceEnd;
185 this.types[this.typeCount - 1].typeDeclaration.bodyEnd = this.unitDeclaration.sourceEnd;
187 int actualCount = existingCount;
188 for (int i = 0; i < this.typeCount; i++){
189 TypeDeclaration typeDecl = this.types[i].updatedTypeDeclaration();
190 // filter out local types (12454)
191 if ((typeDecl.bits & ASTNode.IsLocalTypeMASK) == 0){
192 typeDeclarations[actualCount++] = typeDecl;
195 if (actualCount != this.typeCount){
199 typeDeclarations = new TypeDeclaration[existingCount+actualCount],
201 existingCount+actualCount);
203 this.unitDeclaration.types = typeDeclarations;
205 return this.unitDeclaration;
207 public void updateParseTree(){
208 this.updatedCompilationUnitDeclaration();
211 * Update the sourceEnd of the corresponding parse node
213 public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
214 if (this.unitDeclaration.sourceEnd == 0)
215 this.unitDeclaration.sourceEnd = bodyEnd;