X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Flookup%2FLookupEnvironment.java;fp=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Flookup%2FLookupEnvironment.java;h=0000000000000000000000000000000000000000;hb=6f0cd02d46e011bd5599e1b7fefc6159cb811135;hp=a7a9c9c4b68da4a87df16c1bca094a71fcfc00e2;hpb=622d0e5a4b1b35b6918a516a79a0cc22272a919e;p=org.ibex.tool.git diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/src/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java deleted file mode 100644 index a7a9c9c..0000000 --- a/src/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java +++ /dev/null @@ -1,590 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.compiler.lookup; - -import org.eclipse.jdt.core.compiler.CharOperation; -import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; -import org.eclipse.jdt.internal.compiler.env.IBinaryType; -import org.eclipse.jdt.internal.compiler.env.INameEnvironment; -import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; -import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; -import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor; -import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; -import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage; -import org.eclipse.jdt.internal.compiler.util.Util; - -public class LookupEnvironment implements BaseTypes, ProblemReasons, TypeConstants { - public CompilerOptions options; - public ProblemReporter problemReporter; - public ITypeRequestor typeRequestor; - - PackageBinding defaultPackage; - ImportBinding[] defaultImports; - HashtableOfPackage knownPackages; - static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound); - static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR, NotFound); - - private INameEnvironment nameEnvironment; - private MethodVerifier verifier; - private ArrayBinding[][] uniqueArrayBindings; - - private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4]; - private int lastUnitIndex = -1; - private int lastCompletedUnitIndex = -1; - public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units - - // indicate in which step on the compilation we are. - // step 1 : build the reference binding - // step 2 : conect the hierarchy (connect bindings) - // step 3 : build fields and method bindings. - private int stepCompleted; - final static int BUILD_TYPE_HIERARCHY = 1; - final static int CHECK_AND_SET_IMPORTS = 2; - final static int CONNECT_TYPE_HIERARCHY = 3; - final static int BUILD_FIELDS_AND_METHODS = 4; - - // shared byte[]'s used by ClassFile to avoid allocating MBs during a build - public boolean sharedArraysUsed = true; // set to false once actual arrays are allocated - public byte[] sharedClassFileHeader = null; - public byte[] sharedClassFileContents = null; - -public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options, ProblemReporter problemReporter, INameEnvironment nameEnvironment) { - this.typeRequestor = typeRequestor; - this.options = options; - this.problemReporter = problemReporter; - this.defaultPackage = new PackageBinding(this); // assume the default package always exists - this.defaultImports = null; - this.nameEnvironment = nameEnvironment; - this.knownPackages = new HashtableOfPackage(); - this.uniqueArrayBindings = new ArrayBinding[5][]; - this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50 -} -/* Ask the oracle for a type which corresponds to the compoundName. -* Answer null if the name cannot be found. -*/ - -public ReferenceBinding askForType(char[][] compoundName) { - NameEnvironmentAnswer answer = nameEnvironment.findType(compoundName); - if (answer == null) - return null; - - if (answer.isBinaryType()) - // the type was found as a .class file - typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName)); - else if (answer.isCompilationUnit()) - // the type was found as a .java file, try to build it then search the cache - typeRequestor.accept(answer.getCompilationUnit()); - else if (answer.isSourceType()) - // the type was found as a source model - typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName)); - - return getCachedType(compoundName); -} -/* Ask the oracle for a type named name in the packageBinding. -* Answer null if the name cannot be found. -*/ - -ReferenceBinding askForType(PackageBinding packageBinding, char[] name) { - if (packageBinding == null) { - if (defaultPackage == null) - return null; - packageBinding = defaultPackage; - } - NameEnvironmentAnswer answer = nameEnvironment.findType(name, packageBinding.compoundName); - if (answer == null) - return null; - - if (answer.isBinaryType()) - // the type was found as a .class file - typeRequestor.accept(answer.getBinaryType(), packageBinding); - else if (answer.isCompilationUnit()) - // the type was found as a .java file, try to build it then search the cache - typeRequestor.accept(answer.getCompilationUnit()); - else if (answer.isSourceType()) - // the type was found as a source model - typeRequestor.accept(answer.getSourceTypes(), packageBinding); - - return packageBinding.getType0(name); -} -/* Create the initial type bindings for the compilation unit. -* -* See completeTypeBindings() for a description of the remaining steps -* -* NOTE: This method can be called multiple times as additional source files are needed -*/ - -public void buildTypeBindings(CompilationUnitDeclaration unit) { - CompilationUnitScope scope = new CompilationUnitScope(unit, this); - scope.buildTypeBindings(); - - int unitsLength = units.length; - if (++lastUnitIndex >= unitsLength) - System.arraycopy(units, 0, units = new CompilationUnitDeclaration[2 * unitsLength], 0, unitsLength); - units[lastUnitIndex] = unit; -} -/* Cache the binary type since we know it is needed during this compile. -* -* Answer the created BinaryTypeBinding or null if the type is already in the cache. -*/ - -public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType) { - return cacheBinaryType(binaryType, true); -} -/* Cache the binary type since we know it is needed during this compile. -* -* Answer the created BinaryTypeBinding or null if the type is already in the cache. -*/ - -public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods) { - char[][] compoundName = CharOperation.splitOn('/', binaryType.getName()); - ReferenceBinding existingType = getCachedType(compoundName); - - if (existingType == null || existingType instanceof UnresolvedReferenceBinding) - // only add the binary type if its not already in the cache - return createBinaryTypeFrom(binaryType, computePackageFrom(compoundName), needFieldsAndMethods); - return null; // the type already exists & can be retrieved from the cache -} -/* -* 1. Connect the type hierarchy for the type bindings created for parsedUnits. -* 2. Create the field bindings -* 3. Create the method bindings -*/ - -/* We know each known compilationUnit is free of errors at this point... -* -* Each step will create additional bindings unless a problem is detected, in which -* case either the faulty import/superinterface/field/method will be skipped or a -* suitable replacement will be substituted (such as Object for a missing superclass) -*/ - -public void completeTypeBindings() { - stepCompleted = BUILD_TYPE_HIERARCHY; - - for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) { - (this.unitBeingCompleted = this.units[i]).scope.checkAndSetImports(); - } - stepCompleted = CHECK_AND_SET_IMPORTS; - - for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) { - (this.unitBeingCompleted = this.units[i]).scope.connectTypeHierarchy(); - } - stepCompleted = CONNECT_TYPE_HIERARCHY; - - for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) { - (this.unitBeingCompleted = this.units[i]).scope.buildFieldsAndMethods(); - this.units[i] = null; // release unnecessary reference to the parsed unit - } - stepCompleted = BUILD_FIELDS_AND_METHODS; - this.lastCompletedUnitIndex = this.lastUnitIndex; - this.unitBeingCompleted = null; -} -/* -* 1. Connect the type hierarchy for the type bindings created for parsedUnits. -* 2. Create the field bindings -* 3. Create the method bindings -*/ - -/* -* Each step will create additional bindings unless a problem is detected, in which -* case either the faulty import/superinterface/field/method will be skipped or a -* suitable replacement will be substituted (such as Object for a missing superclass) -*/ - -public void completeTypeBindings(CompilationUnitDeclaration parsedUnit) { - if (stepCompleted == BUILD_FIELDS_AND_METHODS) { - // This can only happen because the original set of units are completely built and - // are now being processed, so we want to treat all the additional units as a group - // until they too are completely processed. - completeTypeBindings(); - } else { - if (parsedUnit.scope == null) return; // parsing errors were too severe - - if (stepCompleted >= CHECK_AND_SET_IMPORTS) - (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports(); - - if (stepCompleted >= CONNECT_TYPE_HIERARCHY) - (this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy(); - - this.unitBeingCompleted = null; - } -} -/* -* Used by other compiler tools which do not start by calling completeTypeBindings(). -* -* 1. Connect the type hierarchy for the type bindings created for parsedUnits. -* 2. Create the field bindings -* 3. Create the method bindings -*/ - -public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean buildFieldsAndMethods) { - if (parsedUnit.scope == null) return; // parsing errors were too severe - - (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports(); - parsedUnit.scope.connectTypeHierarchy(); - if (buildFieldsAndMethods) - parsedUnit.scope.buildFieldsAndMethods(); - this.unitBeingCompleted = null; -} -private PackageBinding computePackageFrom(char[][] constantPoolName) { - if (constantPoolName.length == 1) - return defaultPackage; - - PackageBinding packageBinding = getPackage0(constantPoolName[0]); - if (packageBinding == null || packageBinding == TheNotFoundPackage) { - packageBinding = new PackageBinding(constantPoolName[0], this); - knownPackages.put(constantPoolName[0], packageBinding); - } - - for (int i = 1, length = constantPoolName.length - 1; i < length; i++) { - PackageBinding parent = packageBinding; - if ((packageBinding = parent.getPackage0(constantPoolName[i])) == null || packageBinding == TheNotFoundPackage) { - packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this); - parent.addPackage(packageBinding); - } - } - return packageBinding; -} -/* Used to guarantee array type identity. -*/ - -ArrayBinding createArrayType(TypeBinding type, int dimensionCount) { - if (type instanceof LocalTypeBinding) // cache local type arrays with the local type itself - return ((LocalTypeBinding) type).createArrayType(dimensionCount); - - // find the array binding cache for this dimension - int dimIndex = dimensionCount - 1; - int length = uniqueArrayBindings.length; - ArrayBinding[] arrayBindings; - if (dimIndex < length) { - if ((arrayBindings = uniqueArrayBindings[dimIndex]) == null) - uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10]; - } else { - System.arraycopy( - uniqueArrayBindings, 0, - uniqueArrayBindings = new ArrayBinding[dimensionCount][], 0, - length); - uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10]; - } - - // find the cached array binding for this leaf component type (if any) - int index = -1; - length = arrayBindings.length; - while (++index < length) { - ArrayBinding currentBinding = arrayBindings[index]; - if (currentBinding == null) // no matching array, but space left - return arrayBindings[index] = new ArrayBinding(type, dimensionCount); - if (currentBinding.leafComponentType == type) - return currentBinding; - } - - // no matching array, no space left - System.arraycopy( - arrayBindings, 0, - (arrayBindings = new ArrayBinding[length * 2]), 0, - length); - uniqueArrayBindings[dimIndex] = arrayBindings; - return arrayBindings[length] = new ArrayBinding(type, dimensionCount); -} -public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding) { - return createBinaryTypeFrom(binaryType, packageBinding, true); -} -public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods) { - BinaryTypeBinding binaryBinding = new BinaryTypeBinding(packageBinding, binaryType, this); - - // resolve any array bindings which reference the unresolvedType - ReferenceBinding cachedType = packageBinding.getType0(binaryBinding.compoundName[binaryBinding.compoundName.length - 1]); - if (cachedType != null) { - if (cachedType.isBinaryBinding()) // sanity check before the cast... at this point the cache should ONLY contain unresolved types - return (BinaryTypeBinding) cachedType; - - UnresolvedReferenceBinding unresolvedType = (UnresolvedReferenceBinding) cachedType; - unresolvedType.resolvedType = binaryBinding; - updateArrayCache(unresolvedType, binaryBinding); - } - - packageBinding.addType(binaryBinding); - binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods); - return binaryBinding; -} -/* Used to create packages from the package statement. -*/ - -PackageBinding createPackage(char[][] compoundName) { - PackageBinding packageBinding = getPackage0(compoundName[0]); - if (packageBinding == null || packageBinding == TheNotFoundPackage) { - packageBinding = new PackageBinding(compoundName[0], this); - knownPackages.put(compoundName[0], packageBinding); - } - - for (int i = 1, length = compoundName.length; i < length; i++) { - // check to see if it collides with a known type... - // this case can only happen if the package does not exist as a directory in the file system - // otherwise when the source type was defined, the correct error would have been reported - // unless its an unresolved type which is referenced from an inconsistent class file - ReferenceBinding type = packageBinding.getType0(compoundName[i]); - if (type != null && type != TheNotFoundType && !(type instanceof UnresolvedReferenceBinding)) - return null; - - PackageBinding parent = packageBinding; - if ((packageBinding = parent.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage) { - // if the package is unknown, check to see if a type exists which would collide with the new package - // catches the case of a package statement of: package java.lang.Object; - // since the package can be added after a set of source files have already been compiled, we need - // whenever a package statement is encountered - if (nameEnvironment.findType(compoundName[i], parent.compoundName) != null) - return null; - - packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this); - parent.addPackage(packageBinding); - } - } - return packageBinding; -} -/* Answer the type for the compoundName if it exists in the cache. -* Answer theNotFoundType if it could not be resolved the first time -* it was looked up, otherwise answer null. -* -* NOTE: Do not use for nested types... the answer is NOT the same for a.b.C or a.b.C.D.E -* assuming C is a type in both cases. In the a.b.C.D.E case, null is the answer. -*/ - -public ReferenceBinding getCachedType(char[][] compoundName) { - if (compoundName.length == 1) { - if (defaultPackage == null) - return null; - return defaultPackage.getType0(compoundName[0]); - } - - PackageBinding packageBinding = getPackage0(compoundName[0]); - if (packageBinding == null || packageBinding == TheNotFoundPackage) - return null; - - for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) - if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage) - return null; - return packageBinding.getType0(compoundName[compoundName.length - 1]); -} -/* Answer the top level package named name if it exists in the cache. -* Answer theNotFoundPackage if it could not be resolved the first time -* it was looked up, otherwise answer null. -* -* NOTE: Senders must convert theNotFoundPackage into a real problem -* package if its to returned. -*/ - -PackageBinding getPackage0(char[] name) { - return knownPackages.get(name); -} -/* Answer the top level package named name. -* Ask the oracle for the package if its not in the cache. -* Answer null if the package cannot be found. -*/ - -PackageBinding getTopLevelPackage(char[] name) { - PackageBinding packageBinding = getPackage0(name); - if (packageBinding != null) { - if (packageBinding == TheNotFoundPackage) - return null; - return packageBinding; - } - - if (nameEnvironment.isPackage(null, name)) { - knownPackages.put(name, packageBinding = new PackageBinding(name, this)); - return packageBinding; - } - - knownPackages.put(name, TheNotFoundPackage); // saves asking the oracle next time - return null; -} -/* Answer the type corresponding to the compoundName. -* Ask the oracle for the type if its not in the cache. -* Answer null if the type cannot be found... likely a fatal error. -*/ - -public ReferenceBinding getType(char[][] compoundName) { - ReferenceBinding referenceBinding; - - if (compoundName.length == 1) { - if (defaultPackage == null) - return null; - - if ((referenceBinding = defaultPackage.getType0(compoundName[0])) == null) { - PackageBinding packageBinding = getPackage0(compoundName[0]); - if (packageBinding != null && packageBinding != TheNotFoundPackage) - return null; // collides with a known package... should not call this method in such a case - referenceBinding = askForType(defaultPackage, compoundName[0]); - } - } else { - PackageBinding packageBinding = getPackage0(compoundName[0]); - if (packageBinding == TheNotFoundPackage) - return null; - - if (packageBinding != null) { - for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) { - if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null) - break; - if (packageBinding == TheNotFoundPackage) - return null; - } - } - - if (packageBinding == null) - referenceBinding = askForType(compoundName); - else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.length - 1])) == null) - referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1]); - } - - if (referenceBinding == null || referenceBinding == TheNotFoundType) - return null; - if (referenceBinding instanceof UnresolvedReferenceBinding) - referenceBinding = ((UnresolvedReferenceBinding) referenceBinding).resolve(this); - - // compoundName refers to a nested type incorrectly (for example, package1.A$B) - if (referenceBinding.isNestedType()) - return new ProblemReferenceBinding(compoundName, InternalNameProvided); - return referenceBinding; -} -/* Answer the type corresponding to the name from the binary file. -* Does not ask the oracle for the type if its not found in the cache... instead an -* unresolved type is returned which must be resolved before used. -* -* NOTE: Does NOT answer base types nor array types! -* -* NOTE: Aborts compilation if the class file cannot be found. -*/ - -ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end) { - if (end == -1) - end = signature.length; - - char[][] compoundName = CharOperation.splitOn('/', signature, start, end); - ReferenceBinding binding = getCachedType(compoundName); - if (binding == null) { - PackageBinding packageBinding = computePackageFrom(compoundName); - binding = new UnresolvedReferenceBinding(compoundName, packageBinding); - packageBinding.addType(binding); - } else if (binding == TheNotFoundType) { - problemReporter.isClassPathCorrect(compoundName, null); - return null; // will not get here since the above error aborts the compilation - } - return binding; -} -/* Answer the type corresponding to the signature from the binary file. -* Does not ask the oracle for the type if its not found in the cache... instead an -* unresolved type is returned which must be resolved before used. -* -* NOTE: Does answer base types & array types. -* -* NOTE: Aborts compilation if the class file cannot be found. -*/ - -TypeBinding getTypeFromSignature(char[] signature, int start, int end) { - int dimension = 0; - while (signature[start] == '[') { - start++; - dimension++; - } - if (end == -1) - end = signature.length - 1; - - // Just switch on signature[start] - the L case is the else - TypeBinding binding = null; - if (start == end) { - switch (signature[start]) { - case 'I' : - binding = IntBinding; - break; - case 'Z' : - binding = BooleanBinding; - break; - case 'V' : - binding = VoidBinding; - break; - case 'C' : - binding = CharBinding; - break; - case 'D' : - binding = DoubleBinding; - break; - case 'B' : - binding = ByteBinding; - break; - case 'F' : - binding = FloatBinding; - break; - case 'J' : - binding = LongBinding; - break; - case 'S' : - binding = ShortBinding; - break; - default : - throw new Error(Util.bind("error.undefinedBaseType",String.valueOf(signature[start]))); //$NON-NLS-1$ - } - } else { - binding = getTypeFromConstantPoolName(signature, start + 1, end); - } - - if (dimension == 0) - return binding; - return createArrayType(binding, dimension); -} -/* Ask the oracle if a package exists named name in the package named compoundName. -*/ - -boolean isPackage(char[][] compoundName, char[] name) { - if (compoundName == null || compoundName.length == 0) - return nameEnvironment.isPackage(null, name); - return nameEnvironment.isPackage(compoundName, name); -} -// The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready. - -public MethodVerifier methodVerifier() { - if (verifier == null) - verifier = new MethodVerifier(this); - return verifier; -} -public void reset() { - this.defaultPackage = new PackageBinding(this); // assume the default package always exists - this.defaultImports = null; - this.knownPackages = new HashtableOfPackage(); - - this.verifier = null; - for (int i = this.uniqueArrayBindings.length; --i >= 0;) - this.uniqueArrayBindings[i] = null; - this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50 - - for (int i = this.units.length; --i >= 0;) - this.units[i] = null; - this.lastUnitIndex = -1; - this.lastCompletedUnitIndex = -1; - this.unitBeingCompleted = null; // in case AbortException occurred - - // name environment has a longer life cycle, and must be reset in - // the code which created it. -} -void updateArrayCache(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) { - nextDimension : for (int i = 0, length = uniqueArrayBindings.length; i < length; i++) { - ArrayBinding[] arrayBindings = uniqueArrayBindings[i]; - if (arrayBindings != null) { - for (int j = 0, max = arrayBindings.length; j < max; j++) { - ArrayBinding currentBinding = arrayBindings[j]; - if (currentBinding == null) - continue nextDimension; - if (currentBinding.leafComponentType == unresolvedType) { - currentBinding.leafComponentType = resolvedType; - continue nextDimension; - } - } - } - } -} -}