67415327582c622fd561264487ffee394b47d68a
[phpeclipse.git] /
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.ast;
12
13 import net.sourceforge.phpdt.internal.compiler.ClassFile;
14 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
15 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
16 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
17 import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.ImportBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
21 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilationUnit;
22 import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod;
23 import net.sourceforge.phpdt.internal.compiler.problem.AbortType;
24 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
25 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
26 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
27
28 public class CompilationUnitDeclaration
29         extends AstNode
30         implements ProblemSeverities, ReferenceContext {
31                 
32         public ImportReference currentPackage;
33         public ImportReference[] imports;
34         public TypeDeclaration[] types;
35         //public char[][] name;
36
37         public boolean ignoreFurtherInvestigation = false;      // once pointless to investigate due to errors
38         public boolean ignoreMethodBodies = false;
39         public CompilationUnitScope scope;
40         public ProblemReporter problemReporter;
41         public CompilationResult compilationResult;
42
43         private LocalTypeBinding[] allLocalTypes;
44         public boolean isPropagatingInnerClassEmulation;
45
46         public CompilationUnitDeclaration(
47                 ProblemReporter problemReporter,
48                 CompilationResult compilationResult,
49                 int sourceLength) {
50
51                 this.problemReporter = problemReporter;
52                 this.compilationResult = compilationResult;
53
54                 //by definition of a compilation unit....
55                 sourceStart = 0;
56                 sourceEnd = sourceLength - 1;
57
58         }
59
60         /*
61          *      We cause the compilation task to abort to a given extent.
62          */
63         public void abort(int abortLevel) {
64
65                 switch (abortLevel) {
66                         case AbortType :
67                                 throw new AbortType(compilationResult);
68                         case AbortMethod :
69                                 throw new AbortMethod(compilationResult);
70                         default :
71                                 throw new AbortCompilationUnit(compilationResult);
72                 }
73         }
74
75         /*
76          * Dispatch code analysis AND request saturation of inner emulation
77          */
78         public void analyseCode() {
79
80                 if (ignoreFurtherInvestigation)
81                         return;
82                 try {
83                         if (types != null) {
84                                 for (int i = 0, count = types.length; i < count; i++) {
85                                         types[i].analyseCode(scope);
86                                 }
87                         }
88                         // request inner emulation propagation
89                         propagateInnerEmulationForAllLocalTypes();
90                 } catch (AbortCompilationUnit e) {
91                         this.ignoreFurtherInvestigation = true;
92                         return;
93                 }
94         }
95
96         /*
97          * When unit result is about to be accepted, removed back pointers
98          * to compiler structures.
99          */
100         public void cleanUp() {
101
102                 ClassFile[] classFiles = compilationResult.getClassFiles();
103                 for (int i = 0, max = classFiles.length; i < max; i++) {
104                         // clear the classFile back pointer to the bindings
105                         ClassFile classFile = classFiles[i];
106                         // null out the type's scope backpointers
107                          ((SourceTypeBinding) classFile.referenceBinding).scope = null;
108                         // null out the classfile backpointer to a type binding
109                         classFile.referenceBinding = null;
110                         classFile.codeStream = null; // codeStream holds onto ast and scopes
111                         classFile.innerClassesBindings = null;
112                 }
113         }
114
115         public void checkUnusedImports(){
116                 
117                 if (this.scope.imports != null){
118                         for (int i = 0, max = this.scope.imports.length; i < max; i++){
119                                 ImportBinding importBinding = this.scope.imports[i];
120                                 ImportReference importReference = importBinding.reference;
121                                 if (importReference != null && !importReference.used){
122                                         scope.problemReporter().unusedImport(importReference);
123                                 }
124                         }
125                 }
126         }
127         
128         public CompilationResult compilationResult() {
129                 return compilationResult;
130         }
131         
132         /*
133          * Finds the matching type amoung this compilation unit types.
134          * Returns null if no type with this name is found.
135          * The type name is a compound name
136          * eg. if we're looking for X.A.B then a type name would be {X, A, B}
137          */
138         public TypeDeclaration declarationOfType(char[][] typeName) {
139
140                 for (int i = 0; i < this.types.length; i++) {
141                         TypeDeclaration typeDecl = this.types[i].declarationOfType(typeName);
142                         if (typeDecl != null) {
143                                 return typeDecl;
144                         }
145                 }
146                 return null;
147         }
148
149         /**
150          * Bytecode generation
151          */
152         public void generateCode() {
153
154                 if (ignoreFurtherInvestigation) {
155                         if (types != null) {
156                                 for (int i = 0, count = types.length; i < count; i++) {
157                                         types[i].ignoreFurtherInvestigation = true;
158                                         // propagate the flag to request problem type creation
159                                         types[i].generateCode(scope);
160                                 }
161                         }
162                         return;
163                 }
164                 try {
165                         if (types != null) {
166                                 for (int i = 0, count = types.length; i < count; i++)
167                                         types[i].generateCode(scope);
168                         }
169                 } catch (AbortCompilationUnit e) {
170                 }
171         }
172
173         public char[] getFileName() {
174
175                 return compilationResult.getFileName();
176         }
177
178         public char[] getMainTypeName() {
179
180                 if (compilationResult.compilationUnit == null) {
181                         char[] fileName = compilationResult.getFileName();
182
183                         int start = CharOperation.lastIndexOf('/', fileName) + 1;
184                         if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
185                                 start = CharOperation.lastIndexOf('\\', fileName) + 1;
186
187                         int end = CharOperation.lastIndexOf('.', fileName);
188                         if (end == -1)
189                                 end = fileName.length;
190
191                         return CharOperation.subarray(fileName, start, end);
192                 } else {
193                         return compilationResult.compilationUnit.getMainTypeName();
194                 }
195         }
196
197         public boolean isEmpty() {
198
199                 return (currentPackage == null) && (imports == null) && (types == null);
200         }
201
202         public boolean hasErrors() {
203                 return this.ignoreFurtherInvestigation;
204         }
205
206         /*
207          * Force inner local types to update their innerclass emulation
208          */
209         public void propagateInnerEmulationForAllLocalTypes() {
210
211                 isPropagatingInnerClassEmulation = true;
212                 if (allLocalTypes != null) {
213                         for (int i = 0, max = allLocalTypes.length; i < max; i++) {
214                                 allLocalTypes[i].updateInnerEmulationDependents();
215                         }
216                 }
217         }
218
219         /*
220          * Keep track of all local types, so as to update their innerclass
221          * emulation later on.
222          */
223         public void record(LocalTypeBinding localType) {
224
225                 if (allLocalTypes == null) {
226                         allLocalTypes = new LocalTypeBinding[] { localType };
227                 } else {
228                         int length = allLocalTypes.length;
229                         System.arraycopy(
230                                 allLocalTypes,
231                                 0,
232                                 (allLocalTypes = new LocalTypeBinding[length + 1]),
233                                 0,
234                                 length);
235                         allLocalTypes[length] = localType;
236                 }
237         }
238
239         public void resolve() {
240
241                 try {
242                         if (types != null) {
243                                 for (int i = 0, count = types.length; i < count; i++) {
244                                         types[i].resolve(scope);
245                                 }
246                         }
247                         checkUnusedImports();
248                 } catch (AbortCompilationUnit e) {
249                         this.ignoreFurtherInvestigation = true;
250                         return;
251                 }
252         }
253
254         public void tagAsHavingErrors() {
255                 ignoreFurtherInvestigation = true;
256         }
257
258         public String toString(int tab) {
259
260                 String s = ""; //$NON-NLS-1$
261                 if (currentPackage != null)
262                         s = tabString(tab) + "package " + currentPackage.toString(0, false) + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
263
264                 if (imports != null)
265                         for (int i = 0; i < imports.length; i++) {
266                                 s += tabString(tab) + "import " + imports[i].toString() + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
267                         };
268
269                 if (types != null)
270                         for (int i = 0; i < types.length; i++) {
271                                 s += types[i].toString(tab) + "\n"; //$NON-NLS-1$
272                         }
273                 return s;
274         }
275
276         public void traverse(
277                 IAbstractSyntaxTreeVisitor visitor,
278                 CompilationUnitScope scope) {
279
280                 if (ignoreFurtherInvestigation)
281                         return;
282                 try {
283                         if (visitor.visit(this, scope)) {
284                                 if (imports != null) {
285                                         int importLength = imports.length;
286                                         for (int i = 0; i < importLength; i++)
287                                                 imports[i].traverse(visitor, scope);
288                                 }
289                                 if (types != null) {
290                                         int typesLength = types.length;
291                                         for (int i = 0; i < typesLength; i++)
292                                                 types[i].traverse(visitor, scope);
293                                 }
294                         }
295                         visitor.endVisit(this, scope);
296                 } catch (AbortCompilationUnit e) {
297                 }
298         }
299 }