import eclipse 3.1 M4 compiler
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / LookupEnvironment.java
index a7a9c9c..83b7380 100644 (file)
  *******************************************************************************/
 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;
@@ -66,10 +78,16 @@ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options,
        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);
@@ -78,13 +96,13 @@ public ReferenceBinding askForType(char[][] 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);
 }
@@ -104,13 +122,13 @@ ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
 
        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);
 }
@@ -121,9 +139,9 @@ ReferenceBinding askForType(PackageBinding packageBinding, char[] 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)
@@ -135,21 +153,21 @@ public void buildTypeBindings(CompilationUnitDeclaration unit) {
 * 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
 }
 /*
@@ -233,6 +251,67 @@ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean
                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;
@@ -252,10 +331,10 @@ private PackageBinding computePackageFrom(char[][] constantPoolName) {
        }
        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);
 
@@ -280,7 +359,7 @@ ArrayBinding createArrayType(TypeBinding type, int 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;
        }
@@ -291,26 +370,26 @@ ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
                (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;
 }
@@ -348,13 +427,146 @@ PackageBinding createPackage(char[][] compoundName) {
        }
        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) {
@@ -405,7 +617,7 @@ PackageBinding getTopLevelPackage(char[] name) {
        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.
 */
 
@@ -444,14 +656,24 @@ public ReferenceBinding getType(char[][] compoundName) {
 
        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.
@@ -461,7 +683,7 @@ public ReferenceBinding getType(char[][] compoundName) {
 * 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;
 
@@ -474,6 +696,9 @@ ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int en
        } 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;
 }
@@ -486,7 +711,7 @@ ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int en
 * 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++;
@@ -527,19 +752,111 @@ TypeBinding getTypeFromSignature(char[] signature, int start, int end) {
                                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);
@@ -549,40 +866,66 @@ boolean isPackage(char[][] compoundName, char[] 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;
                        }
                }
        }