--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * Denote a raw type, i.e. a generic type referenced without any type arguments.
+ * e.g. X<T extends Exception> can be used a raw type 'X', in which case it
+ * will behave as X<Exception>
+ */
+public class RawTypeBinding extends ParameterizedTypeBinding {
+
+ /**
+ * Raw type arguments are erasure of respective parameter bounds. But we may not have resolved
+ * these bounds yet if creating raw types while supertype hierarchies are being connected.
+ * Therefore, use 'null' instead, and access these in a lazy way later on (when substituting).
+ */
+ public RawTypeBinding(ReferenceBinding type, ReferenceBinding enclosingType, LookupEnvironment environment){
+ super(type, null, enclosingType, environment);
+ if (enclosingType == null || (enclosingType.modifiers & AccGenericSignature) == 0)
+ this.modifiers &= ~AccGenericSignature; // only need signature if enclosing needs one
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding#createParameterizedMethod(org.eclipse.jdt.internal.compiler.lookup.MethodBinding)
+ */
+ public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
+ if (originalMethod.typeVariables == NoTypeVariables || originalMethod.isStatic()) {
+ return super.createParameterizedMethod(originalMethod);
+ }
+ return new ParameterizedGenericMethodBinding(originalMethod, this, this.environment);
+ }
+
+ public int kind() {
+ return RAW_TYPE;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
+ */
+ public String debugName() {
+ StringBuffer nameBuffer = new StringBuffer(10);
+ nameBuffer.append(this.type.sourceName()).append("#RAW"); //$NON-NLS-1$
+ return nameBuffer.toString();
+ }
+
+ /**
+ * Ltype<param1 ... paramN>;
+ * LY<TT;>;
+ */
+ public char[] genericTypeSignature() {
+
+ if (this.genericTypeSignature == null) {
+ StringBuffer sig = new StringBuffer(10);
+ if (this.isMemberType() && this.enclosingType().isParameterizedType()) {
+ char[] typeSig = this.enclosingType().genericTypeSignature();
+ for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
+ sig.append('.').append(this.sourceName()).append(';');
+ int sigLength = sig.length();
+ this.genericTypeSignature = new char[sigLength];
+ sig.getChars(0, sigLength, this.genericTypeSignature, 0);
+ } else {
+ this.genericTypeSignature = this.type.signature(); // erasure
+ }
+ }
+ return this.genericTypeSignature;
+ }
+
+ public boolean isEquivalentTo(TypeBinding otherType) {
+ if (this == otherType) return true;
+ if (otherType == null) return false;
+ if (otherType.isWildcard()) // wildcard
+ return ((WildcardBinding) otherType).boundCheck(this);
+ return otherType.erasure() == this.erasure();
+ }
+ /**
+ * Raw type is not treated as a standard parameterized type
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
+ */
+ public boolean isParameterizedType() {
+ return false;
+ }
+ public boolean isRawType() {
+ return true;
+ }
+
+ protected void initializeArguments() {
+ TypeVariableBinding[] typeVariables = this.type.typeVariables();
+ int length = typeVariables.length;
+ TypeBinding[] typeArguments = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ typeArguments[i] = typeVariables[i].erasure();
+ }
+ this.arguments = typeArguments;
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
+ */
+ public char[] readableName() /*java.lang.Object, p.X<T> */ {
+ char[] readableName;
+ if (isMemberType()) {
+ readableName = CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+ } else {
+ readableName = CharOperation.concatWith(this.type.compoundName, '.');
+ }
+ return readableName;
+ }
+
+ /**
+ * Returns a type, where original type was substituted using the receiver
+ * raw type.
+ * On raw types, all parameterized type denoting same original type are converted
+ * to raw types. e.g.
+ * class X <T> {
+ * X<T> foo;
+ * X<String> bar;
+ * } when used in raw fashion, then type of both foo and bar is raw type X.
+ */
+ public TypeBinding substitute(TypeBinding originalType) {
+
+ switch (originalType.kind()) {
+
+ case Binding.TYPE_PARAMETER:
+ TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
+ ParameterizedTypeBinding currentType = this;
+ while (true) {
+ TypeVariableBinding[] typeVariables = currentType.type.typeVariables();
+ int length = typeVariables.length;
+ // check this variable can be substituted given parameterized type
+ if (originalVariable.rank < length && typeVariables[originalVariable.rank] == originalVariable) {
+ // lazy init, since cannot do so during binding creation if during supertype connection
+ if (currentType.arguments == null) currentType.initializeArguments();
+ if (currentType.arguments != null)
+ return currentType.arguments[originalVariable.rank];
+ }
+ // recurse on enclosing type, as it may hold more substitutions to perform
+ ReferenceBinding enclosing = currentType.enclosingType();
+ if (!(enclosing instanceof ParameterizedTypeBinding))
+ break;
+ currentType = (ParameterizedTypeBinding) enclosing;
+ }
+ break;
+
+ case Binding.PARAMETERIZED_TYPE:
+ ReferenceBinding substitutedEnclosing = originalType.enclosingType();
+ if (substitutedEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) this.substitute(substitutedEnclosing);
+ }
+ ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
+ return this.environment.createRawType(originalParameterizedType.type, substitutedEnclosing);
+
+ case Binding.GENERIC_TYPE:
+ substitutedEnclosing = originalType.enclosingType();
+ if (substitutedEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) this.substitute(substitutedEnclosing);
+ }
+ return this.environment.createRawType((ReferenceBinding)originalType, substitutedEnclosing);
+
+ case Binding.WILDCARD_TYPE:
+ WildcardBinding wildcard = (WildcardBinding) originalType;
+ if (wildcard.kind != Wildcard.UNBOUND) {
+ TypeBinding originalBound = wildcard.bound;
+ TypeBinding substitutedBound = substitute(originalBound);
+ if (substitutedBound != originalBound) {
+ return this.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, wildcard.kind);
+ }
+ }
+ break;
+
+ case Binding.ARRAY_TYPE:
+ TypeBinding originalLeafComponentType = originalType.leafComponentType();
+ TypeBinding substitute = substitute(originalLeafComponentType); // substitute could itself be array type
+ if (substitute != originalLeafComponentType) {
+ return this.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
+ }
+ break;
+ }
+ return originalType;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
+ */
+ public char[] shortReadableName() /*Object*/ {
+ char[] shortReadableName;
+ if (isMemberType()) {
+ shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
+ } else {
+ shortReadableName = this.type.sourceName;
+ }
+ return shortReadableName;
+ }
+}