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;
35 public int[][] comments;
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[] localTypes;
44 int localTypeCount = 0;
46 public boolean isPropagatingInnerClassEmulation;
48 public CompilationUnitDeclaration(ProblemReporter problemReporter, CompilationResult compilationResult, int sourceLength) {
50 this.problemReporter = problemReporter;
51 this.compilationResult = compilationResult;
52 this.types = new ArrayList();
53 //by definition of a compilation unit....
55 sourceEnd = sourceLength - 1;
60 * We cause the compilation task to abort to a given extent.
62 public void abort(int abortLevel) {
66 throw new AbortType(compilationResult);
68 throw new AbortMethod(compilationResult);
70 throw new AbortCompilationUnit(compilationResult);
75 * Dispatch code analysis AND request saturation of inner emulation
77 public void analyseCode() {
79 if (ignoreFurtherInvestigation)
83 for (int i = 0, count = types.size(); i < count; i++) {
84 if (types.get(i) instanceof TypeDeclaration)
85 ((TypeDeclaration) types.get(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() {
101 if (this.types != null) {
102 for (int i = 0, max = this.types.size(); i < max; i++) {
103 if (this.types.get(i) instanceof TypeDeclaration) {
104 cleanUp((TypeDeclaration) this.types.get(i));
107 for (int i = 0, max = this.localTypeCount; i < max; i++) {
108 // null out the type's scope backpointers
109 localTypes[i].scope = null; // local members are already in the list
112 // ClassFile[] classFiles = compilationResult.getClassFiles();
113 // for (int i = 0, max = classFiles.length; i < max; i++) {
114 // // clear the classFile back pointer to the bindings
115 // ClassFile classFile = classFiles[i];
116 // // null out the classfile backpointer to a type binding
117 // classFile.referenceBinding = null;
118 // classFile.codeStream = null; // codeStream holds onto ast and scopes
119 // classFile.innerClassesBindings = null;
122 private void cleanUp(TypeDeclaration type) {
123 if (type.memberTypes != null) {
124 for (int i = 0, max = type.memberTypes.length; i < max; i++) {
125 cleanUp(type.memberTypes[i]);
128 if (type.binding != null) {
129 // null out the type's scope backpointers
130 type.binding.scope = null;
134 // public void checkUnusedImports() {
136 // if (this.scope.imports != null) {
137 // for (int i = 0, max = this.scope.imports.length; i < max; i++) {
138 // ImportBinding importBinding = this.scope.imports[i];
139 // ImportReference importReference = importBinding.reference;
140 // if (importReference != null && !importReference.used) {
141 // scope.problemReporter().unusedImport(importReference);
147 public CompilationResult compilationResult() {
148 return compilationResult;
152 * Finds the matching type amoung this compilation unit types.
153 * Returns null if no type with this name is found.
154 * The type name is a compound name
155 * eg. if we're looking for X.A.B then a type name would be {X, A, B}
157 public TypeDeclaration declarationOfType(char[][] typeName) {
159 for (int i = 0; i < this.types.size(); i++) {
160 if (this.types.get(i) instanceof TypeDeclaration) {
161 TypeDeclaration typeDecl = ((TypeDeclaration) this.types.get(i)).declarationOfType(typeName);
162 if (typeDecl != null) {
171 * Bytecode generation
173 // public void generateCode() {
175 // if (ignoreFurtherInvestigation) {
176 // if (types != null) {
177 // for (int i = 0, count = types.length; i < count; i++) {
178 // types[i].ignoreFurtherInvestigation = true;
179 // // propagate the flag to request problem type creation
180 // types[i].generateCode(scope);
186 // if (types != null) {
187 // for (int i = 0, count = types.length; i < count; i++)
188 // types[i].generateCode(scope);
190 // } catch (AbortCompilationUnit e) {
194 public char[] getFileName() {
196 return compilationResult.getFileName();
199 public char[] getMainTypeName() {
201 if (compilationResult.compilationUnit == null) {
202 char[] fileName = compilationResult.getFileName();
204 int start = CharOperation.lastIndexOf('/', fileName) + 1;
205 if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
206 start = CharOperation.lastIndexOf('\\', fileName) + 1;
208 int end = CharOperation.lastIndexOf('.', fileName);
210 end = fileName.length;
212 return CharOperation.subarray(fileName, start, end);
214 return compilationResult.compilationUnit.getMainTypeName();
218 public boolean isEmpty() {
220 return (currentPackage == null) && (imports == null) && (types == null);
223 public boolean hasErrors() {
224 return this.ignoreFurtherInvestigation;
228 * Force inner local types to update their innerclass emulation
230 public void propagateInnerEmulationForAllLocalTypes() {
232 isPropagatingInnerClassEmulation = true;
233 for (int i = 0, max = this.localTypeCount; i < max; i++) {
235 LocalTypeBinding localType = localTypes[i];
236 // only propagate for reachable local types
237 if ((localType.scope.referenceType().bits & IsReachableMASK) != 0) {
238 localType.updateInnerEmulationDependents();
244 * Keep track of all local types, so as to update their innerclass
245 * emulation later on.
247 public void record(LocalTypeBinding localType) {
249 if (this.localTypeCount == 0) {
250 this.localTypes = new LocalTypeBinding[5];
251 } else if (this.localTypeCount == this.localTypes.length) {
255 (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]),
257 this.localTypeCount);
259 this.localTypes[this.localTypeCount++] = localType;
262 public void resolve() {
266 for (int i = 0, count = types.size(); i < count; i++) {
267 if (types.get(i) instanceof TypeDeclaration) {
268 ((TypeDeclaration) types.get(i)).resolve(scope);
272 // if (!this.compilationResult.hasSyntaxError())
273 // checkUnusedImports();
274 } catch (AbortCompilationUnit e) {
275 this.ignoreFurtherInvestigation = true;
280 public void tagAsHavingErrors() {
281 ignoreFurtherInvestigation = true;
284 public String toString(int tab) {
286 String s = ""; //$NON-NLS-1$
287 if (currentPackage != null)
288 s = tabString(tab) + "package " + currentPackage.toString(0, false) + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
291 for (int i = 0; i < imports.length; i++) {
292 s += tabString(tab) + "import " + imports[i].toString() + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
296 for (int i = 0; i < types.size(); i++) {
297 s += ((AstNode) types.get(i)).toString(tab) + "\n"; //$NON-NLS-1$
302 public void traverse(IAbstractSyntaxTreeVisitor visitor, CompilationUnitScope scope) {
304 if (ignoreFurtherInvestigation)
307 if (visitor.visit(this, scope)) {
308 if (currentPackage != null) {
309 currentPackage.traverse(visitor, scope);
311 if (imports != null) {
312 int importLength = imports.length;
313 for (int i = 0; i < importLength; i++) {
314 imports[i].traverse(visitor, scope);
318 int typesLength = types.size();
319 for (int i = 0; i < typesLength; i++) {
320 if (types.get(i) instanceof TypeDeclaration) {
321 ((TypeDeclaration) types.get(i)).traverse(visitor, scope);
326 visitor.endVisit(this, scope);
327 } catch (AbortCompilationUnit e) {