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.phpdt.internal.compiler.ast;
13 import java.util.ArrayList;
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
17 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
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.LocalTypeBinding;
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;
27 public class CompilationUnitDeclaration extends ASTNode implements
28 ProblemSeverities, ReferenceContext {
30 public ImportReference currentPackage;
32 public ImportReference[] imports;
34 // public TypeDeclaration[] types;
35 public ArrayList types;
37 // public char[][] name;
38 public int[][] comments;
40 public boolean ignoreFurtherInvestigation = false; // once pointless to
44 public boolean ignoreMethodBodies = false;
46 public CompilationUnitScope scope;
48 public ProblemReporter problemReporter;
50 public CompilationResult compilationResult;
52 private LocalTypeBinding[] localTypes;
54 int localTypeCount = 0;
56 public boolean isPropagatingInnerClassEmulation;
58 public CompilationUnitDeclaration(ProblemReporter problemReporter,
59 CompilationResult compilationResult, int sourceLength) {
61 this.problemReporter = problemReporter;
62 this.compilationResult = compilationResult;
63 this.types = new ArrayList();
64 // by definition of a compilation unit....
66 sourceEnd = sourceLength - 1;
70 * We cause the compilation task to abort to a given extent.
72 public void abort(int abortLevel) {
76 throw new AbortType(compilationResult);
78 throw new AbortMethod(compilationResult);
80 throw new AbortCompilationUnit(compilationResult);
85 * Dispatch code analysis AND request saturation of inner emulation
87 public void analyseCode() {
89 if (ignoreFurtherInvestigation)
93 for (int i = 0, count = types.size(); i < count; i++) {
94 if (types.get(i) instanceof TypeDeclaration)
95 ((TypeDeclaration) types.get(i)).analyseCode(scope);
98 // request inner emulation propagation
99 propagateInnerEmulationForAllLocalTypes();
100 } catch (AbortCompilationUnit e) {
101 this.ignoreFurtherInvestigation = true;
107 * When unit result is about to be accepted, removed back pointers to
108 * compiler structures.
110 public void cleanUp() {
111 if (this.types != null) {
112 for (int i = 0, max = this.types.size(); i < max; i++) {
113 if (this.types.get(i) instanceof TypeDeclaration) {
114 cleanUp((TypeDeclaration) this.types.get(i));
117 for (int i = 0, max = this.localTypeCount; i < max; i++) {
118 // null out the type's scope backpointers
119 localTypes[i].scope = null; // local members are already in the
123 // ClassFile[] classFiles = compilationResult.getClassFiles();
124 // for (int i = 0, max = classFiles.length; i < max; i++) {
125 // // clear the classFile back pointer to the bindings
126 // ClassFile classFile = classFiles[i];
127 // // null out the classfile backpointer to a type binding
128 // classFile.referenceBinding = null;
129 // classFile.codeStream = null; // codeStream holds onto ast and scopes
130 // classFile.innerClassesBindings = null;
134 private void cleanUp(TypeDeclaration type) {
135 if (type.memberTypes != null) {
136 for (int i = 0, max = type.memberTypes.length; i < max; i++) {
137 cleanUp(type.memberTypes[i]);
140 if (type.binding != null) {
141 // null out the type's scope backpointers
142 type.binding.scope = null;
146 // public void checkUnusedImports() {
148 // if (this.scope.imports != null) {
149 // for (int i = 0, max = this.scope.imports.length; i < max; i++) {
150 // ImportBinding importBinding = this.scope.imports[i];
151 // ImportReference importReference = importBinding.reference;
152 // if (importReference != null && !importReference.used) {
153 // scope.problemReporter().unusedImport(importReference);
159 public CompilationResult compilationResult() {
160 return compilationResult;
164 * Finds the matching type amoung this compilation unit types. Returns null
165 * if no type with this name is found. The type name is a compound name eg.
166 * if we're looking for X.A.B then a type name would be {X, A, B}
168 public TypeDeclaration declarationOfType(char[][] typeName) {
170 for (int i = 0; i < this.types.size(); i++) {
171 if (this.types.get(i) instanceof TypeDeclaration) {
172 TypeDeclaration typeDecl = ((TypeDeclaration) this.types.get(i))
173 .declarationOfType(typeName);
174 if (typeDecl != null) {
183 * Bytecode generation
185 // public void generateCode() {
187 // if (ignoreFurtherInvestigation) {
188 // if (types != null) {
189 // for (int i = 0, count = types.length; i < count; i++) {
190 // types[i].ignoreFurtherInvestigation = true;
191 // // propagate the flag to request problem type creation
192 // types[i].generateCode(scope);
198 // if (types != null) {
199 // for (int i = 0, count = types.length; i < count; i++)
200 // types[i].generateCode(scope);
202 // } catch (AbortCompilationUnit e) {
205 public char[] getFileName() {
207 return compilationResult.getFileName();
210 public char[] getMainTypeName() {
212 if (compilationResult.compilationUnit == null) {
213 char[] fileName = compilationResult.getFileName();
215 int start = CharOperation.lastIndexOf('/', fileName) + 1;
216 if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
217 start = CharOperation.lastIndexOf('\\', fileName) + 1;
219 int end = CharOperation.lastIndexOf('.', fileName);
221 end = fileName.length;
223 return CharOperation.subarray(fileName, start, end);
225 return compilationResult.compilationUnit.getMainTypeName();
229 public boolean isEmpty() {
231 return (currentPackage == null) && (imports == null) && (types == null);
234 public boolean hasErrors() {
235 return this.ignoreFurtherInvestigation;
238 public StringBuffer print(int indent, StringBuffer output) {
240 if (currentPackage != null) {
241 printIndent(indent, output).append("package "); //$NON-NLS-1$
242 currentPackage.print(0, output, false).append(";\n"); //$NON-NLS-1$
245 for (int i = 0; i < imports.length; i++) {
246 printIndent(indent, output).append("import "); //$NON-NLS-1$
247 imports[i].print(0, output).append(";\n"); //$NON-NLS-1$
251 for (int i = 0; i < types.size(); i++) {
252 ((ASTNode) types.get(i)).print(indent, output).append("\n"); //$NON-NLS-1$
259 * Force inner local types to update their innerclass emulation
261 public void propagateInnerEmulationForAllLocalTypes() {
263 isPropagatingInnerClassEmulation = true;
264 for (int i = 0, max = this.localTypeCount; i < max; i++) {
266 LocalTypeBinding localType = localTypes[i];
267 // only propagate for reachable local types
268 if ((localType.scope.referenceType().bits & IsReachableMASK) != 0) {
269 localType.updateInnerEmulationDependents();
275 * Keep track of all local types, so as to update their innerclass emulation
278 public void record(LocalTypeBinding localType) {
280 if (this.localTypeCount == 0) {
281 this.localTypes = new LocalTypeBinding[5];
282 } else if (this.localTypeCount == this.localTypes.length) {
287 (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]),
288 0, this.localTypeCount);
290 this.localTypes[this.localTypeCount++] = localType;
293 public void resolve() {
297 for (int i = 0, count = types.size(); i < count; i++) {
298 if (types.get(i) instanceof TypeDeclaration) {
299 ((TypeDeclaration) types.get(i)).resolve(scope);
303 // if (!this.compilationResult.hasSyntaxError())
304 // checkUnusedImports();
305 } catch (AbortCompilationUnit e) {
306 this.ignoreFurtherInvestigation = true;
311 public void tagAsHavingErrors() {
312 ignoreFurtherInvestigation = true;
315 public String toString(int tab) {
317 String s = ""; //$NON-NLS-1$
318 if (currentPackage != null)
320 + "package " + currentPackage.toString(0, false) + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
323 for (int i = 0; i < imports.length; i++) {
325 + "include " + imports[i].toString() + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
330 for (int i = 0; i < types.size(); i++) {
331 s += ((ASTNode) types.get(i)).toString(tab) + "\n"; //$NON-NLS-1$
336 public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
338 if (ignoreFurtherInvestigation)
341 if (visitor.visit(this, scope)) {
342 if (currentPackage != null) {
343 currentPackage.traverse(visitor, scope);
345 if (imports != null) {
346 int importLength = imports.length;
347 for (int i = 0; i < importLength; i++) {
348 imports[i].traverse(visitor, scope);
352 int typesLength = types.size();
353 for (int i = 0; i < typesLength; i++) {
354 if (types.get(i) instanceof TypeDeclaration) {
355 ((TypeDeclaration) types.get(i)).traverse(visitor,
361 visitor.endVisit(this, scope);
362 } catch (AbortCompilationUnit e) {