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;
12 import java.util.ArrayList;
14 import net.sourceforge.phpdt.core.compiler.CharOperation;
15 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
16 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
17 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
18 import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
20 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilationUnit;
21 import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod;
22 import net.sourceforge.phpdt.internal.compiler.problem.AbortType;
23 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
24 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
26 public class CompilationUnitDeclaration extends ASTNode implements ProblemSeverities, ReferenceContext {
28 public ImportReference currentPackage;
29 public ImportReference[] imports;
30 // public TypeDeclaration[] types;
31 public ArrayList types;
33 //public char[][] name;
34 public int[][] comments;
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;
58 * We cause the compilation task to abort to a given extent.
60 public void abort(int abortLevel) {
64 throw new AbortType(compilationResult);
66 throw new AbortMethod(compilationResult);
68 throw new AbortCompilationUnit(compilationResult);
73 * Dispatch code analysis AND request saturation of inner emulation
75 public void analyseCode() {
77 if (ignoreFurtherInvestigation)
81 for (int i = 0, count = types.size(); i < count; i++) {
82 if (types.get(i) instanceof TypeDeclaration)
83 ((TypeDeclaration) types.get(i)).analyseCode(scope);
86 // request inner emulation propagation
87 propagateInnerEmulationForAllLocalTypes();
88 } catch (AbortCompilationUnit e) {
89 this.ignoreFurtherInvestigation = true;
95 * When unit result is about to be accepted, removed back pointers
96 * to compiler structures.
98 public void cleanUp() {
99 if (this.types != null) {
100 for (int i = 0, max = this.types.size(); i < max; i++) {
101 if (this.types.get(i) instanceof TypeDeclaration) {
102 cleanUp((TypeDeclaration) this.types.get(i));
105 for (int i = 0, max = this.localTypeCount; i < max; i++) {
106 // null out the type's scope backpointers
107 localTypes[i].scope = null; // local members are already in the list
110 // ClassFile[] classFiles = compilationResult.getClassFiles();
111 // for (int i = 0, max = classFiles.length; i < max; i++) {
112 // // clear the classFile back pointer to the bindings
113 // ClassFile classFile = classFiles[i];
114 // // null out the classfile backpointer to a type binding
115 // classFile.referenceBinding = null;
116 // classFile.codeStream = null; // codeStream holds onto ast and scopes
117 // classFile.innerClassesBindings = null;
120 private void cleanUp(TypeDeclaration type) {
121 if (type.memberTypes != null) {
122 for (int i = 0, max = type.memberTypes.length; i < max; i++) {
123 cleanUp(type.memberTypes[i]);
126 if (type.binding != null) {
127 // null out the type's scope backpointers
128 type.binding.scope = null;
132 // public void checkUnusedImports() {
134 // if (this.scope.imports != null) {
135 // for (int i = 0, max = this.scope.imports.length; i < max; i++) {
136 // ImportBinding importBinding = this.scope.imports[i];
137 // ImportReference importReference = importBinding.reference;
138 // if (importReference != null && !importReference.used) {
139 // scope.problemReporter().unusedImport(importReference);
145 public CompilationResult compilationResult() {
146 return compilationResult;
150 * Finds the matching type amoung this compilation unit types.
151 * Returns null if no type with this name is found.
152 * The type name is a compound name
153 * eg. if we're looking for X.A.B then a type name would be {X, A, B}
155 public TypeDeclaration declarationOfType(char[][] typeName) {
157 for (int i = 0; i < this.types.size(); i++) {
158 if (this.types.get(i) instanceof TypeDeclaration) {
159 TypeDeclaration typeDecl = ((TypeDeclaration) this.types.get(i)).declarationOfType(typeName);
160 if (typeDecl != null) {
169 * Bytecode generation
171 // public void generateCode() {
173 // if (ignoreFurtherInvestigation) {
174 // if (types != null) {
175 // for (int i = 0, count = types.length; i < count; i++) {
176 // types[i].ignoreFurtherInvestigation = true;
177 // // propagate the flag to request problem type creation
178 // types[i].generateCode(scope);
184 // if (types != null) {
185 // for (int i = 0, count = types.length; i < count; i++)
186 // types[i].generateCode(scope);
188 // } catch (AbortCompilationUnit e) {
192 public char[] getFileName() {
194 return compilationResult.getFileName();
197 public char[] getMainTypeName() {
199 if (compilationResult.compilationUnit == null) {
200 char[] fileName = compilationResult.getFileName();
202 int start = CharOperation.lastIndexOf('/', fileName) + 1;
203 if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
204 start = CharOperation.lastIndexOf('\\', fileName) + 1;
206 int end = CharOperation.lastIndexOf('.', fileName);
208 end = fileName.length;
210 return CharOperation.subarray(fileName, start, end);
212 return compilationResult.compilationUnit.getMainTypeName();
216 public boolean isEmpty() {
218 return (currentPackage == null) && (imports == null) && (types == null);
221 public boolean hasErrors() {
222 return this.ignoreFurtherInvestigation;
224 public StringBuffer print(int indent, StringBuffer output) {
226 if (currentPackage != null) {
227 printIndent(indent, output).append("package "); //$NON-NLS-1$
228 currentPackage.print(0, output, false).append(";\n"); //$NON-NLS-1$
231 for (int i = 0; i < imports.length; i++) {
232 printIndent(indent, output).append("import "); //$NON-NLS-1$
233 imports[i].print(0, output).append(";\n"); //$NON-NLS-1$
237 for (int i = 0; i < types.size(); i++) {
238 ((ASTNode)types.get(i)).print(indent, output).append("\n"); //$NON-NLS-1$
245 * Force inner local types to update their innerclass emulation
247 public void propagateInnerEmulationForAllLocalTypes() {
249 isPropagatingInnerClassEmulation = true;
250 for (int i = 0, max = this.localTypeCount; i < max; i++) {
252 LocalTypeBinding localType = localTypes[i];
253 // only propagate for reachable local types
254 if ((localType.scope.referenceType().bits & IsReachableMASK) != 0) {
255 localType.updateInnerEmulationDependents();
261 * Keep track of all local types, so as to update their innerclass
262 * emulation later on.
264 public void record(LocalTypeBinding localType) {
266 if (this.localTypeCount == 0) {
267 this.localTypes = new LocalTypeBinding[5];
268 } else if (this.localTypeCount == this.localTypes.length) {
272 (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]),
274 this.localTypeCount);
276 this.localTypes[this.localTypeCount++] = localType;
279 public void resolve() {
283 for (int i = 0, count = types.size(); i < count; i++) {
284 if (types.get(i) instanceof TypeDeclaration) {
285 ((TypeDeclaration) types.get(i)).resolve(scope);
289 // if (!this.compilationResult.hasSyntaxError())
290 // checkUnusedImports();
291 } catch (AbortCompilationUnit e) {
292 this.ignoreFurtherInvestigation = true;
297 public void tagAsHavingErrors() {
298 ignoreFurtherInvestigation = true;
301 public String toString(int tab) {
303 String s = ""; //$NON-NLS-1$
304 if (currentPackage != null)
305 s = tabString(tab) + "package " + currentPackage.toString(0, false) + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
308 for (int i = 0; i < imports.length; i++) {
309 s += tabString(tab) + "include " + imports[i].toString() + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
313 for (int i = 0; i < types.size(); i++) {
314 s += ((ASTNode) types.get(i)).toString(tab) + "\n"; //$NON-NLS-1$
319 public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
321 if (ignoreFurtherInvestigation)
324 if (visitor.visit(this, scope)) {
325 if (currentPackage != null) {
326 currentPackage.traverse(visitor, scope);
328 if (imports != null) {
329 int importLength = imports.length;
330 for (int i = 0; i < importLength; i++) {
331 imports[i].traverse(visitor, scope);
335 int typesLength = types.size();
336 for (int i = 0; i < typesLength; i++) {
337 if (types.get(i) instanceof TypeDeclaration) {
338 ((TypeDeclaration) types.get(i)).traverse(visitor, scope);
343 visitor.endVisit(this, scope);
344 } catch (AbortCompilationUnit e) {