| /******************************************************************************* |
| * 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; |
| |
| /** |
| * 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) { |
| return super.createParameterizedMethod(originalMethod); |
| } |
| return new ParameterizedGenericMethodBinding(originalMethod, this, this.environment); |
| } |
| /** |
| * @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) { |
| |
| if (originalType.isTypeVariable()) { |
| 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; |
| } |
| } else if (originalType.isParameterizedType()) { |
| ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType; |
| return this.environment.createRawType(originalParameterizedType.type, originalParameterizedType.enclosingType()); |
| } else if (originalType.isGenericType()) { |
| return this.environment.createRawType((ReferenceBinding)originalType, null); |
| } else if (originalType.isArrayType()) { |
| 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()); |
| } |
| } |
| 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; |
| } |
| } |