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