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
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
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;
28 public class CompilationUnitDeclaration
30 implements ProblemSeverities, ReferenceContext {
32 public ImportReference currentPackage;
33 public ImportReference[] imports;
34 public TypeDeclaration[] types;
35 //public char[][] name;
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;
43 private LocalTypeBinding[] allLocalTypes;
44 public boolean isPropagatingInnerClassEmulation;
46 public CompilationUnitDeclaration(
47 ProblemReporter problemReporter,
48 CompilationResult compilationResult,
51 this.problemReporter = problemReporter;
52 this.compilationResult = compilationResult;
54 //by definition of a compilation unit....
56 sourceEnd = sourceLength - 1;
61 * We cause the compilation task to abort to a given extent.
63 public void abort(int abortLevel) {
67 throw new AbortType(compilationResult);
69 throw new AbortMethod(compilationResult);
71 throw new AbortCompilationUnit(compilationResult);
76 * Dispatch code analysis AND request saturation of inner emulation
78 public void analyseCode() {
80 if (ignoreFurtherInvestigation)
84 for (int i = 0, count = types.length; i < count; i++) {
85 types[i].analyseCode(scope);
88 // request inner emulation propagation
89 propagateInnerEmulationForAllLocalTypes();
90 } catch (AbortCompilationUnit e) {
91 this.ignoreFurtherInvestigation = true;
97 * When unit result is about to be accepted, removed back pointers
98 * to compiler structures.
100 public void cleanUp() {
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;
115 public void checkUnusedImports(){
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);
128 public CompilationResult compilationResult() {
129 return compilationResult;
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}
138 public TypeDeclaration declarationOfType(char[][] typeName) {
140 for (int i = 0; i < this.types.length; i++) {
141 TypeDeclaration typeDecl = this.types[i].declarationOfType(typeName);
142 if (typeDecl != null) {
150 * Bytecode generation
152 public void generateCode() {
154 if (ignoreFurtherInvestigation) {
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);
166 for (int i = 0, count = types.length; i < count; i++)
167 types[i].generateCode(scope);
169 } catch (AbortCompilationUnit e) {
173 public char[] getFileName() {
175 return compilationResult.getFileName();
178 public char[] getMainTypeName() {
180 if (compilationResult.compilationUnit == null) {
181 char[] fileName = compilationResult.getFileName();
183 int start = CharOperation.lastIndexOf('/', fileName) + 1;
184 if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
185 start = CharOperation.lastIndexOf('\\', fileName) + 1;
187 int end = CharOperation.lastIndexOf('.', fileName);
189 end = fileName.length;
191 return CharOperation.subarray(fileName, start, end);
193 return compilationResult.compilationUnit.getMainTypeName();
197 public boolean isEmpty() {
199 return (currentPackage == null) && (imports == null) && (types == null);
202 public boolean hasErrors() {
203 return this.ignoreFurtherInvestigation;
207 * Force inner local types to update their innerclass emulation
209 public void propagateInnerEmulationForAllLocalTypes() {
211 isPropagatingInnerClassEmulation = true;
212 if (allLocalTypes != null) {
213 for (int i = 0, max = allLocalTypes.length; i < max; i++) {
214 allLocalTypes[i].updateInnerEmulationDependents();
220 * Keep track of all local types, so as to update their innerclass
221 * emulation later on.
223 public void record(LocalTypeBinding localType) {
225 if (allLocalTypes == null) {
226 allLocalTypes = new LocalTypeBinding[] { localType };
228 int length = allLocalTypes.length;
232 (allLocalTypes = new LocalTypeBinding[length + 1]),
235 allLocalTypes[length] = localType;
239 public void resolve() {
243 for (int i = 0, count = types.length; i < count; i++) {
244 types[i].resolve(scope);
247 checkUnusedImports();
248 } catch (AbortCompilationUnit e) {
249 this.ignoreFurtherInvestigation = true;
254 public void tagAsHavingErrors() {
255 ignoreFurtherInvestigation = true;
258 public String toString(int tab) {
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$
265 for (int i = 0; i < imports.length; i++) {
266 s += tabString(tab) + "import " + imports[i].toString() + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
270 for (int i = 0; i < types.length; i++) {
271 s += types[i].toString(tab) + "\n"; //$NON-NLS-1$
276 public void traverse(
277 IAbstractSyntaxTreeVisitor visitor,
278 CompilationUnitScope scope) {
280 if (ignoreFurtherInvestigation)
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);
290 int typesLength = types.length;
291 for (int i = 0; i < typesLength; i++)
292 types[i].traverse(visitor, scope);
295 visitor.endVisit(this, scope);
296 } catch (AbortCompilationUnit e) {