X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/LookupEnvironment.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/LookupEnvironment.java index 54e6de2..bbe5a89 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/LookupEnvironment.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/LookupEnvironment.java @@ -20,23 +20,35 @@ import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter; import net.sourceforge.phpdt.internal.compiler.util.HashtableOfPackage; import net.sourceforge.phpdt.internal.compiler.util.Util; -public class LookupEnvironment implements BaseTypes, ProblemReasons, TypeConstants { -// public CompilerOptions options; +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); + + 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; // indicate in which step on the compilation we are. @@ -44,542 +56,655 @@ public class LookupEnvironment implements BaseTypes, ProblemReasons, TypeConstan // 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; -public LookupEnvironment(ITypeRequestor typeRequestor,ProblemReporter problemReporter, INameEnvironment nameEnvironment) { -// 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; + public LookupEnvironment(ITypeRequestor typeRequestor, + ProblemReporter problemReporter, INameEnvironment nameEnvironment) { + // 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 + } - 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. -*/ + /* + * Ask the oracle for a type which corresponds to the compoundName. Answer + * null if the name cannot be found. + */ -ReferenceBinding askForType(PackageBinding packageBinding, char[] name) { - if (packageBinding == null) { - if (defaultPackage == null) + public ReferenceBinding askForType(char[][] compoundName) { + NameEnvironmentAnswer answer = nameEnvironment.findType(compoundName); + if (answer == null) return null; - packageBinding = defaultPackage; + + 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); } - 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. -*/ + /* + * Ask the oracle for a type named name in the packageBinding. Answer null + * if the name cannot be found. + */ -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 = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { -// units[i].scope.checkAndSetImports(); -// } - stepCompleted = CHECK_AND_SET_IMPORTS; - -// for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { -// units[i].scope.connectTypeHierarchy(); -// } - stepCompleted = CONNECT_TYPE_HIERARCHY; - - for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { -// units[i].scope.buildFieldsAndMethods(); - units[i] = null; // release unnecessary reference to the parsed unit + 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); } - stepCompleted = BUILD_FIELDS_AND_METHODS; - lastCompletedUnitIndex = lastUnitIndex; -} -/* -* 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) -// parsedUnit.scope.checkAndSetImports(); - - if (stepCompleted >= CONNECT_TYPE_HIERARCHY) - parsedUnit.scope.connectTypeHierarchy(); + + /* + * 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; } -} -/* -* 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 - - parsedUnit.scope.checkAndSetImports(); - parsedUnit.scope.connectTypeHierarchy(); - - if (buildFieldsAndMethods) - parsedUnit.scope.buildFieldsAndMethods(); -} -private PackageBinding computePackageFrom(char[][] constantPoolName) { - if (constantPoolName.length == 1) - return defaultPackage; + /* + * 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. + */ - PackageBinding packageBinding = getPackage0(constantPoolName[0]); - if (packageBinding == null || packageBinding == TheNotFoundPackage) { - packageBinding = new PackageBinding(constantPoolName[0], this); - knownPackages.put(constantPoolName[0], packageBinding); + public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType) { + return cacheBinaryType(binaryType, true); } - 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); - } + /* + * 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 } - 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]; + + /* + * 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 = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + // units[i].scope.checkAndSetImports(); + // } + stepCompleted = CHECK_AND_SET_IMPORTS; + + // for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + // units[i].scope.connectTypeHierarchy(); + // } + stepCompleted = CONNECT_TYPE_HIERARCHY; + + for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + // units[i].scope.buildFieldsAndMethods(); + units[i] = null; // release unnecessary reference to the parsed + // unit + } + stepCompleted = BUILD_FIELDS_AND_METHODS; + lastCompletedUnitIndex = lastUnitIndex; } - // 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; + /* + * 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) + // parsedUnit.scope.checkAndSetImports(); + + if (stepCompleted >= CONNECT_TYPE_HIERARCHY) + parsedUnit.scope.connectTypeHierarchy(); + } } - // 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); + /* + * 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 + + parsedUnit.scope.checkAndSetImports(); + parsedUnit.scope.connectTypeHierarchy(); + + if (buildFieldsAndMethods) + parsedUnit.scope.buildFieldsAndMethods(); } - packageBinding.addType(binaryBinding); - binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods); - return binaryBinding; -} -/* Used to create packages from the package statement. -*/ - -PackageBinding createPackage(char[][] compoundName) { - return null; -// 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]); + 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; } - PackageBinding packageBinding = getPackage0(compoundName[0]); - if (packageBinding == null || packageBinding == TheNotFoundPackage) - return null; + /* + * 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]; + } - 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; - else - return packageBinding; + // 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); } - if (nameEnvironment.isPackage(null, name)) { - knownPackages.put(name, packageBinding = new PackageBinding(name, this)); - return packageBinding; + public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, + PackageBinding packageBinding) { + return createBinaryTypeFrom(binaryType, packageBinding, true); } - 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 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); + } -public ReferenceBinding getType(char[][] compoundName) { - ReferenceBinding referenceBinding; + packageBinding.addType(binaryBinding); + binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods); + return binaryBinding; + } - if (compoundName.length == 1) { - if (defaultPackage == null) - return null; + /* + * Used to create packages from the package statement. + */ - 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]); + PackageBinding createPackage(char[][] compoundName) { + return null; + // 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]); } - } else { + PackageBinding packageBinding = getPackage0(compoundName[0]); - if (packageBinding == TheNotFoundPackage) + 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) { - 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 == TheNotFoundPackage) + return null; + else + return packageBinding; } - if (packageBinding == null) - referenceBinding = askForType(compoundName); - else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.length - 1])) == null) - referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1]); - } + if (nameEnvironment.isPackage(null, name)) { + knownPackages.put(name, packageBinding = new PackageBinding(name, + this)); + return packageBinding; + } - if (referenceBinding == null || referenceBinding == TheNotFoundType) + knownPackages.put(name, TheNotFoundPackage); // saves asking the + // oracle next time 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); - else - 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++; + + /* + * 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); + else + 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; } - 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' : + + /* + * 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' : + case 'Z': binding = BooleanBinding; break; - case 'V' : + case 'V': binding = VoidBinding; break; - case 'C' : + case 'C': binding = CharBinding; break; - case 'D' : + case 'D': binding = DoubleBinding; break; - case 'B' : + case 'B': binding = ByteBinding; break; - case 'F' : + case 'F': binding = FloatBinding; break; - case 'J' : + case 'J': binding = LongBinding; break; - case 'S' : + case 'S': binding = ShortBinding; break; - default : - throw new Error(Util.bind("error.undefinedBaseType",String.valueOf(signature[start]))); //$NON-NLS-1$ + default: + throw new Error( + Util + .bind( + "error.undefinedBaseType", String.valueOf(signature[start]))); //$NON-NLS-1$ + } + } else { + binding = getTypeFromConstantPoolName(signature, start + 1, end); } - } else { - binding = getTypeFromConstantPoolName(signature, start + 1, end); + + if (dimension == 0) + return binding; + else + return createArrayType(binding, dimension); } - if (dimension == 0) - return binding; - else - 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); - else - return nameEnvironment.isPackage(compoundName, name); -} -// The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready. + /* + * Ask the oracle if a package exists named name in the package named + * compoundName. + */ -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; - - // 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; + boolean isPackage(char[][] compoundName, char[] name) { + if (compoundName == null || compoundName.length == 0) + return nameEnvironment.isPackage(null, name); + else + 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; + + // 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; + } } } } } } -}