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 private static final char[] PACKAGE_INFO_FILE_NAME = "package-info.java".toCharArray(); //$NON-NLS-1$
25 public ImportReference currentPackage;
26 public ImportReference[] imports;
27 public TypeDeclaration[] types;
28 public int[][] comments;
30 public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors
31 public boolean ignoreMethodBodies = false;
32 public CompilationUnitScope scope;
33 public ProblemReporter problemReporter;
34 public CompilationResult compilationResult;
36 public LocalTypeBinding[] localTypes;
37 public int localTypeCount = 0;
39 public boolean isPropagatingInnerClassEmulation;
41 public CompilationUnitDeclaration(
42 ProblemReporter problemReporter,
43 CompilationResult compilationResult,
46 this.problemReporter = problemReporter;
47 this.compilationResult = compilationResult;
49 //by definition of a compilation unit....
51 sourceEnd = sourceLength - 1;
56 * We cause the compilation task to abort to a given extent.
58 public void abort(int abortLevel, IProblem problem) {
62 throw new AbortType(this.compilationResult, problem);
64 throw new AbortMethod(this.compilationResult, problem);
66 throw new AbortCompilationUnit(this.compilationResult, problem);
71 * Dispatch code analysis AND request saturation of inner emulation
73 public void analyseCode() {
75 if (ignoreFurtherInvestigation)
79 for (int i = 0, count = types.length; i < count; i++) {
80 types[i].analyseCode(scope);
83 // request inner emulation propagation
84 propagateInnerEmulationForAllLocalTypes();
85 } catch (AbortCompilationUnit e) {
86 this.ignoreFurtherInvestigation = true;
92 * When unit result is about to be accepted, removed back pointers
93 * to compiler structures.
95 public void cleanUp() {
96 if (this.types != null) {
97 for (int i = 0, max = this.types.length; i < max; i++) {
98 cleanUp(this.types[i]);
100 for (int i = 0, max = this.localTypeCount; i < max; i++) {
101 LocalTypeBinding localType = localTypes[i];
102 // null out the type's scope backpointers
103 localType.scope = null; // local members are already in the list
106 ClassFile[] classFiles = compilationResult.getClassFiles();
107 for (int i = 0, max = classFiles.length; i < max; i++) {
108 // clear the classFile back pointer to the bindings
109 ClassFile classFile = classFiles[i];
110 // null out the classfile backpointer to a type binding
111 classFile.referenceBinding = null;
112 classFile.codeStream = null; // codeStream holds onto ast and scopes
113 classFile.innerClassesBindings = null;
116 private void cleanUp(TypeDeclaration type) {
117 if (type.memberTypes != null) {
118 for (int i = 0, max = type.memberTypes.length; i < max; i++){
119 cleanUp(type.memberTypes[i]);
122 if (type.binding != null) {
123 // null out the type's scope backpointers
124 type.binding.scope = null;
128 public void checkUnusedImports(){
130 if (this.scope.imports != null){
131 for (int i = 0, max = this.scope.imports.length; i < max; i++){
132 ImportBinding importBinding = this.scope.imports[i];
133 ImportReference importReference = importBinding.reference;
134 if (importReference != null && !importReference.used){
135 scope.problemReporter().unusedImport(importReference);
141 public CompilationResult compilationResult() {
142 return compilationResult;
146 * Finds the matching type amoung this compilation unit types.
147 * Returns null if no type with this name is found.
148 * The type name is a compound name
149 * eg. if we're looking for X.A.B then a type name would be {X, A, B}
151 public TypeDeclaration declarationOfType(char[][] typeName) {
153 for (int i = 0; i < this.types.length; i++) {
154 TypeDeclaration typeDecl = this.types[i].declarationOfType(typeName);
155 if (typeDecl != null) {
163 * Bytecode generation
165 public void generateCode() {
167 if (ignoreFurtherInvestigation) {
169 for (int i = 0, count = types.length; i < count; i++) {
170 types[i].ignoreFurtherInvestigation = true;
171 // propagate the flag to request problem type creation
172 types[i].generateCode(scope);
179 for (int i = 0, count = types.length; i < count; i++)
180 types[i].generateCode(scope);
182 } catch (AbortCompilationUnit e) {
187 public char[] getFileName() {
189 return compilationResult.getFileName();
192 public char[] getMainTypeName() {
194 if (compilationResult.compilationUnit == null) {
195 char[] fileName = compilationResult.getFileName();
197 int start = CharOperation.lastIndexOf('/', fileName) + 1;
198 if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
199 start = CharOperation.lastIndexOf('\\', fileName) + 1;
201 int end = CharOperation.lastIndexOf('.', fileName);
203 end = fileName.length;
205 return CharOperation.subarray(fileName, start, end);
207 return compilationResult.compilationUnit.getMainTypeName();
211 public boolean isEmpty() {
213 return (currentPackage == null) && (imports == null) && (types == null);
216 public boolean hasErrors() {
217 return this.ignoreFurtherInvestigation;
220 public StringBuffer print(int indent, StringBuffer output) {
222 if (currentPackage != null) {
223 printIndent(indent, output).append("package "); //$NON-NLS-1$
224 currentPackage.print(0, output, false).append(";\n"); //$NON-NLS-1$
227 for (int i = 0; i < imports.length; i++) {
228 printIndent(indent, output).append("import "); //$NON-NLS-1$
229 imports[i].print(0, output).append(";\n"); //$NON-NLS-1$
233 for (int i = 0; i < types.length; i++) {
234 types[i].print(indent, output).append("\n"); //$NON-NLS-1$
241 * Force inner local types to update their innerclass emulation
243 public void propagateInnerEmulationForAllLocalTypes() {
245 isPropagatingInnerClassEmulation = true;
246 for (int i = 0, max = this.localTypeCount; i < max; i++) {
248 LocalTypeBinding localType = localTypes[i];
249 // only propagate for reachable local types
250 if ((localType.scope.referenceType().bits & IsReachableMASK) != 0) {
251 localType.updateInnerEmulationDependents();
257 * Keep track of all local types, so as to update their innerclass
258 * emulation later on.
260 public void record(LocalTypeBinding localType) {
262 if (this.localTypeCount == 0) {
263 this.localTypes = new LocalTypeBinding[5];
264 } else if (this.localTypeCount == this.localTypes.length) {
265 System.arraycopy(this.localTypes, 0, (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]), 0, this.localTypeCount);
267 this.localTypes[this.localTypeCount++] = localType;
270 public void resolve() {
271 if (this.currentPackage != null) {
272 if (this.currentPackage.annotations != null
273 && !CharOperation.endsWith(getFileName(), PACKAGE_INFO_FILE_NAME)) {
274 scope.problemReporter().invalidFileNameForPackageAnnotations(this.currentPackage.annotations[0]);
279 for (int i = 0, count = types.length; i < count; i++) {
280 types[i].resolve(scope);
283 if (!this.compilationResult.hasSyntaxError()) checkUnusedImports();
284 } catch (AbortCompilationUnit e) {
285 this.ignoreFurtherInvestigation = true;
290 public void tagAsHavingErrors() {
291 ignoreFurtherInvestigation = true;
294 public void traverse(
296 CompilationUnitScope unitScope) {
298 if (ignoreFurtherInvestigation)
301 if (visitor.visit(this, this.scope)) {
302 if (currentPackage != null) {
303 currentPackage.traverse(visitor, this.scope);
305 if (imports != null) {
306 int importLength = imports.length;
307 for (int i = 0; i < importLength; i++) {
308 imports[i].traverse(visitor, this.scope);
312 int typesLength = types.length;
313 for (int i = 0; i < typesLength; i++) {
314 types[i].traverse(visitor, this.scope);
318 visitor.endVisit(this, this.scope);
319 } catch (AbortCompilationUnit e) {