*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import java.util.HashMap;
+import java.util.Map;
+
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.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.*;
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;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
public class LookupEnvironment implements BaseTypes, ProblemReasons, TypeConstants {
- public CompilerOptions options;
- public ProblemReporter problemReporter;
- public ITypeRequestor typeRequestor;
+ final static int BUILD_FIELDS_AND_METHODS = 4;
+ final static int BUILD_TYPE_HIERARCHY = 1;
+ final static int CHECK_AND_SET_IMPORTS = 2;
+ final static int CONNECT_TYPE_HIERARCHY = 3;
+ static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
+ static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR, NotFound);
+
+ /**
+ * Map from typeBinding -> accessRestriction rule
+ */
+ private Map accessRestrictions;
+ ImportBinding[] defaultImports;
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 int lastCompletedUnitIndex = -1;
+ private int lastUnitIndex = -1;
- private INameEnvironment nameEnvironment;
- private MethodVerifier verifier;
- private ArrayBinding[][] uniqueArrayBindings;
+ public INameEnvironment nameEnvironment;
+ public CompilerOptions options;
+ public ProblemReporter problemReporter;
- private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
- private int lastUnitIndex = -1;
- private int lastCompletedUnitIndex = -1;
- public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
+ // 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[] sharedClassFileContents = null;
+ public byte[] sharedClassFileHeader = null;
// 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;
+ public ITypeRequestor typeRequestor;
+ private ArrayBinding[][] uniqueArrayBindings;
+ private SimpleLookupTable uniqueParameterizedTypeBindings;
+ private SimpleLookupTable uniqueRawTypeBindings;
+ private SimpleLookupTable uniqueWildcardBindings;
+
+ public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
- // 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;
+ private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
+ private MethodVerifier verifier;
public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
this.typeRequestor = typeRequestor;
this.knownPackages = new HashtableOfPackage();
this.uniqueArrayBindings = new ArrayBinding[5][];
this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
+ this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
+ this.uniqueRawTypeBindings = new SimpleLookupTable(3);
+ this.uniqueWildcardBindings = new SimpleLookupTable(3);
+ this.accessRestrictions = new HashMap(3);
}
-/* Ask the oracle for a type which corresponds to the compoundName.
-* Answer null if the name cannot be found.
-*/
+
+/**
+ * Ask the name environment 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.isBinaryType())
// the type was found as a .class file
- typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName));
+ typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName), answer.getAccessRestriction());
else if (answer.isCompilationUnit())
// the type was found as a .java file, try to build it then search the cache
- typeRequestor.accept(answer.getCompilationUnit());
+ typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
else if (answer.isSourceType())
// the type was found as a source model
- typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName));
+ typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName), answer.getAccessRestriction());
return getCachedType(compoundName);
}
if (answer.isBinaryType())
// the type was found as a .class file
- typeRequestor.accept(answer.getBinaryType(), packageBinding);
+ typeRequestor.accept(answer.getBinaryType(), packageBinding, answer.getAccessRestriction());
else if (answer.isCompilationUnit())
// the type was found as a .java file, try to build it then search the cache
- typeRequestor.accept(answer.getCompilationUnit());
+ typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
else if (answer.isSourceType())
// the type was found as a source model
- typeRequestor.accept(answer.getSourceTypes(), packageBinding);
+ typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction());
return packageBinding.getType0(name);
}
* NOTE: This method can be called multiple times as additional source files are needed
*/
-public void buildTypeBindings(CompilationUnitDeclaration unit) {
+public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) {
CompilationUnitScope scope = new CompilationUnitScope(unit, this);
- scope.buildTypeBindings();
+ scope.buildTypeBindings(accessRestriction);
int unitsLength = units.length;
if (++lastUnitIndex >= unitsLength)
* Answer the created BinaryTypeBinding or null if the type is already in the cache.
*/
-public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType) {
- return cacheBinaryType(binaryType, true);
+public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, AccessRestriction accessRestriction) {
+ return cacheBinaryType(binaryType, true, accessRestriction);
}
/* 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) {
+public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
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 createBinaryTypeFrom(binaryType, computePackageFrom(compoundName), needFieldsAndMethods, accessRestriction);
return null; // the type already exists & can be retrieved from the cache
}
/*
parsedUnit.scope.buildFieldsAndMethods();
this.unitBeingCompleted = null;
}
+public TypeBinding computeBoxingType(TypeBinding type) {
+ TypeBinding boxedType;
+ switch (type.id) {
+ case TypeIds.T_JavaLangBoolean :
+ return BooleanBinding;
+ case TypeIds.T_JavaLangByte :
+ return ByteBinding;
+ case TypeIds.T_JavaLangCharacter :
+ return CharBinding;
+ case TypeIds.T_JavaLangShort :
+ return ShortBinding;
+ case TypeIds.T_JavaLangDouble :
+ return DoubleBinding;
+ case TypeIds.T_JavaLangFloat :
+ return FloatBinding;
+ case TypeIds.T_JavaLangInteger :
+ return IntBinding;
+ case TypeIds.T_JavaLangLong :
+ return LongBinding;
+ case TypeIds.T_JavaLangVoid :
+ return VoidBinding;
+
+ case TypeIds.T_int :
+ boxedType = getType(JAVA_LANG_INTEGER);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_INTEGER, NotFound);
+ case TypeIds.T_byte :
+ boxedType = getType(JAVA_LANG_BYTE);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_BYTE, NotFound);
+ case TypeIds.T_short :
+ boxedType = getType(JAVA_LANG_SHORT);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_SHORT, NotFound);
+ case TypeIds.T_char :
+ boxedType = getType(JAVA_LANG_CHARACTER);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_CHARACTER, NotFound);
+ case TypeIds.T_long :
+ boxedType = getType(JAVA_LANG_LONG);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_LONG, NotFound);
+ case TypeIds.T_float :
+ boxedType = getType(JAVA_LANG_FLOAT);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_FLOAT, NotFound);
+ case TypeIds.T_double :
+ boxedType = getType(JAVA_LANG_DOUBLE);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_DOUBLE, NotFound);
+ case TypeIds.T_boolean :
+ boxedType = getType(JAVA_LANG_BOOLEAN);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_BOOLEAN, NotFound);
+ case TypeIds.T_void :
+ boxedType = getType(JAVA_LANG_VOID);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_VOID, NotFound);
+ }
+ return type;
+}
private PackageBinding computePackageFrom(char[][] constantPoolName) {
if (constantPoolName.length == 1)
return defaultPackage;
}
return packageBinding;
}
+
/* Used to guarantee array type identity.
*/
-
-ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
+public ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
if (type instanceof LocalTypeBinding) // cache local type arrays with the local type itself
return ((LocalTypeBinding) type).createArrayType(dimensionCount);
while (++index < length) {
ArrayBinding currentBinding = arrayBindings[index];
if (currentBinding == null) // no matching array, but space left
- return arrayBindings[index] = new ArrayBinding(type, dimensionCount);
+ return arrayBindings[index] = new ArrayBinding(type, dimensionCount, this);
if (currentBinding.leafComponentType == type)
return currentBinding;
}
(arrayBindings = new ArrayBinding[length * 2]), 0,
length);
uniqueArrayBindings[dimIndex] = arrayBindings;
- return arrayBindings[length] = new ArrayBinding(type, dimensionCount);
+ return arrayBindings[length] = new ArrayBinding(type, dimensionCount, this);
}
-public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding) {
- return createBinaryTypeFrom(binaryType, packageBinding, true);
+public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+ return createBinaryTypeFrom(binaryType, packageBinding, true, accessRestriction);
}
-public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods) {
+public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
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 != null) { // update reference to unresolved binding after having read classfile (knows whether generic for raw conversion)
+ // TODO (kent) suspect the check below is no longer required, since we should not be requesting a binary which is already in the cache
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);
+ ((UnresolvedReferenceBinding) cachedType).setResolvedType(binaryBinding, this);
}
packageBinding.addType(binaryBinding);
+ setAccessRestriction(binaryBinding, accessRestriction);
binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods);
return binaryBinding;
}
}
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 ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] originalArguments, ReferenceBinding enclosingType) {
+
+ // relocalize wildcard onto genericType (could come from other types)
+ TypeBinding[] typeArguments = originalArguments;
+ for (int i = 0, length = typeArguments == null ? 0 : typeArguments.length; i < length; i++) {
+ TypeBinding argument = originalArguments[i];
+ if (argument.isWildcard()) {
+ WildcardBinding wildcard = (WildcardBinding) argument;
+ if (wildcard.genericType != genericType) { // wildcard comes from different type
+ if (typeArguments == originalArguments) {
+ System.arraycopy(originalArguments, 0, typeArguments = new TypeBinding[length], 0, i);
+ }
+ typeArguments[i] = createWildcard(genericType, i, wildcard.bound, wildcard.kind);
+ } else if (typeArguments != originalArguments) {
+ typeArguments[i] = argument;
+ }
+ } else if (typeArguments != originalArguments) {
+ typeArguments[i] = argument;
+ }
+ }
+
+ // cached info is array of already created parameterized types for this type
+ ParameterizedTypeBinding[] cachedInfo = (ParameterizedTypeBinding[])this.uniqueParameterizedTypeBindings.get(genericType);
+ int argLength = typeArguments == null ? 0: typeArguments.length;
+ boolean needToGrow = false;
+ if (cachedInfo != null){
+ nextCachedType :
+ // iterate existing parameterized for reusing one with same type arguments if any
+ for (int i = 0, max = cachedInfo.length; i < max; i++){
+ ParameterizedTypeBinding cachedType = cachedInfo[i];
+ if (cachedType.type != genericType) continue nextCachedType; // remain of unresolved type
+ if (cachedType.enclosingType() != enclosingType) continue nextCachedType;
+ TypeBinding[] cachedArguments = cachedType.arguments;
+ int cachedArgLength = cachedArguments == null ? 0 : cachedArguments.length;
+ if (argLength != cachedArgLength) continue nextCachedType; // would be an error situation (from unresolved binaries)
+ for (int j = 0; j < cachedArgLength; j++){
+ if (typeArguments[j] != cachedArguments[j]) continue nextCachedType;
+ }
+ // all arguments match, reuse current
+ return cachedType;
+ }
+ needToGrow = true;
+ } else {
+ cachedInfo = new ParameterizedTypeBinding[1];
+ this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
+ }
+ // grow cache ?
+ if (needToGrow){
+ int length = cachedInfo.length;
+ System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedTypeBinding[length+1], 0, length);
+ this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
+ }
+ // add new binding
+ ParameterizedTypeBinding parameterizedType = new ParameterizedTypeBinding(genericType,typeArguments, enclosingType, this);
+ cachedInfo[cachedInfo.length-1] = parameterizedType;
+ return parameterizedType;
+}
+
+public RawTypeBinding createRawType(ReferenceBinding genericType, ReferenceBinding enclosingType) {
+ // cached info is array of already created raw types for this type
+ RawTypeBinding[] cachedInfo = (RawTypeBinding[])this.uniqueRawTypeBindings.get(genericType);
+ boolean needToGrow = false;
+ if (cachedInfo != null){
+ nextCachedType :
+ // iterate existing parameterized for reusing one with same type arguments if any
+ for (int i = 0, max = cachedInfo.length; i < max; i++){
+ RawTypeBinding cachedType = cachedInfo[i];
+ if (cachedType.type != genericType) continue nextCachedType; // remain of unresolved type
+ if (cachedType.enclosingType() != enclosingType) continue nextCachedType;
+ // all enclosing type match, reuse current
+ return cachedType;
+ }
+ needToGrow = true;
+ } else {
+ cachedInfo = new RawTypeBinding[1];
+ this.uniqueRawTypeBindings.put(genericType, cachedInfo);
+ }
+ // grow cache ?
+ if (needToGrow){
+ int length = cachedInfo.length;
+ System.arraycopy(cachedInfo, 0, cachedInfo = new RawTypeBinding[length+1], 0, length);
+ this.uniqueRawTypeBindings.put(genericType, cachedInfo);
+ }
+ // add new binding
+ RawTypeBinding rawType = new RawTypeBinding(genericType, enclosingType, this);
+ cachedInfo[cachedInfo.length-1] = rawType;
+ return rawType;
+
+}
+
+public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, int kind) {
+
+ // cached info is array of already created wildcard types for this type
+ WildcardBinding[] cachedInfo = (WildcardBinding[])this.uniqueWildcardBindings.get(genericType);
+ boolean needToGrow = false;
+ if (cachedInfo != null){
+ nextCachedType :
+ // iterate existing wildcards for reusing one with same information if any
+ for (int i = 0, max = cachedInfo.length; i < max; i++){
+ WildcardBinding cachedType = cachedInfo[i];
+ if (cachedType.genericType != genericType) continue nextCachedType; // remain of unresolved type
+ if (cachedType.rank != rank) continue nextCachedType;
+ if (cachedType.kind != kind) continue nextCachedType;
+ if (cachedType.bound != bound) continue nextCachedType;
+ // all match, reuse current
+ return cachedType;
+ }
+ needToGrow = true;
+ } else {
+ cachedInfo = new WildcardBinding[1];
+ this.uniqueWildcardBindings.put(genericType, cachedInfo);
+ }
+ // grow cache ?
+ if (needToGrow){
+ int length = cachedInfo.length;
+ System.arraycopy(cachedInfo, 0, cachedInfo = new WildcardBinding[length+1], 0, length);
+ this.uniqueWildcardBindings.put(genericType, cachedInfo);
+ }
+ // add new binding
+ WildcardBinding wildcard = new WildcardBinding(genericType, rank, bound, kind, this);
+ cachedInfo[cachedInfo.length-1] = wildcard;
+ return wildcard;
+}
+
+/**
+ * Returns the access restriction associated to a given type, or null if none
+ */
+public AccessRestriction getAccessRestriction(TypeBinding type) {
+ return (AccessRestriction) this.accessRestrictions.get(type);
+}
+
+/**
+ * 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) {
return null;
}
/* Answer the type corresponding to the compoundName.
-* Ask the oracle for the type if its not in the cache.
+* Ask the name environment for the type if its not in the cache.
* Answer null if the type cannot be found... likely a fatal error.
*/
if (referenceBinding == null || referenceBinding == TheNotFoundType)
return null;
- if (referenceBinding instanceof UnresolvedReferenceBinding)
- referenceBinding = ((UnresolvedReferenceBinding) referenceBinding).resolve(this);
+ referenceBinding = BinaryTypeBinding.resolveType(referenceBinding, this, false); // no raw conversion for now
// compoundName refers to a nested type incorrectly (for example, package1.A$B)
if (referenceBinding.isNestedType())
return new ProblemReferenceBinding(compoundName, InternalNameProvided);
return referenceBinding;
}
+private TypeBinding[] getTypeArgumentsFromSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType, ReferenceBinding genericType) {
+ java.util.ArrayList args = new java.util.ArrayList(2);
+ int rank = 0;
+ do {
+ args.add(getTypeFromVariantTypeSignature(wrapper, staticVariables, enclosingType, genericType, rank++));
+ } while (wrapper.signature[wrapper.start] != '>');
+ wrapper.start++; // skip '>'
+ TypeBinding[] typeArguments = new TypeBinding[args.size()];
+ args.toArray(typeArguments);
+ return typeArguments;
+}
/* 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: Aborts compilation if the class file cannot be found.
*/
-ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end) {
+ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end, boolean isParameterized) {
if (end == -1)
end = signature.length;
} else if (binding == TheNotFoundType) {
problemReporter.isClassPathCorrect(compoundName, null);
return null; // will not get here since the above error aborts the compilation
+ } else if (!isParameterized && binding.isGenericType()) {
+ // check raw type, only for resolved types
+ binding = createRawType(binding, binding.enclosingType());
}
return binding;
}
* NOTE: Aborts compilation if the class file cannot be found.
*/
-TypeBinding getTypeFromSignature(char[] signature, int start, int end) {
+TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean isParameterized, TypeBinding enclosingType) {
int dimension = 0;
while (signature[start] == '[') {
start++;
binding = ShortBinding;
break;
default :
- throw new Error(Util.bind("error.undefinedBaseType",String.valueOf(signature[start]))); //$NON-NLS-1$
+ problemReporter.corruptedSignature(enclosingType, signature, start);
+ // will never reach here, since error will cause abort
}
} else {
- binding = getTypeFromConstantPoolName(signature, start + 1, end);
+ binding = getTypeFromConstantPoolName(signature, start + 1, end, isParameterized); // skip leading 'L' or 'T'
}
if (dimension == 0)
return binding;
return createArrayType(binding, dimension);
}
+TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType) {
+ // TypeVariableSignature = 'T' Identifier ';'
+ // ArrayTypeSignature = '[' TypeSignature
+ // ClassTypeSignature = 'L' Identifier TypeArgs(optional) ';'
+ // or ClassTypeSignature '.' 'L' Identifier TypeArgs(optional) ';'
+ // TypeArgs = '<' VariantTypeSignature VariantTypeSignatures '>'
+ int dimension = 0;
+ while (wrapper.signature[wrapper.start] == '[') {
+ wrapper.start++;
+ dimension++;
+ }
+
+ if (wrapper.signature[wrapper.start] == 'T') {
+ int varStart = wrapper.start + 1;
+ int varEnd = wrapper.computeEnd();
+ for (int i = staticVariables.length; --i >= 0;)
+ if (CharOperation.equals(staticVariables[i].sourceName, wrapper.signature, varStart, varEnd))
+ return dimension == 0 ? (TypeBinding) staticVariables[i] : createArrayType(staticVariables[i], dimension);
+ ReferenceBinding initialType = enclosingType;
+ do {
+ if (enclosingType instanceof BinaryTypeBinding) { // per construction can only be binary type binding
+ TypeVariableBinding[] enclosingVariables = ((BinaryTypeBinding)enclosingType).typeVariables; // do not trigger resolution of variables
+ for (int i = enclosingVariables.length; --i >= 0;)
+ if (CharOperation.equals(enclosingVariables[i].sourceName, wrapper.signature, varStart, varEnd))
+ return dimension == 0 ? (TypeBinding) enclosingVariables[i] : createArrayType(enclosingVariables[i], dimension);
+ }
+ } while ((enclosingType = enclosingType.enclosingType()) != null);
+ problemReporter.undefinedTypeVariableSignature(CharOperation.subarray(wrapper.signature, varStart, varEnd), initialType);
+ return null; // cannot reach this, since previous problem will abort compilation
+ }
+ boolean isParameterized;
+ TypeBinding type = getTypeFromSignature(wrapper.signature, wrapper.start, wrapper.computeEnd(), isParameterized = (wrapper.end == wrapper.bracket), enclosingType);
+ if (!isParameterized)
+ return dimension == 0 ? type : createArrayType(type, dimension);
+
+ // type must be a ReferenceBinding at this point, cannot be a BaseTypeBinding or ArrayTypeBinding
+ ReferenceBinding actualType = (ReferenceBinding) type;
+ TypeBinding[] typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, actualType);
+ ParameterizedTypeBinding parameterizedType = createParameterizedType(actualType, typeArguments, null);
+
+ while (wrapper.signature[wrapper.start] == '.') {
+ wrapper.start++; // skip '.'
+ char[] memberName = wrapper.nextWord();
+ BinaryTypeBinding.resolveType(parameterizedType, this, false);
+ ReferenceBinding memberType = parameterizedType.type.getMemberType(memberName);
+ if (wrapper.signature[wrapper.start] == '<') {
+ wrapper.start++; // skip '<'
+ typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, memberType);
+ } else {
+ typeArguments = null;
+ }
+ parameterizedType = createParameterizedType(memberType, typeArguments, parameterizedType);
+ }
+ wrapper.start++; // skip ';'
+ return dimension == 0 ? (TypeBinding) parameterizedType : createArrayType(parameterizedType, dimension);
+}
+TypeBinding getTypeFromVariantTypeSignature(
+ SignatureWrapper wrapper,
+ TypeVariableBinding[] staticVariables,
+ ReferenceBinding enclosingType,
+ ReferenceBinding genericType,
+ int rank) {
+ // VariantTypeSignature = '-' TypeSignature
+ // or '+' TypeSignature
+ // or TypeSignature
+ // or '*'
+ switch (wrapper.signature[wrapper.start]) {
+ case '-' :
+ // ? super aType
+ wrapper.start++;
+ TypeBinding bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
+ return createWildcard(genericType, rank, bound, Wildcard.SUPER);
+ case '+' :
+ // ? extends aType
+ wrapper.start++;
+ bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
+ return createWildcard(genericType, rank, bound, Wildcard.EXTENDS);
+ case '*' :
+ // ?
+ wrapper.start++;
+ return createWildcard(genericType, rank, null, Wildcard.UNBOUND);
+ default :
+ return getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
+ }
+}
+public boolean isBoxingCompatibleWith(TypeBinding left, TypeBinding right) {
+ if (options.sourceLevel < ClassFileConstants.JDK1_5 || left.isBaseType() == right.isBaseType())
+ return false;
+
+ TypeBinding convertedType = computeBoxingType(left);
+ return convertedType == right || convertedType.isCompatibleWith(right);
+}
/* 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);
public MethodVerifier methodVerifier() {
if (verifier == null)
- verifier = new MethodVerifier(this);
+ verifier = this.options.sourceLevel < ClassFileConstants.JDK1_5
+ ? new MethodVerifier(this)
+ : new MethodVerifier15(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.accessRestrictions = new HashMap(3);
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.uniqueArrayBindings.length; --i >= 0;) {
+ ArrayBinding[] arrayBindings = this.uniqueArrayBindings[i];
+ if (arrayBindings != null)
+ for (int j = arrayBindings.length; --j >= 0;)
+ arrayBindings[j] = null;
+ }
+ this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
+ this.uniqueRawTypeBindings = new SimpleLookupTable(3);
+ this.uniqueWildcardBindings = new SimpleLookupTable(3);
+
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;
- }
+/**
+ * Associate a given type with some access restriction
+ * (did not store the restriction directly into binding, since sparse information)
+ */
+public void setAccessRestriction(ReferenceBinding type, AccessRestriction accessRestriction) {
+ if (accessRestriction == null) return;
+ type.modifiers |= CompilerModifiers.AccRestrictedAccess;
+ this.accessRestrictions.put(type, accessRestriction);
+}
+
+void updateCaches(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) {
+ // walk all the unique collections & replace the unresolvedType with the resolvedType
+ // must prevent 2 entries so == still works (1 containing the unresolvedType and the other containing the resolvedType)
+ if (this.uniqueParameterizedTypeBindings.get(unresolvedType) != null) { // update the key
+ Object[] keys = this.uniqueParameterizedTypeBindings.keyTable;
+ for (int i = 0, l = keys.length; i < l; i++) {
+ if (keys[i] == unresolvedType) {
+ keys[i] = resolvedType; // hashCode is based on compoundName so this works - cannot be raw since type of parameterized type
+ break;
+ }
+ }
+ }
+
+ if (this.uniqueWildcardBindings.get(unresolvedType) != null) { // update the key
+ Object[] keys = this.uniqueWildcardBindings.keyTable;
+ for (int i = 0, l = keys.length; i < l; i++) {
+ if (keys[i] == unresolvedType) {
+ keys[i] = resolvedType; // hashCode is based on compoundName so this works
+ break;
}
}
}