first scanner /parser copied from the jdt java version
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / RecoveredUnit.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.parser;
12
13 /**
14  * Internal field structure for parsing recovery 
15  */
16 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
17 import net.sourceforge.phpdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
18 import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
19 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
21 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
22 import net.sourceforge.phpdt.internal.compiler.ast.LocalTypeDeclaration;
23 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
24
25 public class RecoveredUnit extends RecoveredElement {
26
27         public CompilationUnitDeclaration unitDeclaration;
28         
29         public RecoveredImport[] imports;
30         public int importCount;
31         public RecoveredType[] types;
32         public int typeCount;
33 public RecoveredUnit(CompilationUnitDeclaration unitDeclaration, int bracketBalance, Parser parser){
34         super(null, bracketBalance, parser);
35         this.unitDeclaration = unitDeclaration;
36 }
37 /*
38  *      Record a method declaration: should be attached to last type
39  */
40 public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalance) {
41
42         /* attach it to last type - if any */
43         if (typeCount > 0){
44                 RecoveredType type = this.types[typeCount -1];
45                 type.bodyEnd = 0; // reset position
46                 type.typeDeclaration.declarationSourceEnd = 0; // reset position
47                 type.typeDeclaration.bodyEnd = 0;
48                 return type.add(methodDeclaration, bracketBalance);
49         }
50         return this; // ignore
51 }
52 /*
53  *      Record a field declaration: should be attached to last type
54  */
55 public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
56
57         /* attach it to last type - if any */
58         if (typeCount > 0){
59                 RecoveredType type = this.types[typeCount -1];
60                 type.bodyEnd = 0; // reset position
61                 type.typeDeclaration.declarationSourceEnd = 0; // reset position
62                 type.typeDeclaration.bodyEnd = 0;
63                 return type.add(fieldDeclaration, bracketBalance);
64         }
65         return this; // ignore
66 }
67 public RecoveredElement add(ImportReference importReference, int bracketBalance) {
68         if (imports == null) {
69                 imports = new RecoveredImport[5];
70                 importCount = 0;
71         } else {
72                 if (importCount == imports.length) {
73                         System.arraycopy(
74                                 imports, 
75                                 0, 
76                                 (imports = new RecoveredImport[2 * importCount]), 
77                                 0, 
78                                 importCount); 
79                 }
80         }
81         RecoveredImport element = new RecoveredImport(importReference, this, bracketBalance);
82         imports[importCount++] = element;
83
84         /* if import not finished, then import becomes current */
85         if (importReference.declarationSourceEnd == 0) return element;
86         return this;            
87 }
88 public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
89         
90         if (typeDeclaration instanceof AnonymousLocalTypeDeclaration){
91                 if (this.typeCount > 0) {
92                         // add it to the last type
93                         RecoveredType lastType = this.types[this.typeCount-1];
94                         lastType.bodyEnd = 0; // reopen type
95                         lastType.typeDeclaration.bodyEnd = 0; // reopen type
96                         lastType.typeDeclaration.declarationSourceEnd = 0; // reopen type
97                         lastType.bracketBalance++; // expect one closing brace
98                         return lastType.add(typeDeclaration, bracketBalance);
99                 }
100         }
101         if (types == null) {
102                 types = new RecoveredType[5];
103                 typeCount = 0;
104         } else {
105                 if (typeCount == types.length) {
106                         System.arraycopy(
107                                 types, 
108                                 0, 
109                                 (types = new RecoveredType[2 * typeCount]), 
110                                 0, 
111                                 typeCount); 
112                 }
113         }
114         RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalance);
115         types[typeCount++] = element;
116
117         /* if type not finished, then type becomes current */
118         if (typeDeclaration.declarationSourceEnd == 0) return element;
119         return this;    
120 }
121 /* 
122  * Answer the associated parsed structure
123  */
124 public AstNode parseTree(){
125         return unitDeclaration;
126 }
127 /*
128  * Answer the very source end of the corresponding parse node
129  */
130 public int sourceEnd(){
131         return this.unitDeclaration.sourceEnd;
132 }
133 public String toString(int tab) {
134         StringBuffer result = new StringBuffer(tabString(tab));
135         result.append("Recovered unit: [\n"); //$NON-NLS-1$
136         result.append(unitDeclaration.toString(tab + 1));
137         result.append(tabString(tab + 1));
138         result.append("]"); //$NON-NLS-1$
139         if (this.imports != null) {
140                 for (int i = 0; i < this.importCount; i++) {
141                         result.append("\n"); //$NON-NLS-1$
142                         result.append(this.imports[i].toString(tab + 1));
143                 }
144         }
145         if (this.types != null) {
146                 for (int i = 0; i < this.typeCount; i++) {
147                         result.append("\n"); //$NON-NLS-1$
148                         result.append(this.types[i].toString(tab + 1));
149                 }
150         }
151         return result.toString();
152 }
153 public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){
154
155         /* update imports */
156         if (importCount > 0){
157                 ImportReference[] importRefences = new ImportReference[importCount];
158                 for (int i = 0; i < importCount; i++){
159                         importRefences[i] = imports[i].updatedImportReference();
160                 }
161                 unitDeclaration.imports = importRefences;
162         }
163         /* update types */
164         if (typeCount > 0){
165                 int existingCount = unitDeclaration.types == null ? 0 : unitDeclaration.types.length;
166                 TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + typeCount];
167                 if (existingCount > 0){
168                         System.arraycopy(unitDeclaration.types, 0, typeDeclarations, 0, existingCount);
169                 }
170                 // may need to update the declarationSourceEnd of the last type
171                 if (types[typeCount - 1].typeDeclaration.declarationSourceEnd == 0){
172                         types[typeCount - 1].typeDeclaration.declarationSourceEnd = unitDeclaration.sourceEnd;
173                         types[typeCount - 1].typeDeclaration.bodyEnd = unitDeclaration.sourceEnd;
174                 }
175                 int actualCount = existingCount;
176                 for (int i = 0; i < typeCount; i++){
177                         TypeDeclaration typeDecl = types[i].updatedTypeDeclaration();
178                         // filter out local types (12454)
179                         if (!(typeDecl instanceof LocalTypeDeclaration)){
180                                 typeDeclarations[actualCount++] = typeDecl;
181                         }
182                 }
183                 if (actualCount != typeCount){
184                         System.arraycopy(
185                                 typeDeclarations, 
186                                 0, 
187                                 typeDeclarations = new TypeDeclaration[existingCount+actualCount], 
188                                 0, 
189                                 existingCount+actualCount);
190                 }
191                 unitDeclaration.types = typeDeclarations;
192         }
193         return unitDeclaration;
194 }
195 public void updateParseTree(){
196         this.updatedCompilationUnitDeclaration();
197 }
198 /*
199  * Update the sourceEnd of the corresponding parse node
200  */
201 public void updateSourceEndIfNecessary(int sourceEnd){
202         if (this.unitDeclaration.sourceEnd == 0)
203                 this.unitDeclaration.sourceEnd = sourceEnd;
204 }
205 }