1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 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 net.sourceforge.phpeclipse.internal.compiler.ast;
13 import java.util.ArrayList;
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
17 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
18 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
19 import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
20 import net.sourceforge.phpdt.internal.compiler.lookup.ImportBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
22 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilationUnit;
23 import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod;
24 import net.sourceforge.phpdt.internal.compiler.problem.AbortType;
25 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
26 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
28 public class CompilationUnitDeclaration extends AstNode implements ProblemSeverities, ReferenceContext {
30 public ImportReference currentPackage;
31 public ImportReference[] imports;
32 // public TypeDeclaration[] types;
33 public ArrayList types;
34 //public char[][] name;
36 public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors
37 public boolean ignoreMethodBodies = false;
38 public CompilationUnitScope scope;
39 public ProblemReporter problemReporter;
40 public CompilationResult compilationResult;
42 private LocalTypeBinding[] localTypes;
43 int localTypeCount = 0;
45 public boolean isPropagatingInnerClassEmulation;
47 public CompilationUnitDeclaration(ProblemReporter problemReporter, CompilationResult compilationResult, int sourceLength) {
49 this.problemReporter = problemReporter;
50 this.compilationResult = compilationResult;
51 this.types = new ArrayList();
52 //by definition of a compilation unit....
54 sourceEnd = sourceLength - 1;
59 * We cause the compilation task to abort to a given extent.
61 public void abort(int abortLevel) {
65 throw new AbortType(compilationResult);
67 throw new AbortMethod(compilationResult);
69 throw new AbortCompilationUnit(compilationResult);
74 * Dispatch code analysis AND request saturation of inner emulation
76 public void analyseCode() {
78 if (ignoreFurtherInvestigation)
82 for (int i = 0, count = types.size(); i < count; i++) {
83 if (types.get(i) instanceof TypeDeclaration)
84 ((TypeDeclaration) types.get(i)).analyseCode(scope);
87 // request inner emulation propagation
88 propagateInnerEmulationForAllLocalTypes();
89 } catch (AbortCompilationUnit e) {
90 this.ignoreFurtherInvestigation = true;
96 * When unit result is about to be accepted, removed back pointers
97 * to compiler structures.
99 public void cleanUp() {
100 if (this.types != null) {
101 for (int i = 0, max = this.types.size(); i < max; i++) {
102 if (this.types.get(i) instanceof TypeDeclaration) {
103 cleanUp((TypeDeclaration) this.types.get(i));
106 for (int i = 0, max = this.localTypeCount; i < max; i++) {
107 // null out the type's scope backpointers
108 localTypes[i].scope = null; // local members are already in the list
111 // ClassFile[] classFiles = compilationResult.getClassFiles();
112 // for (int i = 0, max = classFiles.length; i < max; i++) {
113 // // clear the classFile back pointer to the bindings
114 // ClassFile classFile = classFiles[i];
115 // // null out the classfile backpointer to a type binding
116 // classFile.referenceBinding = null;
117 // classFile.codeStream = null; // codeStream holds onto ast and scopes
118 // classFile.innerClassesBindings = null;
121 private void cleanUp(TypeDeclaration type) {
122 if (type.memberTypes != null) {
123 for (int i = 0, max = type.memberTypes.length; i < max; i++) {
124 cleanUp(type.memberTypes[i]);
127 if (type.binding != null) {
128 // null out the type's scope backpointers
129 type.binding.scope = null;
133 public void checkUnusedImports() {
135 if (this.scope.imports != null) {
136 for (int i = 0, max = this.scope.imports.length; i < max; i++) {
137 ImportBinding importBinding = this.scope.imports[i];
138 ImportReference importReference = importBinding.reference;
139 if (importReference != null && !importReference.used) {
140 scope.problemReporter().unusedImport(importReference);
146 public CompilationResult compilationResult() {
147 return compilationResult;
151 * Finds the matching type amoung this compilation unit types.
152 * Returns null if no type with this name is found.
153 * The type name is a compound name
154 * eg. if we're looking for X.A.B then a type name would be {X, A, B}
156 public TypeDeclaration declarationOfType(char[][] typeName) {
158 for (int i = 0; i < this.types.size(); i++) {
159 if (this.types.get(i) instanceof TypeDeclaration) {
160 TypeDeclaration typeDecl = ((TypeDeclaration) this.types.get(i)).declarationOfType(typeName);
161 if (typeDecl != null) {
170 * Bytecode generation
172 // public void generateCode() {
174 // if (ignoreFurtherInvestigation) {
175 // if (types != null) {
176 // for (int i = 0, count = types.length; i < count; i++) {
177 // types[i].ignoreFurtherInvestigation = true;
178 // // propagate the flag to request problem type creation
179 // types[i].generateCode(scope);
185 // if (types != null) {
186 // for (int i = 0, count = types.length; i < count; i++)
187 // types[i].generateCode(scope);
189 // } catch (AbortCompilationUnit e) {
193 public char[] getFileName() {
195 return compilationResult.getFileName();
198 public char[] getMainTypeName() {
200 if (compilationResult.compilationUnit == null) {
201 char[] fileName = compilationResult.getFileName();
203 int start = CharOperation.lastIndexOf('/', fileName) + 1;
204 if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
205 start = CharOperation.lastIndexOf('\\', fileName) + 1;
207 int end = CharOperation.lastIndexOf('.', fileName);
209 end = fileName.length;
211 return CharOperation.subarray(fileName, start, end);
213 return compilationResult.compilationUnit.getMainTypeName();
217 public boolean isEmpty() {
219 return (currentPackage == null) && (imports == null) && (types == null);
222 public boolean hasErrors() {
223 return this.ignoreFurtherInvestigation;
227 * Force inner local types to update their innerclass emulation
229 public void propagateInnerEmulationForAllLocalTypes() {
231 isPropagatingInnerClassEmulation = true;
232 for (int i = 0, max = this.localTypeCount; i < max; i++) {
234 LocalTypeBinding localType = localTypes[i];
235 // only propagate for reachable local types
236 if ((localType.scope.referenceType().bits & IsReachableMASK) != 0) {
237 localType.updateInnerEmulationDependents();
243 * Keep track of all local types, so as to update their innerclass
244 * emulation later on.
246 public void record(LocalTypeBinding localType) {
248 if (this.localTypeCount == 0) {
249 this.localTypes = new LocalTypeBinding[5];
250 } else if (this.localTypeCount == this.localTypes.length) {
254 (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]),
256 this.localTypeCount);
258 this.localTypes[this.localTypeCount++] = localType;
261 public void resolve() {
265 for (int i = 0, count = types.size(); i < count; i++) {
266 if (types.get(i) instanceof TypeDeclaration) {
267 ((TypeDeclaration) types.get(i)).resolve(scope);
271 // if (!this.compilationResult.hasSyntaxError())
272 // checkUnusedImports();
273 } catch (AbortCompilationUnit e) {
274 this.ignoreFurtherInvestigation = true;
279 public void tagAsHavingErrors() {
280 ignoreFurtherInvestigation = true;
283 public String toString(int tab) {
285 String s = ""; //$NON-NLS-1$
286 if (currentPackage != null)
287 s = tabString(tab) + "package " + currentPackage.toString(0, false) + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
290 for (int i = 0; i < imports.length; i++) {
291 s += tabString(tab) + "import " + imports[i].toString() + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
295 for (int i = 0; i < types.size(); i++) {
296 s += ((AstNode) types.get(i)).toString(tab) + "\n"; //$NON-NLS-1$
301 public void traverse(IAbstractSyntaxTreeVisitor visitor, CompilationUnitScope scope) {
303 if (ignoreFurtherInvestigation)
306 if (visitor.visit(this, scope)) {
307 if (currentPackage != null) {
308 currentPackage.traverse(visitor, scope);
310 if (imports != null) {
311 int importLength = imports.length;
312 for (int i = 0; i < importLength; i++) {
313 imports[i].traverse(visitor, scope);
317 int typesLength = types.size();
318 for (int i = 0; i < typesLength; i++) {
319 if (types.get(i) instanceof TypeDeclaration) {
320 ((TypeDeclaration) types.get(i)).traverse(visitor, scope);
325 visitor.endVisit(this, scope);
326 } catch (AbortCompilationUnit e) {