0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.lookup;
0011:
0012: import java.util.HashMap;
0013: import java.util.Map;
0014:
0015: import org.eclipse.jdt.core.compiler.CharOperation;
0016: import org.eclipse.jdt.internal.compiler.ClassFilePool;
0017: import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
0018: import org.eclipse.jdt.internal.compiler.ast.Wildcard;
0019: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
0020: import org.eclipse.jdt.internal.compiler.env.*;
0021: import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
0022: import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
0023: import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
0024: import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
0025: import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
0026:
0027: public class LookupEnvironment implements ProblemReasons, TypeConstants {
0028:
0029: final static int BUILD_FIELDS_AND_METHODS = 4;
0030: final static int BUILD_TYPE_HIERARCHY = 1;
0031: final static int CHECK_AND_SET_IMPORTS = 2;
0032: final static int CONNECT_TYPE_HIERARCHY = 3;
0033: static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(
0034: CharOperation.NO_CHAR, NotFound);
0035: static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(
0036: CharOperation.NO_CHAR, null, NotFound);
0037:
0038: /**
0039: * Map from typeBinding -> accessRestriction rule
0040: */
0041: private Map accessRestrictions;
0042: ImportBinding[] defaultImports;
0043:
0044: public PackageBinding defaultPackage;
0045: HashtableOfPackage knownPackages;
0046: private int lastCompletedUnitIndex = -1;
0047: private int lastUnitIndex = -1;
0048:
0049: public INameEnvironment nameEnvironment;
0050: public CompilerOptions globalOptions;
0051: public ProblemReporter problemReporter;
0052:
0053: public ClassFilePool classFilePool;
0054:
0055: // indicate in which step on the compilation we are.
0056: // step 1 : build the reference binding
0057: // step 2 : conect the hierarchy (connect bindings)
0058: // step 3 : build fields and method bindings.
0059: private int stepCompleted;
0060: public ITypeRequestor typeRequestor;
0061: private ArrayBinding[][] uniqueArrayBindings;
0062: private SimpleLookupTable uniqueParameterizedTypeBindings;
0063: private SimpleLookupTable uniqueRawTypeBindings;
0064: private SimpleLookupTable uniqueWildcardBindings;
0065: private SimpleLookupTable uniqueParameterizedGenericMethodBindings;
0066:
0067: public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
0068: public Object missingClassFileLocation = null; // only set when resolving certain references, to help locating problems
0069:
0070: private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
0071: private MethodVerifier verifier;
0072:
0073: public LookupEnvironment(ITypeRequestor typeRequestor,
0074: CompilerOptions globalOptions,
0075: ProblemReporter problemReporter,
0076: INameEnvironment nameEnvironment) {
0077: this .typeRequestor = typeRequestor;
0078: this .globalOptions = globalOptions;
0079: this .problemReporter = problemReporter;
0080: this .defaultPackage = new PackageBinding(this ); // assume the default package always exists
0081: this .defaultImports = null;
0082: this .nameEnvironment = nameEnvironment;
0083: this .knownPackages = new HashtableOfPackage();
0084: this .uniqueArrayBindings = new ArrayBinding[5][];
0085: this .uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
0086: this .uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
0087: this .uniqueRawTypeBindings = new SimpleLookupTable(3);
0088: this .uniqueWildcardBindings = new SimpleLookupTable(3);
0089: this .uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(
0090: 3);
0091: this .accessRestrictions = new HashMap(3);
0092: this .classFilePool = ClassFilePool.newInstance();
0093: }
0094:
0095: /**
0096: * Ask the name environment for a type which corresponds to the compoundName.
0097: * Answer null if the name cannot be found.
0098: */
0099:
0100: public ReferenceBinding askForType(char[][] compoundName) {
0101: NameEnvironmentAnswer answer = nameEnvironment
0102: .findType(compoundName);
0103: if (answer == null)
0104: return null;
0105:
0106: if (answer.isBinaryType())
0107: // the type was found as a .class file
0108: typeRequestor.accept(answer.getBinaryType(),
0109: computePackageFrom(compoundName), answer
0110: .getAccessRestriction());
0111: else if (answer.isCompilationUnit())
0112: // the type was found as a .java file, try to build it then search the cache
0113: typeRequestor.accept(answer.getCompilationUnit(), answer
0114: .getAccessRestriction());
0115: else if (answer.isSourceType())
0116: // the type was found as a source model
0117: typeRequestor.accept(answer.getSourceTypes(),
0118: computePackageFrom(compoundName), answer
0119: .getAccessRestriction());
0120:
0121: return getCachedType(compoundName);
0122: }
0123:
0124: /* Ask the oracle for a type named name in the packageBinding.
0125: * Answer null if the name cannot be found.
0126: */
0127:
0128: ReferenceBinding askForType(PackageBinding packageBinding,
0129: char[] name) {
0130: if (packageBinding == null) {
0131: if (defaultPackage == null)
0132: return null;
0133: packageBinding = defaultPackage;
0134: }
0135: NameEnvironmentAnswer answer = nameEnvironment.findType(name,
0136: packageBinding.compoundName);
0137: if (answer == null)
0138: return null;
0139:
0140: if (answer.isBinaryType())
0141: // the type was found as a .class file
0142: typeRequestor.accept(answer.getBinaryType(),
0143: packageBinding, answer.getAccessRestriction());
0144: else if (answer.isCompilationUnit())
0145: // the type was found as a .java file, try to build it then search the cache
0146: typeRequestor.accept(answer.getCompilationUnit(), answer
0147: .getAccessRestriction());
0148: else if (answer.isSourceType())
0149: // the type was found as a source model
0150: typeRequestor.accept(answer.getSourceTypes(),
0151: packageBinding, answer.getAccessRestriction());
0152:
0153: return packageBinding.getType0(name);
0154: }
0155:
0156: /* Create the initial type bindings for the compilation unit.
0157: *
0158: * See completeTypeBindings() for a description of the remaining steps
0159: *
0160: * NOTE: This method can be called multiple times as additional source files are needed
0161: */
0162:
0163: public void buildTypeBindings(CompilationUnitDeclaration unit,
0164: AccessRestriction accessRestriction) {
0165: CompilationUnitScope scope = new CompilationUnitScope(unit,
0166: this );
0167: scope.buildTypeBindings(accessRestriction);
0168:
0169: int unitsLength = units.length;
0170: if (++lastUnitIndex >= unitsLength)
0171: System
0172: .arraycopy(
0173: units,
0174: 0,
0175: units = new CompilationUnitDeclaration[2 * unitsLength],
0176: 0, unitsLength);
0177: units[lastUnitIndex] = unit;
0178: }
0179:
0180: /* Cache the binary type since we know it is needed during this compile.
0181: *
0182: * Answer the created BinaryTypeBinding or null if the type is already in the cache.
0183: */
0184:
0185: public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType,
0186: AccessRestriction accessRestriction) {
0187: return cacheBinaryType(binaryType, true, accessRestriction);
0188: }
0189:
0190: /* Cache the binary type since we know it is needed during this compile.
0191: *
0192: * Answer the created BinaryTypeBinding or null if the type is already in the cache.
0193: */
0194:
0195: public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType,
0196: boolean needFieldsAndMethods,
0197: AccessRestriction accessRestriction) {
0198: char[][] compoundName = CharOperation.splitOn('/', binaryType
0199: .getName());
0200: ReferenceBinding existingType = getCachedType(compoundName);
0201:
0202: if (existingType == null
0203: || existingType instanceof UnresolvedReferenceBinding)
0204: // only add the binary type if its not already in the cache
0205: return createBinaryTypeFrom(binaryType,
0206: computePackageFrom(compoundName),
0207: needFieldsAndMethods, accessRestriction);
0208: return null; // the type already exists & can be retrieved from the cache
0209: }
0210:
0211: public BinaryTypeBinding cacheMissingBinaryType(
0212: char[][] compoundName, CompilationUnitDeclaration unit) {
0213: // report the missing class file first
0214: problemReporter.isClassPathCorrect(compoundName,
0215: unit == null ? this .unitBeingCompleted : unit,
0216: this .missingClassFileLocation);
0217:
0218: PackageBinding packageBinding = computePackageFrom(compoundName);
0219: // create a proxy for the missing BinaryType
0220: MissingBinaryTypeBinding type = new MissingBinaryTypeBinding(
0221: packageBinding, compoundName, this );
0222: if (type.id != TypeIds.T_JavaLangObject) {
0223: // make Object be its superclass - it could in turn be missing as well
0224: ReferenceBinding objectType = getType(TypeConstants.JAVA_LANG_OBJECT);
0225: if (objectType == null)
0226: objectType = cacheMissingBinaryType(
0227: TypeConstants.JAVA_LANG_OBJECT, unit); // create a proxy for the missing Object type
0228: type.setMissingSuperclass(objectType);
0229: }
0230: packageBinding.addType(type);
0231: return type;
0232: }
0233:
0234: /*
0235: * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
0236: * 2. Create the field bindings
0237: * 3. Create the method bindings
0238: */
0239:
0240: /* We know each known compilationUnit is free of errors at this point...
0241: *
0242: * Each step will create additional bindings unless a problem is detected, in which
0243: * case either the faulty import/superinterface/field/method will be skipped or a
0244: * suitable replacement will be substituted (such as Object for a missing superclass)
0245: */
0246:
0247: public void completeTypeBindings() {
0248: stepCompleted = BUILD_TYPE_HIERARCHY;
0249:
0250: for (int i = this .lastCompletedUnitIndex + 1; i <= this .lastUnitIndex; i++) {
0251: (this .unitBeingCompleted = this .units[i]).scope
0252: .checkAndSetImports();
0253: }
0254: stepCompleted = CHECK_AND_SET_IMPORTS;
0255:
0256: for (int i = this .lastCompletedUnitIndex + 1; i <= this .lastUnitIndex; i++) {
0257: (this .unitBeingCompleted = this .units[i]).scope
0258: .connectTypeHierarchy();
0259: }
0260: stepCompleted = CONNECT_TYPE_HIERARCHY;
0261:
0262: for (int i = this .lastCompletedUnitIndex + 1; i <= this .lastUnitIndex; i++) {
0263: CompilationUnitScope unitScope = (this .unitBeingCompleted = this .units[i]).scope;
0264: unitScope.checkParameterizedTypes();
0265: unitScope.buildFieldsAndMethods();
0266: this .units[i] = null; // release unnecessary reference to the parsed unit
0267: }
0268: stepCompleted = BUILD_FIELDS_AND_METHODS;
0269: this .lastCompletedUnitIndex = this .lastUnitIndex;
0270: this .unitBeingCompleted = null;
0271: }
0272:
0273: /*
0274: * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
0275: * 2. Create the field bindings
0276: * 3. Create the method bindings
0277: */
0278:
0279: /*
0280: * Each step will create additional bindings unless a problem is detected, in which
0281: * case either the faulty import/superinterface/field/method will be skipped or a
0282: * suitable replacement will be substituted (such as Object for a missing superclass)
0283: */
0284:
0285: public void completeTypeBindings(
0286: CompilationUnitDeclaration parsedUnit) {
0287: if (stepCompleted == BUILD_FIELDS_AND_METHODS) {
0288: // This can only happen because the original set of units are completely built and
0289: // are now being processed, so we want to treat all the additional units as a group
0290: // until they too are completely processed.
0291: completeTypeBindings();
0292: } else {
0293: if (parsedUnit.scope == null)
0294: return; // parsing errors were too severe
0295:
0296: if (stepCompleted >= CHECK_AND_SET_IMPORTS)
0297: (this .unitBeingCompleted = parsedUnit).scope
0298: .checkAndSetImports();
0299:
0300: if (stepCompleted >= CONNECT_TYPE_HIERARCHY)
0301: (this .unitBeingCompleted = parsedUnit).scope
0302: .connectTypeHierarchy();
0303:
0304: this .unitBeingCompleted = null;
0305: }
0306: }
0307:
0308: /*
0309: * Used by other compiler tools which do not start by calling completeTypeBindings().
0310: *
0311: * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
0312: * 2. Create the field bindings
0313: * 3. Create the method bindings
0314: */
0315:
0316: public void completeTypeBindings(
0317: CompilationUnitDeclaration parsedUnit,
0318: boolean buildFieldsAndMethods) {
0319: if (parsedUnit.scope == null)
0320: return; // parsing errors were too severe
0321:
0322: (this .unitBeingCompleted = parsedUnit).scope
0323: .checkAndSetImports();
0324: parsedUnit.scope.connectTypeHierarchy();
0325: parsedUnit.scope.checkParameterizedTypes();
0326: if (buildFieldsAndMethods)
0327: parsedUnit.scope.buildFieldsAndMethods();
0328: this .unitBeingCompleted = null;
0329: }
0330:
0331: public TypeBinding computeBoxingType(TypeBinding type) {
0332: TypeBinding boxedType;
0333: switch (type.id) {
0334: case TypeIds.T_JavaLangBoolean:
0335: return TypeBinding.BOOLEAN;
0336: case TypeIds.T_JavaLangByte:
0337: return TypeBinding.BYTE;
0338: case TypeIds.T_JavaLangCharacter:
0339: return TypeBinding.CHAR;
0340: case TypeIds.T_JavaLangShort:
0341: return TypeBinding.SHORT;
0342: case TypeIds.T_JavaLangDouble:
0343: return TypeBinding.DOUBLE;
0344: case TypeIds.T_JavaLangFloat:
0345: return TypeBinding.FLOAT;
0346: case TypeIds.T_JavaLangInteger:
0347: return TypeBinding.INT;
0348: case TypeIds.T_JavaLangLong:
0349: return TypeBinding.LONG;
0350:
0351: case TypeIds.T_int:
0352: boxedType = getType(JAVA_LANG_INTEGER);
0353: if (boxedType != null)
0354: return boxedType;
0355: return new ProblemReferenceBinding(JAVA_LANG_INTEGER, null,
0356: NotFound);
0357: case TypeIds.T_byte:
0358: boxedType = getType(JAVA_LANG_BYTE);
0359: if (boxedType != null)
0360: return boxedType;
0361: return new ProblemReferenceBinding(JAVA_LANG_BYTE, null,
0362: NotFound);
0363: case TypeIds.T_short:
0364: boxedType = getType(JAVA_LANG_SHORT);
0365: if (boxedType != null)
0366: return boxedType;
0367: return new ProblemReferenceBinding(JAVA_LANG_SHORT, null,
0368: NotFound);
0369: case TypeIds.T_char:
0370: boxedType = getType(JAVA_LANG_CHARACTER);
0371: if (boxedType != null)
0372: return boxedType;
0373: return new ProblemReferenceBinding(JAVA_LANG_CHARACTER,
0374: null, NotFound);
0375: case TypeIds.T_long:
0376: boxedType = getType(JAVA_LANG_LONG);
0377: if (boxedType != null)
0378: return boxedType;
0379: return new ProblemReferenceBinding(JAVA_LANG_LONG, null,
0380: NotFound);
0381: case TypeIds.T_float:
0382: boxedType = getType(JAVA_LANG_FLOAT);
0383: if (boxedType != null)
0384: return boxedType;
0385: return new ProblemReferenceBinding(JAVA_LANG_FLOAT, null,
0386: NotFound);
0387: case TypeIds.T_double:
0388: boxedType = getType(JAVA_LANG_DOUBLE);
0389: if (boxedType != null)
0390: return boxedType;
0391: return new ProblemReferenceBinding(JAVA_LANG_DOUBLE, null,
0392: NotFound);
0393: case TypeIds.T_boolean:
0394: boxedType = getType(JAVA_LANG_BOOLEAN);
0395: if (boxedType != null)
0396: return boxedType;
0397: return new ProblemReferenceBinding(JAVA_LANG_BOOLEAN, null,
0398: NotFound);
0399: // case TypeIds.T_int :
0400: // return getResolvedType(JAVA_LANG_INTEGER, null);
0401: // case TypeIds.T_byte :
0402: // return getResolvedType(JAVA_LANG_BYTE, null);
0403: // case TypeIds.T_short :
0404: // return getResolvedType(JAVA_LANG_SHORT, null);
0405: // case TypeIds.T_char :
0406: // return getResolvedType(JAVA_LANG_CHARACTER, null);
0407: // case TypeIds.T_long :
0408: // return getResolvedType(JAVA_LANG_LONG, null);
0409: // case TypeIds.T_float :
0410: // return getResolvedType(JAVA_LANG_FLOAT, null);
0411: // case TypeIds.T_double :
0412: // return getResolvedType(JAVA_LANG_DOUBLE, null);
0413: // case TypeIds.T_boolean :
0414: // return getResolvedType(JAVA_LANG_BOOLEAN, null);
0415: }
0416: // allow indirect unboxing conversion for wildcards and type parameters
0417: switch (type.kind()) {
0418: case Binding.WILDCARD_TYPE:
0419: case Binding.TYPE_PARAMETER:
0420: switch (type.erasure().id) {
0421: case TypeIds.T_JavaLangBoolean:
0422: return TypeBinding.BOOLEAN;
0423: case TypeIds.T_JavaLangByte:
0424: return TypeBinding.BYTE;
0425: case TypeIds.T_JavaLangCharacter:
0426: return TypeBinding.CHAR;
0427: case TypeIds.T_JavaLangShort:
0428: return TypeBinding.SHORT;
0429: case TypeIds.T_JavaLangDouble:
0430: return TypeBinding.DOUBLE;
0431: case TypeIds.T_JavaLangFloat:
0432: return TypeBinding.FLOAT;
0433: case TypeIds.T_JavaLangInteger:
0434: return TypeBinding.INT;
0435: case TypeIds.T_JavaLangLong:
0436: return TypeBinding.LONG;
0437: }
0438: }
0439: return type;
0440: }
0441:
0442: private PackageBinding computePackageFrom(char[][] constantPoolName) {
0443: if (constantPoolName.length == 1)
0444: return defaultPackage;
0445:
0446: PackageBinding packageBinding = getPackage0(constantPoolName[0]);
0447: if (packageBinding == null
0448: || packageBinding == TheNotFoundPackage) {
0449: packageBinding = new PackageBinding(constantPoolName[0],
0450: this );
0451: knownPackages.put(constantPoolName[0], packageBinding);
0452: }
0453:
0454: for (int i = 1, length = constantPoolName.length - 1; i < length; i++) {
0455: PackageBinding parent = packageBinding;
0456: if ((packageBinding = parent
0457: .getPackage0(constantPoolName[i])) == null
0458: || packageBinding == TheNotFoundPackage) {
0459: packageBinding = new PackageBinding(CharOperation
0460: .subarray(constantPoolName, 0, i + 1), parent,
0461: this );
0462: parent.addPackage(packageBinding);
0463: }
0464: }
0465: return packageBinding;
0466: }
0467:
0468: /**
0469: * Convert a given source type into a parameterized form if generic.
0470: * generic X<E> --> param X<E>
0471: */
0472: public ReferenceBinding convertToParameterizedType(
0473: ReferenceBinding originalType) {
0474: if (originalType != null) {
0475: boolean isGeneric = originalType.isGenericType();
0476: ReferenceBinding originalEnclosingType = originalType
0477: .enclosingType();
0478: ReferenceBinding convertedEnclosingType = originalEnclosingType;
0479: boolean needToConvert = isGeneric;
0480: if (originalEnclosingType != null) {
0481: convertedEnclosingType = originalType.isStatic() ? (ReferenceBinding) convertToRawType(originalEnclosingType)
0482: : convertToParameterizedType(originalEnclosingType);
0483: needToConvert |= originalEnclosingType != convertedEnclosingType;
0484: }
0485: if (needToConvert) {
0486: return createParameterizedType(
0487: originalType,
0488: isGeneric ? originalType.typeVariables() : null,
0489: convertedEnclosingType);
0490: }
0491: }
0492: return originalType;
0493: }
0494:
0495: public TypeBinding convertToRawType(TypeBinding type) {
0496: int dimension;
0497: TypeBinding originalType;
0498: switch (type.kind()) {
0499: case Binding.BASE_TYPE:
0500: case Binding.TYPE_PARAMETER:
0501: case Binding.WILDCARD_TYPE:
0502: case Binding.RAW_TYPE:
0503: return type;
0504: case Binding.ARRAY_TYPE:
0505: dimension = type.dimensions();
0506: originalType = type.leafComponentType();
0507: break;
0508: default:
0509: if (type.id == TypeIds.T_JavaLangObject)
0510: return type; // Object is not generic
0511: dimension = 0;
0512: originalType = type;
0513: }
0514: boolean needToConvert;
0515: switch (originalType.kind()) {
0516: case Binding.BASE_TYPE:
0517: return type;
0518: case Binding.GENERIC_TYPE:
0519: needToConvert = true;
0520: break;
0521: case Binding.PARAMETERIZED_TYPE:
0522: ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) originalType;
0523: needToConvert = paramType.genericType().isGenericType(); // only recursive call to enclosing type can find parameterizedType with arguments
0524: break;
0525: default:
0526: needToConvert = false;
0527: break;
0528: }
0529: ReferenceBinding originalEnclosing = originalType
0530: .enclosingType();
0531: TypeBinding convertedType;
0532: if (originalEnclosing == null) {
0533: convertedType = needToConvert ? createRawType(
0534: (ReferenceBinding) originalType.erasure(), null)
0535: : originalType;
0536: } else {
0537: ReferenceBinding convertedEnclosing;
0538: if (originalEnclosing.kind() == Binding.RAW_TYPE) {
0539: needToConvert |= !((ReferenceBinding) originalType)
0540: .isStatic();
0541: convertedEnclosing = originalEnclosing;
0542: } else if (needToConvert
0543: || ((ReferenceBinding) originalType).isStatic()) {
0544: convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
0545: } else {
0546: convertedEnclosing = convertToParameterizedType(originalEnclosing);
0547: }
0548: if (needToConvert) {
0549: convertedType = createRawType(
0550: (ReferenceBinding) originalType.erasure(),
0551: convertedEnclosing);
0552: } else if (originalEnclosing != convertedEnclosing) {
0553: convertedType = createParameterizedType(
0554: (ReferenceBinding) originalType.erasure(),
0555: null, convertedEnclosing);
0556: } else {
0557: convertedType = originalType;
0558: }
0559: }
0560: if (originalType != convertedType) {
0561: return dimension > 0 ? (TypeBinding) createArrayType(
0562: convertedType, dimension) : convertedType;
0563: }
0564: return type;
0565: }
0566:
0567: // variation for unresolved types in binaries (consider generic type as raw)
0568: public TypeBinding convertUnresolvedBinaryToRawType(TypeBinding type) {
0569: int dimension;
0570: TypeBinding originalType;
0571: switch (type.kind()) {
0572: case Binding.BASE_TYPE:
0573: case Binding.TYPE_PARAMETER:
0574: case Binding.WILDCARD_TYPE:
0575: case Binding.RAW_TYPE:
0576: return type;
0577: case Binding.ARRAY_TYPE:
0578: dimension = type.dimensions();
0579: originalType = type.leafComponentType();
0580: break;
0581: default:
0582: if (type.id == TypeIds.T_JavaLangObject)
0583: return type; // Object is not generic
0584: dimension = 0;
0585: originalType = type;
0586: }
0587: boolean needToConvert;
0588: switch (originalType.kind()) {
0589: case Binding.BASE_TYPE:
0590: return type;
0591: case Binding.GENERIC_TYPE:
0592: needToConvert = true;
0593: break;
0594: case Binding.PARAMETERIZED_TYPE:
0595: ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) originalType;
0596: needToConvert = paramType.genericType().isGenericType(); // only recursive call to enclosing type can find parameterizedType with arguments
0597: break;
0598: default:
0599: needToConvert = false;
0600: break;
0601: }
0602: ReferenceBinding originalEnclosing = originalType
0603: .enclosingType();
0604: TypeBinding convertedType;
0605: if (originalEnclosing == null) {
0606: convertedType = needToConvert ? createRawType(
0607: (ReferenceBinding) originalType.erasure(), null)
0608: : originalType;
0609: } else {
0610: ReferenceBinding convertedEnclosing = (ReferenceBinding) convertUnresolvedBinaryToRawType(originalEnclosing);
0611: if (convertedEnclosing != originalEnclosing) {
0612: needToConvert |= !((ReferenceBinding) originalType)
0613: .isStatic();
0614: }
0615: if (needToConvert) {
0616: convertedType = createRawType(
0617: (ReferenceBinding) originalType.erasure(),
0618: convertedEnclosing);
0619: } else if (originalEnclosing != convertedEnclosing) {
0620: convertedType = createParameterizedType(
0621: (ReferenceBinding) originalType.erasure(),
0622: null, convertedEnclosing);
0623: } else {
0624: convertedType = originalType;
0625: }
0626: }
0627: if (originalType != convertedType) {
0628: return dimension > 0 ? (TypeBinding) createArrayType(
0629: convertedType, dimension) : convertedType;
0630: }
0631: return type;
0632: }
0633:
0634: /*
0635: * Used to guarantee annotation identity.
0636: */
0637: public AnnotationBinding createAnnotation(
0638: ReferenceBinding annotationType, ElementValuePair[] pairs) {
0639: if (pairs.length != 0) {
0640: AnnotationBinding.setMethodBindings(annotationType, pairs);
0641: }
0642: return new AnnotationBinding(annotationType, pairs);
0643: }
0644:
0645: /*
0646: * Used to guarantee array type identity.
0647: */
0648: public ArrayBinding createArrayType(TypeBinding leafComponentType,
0649: int dimensionCount) {
0650: if (leafComponentType instanceof LocalTypeBinding) // cache local type arrays with the local type itself
0651: return ((LocalTypeBinding) leafComponentType)
0652: .createArrayType(dimensionCount, this );
0653:
0654: // find the array binding cache for this dimension
0655: int dimIndex = dimensionCount - 1;
0656: int length = uniqueArrayBindings.length;
0657: ArrayBinding[] arrayBindings;
0658: if (dimIndex < length) {
0659: if ((arrayBindings = uniqueArrayBindings[dimIndex]) == null)
0660: uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10];
0661: } else {
0662: System
0663: .arraycopy(
0664: uniqueArrayBindings,
0665: 0,
0666: uniqueArrayBindings = new ArrayBinding[dimensionCount][],
0667: 0, length);
0668: uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10];
0669: }
0670:
0671: // find the cached array binding for this leaf component type (if any)
0672: int index = -1;
0673: length = arrayBindings.length;
0674: while (++index < length) {
0675: ArrayBinding currentBinding = arrayBindings[index];
0676: if (currentBinding == null) // no matching array, but space left
0677: return arrayBindings[index] = new ArrayBinding(
0678: leafComponentType, dimensionCount, this );
0679: if (currentBinding.leafComponentType == leafComponentType)
0680: return currentBinding;
0681: }
0682:
0683: // no matching array, no space left
0684: System.arraycopy(arrayBindings, 0,
0685: (arrayBindings = new ArrayBinding[length * 2]), 0,
0686: length);
0687: uniqueArrayBindings[dimIndex] = arrayBindings;
0688: return arrayBindings[length] = new ArrayBinding(
0689: leafComponentType, dimensionCount, this );
0690: }
0691:
0692: public BinaryTypeBinding createBinaryTypeFrom(
0693: IBinaryType binaryType, PackageBinding packageBinding,
0694: AccessRestriction accessRestriction) {
0695: return createBinaryTypeFrom(binaryType, packageBinding, true,
0696: accessRestriction);
0697: }
0698:
0699: public BinaryTypeBinding createBinaryTypeFrom(
0700: IBinaryType binaryType, PackageBinding packageBinding,
0701: boolean needFieldsAndMethods,
0702: AccessRestriction accessRestriction) {
0703: BinaryTypeBinding binaryBinding = new BinaryTypeBinding(
0704: packageBinding, binaryType, this );
0705:
0706: // resolve any array bindings which reference the unresolvedType
0707: ReferenceBinding cachedType = packageBinding
0708: .getType0(binaryBinding.compoundName[binaryBinding.compoundName.length - 1]);
0709: if (cachedType != null) { // update reference to unresolved binding after having read classfile (knows whether generic for raw conversion)
0710: if (cachedType instanceof UnresolvedReferenceBinding) {
0711: ((UnresolvedReferenceBinding) cachedType)
0712: .setResolvedType(binaryBinding, this );
0713: } else {
0714: if (cachedType.isBinaryBinding()) // sanity check... at this point the cache should ONLY contain unresolved types
0715: return (BinaryTypeBinding) cachedType;
0716: // it is possible with a large number of source files (exceeding AbstractImageBuilder.MAX_AT_ONCE) that a member type can be in the cache as an UnresolvedType,
0717: // but because its enclosingType is resolved while its created (call to BinaryTypeBinding constructor), its replaced with a source type
0718: return null;
0719: }
0720: }
0721:
0722: packageBinding.addType(binaryBinding);
0723: setAccessRestriction(binaryBinding, accessRestriction);
0724: binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods);
0725: return binaryBinding;
0726: }
0727:
0728: /* Used to create packages from the package statement.
0729: */
0730:
0731: public PackageBinding createPackage(char[][] compoundName) {
0732: PackageBinding packageBinding = getPackage0(compoundName[0]);
0733: if (packageBinding == null
0734: || packageBinding == TheNotFoundPackage) {
0735: packageBinding = new PackageBinding(compoundName[0], this );
0736: knownPackages.put(compoundName[0], packageBinding);
0737: }
0738:
0739: for (int i = 1, length = compoundName.length; i < length; i++) {
0740: // check to see if it collides with a known type...
0741: // this case can only happen if the package does not exist as a directory in the file system
0742: // otherwise when the source type was defined, the correct error would have been reported
0743: // unless its an unresolved type which is referenced from an inconsistent class file
0744: // NOTE: empty packages are not packages according to changes in JLS v2, 7.4.3
0745: // so not all types cause collision errors when they're created even though the package did exist
0746: ReferenceBinding type = packageBinding
0747: .getType0(compoundName[i]);
0748: if (type != null && type != TheNotFoundType
0749: && !(type instanceof UnresolvedReferenceBinding))
0750: return null;
0751:
0752: PackageBinding parent = packageBinding;
0753: if ((packageBinding = parent.getPackage0(compoundName[i])) == null
0754: || packageBinding == TheNotFoundPackage) {
0755: // if the package is unknown, check to see if a type exists which would collide with the new package
0756: // catches the case of a package statement of: package java.lang.Object;
0757: // since the package can be added after a set of source files have already been compiled,
0758: // we need to check whenever a package is created
0759: if (nameEnvironment.findType(compoundName[i],
0760: parent.compoundName) != null)
0761: return null;
0762:
0763: packageBinding = new PackageBinding(CharOperation
0764: .subarray(compoundName, 0, i + 1), parent, this );
0765: parent.addPackage(packageBinding);
0766: }
0767: }
0768: return packageBinding;
0769: }
0770:
0771: public ParameterizedGenericMethodBinding createParameterizedGenericMethod(
0772: MethodBinding genericMethod, RawTypeBinding rawType) {
0773:
0774: // cached info is array of already created parameterized types for this type
0775: ParameterizedGenericMethodBinding[] cachedInfo = (ParameterizedGenericMethodBinding[]) this .uniqueParameterizedGenericMethodBindings
0776: .get(genericMethod);
0777: boolean needToGrow = false;
0778: int index = 0;
0779: if (cachedInfo != null) {
0780: nextCachedMethod:
0781: // iterate existing parameterized for reusing one with same type arguments if any
0782: for (int max = cachedInfo.length; index < max; index++) {
0783: ParameterizedGenericMethodBinding cachedMethod = cachedInfo[index];
0784: if (cachedMethod == null)
0785: break nextCachedMethod;
0786: if (!cachedMethod.isRaw)
0787: continue nextCachedMethod;
0788: if (cachedMethod.declaringClass != (rawType == null ? genericMethod.declaringClass
0789: : rawType))
0790: continue nextCachedMethod;
0791: return cachedMethod;
0792: }
0793: needToGrow = true;
0794: } else {
0795: cachedInfo = new ParameterizedGenericMethodBinding[5];
0796: this .uniqueParameterizedGenericMethodBindings.put(
0797: genericMethod, cachedInfo);
0798: }
0799: // grow cache ?
0800: int length = cachedInfo.length;
0801: if (needToGrow && index == length) {
0802: System
0803: .arraycopy(
0804: cachedInfo,
0805: 0,
0806: cachedInfo = new ParameterizedGenericMethodBinding[length * 2],
0807: 0, length);
0808: this .uniqueParameterizedGenericMethodBindings.put(
0809: genericMethod, cachedInfo);
0810: }
0811: // add new binding
0812: ParameterizedGenericMethodBinding parameterizedGenericMethod = new ParameterizedGenericMethodBinding(
0813: genericMethod, rawType, this );
0814: cachedInfo[index] = parameterizedGenericMethod;
0815: return parameterizedGenericMethod;
0816: }
0817:
0818: public ParameterizedGenericMethodBinding createParameterizedGenericMethod(
0819: MethodBinding genericMethod, TypeBinding[] typeArguments) {
0820:
0821: // cached info is array of already created parameterized types for this type
0822: ParameterizedGenericMethodBinding[] cachedInfo = (ParameterizedGenericMethodBinding[]) this .uniqueParameterizedGenericMethodBindings
0823: .get(genericMethod);
0824: int argLength = typeArguments == null ? 0
0825: : typeArguments.length;
0826: boolean needToGrow = false;
0827: int index = 0;
0828: if (cachedInfo != null) {
0829: nextCachedMethod:
0830: // iterate existing parameterized for reusing one with same type arguments if any
0831: for (int max = cachedInfo.length; index < max; index++) {
0832: ParameterizedGenericMethodBinding cachedMethod = cachedInfo[index];
0833: if (cachedMethod == null)
0834: break nextCachedMethod;
0835: if (cachedMethod.isRaw)
0836: continue nextCachedMethod;
0837: TypeBinding[] cachedArguments = cachedMethod.typeArguments;
0838: int cachedArgLength = cachedArguments == null ? 0
0839: : cachedArguments.length;
0840: if (argLength != cachedArgLength)
0841: continue nextCachedMethod;
0842: for (int j = 0; j < cachedArgLength; j++) {
0843: if (typeArguments[j] != cachedArguments[j])
0844: continue nextCachedMethod;
0845: }
0846: // all arguments match, reuse current
0847: return cachedMethod;
0848: }
0849: needToGrow = true;
0850: } else {
0851: cachedInfo = new ParameterizedGenericMethodBinding[5];
0852: this .uniqueParameterizedGenericMethodBindings.put(
0853: genericMethod, cachedInfo);
0854: }
0855: // grow cache ?
0856: int length = cachedInfo.length;
0857: if (needToGrow && index == length) {
0858: System
0859: .arraycopy(
0860: cachedInfo,
0861: 0,
0862: cachedInfo = new ParameterizedGenericMethodBinding[length * 2],
0863: 0, length);
0864: this .uniqueParameterizedGenericMethodBindings.put(
0865: genericMethod, cachedInfo);
0866: }
0867: // add new binding
0868: ParameterizedGenericMethodBinding parameterizedGenericMethod = new ParameterizedGenericMethodBinding(
0869: genericMethod, typeArguments, this );
0870: cachedInfo[index] = parameterizedGenericMethod;
0871: return parameterizedGenericMethod;
0872: }
0873:
0874: public ParameterizedTypeBinding createParameterizedType(
0875: ReferenceBinding genericType, TypeBinding[] typeArguments,
0876: ReferenceBinding enclosingType) {
0877:
0878: // cached info is array of already created parameterized types for this type
0879: ParameterizedTypeBinding[] cachedInfo = (ParameterizedTypeBinding[]) this .uniqueParameterizedTypeBindings
0880: .get(genericType);
0881: int argLength = typeArguments == null ? 0
0882: : typeArguments.length;
0883: boolean needToGrow = false;
0884: int index = 0;
0885: if (cachedInfo != null) {
0886: nextCachedType:
0887: // iterate existing parameterized for reusing one with same type arguments if any
0888: for (int max = cachedInfo.length; index < max; index++) {
0889: ParameterizedTypeBinding cachedType = cachedInfo[index];
0890: if (cachedType == null)
0891: break nextCachedType;
0892: if (cachedType.actualType() != genericType)
0893: continue nextCachedType; // remain of unresolved type
0894: if (cachedType.enclosingType() != enclosingType)
0895: continue nextCachedType;
0896: TypeBinding[] cachedArguments = cachedType.arguments;
0897: int cachedArgLength = cachedArguments == null ? 0
0898: : cachedArguments.length;
0899: if (argLength != cachedArgLength)
0900: continue nextCachedType; // would be an error situation (from unresolved binaries)
0901: for (int j = 0; j < cachedArgLength; j++) {
0902: if (typeArguments[j] != cachedArguments[j])
0903: continue nextCachedType;
0904: }
0905: // all arguments match, reuse current
0906: return cachedType;
0907: }
0908: needToGrow = true;
0909: } else {
0910: cachedInfo = new ParameterizedTypeBinding[5];
0911: this .uniqueParameterizedTypeBindings.put(genericType,
0912: cachedInfo);
0913: }
0914: // grow cache ?
0915: int length = cachedInfo.length;
0916: if (needToGrow && index == length) {
0917: System
0918: .arraycopy(
0919: cachedInfo,
0920: 0,
0921: cachedInfo = new ParameterizedTypeBinding[length * 2],
0922: 0, length);
0923: this .uniqueParameterizedTypeBindings.put(genericType,
0924: cachedInfo);
0925: }
0926: // add new binding
0927: ParameterizedTypeBinding parameterizedType = new ParameterizedTypeBinding(
0928: genericType, typeArguments, enclosingType, this );
0929: cachedInfo[index] = parameterizedType;
0930: return parameterizedType;
0931: }
0932:
0933: public RawTypeBinding createRawType(ReferenceBinding genericType,
0934: ReferenceBinding enclosingType) {
0935: // cached info is array of already created raw types for this type
0936: RawTypeBinding[] cachedInfo = (RawTypeBinding[]) this .uniqueRawTypeBindings
0937: .get(genericType);
0938: boolean needToGrow = false;
0939: int index = 0;
0940: if (cachedInfo != null) {
0941: nextCachedType:
0942: // iterate existing parameterized for reusing one with same type arguments if any
0943: for (int max = cachedInfo.length; index < max; index++) {
0944: RawTypeBinding cachedType = cachedInfo[index];
0945: if (cachedType == null)
0946: break nextCachedType;
0947: if (cachedType.actualType() != genericType)
0948: continue nextCachedType; // remain of unresolved type
0949: if (cachedType.enclosingType() != enclosingType)
0950: continue nextCachedType;
0951: // all enclosing type match, reuse current
0952: return cachedType;
0953: }
0954: needToGrow = true;
0955: } else {
0956: cachedInfo = new RawTypeBinding[1];
0957: this .uniqueRawTypeBindings.put(genericType, cachedInfo);
0958: }
0959: // grow cache ?
0960: int length = cachedInfo.length;
0961: if (needToGrow && index == length) {
0962: System.arraycopy(cachedInfo, 0,
0963: cachedInfo = new RawTypeBinding[length * 2], 0,
0964: length);
0965: this .uniqueRawTypeBindings.put(genericType, cachedInfo);
0966: }
0967: // add new binding
0968: RawTypeBinding rawType = new RawTypeBinding(genericType,
0969: enclosingType, this );
0970: cachedInfo[index] = rawType;
0971: return rawType;
0972:
0973: }
0974:
0975: public WildcardBinding createWildcard(ReferenceBinding genericType,
0976: int rank, TypeBinding bound, TypeBinding[] otherBounds,
0977: int boundKind) {
0978:
0979: // cached info is array of already created wildcard types for this type
0980: if (genericType == null) // pseudo wildcard denoting composite bounds for lub computation
0981: genericType = ReferenceBinding.LUB_GENERIC;
0982: WildcardBinding[] cachedInfo = (WildcardBinding[]) this .uniqueWildcardBindings
0983: .get(genericType);
0984: boolean needToGrow = false;
0985: int index = 0;
0986: if (cachedInfo != null) {
0987: nextCachedType:
0988: // iterate existing wildcards for reusing one with same information if any
0989: for (int max = cachedInfo.length; index < max; index++) {
0990: WildcardBinding cachedType = cachedInfo[index];
0991: if (cachedType == null)
0992: break nextCachedType;
0993: if (cachedType.genericType != genericType)
0994: continue nextCachedType; // remain of unresolved type
0995: if (cachedType.rank != rank)
0996: continue nextCachedType;
0997: if (cachedType.boundKind != boundKind)
0998: continue nextCachedType;
0999: if (cachedType.bound != bound)
1000: continue nextCachedType;
1001: if (cachedType.otherBounds != otherBounds) {
1002: int cachedLength = cachedType.otherBounds == null ? 0
1003: : cachedType.otherBounds.length;
1004: int length = otherBounds == null ? 0
1005: : otherBounds.length;
1006: if (cachedLength != length)
1007: continue nextCachedType;
1008: for (int j = 0; j < length; j++) {
1009: if (cachedType.otherBounds[j] != otherBounds[j])
1010: continue nextCachedType;
1011: }
1012: }
1013: // all match, reuse current
1014: return cachedType;
1015: }
1016: needToGrow = true;
1017: } else {
1018: cachedInfo = new WildcardBinding[10];
1019: this .uniqueWildcardBindings.put(genericType, cachedInfo);
1020: }
1021: // grow cache ?
1022: int length = cachedInfo.length;
1023: if (needToGrow && index == length) {
1024: System.arraycopy(cachedInfo, 0,
1025: cachedInfo = new WildcardBinding[length * 2], 0,
1026: length);
1027: this .uniqueWildcardBindings.put(genericType, cachedInfo);
1028: }
1029: // add new binding
1030: WildcardBinding wildcard = new WildcardBinding(genericType,
1031: rank, bound, otherBounds, boundKind, this );
1032: cachedInfo[index] = wildcard;
1033: return wildcard;
1034: }
1035:
1036: /**
1037: * Returns the access restriction associated to a given type, or null if none
1038: */
1039: public AccessRestriction getAccessRestriction(TypeBinding type) {
1040: return (AccessRestriction) this .accessRestrictions.get(type);
1041: }
1042:
1043: /**
1044: * Answer the type for the compoundName if it exists in the cache.
1045: * Answer theNotFoundType if it could not be resolved the first time
1046: * it was looked up, otherwise answer null.
1047: *
1048: * NOTE: Do not use for nested types... the answer is NOT the same for a.b.C or a.b.C.D.E
1049: * assuming C is a type in both cases. In the a.b.C.D.E case, null is the answer.
1050: */
1051:
1052: public ReferenceBinding getCachedType(char[][] compoundName) {
1053: if (compoundName.length == 1) {
1054: if (defaultPackage == null)
1055: return null;
1056: return defaultPackage.getType0(compoundName[0]);
1057: }
1058:
1059: PackageBinding packageBinding = getPackage0(compoundName[0]);
1060: if (packageBinding == null
1061: || packageBinding == TheNotFoundPackage)
1062: return null;
1063:
1064: for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++)
1065: if ((packageBinding = packageBinding
1066: .getPackage0(compoundName[i])) == null
1067: || packageBinding == TheNotFoundPackage)
1068: return null;
1069: return packageBinding
1070: .getType0(compoundName[compoundName.length - 1]);
1071: }
1072:
1073: /* Answer the top level package named name if it exists in the cache.
1074: * Answer theNotFoundPackage if it could not be resolved the first time
1075: * it was looked up, otherwise answer null.
1076: *
1077: * NOTE: Senders must convert theNotFoundPackage into a real problem
1078: * package if its to returned.
1079: */
1080:
1081: PackageBinding getPackage0(char[] name) {
1082: return knownPackages.get(name);
1083: }
1084:
1085: /* Answer the type corresponding to the compoundName.
1086: * Ask the name environment for the type if its not in the cache.
1087: * Fail with a classpath error if the type cannot be found.
1088: */
1089: public ReferenceBinding getResolvedType(char[][] compoundName,
1090: Scope scope) {
1091: ReferenceBinding type = getType(compoundName);
1092: if (type != null)
1093: return type;
1094:
1095: // create a proxy for the missing BinaryType
1096: return cacheMissingBinaryType(compoundName,
1097: scope == null ? this .unitBeingCompleted : scope
1098: .referenceCompilationUnit());
1099: }
1100:
1101: /* Answer the top level package named name.
1102: * Ask the oracle for the package if its not in the cache.
1103: * Answer null if the package cannot be found.
1104: */
1105:
1106: PackageBinding getTopLevelPackage(char[] name) {
1107: PackageBinding packageBinding = getPackage0(name);
1108: if (packageBinding != null) {
1109: if (packageBinding == TheNotFoundPackage)
1110: return null;
1111: return packageBinding;
1112: }
1113:
1114: if (nameEnvironment.isPackage(null, name)) {
1115: knownPackages.put(name,
1116: packageBinding = new PackageBinding(name, this ));
1117: return packageBinding;
1118: }
1119:
1120: knownPackages.put(name, TheNotFoundPackage); // saves asking the oracle next time
1121: return null;
1122: }
1123:
1124: /* Answer the type corresponding to the compoundName.
1125: * Ask the name environment for the type if its not in the cache.
1126: * Answer null if the type cannot be found.
1127: */
1128:
1129: public ReferenceBinding getType(char[][] compoundName) {
1130: ReferenceBinding referenceBinding;
1131:
1132: if (compoundName.length == 1) {
1133: if (defaultPackage == null)
1134: return null;
1135:
1136: if ((referenceBinding = defaultPackage
1137: .getType0(compoundName[0])) == null) {
1138: PackageBinding packageBinding = getPackage0(compoundName[0]);
1139: if (packageBinding != null
1140: && packageBinding != TheNotFoundPackage)
1141: return null; // collides with a known package... should not call this method in such a case
1142: referenceBinding = askForType(defaultPackage,
1143: compoundName[0]);
1144: }
1145: } else {
1146: PackageBinding packageBinding = getPackage0(compoundName[0]);
1147: if (packageBinding == TheNotFoundPackage)
1148: return null;
1149:
1150: if (packageBinding != null) {
1151: for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) {
1152: if ((packageBinding = packageBinding
1153: .getPackage0(compoundName[i])) == null)
1154: break;
1155: if (packageBinding == TheNotFoundPackage)
1156: return null;
1157: }
1158: }
1159:
1160: if (packageBinding == null)
1161: referenceBinding = askForType(compoundName);
1162: else if ((referenceBinding = packageBinding
1163: .getType0(compoundName[compoundName.length - 1])) == null)
1164: referenceBinding = askForType(packageBinding,
1165: compoundName[compoundName.length - 1]);
1166: }
1167:
1168: if (referenceBinding == null
1169: || referenceBinding == TheNotFoundType)
1170: return null;
1171: referenceBinding = BinaryTypeBinding.resolveType(
1172: referenceBinding, this , false); // no raw conversion for now
1173:
1174: // compoundName refers to a nested type incorrectly (for example, package1.A$B)
1175: if (referenceBinding.isNestedType())
1176: return new ProblemReferenceBinding(compoundName,
1177: referenceBinding, InternalNameProvided);
1178: return referenceBinding;
1179: }
1180:
1181: private TypeBinding[] getTypeArgumentsFromSignature(
1182: SignatureWrapper wrapper,
1183: TypeVariableBinding[] staticVariables,
1184: ReferenceBinding enclosingType, ReferenceBinding genericType) {
1185: java.util.ArrayList args = new java.util.ArrayList(2);
1186: int rank = 0;
1187: do {
1188: args
1189: .add(getTypeFromVariantTypeSignature(wrapper,
1190: staticVariables, enclosingType,
1191: genericType, rank++));
1192: } while (wrapper.signature[wrapper.start] != '>');
1193: wrapper.start++; // skip '>'
1194: TypeBinding[] typeArguments = new TypeBinding[args.size()];
1195: args.toArray(typeArguments);
1196: return typeArguments;
1197: }
1198:
1199: /* Answer the type corresponding to the compound name.
1200: * Does not ask the oracle for the type if its not found in the cache... instead an
1201: * unresolved type is returned which must be resolved before used.
1202: *
1203: * NOTE: Does NOT answer base types nor array types!
1204: */
1205:
1206: ReferenceBinding getTypeFromCompoundName(char[][] compoundName,
1207: boolean isParameterized) {
1208: ReferenceBinding binding = getCachedType(compoundName);
1209: if (binding == null) {
1210: PackageBinding packageBinding = computePackageFrom(compoundName);
1211: binding = new UnresolvedReferenceBinding(compoundName,
1212: packageBinding);
1213: packageBinding.addType(binding);
1214: } else if (binding == TheNotFoundType) {
1215: // create a proxy for the missing BinaryType
1216: binding = cacheMissingBinaryType(compoundName,
1217: this .unitBeingCompleted);
1218: } else if (!isParameterized) {
1219: // check raw type, only for resolved types
1220: binding = (ReferenceBinding) convertUnresolvedBinaryToRawType(binding);
1221: }
1222: return binding;
1223: }
1224:
1225: /* Answer the type corresponding to the name from the binary file.
1226: * Does not ask the oracle for the type if its not found in the cache... instead an
1227: * unresolved type is returned which must be resolved before used.
1228: *
1229: * NOTE: Does NOT answer base types nor array types!
1230: */
1231:
1232: ReferenceBinding getTypeFromConstantPoolName(char[] signature,
1233: int start, int end, boolean isParameterized) {
1234: if (end == -1)
1235: end = signature.length;
1236:
1237: char[][] compoundName = CharOperation.splitOn('/', signature,
1238: start, end);
1239: return getTypeFromCompoundName(compoundName, isParameterized);
1240: }
1241:
1242: /* Answer the type corresponding to the signature from the binary file.
1243: * Does not ask the oracle for the type if its not found in the cache... instead an
1244: * unresolved type is returned which must be resolved before used.
1245: *
1246: * NOTE: Does answer base types & array types.
1247: */
1248:
1249: TypeBinding getTypeFromSignature(char[] signature, int start,
1250: int end, boolean isParameterized, TypeBinding enclosingType) {
1251: int dimension = 0;
1252: while (signature[start] == '[') {
1253: start++;
1254: dimension++;
1255: }
1256: if (end == -1)
1257: end = signature.length - 1;
1258:
1259: // Just switch on signature[start] - the L case is the else
1260: TypeBinding binding = null;
1261: if (start == end) {
1262: switch (signature[start]) {
1263: case 'I':
1264: binding = TypeBinding.INT;
1265: break;
1266: case 'Z':
1267: binding = TypeBinding.BOOLEAN;
1268: break;
1269: case 'V':
1270: binding = TypeBinding.VOID;
1271: break;
1272: case 'C':
1273: binding = TypeBinding.CHAR;
1274: break;
1275: case 'D':
1276: binding = TypeBinding.DOUBLE;
1277: break;
1278: case 'B':
1279: binding = TypeBinding.BYTE;
1280: break;
1281: case 'F':
1282: binding = TypeBinding.FLOAT;
1283: break;
1284: case 'J':
1285: binding = TypeBinding.LONG;
1286: break;
1287: case 'S':
1288: binding = TypeBinding.SHORT;
1289: break;
1290: default:
1291: problemReporter.corruptedSignature(enclosingType,
1292: signature, start);
1293: // will never reach here, since error will cause abort
1294: }
1295: } else {
1296: binding = getTypeFromConstantPoolName(signature, start + 1,
1297: end, isParameterized); // skip leading 'L' or 'T'
1298: }
1299:
1300: if (dimension == 0)
1301: return binding;
1302: return createArrayType(binding, dimension);
1303: }
1304:
1305: TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper,
1306: TypeVariableBinding[] staticVariables,
1307: ReferenceBinding enclosingType) {
1308: // TypeVariableSignature = 'T' Identifier ';'
1309: // ArrayTypeSignature = '[' TypeSignature
1310: // ClassTypeSignature = 'L' Identifier TypeArgs(optional) ';'
1311: // or ClassTypeSignature '.' 'L' Identifier TypeArgs(optional) ';'
1312: // TypeArgs = '<' VariantTypeSignature VariantTypeSignatures '>'
1313: int dimension = 0;
1314: while (wrapper.signature[wrapper.start] == '[') {
1315: wrapper.start++;
1316: dimension++;
1317: }
1318:
1319: if (wrapper.signature[wrapper.start] == 'T') {
1320: int varStart = wrapper.start + 1;
1321: int varEnd = wrapper.computeEnd();
1322: for (int i = staticVariables.length; --i >= 0;)
1323: if (CharOperation.equals(staticVariables[i].sourceName,
1324: wrapper.signature, varStart, varEnd))
1325: return dimension == 0 ? (TypeBinding) staticVariables[i]
1326: : createArrayType(staticVariables[i],
1327: dimension);
1328: ReferenceBinding initialType = enclosingType;
1329: do {
1330: if (enclosingType instanceof BinaryTypeBinding) { // per construction can only be binary type binding
1331: TypeVariableBinding[] enclosingVariables = ((BinaryTypeBinding) enclosingType).typeVariables; // do not trigger resolution of variables
1332: for (int i = enclosingVariables.length; --i >= 0;)
1333: if (CharOperation.equals(
1334: enclosingVariables[i].sourceName,
1335: wrapper.signature, varStart, varEnd))
1336: return dimension == 0 ? (TypeBinding) enclosingVariables[i]
1337: : createArrayType(
1338: enclosingVariables[i],
1339: dimension);
1340: }
1341: } while ((enclosingType = enclosingType.enclosingType()) != null);
1342: problemReporter.undefinedTypeVariableSignature(
1343: CharOperation.subarray(wrapper.signature, varStart,
1344: varEnd), initialType);
1345: return null; // cannot reach this, since previous problem will abort compilation
1346: }
1347: boolean isParameterized;
1348: TypeBinding type = getTypeFromSignature(wrapper.signature,
1349: wrapper.start, wrapper.computeEnd(),
1350: isParameterized = (wrapper.end == wrapper.bracket),
1351: enclosingType);
1352: if (!isParameterized)
1353: return dimension == 0 ? type : createArrayType(type,
1354: dimension);
1355:
1356: // type must be a ReferenceBinding at this point, cannot be a BaseTypeBinding or ArrayTypeBinding
1357: ReferenceBinding actualType = (ReferenceBinding) type;
1358: if (actualType instanceof UnresolvedReferenceBinding)
1359: if (CharOperation
1360: .indexOf(
1361: '$',
1362: actualType.compoundName[actualType.compoundName.length - 1]) > 0)
1363: actualType = BinaryTypeBinding.resolveType(actualType,
1364: this , false); // must resolve member types before asking for enclosingType
1365: ReferenceBinding genericType = actualType;
1366: ReferenceBinding actualEnclosing = actualType.enclosingType();
1367: if (actualEnclosing != null) { // convert needed if read some static member type
1368: actualEnclosing = (ReferenceBinding) convertToRawType(actualEnclosing);
1369: // The actualType needs to be a ParameterizedTypeBinding when its a member type, whose enclosing type is a generic
1370: genericType = createParameterizedType(actualType, null,
1371: actualEnclosing);
1372: }
1373: TypeBinding[] typeArguments = getTypeArgumentsFromSignature(
1374: wrapper, staticVariables, enclosingType, genericType);
1375: ParameterizedTypeBinding parameterizedType = createParameterizedType(
1376: actualType, typeArguments, actualEnclosing);
1377:
1378: while (wrapper.signature[wrapper.start] == '.') {
1379: wrapper.start++; // skip '.'
1380: char[] memberName = wrapper.nextWord();
1381: BinaryTypeBinding.resolveType(parameterizedType, this ,
1382: false);
1383: ReferenceBinding memberType = parameterizedType
1384: .genericType().getMemberType(memberName);
1385: if (wrapper.signature[wrapper.start] == '<') {
1386: wrapper.start++; // skip '<'
1387: typeArguments = getTypeArgumentsFromSignature(wrapper,
1388: staticVariables, enclosingType, memberType);
1389: } else {
1390: typeArguments = null;
1391: }
1392: parameterizedType = createParameterizedType(memberType,
1393: typeArguments, parameterizedType);
1394: }
1395: wrapper.start++; // skip ';'
1396: return dimension == 0 ? (TypeBinding) parameterizedType
1397: : createArrayType(parameterizedType, dimension);
1398: }
1399:
1400: TypeBinding getTypeFromVariantTypeSignature(
1401: SignatureWrapper wrapper,
1402: TypeVariableBinding[] staticVariables,
1403: ReferenceBinding enclosingType,
1404: ReferenceBinding genericType, int rank) {
1405: // VariantTypeSignature = '-' TypeSignature
1406: // or '+' TypeSignature
1407: // or TypeSignature
1408: // or '*'
1409: switch (wrapper.signature[wrapper.start]) {
1410: case '-':
1411: // ? super aType
1412: wrapper.start++;
1413: TypeBinding bound = getTypeFromTypeSignature(wrapper,
1414: staticVariables, enclosingType);
1415: return createWildcard(genericType, rank, bound,
1416: null /*no extra bound*/, Wildcard.SUPER);
1417: case '+':
1418: // ? extends aType
1419: wrapper.start++;
1420: bound = getTypeFromTypeSignature(wrapper, staticVariables,
1421: enclosingType);
1422: return createWildcard(genericType, rank, bound,
1423: null /*no extra bound*/, Wildcard.EXTENDS);
1424: case '*':
1425: // ?
1426: wrapper.start++;
1427: return createWildcard(genericType, rank, null,
1428: null /*no extra bound*/, Wildcard.UNBOUND);
1429: default:
1430: return getTypeFromTypeSignature(wrapper, staticVariables,
1431: enclosingType);
1432: }
1433: }
1434:
1435: /* Ask the oracle if a package exists named name in the package named compoundName.
1436: */
1437: boolean isPackage(char[][] compoundName, char[] name) {
1438: if (compoundName == null || compoundName.length == 0)
1439: return nameEnvironment.isPackage(null, name);
1440: return nameEnvironment.isPackage(compoundName, name);
1441: }
1442:
1443: // The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready.
1444:
1445: public MethodVerifier methodVerifier() {
1446: if (verifier == null)
1447: verifier = this .globalOptions.sourceLevel < ClassFileConstants.JDK1_5 ? new MethodVerifier(
1448: this )
1449: : new MethodVerifier15(this ); // covariance only if sourceLevel is >= 1.5
1450: return verifier;
1451: }
1452:
1453: public void reset() {
1454: this .defaultPackage = new PackageBinding(this ); // assume the default package always exists
1455: this .defaultImports = null;
1456: this .knownPackages = new HashtableOfPackage();
1457: this .accessRestrictions = new HashMap(3);
1458:
1459: this .verifier = null;
1460: for (int i = this .uniqueArrayBindings.length; --i >= 0;) {
1461: ArrayBinding[] arrayBindings = this .uniqueArrayBindings[i];
1462: if (arrayBindings != null)
1463: for (int j = arrayBindings.length; --j >= 0;)
1464: arrayBindings[j] = null;
1465: }
1466: this .uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
1467: this .uniqueRawTypeBindings = new SimpleLookupTable(3);
1468: this .uniqueWildcardBindings = new SimpleLookupTable(3);
1469: this .uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(
1470: 3);
1471:
1472: for (int i = this .units.length; --i >= 0;)
1473: this .units[i] = null;
1474: this .lastUnitIndex = -1;
1475: this .lastCompletedUnitIndex = -1;
1476: this .unitBeingCompleted = null; // in case AbortException occurred
1477:
1478: this .classFilePool.reset();
1479: // name environment has a longer life cycle, and must be reset in
1480: // the code which created it.
1481: }
1482:
1483: /**
1484: * Associate a given type with some access restriction
1485: * (did not store the restriction directly into binding, since sparse information)
1486: */
1487: public void setAccessRestriction(ReferenceBinding type,
1488: AccessRestriction accessRestriction) {
1489: if (accessRestriction == null)
1490: return;
1491: type.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
1492: this .accessRestrictions.put(type, accessRestriction);
1493: }
1494:
1495: void updateCaches(UnresolvedReferenceBinding unresolvedType,
1496: ReferenceBinding resolvedType) {
1497: // walk all the unique collections & replace the unresolvedType with the resolvedType
1498: // must prevent 2 entries so == still works (1 containing the unresolvedType and the other containing the resolvedType)
1499: if (this .uniqueParameterizedTypeBindings.get(unresolvedType) != null) { // update the key
1500: Object[] keys = this .uniqueParameterizedTypeBindings.keyTable;
1501: for (int i = 0, l = keys.length; i < l; i++) {
1502: if (keys[i] == unresolvedType) {
1503: keys[i] = resolvedType; // hashCode is based on compoundName so this works - cannot be raw since type of parameterized type
1504: break;
1505: }
1506: }
1507: }
1508:
1509: if (this .uniqueWildcardBindings.get(unresolvedType) != null) { // update the key
1510: Object[] keys = this .uniqueWildcardBindings.keyTable;
1511: for (int i = 0, l = keys.length; i < l; i++) {
1512: if (keys[i] == unresolvedType) {
1513: keys[i] = resolvedType; // hashCode is based on compoundName so this works
1514: break;
1515: }
1516: }
1517: }
1518: }
1519: }
|