1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 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 org.eclipse.jdt.internal.compiler.ast;
13 import org.eclipse.jdt.core.compiler.*;
14 import org.eclipse.jdt.internal.compiler.*;
15 import org.eclipse.jdt.internal.compiler.impl.*;
16 import org.eclipse.jdt.internal.compiler.lookup.*;
17 import org.eclipse.jdt.internal.compiler.problem.*;
19 public class CompilationUnitDeclaration
21 implements ProblemSeverities, ReferenceContext {
23 public ImportReference currentPackage;
24 public ImportReference[] imports;
25 public TypeDeclaration[] types;
26 public int[][] comments;
28 public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors
29 public boolean ignoreMethodBodies = false;
30 public CompilationUnitScope scope;
31 public ProblemReporter problemReporter;
32 public CompilationResult compilationResult;
34 public LocalTypeBinding[] localTypes;
35 public int localTypeCount = 0;
37 public boolean isPropagatingInnerClassEmulation;
39 public CompilationUnitDeclaration(
40 ProblemReporter problemReporter,
41 CompilationResult compilationResult,
44 this.problemReporter = problemReporter;
45 this.compilationResult = compilationResult;
47 //by definition of a compilation unit....
49 sourceEnd = sourceLength - 1;
54 * We cause the compilation task to abort to a given extent.
56 public void abort(int abortLevel, IProblem problem) {
60 throw new AbortType(this.compilationResult, problem);
62 throw new AbortMethod(this.compilationResult, problem);
64 throw new AbortCompilationUnit(this.compilationResult, problem);
69 * Dispatch code analysis AND request saturation of inner emulation
71 public void analyseCode() {
73 if (ignoreFurtherInvestigation)
77 for (int i = 0, count = types.length; i < count; i++) {
78 types[i].analyseCode(scope);
81 // request inner emulation propagation
82 propagateInnerEmulationForAllLocalTypes();
83 } catch (AbortCompilationUnit e) {
84 this.ignoreFurtherInvestigation = true;
90 * When unit result is about to be accepted, removed back pointers
91 * to compiler structures.
93 public void cleanUp() {
94 if (this.types != null) {
95 for (int i = 0, max = this.types.length; i < max; i++) {
96 cleanUp(this.types[i]);
98 for (int i = 0, max = this.localTypeCount; i < max; i++) {
99 LocalTypeBinding localType = localTypes[i];
100 // null out the type's scope backpointers
101 localType.scope = null; // local members are already in the list
104 ClassFile[] classFiles = compilationResult.getClassFiles();
105 for (int i = 0, max = classFiles.length; i < max; i++) {
106 // clear the classFile back pointer to the bindings
107 ClassFile classFile = classFiles[i];
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;
114 private void cleanUp(TypeDeclaration type) {
115 if (type.memberTypes != null) {
116 for (int i = 0, max = type.memberTypes.length; i < max; i++){
117 cleanUp(type.memberTypes[i]);
120 if (type.binding != null) {
121 // null out the type's scope backpointers
122 type.binding.scope = null;
126 public void checkUnusedImports(){
128 if (this.scope.imports != null){
129 for (int i = 0, max = this.scope.imports.length; i < max; i++){
130 ImportBinding importBinding = this.scope.imports[i];
131 ImportReference importReference = importBinding.reference;
132 if (importReference != null && !importReference.used){
133 scope.problemReporter().unusedImport(importReference);
139 public CompilationResult compilationResult() {
140 return compilationResult;
144 * Finds the matching type amoung this compilation unit types.
145 * Returns null if no type with this name is found.
146 * The type name is a compound name
147 * eg. if we're looking for X.A.B then a type name would be {X, A, B}
149 public TypeDeclaration declarationOfType(char[][] typeName) {
151 for (int i = 0; i < this.types.length; i++) {
152 TypeDeclaration typeDecl = this.types[i].declarationOfType(typeName);
153 if (typeDecl != null) {
161 * Bytecode generation
163 public void generateCode() {
165 if (ignoreFurtherInvestigation) {
167 for (int i = 0, count = types.length; i < count; i++) {
168 types[i].ignoreFurtherInvestigation = true;
169 // propagate the flag to request problem type creation
170 types[i].generateCode(scope);
177 for (int i = 0, count = types.length; i < count; i++)
178 types[i].generateCode(scope);
180 } catch (AbortCompilationUnit e) {
185 public char[] getFileName() {
187 return compilationResult.getFileName();
190 public char[] getMainTypeName() {
192 if (compilationResult.compilationUnit == null) {
193 char[] fileName = compilationResult.getFileName();
195 int start = CharOperation.lastIndexOf('/', fileName) + 1;
196 if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
197 start = CharOperation.lastIndexOf('\\', fileName) + 1;
199 int end = CharOperation.lastIndexOf('.', fileName);
201 end = fileName.length;
203 return CharOperation.subarray(fileName, start, end);
205 return compilationResult.compilationUnit.getMainTypeName();
209 public boolean isEmpty() {
211 return (currentPackage == null) && (imports == null) && (types == null);
214 public boolean hasErrors() {
215 return this.ignoreFurtherInvestigation;
218 public StringBuffer print(int indent, StringBuffer output) {
220 if (currentPackage != null) {
221 printIndent(indent, output).append("package "); //$NON-NLS-1$
222 currentPackage.print(0, output, false).append(";\n"); //$NON-NLS-1$
225 for (int i = 0; i < imports.length; i++) {
226 printIndent(indent, output).append("import "); //$NON-NLS-1$
227 imports[i].print(0, output).append(";\n"); //$NON-NLS-1$
231 for (int i = 0; i < types.length; i++) {
232 types[i].print(indent, output).append("\n"); //$NON-NLS-1$
239 * Force inner local types to update their innerclass emulation
241 public void propagateInnerEmulationForAllLocalTypes() {
243 isPropagatingInnerClassEmulation = true;
244 for (int i = 0, max = this.localTypeCount; i < max; i++) {
246 LocalTypeBinding localType = localTypes[i];
247 // only propagate for reachable local types
248 if ((localType.scope.referenceType().bits & IsReachableMASK) != 0) {
249 localType.updateInnerEmulationDependents();
255 * Keep track of all local types, so as to update their innerclass
256 * emulation later on.
258 public void record(LocalTypeBinding localType) {
260 if (this.localTypeCount == 0) {
261 this.localTypes = new LocalTypeBinding[5];
262 } else if (this.localTypeCount == this.localTypes.length) {
263 System.arraycopy(this.localTypes, 0, (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]), 0, this.localTypeCount);
265 this.localTypes[this.localTypeCount++] = localType;
268 public void resolve() {
272 for (int i = 0, count = types.length; i < count; i++) {
273 types[i].resolve(scope);
276 if (!this.compilationResult.hasSyntaxError()) checkUnusedImports();
277 } catch (AbortCompilationUnit e) {
278 this.ignoreFurtherInvestigation = true;
283 public void tagAsHavingErrors() {
284 ignoreFurtherInvestigation = true;
287 public void traverse(
289 CompilationUnitScope unitScope) {
291 if (ignoreFurtherInvestigation)
294 if (visitor.visit(this, this.scope)) {
295 if (currentPackage != null) {
296 currentPackage.traverse(visitor, this.scope);
298 if (imports != null) {
299 int importLength = imports.length;
300 for (int i = 0; i < importLength; i++) {
301 imports[i].traverse(visitor, this.scope);
305 int typesLength = types.length;
306 for (int i = 0; i < typesLength; i++) {
307 types[i].traverse(visitor, this.scope);
311 visitor.endVisit(this, this.scope);
312 } catch (AbortCompilationUnit e) {