123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967 |
- /* *******************************************************************
- * Copyright (c) 2002,2005 Contributors
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * PARC initial implementation
- * Andy Clement start of generics upgrade...
- * Adrian Colyer - overhaul
- * ******************************************************************/
-
- package org.aspectj.weaver;
-
- import java.io.DataInputStream;
- import java.io.IOException;
- import java.util.Map;
-
- import org.aspectj.util.GenericSignature;
- import org.aspectj.util.GenericSignature.ClassSignature;
- import org.aspectj.util.GenericSignatureParser;
- import org.aspectj.weaver.tools.Traceable;
-
- /**
- * A UnresolvedType represents a type to the weaver. UnresolvedTypes are resolved in some World (a type repository). When a
- * UnresolvedType is resolved it turns into a ResolvedType which may be a primitive type, or a ReferenceType. ReferenceTypes may
- * refer to simple, generic, parameterized or type-variable based reference types. A ReferenceType is backed by a delegate that
- * provides information about the type based on some repository (for example an Eclipse based delegate, a bytecode based delegate or
- * a reflection based delegate).
- * <p>
- * Every UnresolvedType has a signature, the unique key for the type in the world.
- */
- public class UnresolvedType implements Traceable, TypeVariableDeclaringElement {
-
- // common type structures
- public static final UnresolvedType[] NONE = new UnresolvedType[0];
- public static final UnresolvedType OBJECT = forSignature("Ljava/lang/Object;");
- public static final UnresolvedType OBJECTARRAY = forSignature("[Ljava/lang/Object;");
- public static final UnresolvedType CLONEABLE = forSignature("Ljava/lang/Cloneable;");
- public static final UnresolvedType SERIALIZABLE = forSignature("Ljava/io/Serializable;");
- public static final UnresolvedType THROWABLE = forSignature("Ljava/lang/Throwable;");
- public static final UnresolvedType RUNTIME_EXCEPTION = forSignature("Ljava/lang/RuntimeException;");
- public static final UnresolvedType ERROR = forSignature("Ljava/lang/Error;");
- public static final UnresolvedType AT_INHERITED = forSignature("Ljava/lang/annotation/Inherited;");
- public static final UnresolvedType AT_RETENTION = forSignature("Ljava/lang/annotation/Retention;");
- public static final UnresolvedType ENUM = forSignature("Ljava/lang/Enum;");
- public static final UnresolvedType ANNOTATION = forSignature("Ljava/lang/annotation/Annotation;");
- public static final UnresolvedType JL_CLASS = forSignature("Ljava/lang/Class;");
- public static final UnresolvedType JAVA_LANG_CLASS_ARRAY = forSignature("[Ljava/lang/Class;");
- public static final UnresolvedType JL_STRING = forSignature("Ljava/lang/String;");
- public static final UnresolvedType JL_EXCEPTION = forSignature("Ljava/lang/Exception;");
- public static final UnresolvedType JAVA_LANG_REFLECT_METHOD = forSignature("Ljava/lang/reflect/Method;");
- public static final UnresolvedType JAVA_LANG_REFLECT_FIELD = forSignature("Ljava/lang/reflect/Field;");
- public static final UnresolvedType JAVA_LANG_REFLECT_CONSTRUCTOR = forSignature("Ljava/lang/reflect/Constructor;");
- public static final UnresolvedType JAVA_LANG_ANNOTATION = forSignature("Ljava/lang/annotation/Annotation;");
- public static final UnresolvedType SUPPRESS_AJ_WARNINGS = forSignature("Lorg/aspectj/lang/annotation/SuppressAjWarnings;");
- public static final UnresolvedType AT_TARGET = forSignature("Ljava/lang/annotation/Target;");
- public static final UnresolvedType SOMETHING = new UnresolvedType("?");
- public static final UnresolvedType[] ARRAY_WITH_JUST_OBJECT = new UnresolvedType[] { OBJECT };
- public static final UnresolvedType JOINPOINT_STATICPART = forSignature("Lorg/aspectj/lang/JoinPoint$StaticPart;");
- public static final UnresolvedType JOINPOINT_ENCLOSINGSTATICPART = forSignature("Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;");
- public static final UnresolvedType AJC_PRIVILEGED = forSignature("Lorg/aspectj/internal/lang/annotation/ajcPrivileged;");
- public static final UnresolvedType PROCEEDING_JOINPOINT = forSignature("Lorg/aspectj/lang/ProceedingJoinPoint;");
- public static final UnresolvedType BOOLEAN = forPrimitiveType("Z");
- public static final UnresolvedType BYTE = forPrimitiveType("B");
- public static final UnresolvedType CHAR = forPrimitiveType("C");
- public static final UnresolvedType DOUBLE = forPrimitiveType("D");
- public static final UnresolvedType FLOAT = forPrimitiveType("F");
- public static final UnresolvedType INT = forPrimitiveType("I");
- public static final UnresolvedType LONG = forPrimitiveType("J");
- public static final UnresolvedType SHORT = forPrimitiveType("S");
- public static final UnresolvedType VOID = forPrimitiveType("V");
-
- // A type is considered missing if we have a signature for it but cannot find the delegate
- public static final String MISSING_NAME = "@missing@";
-
- // OPTIMIZE I dont think you can ask something unresolved what kind of type it is, how can it always know? Push down into
- // resolvedtype that will force references to resolvedtypes to be correct rather than relying on unresolvedtypes to answer
- // questions
- protected TypeKind typeKind = TypeKind.SIMPLE; // what kind of type am I?
-
- protected String signature;
-
- /**
- * The erasure of the signature. Contains only the Java signature of the type with all supertype, superinterface, type variable,
- * and parameter information removed.
- */
- protected String signatureErasure;
-
- /**
- * Calculated on first request - the package name (java.lang for type java.lang.String)
- */
- private String packageName;
-
- /**
- * Calculated on first request - the class name (String for type java.lang.String)
- */
- private String className;
-
- /**
- * Iff isParameterized(), then these are the type parameters
- */
- protected UnresolvedType[] typeParameters;
-
- /**
- * Iff isGeneric(), then these are the type variables declared on the type Iff isParameterized(), then these are the type
- * variables bound as parameters in the type
- */
- // OPTIMIZE should be no state in here that will damage whether equals() is correct...
- protected TypeVariable[] typeVariables;
-
- public boolean isPrimitiveType() {
- return typeKind == TypeKind.PRIMITIVE;
- }
-
- public boolean isVoid() {
- // OPTIMIZE promote to bitflag?
- return signature.equals("V");
- }
-
- public boolean isSimpleType() {
- return typeKind == TypeKind.SIMPLE;
- }
-
- public boolean isRawType() {
- return typeKind == TypeKind.RAW;
- }
-
- public boolean isGenericType() {
- return typeKind == TypeKind.GENERIC;
- }
-
- public boolean isParameterizedType() {
- return typeKind == TypeKind.PARAMETERIZED;
- }
-
- public boolean isParameterizedOrGenericType() {
- return typeKind == TypeKind.GENERIC || typeKind == TypeKind.PARAMETERIZED;
- }
-
- public boolean isParameterizedOrRawType() {
- return typeKind == TypeKind.PARAMETERIZED || typeKind == TypeKind.RAW;
- }
-
- public boolean isTypeVariableReference() {
- return typeKind == TypeKind.TYPE_VARIABLE;
- }
-
- public boolean isGenericWildcard() {
- return typeKind == TypeKind.WILDCARD;
- }
-
- public TypeKind getTypekind() {
- return typeKind;
- }
-
- // for any reference type, we can get some extra information...
- public final boolean isArray() {
- return signature.length() > 0 && signature.charAt(0) == '[';
- }
-
- /**
- * Equality is checked based on the underlying signature.
- */
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof UnresolvedType)) {
- return false;
- }
- return signature.equals(((UnresolvedType) other).signature);
- }
-
- /**
- * Equality is checked based on the underlying signature, so the hash code of a particular type is the hash code of its
- * signature string.
- */
- @Override
- public int hashCode() {
- return signature.hashCode();
- }
-
- protected UnresolvedType(String signature) {
- this.signature = signature;
- this.signatureErasure = signature;
- }
-
- protected UnresolvedType(String signature, String signatureErasure) {
- this.signature = signature;
- this.signatureErasure = signatureErasure;
- }
-
- // called from TypeFactory
- public UnresolvedType(String signature, String signatureErasure, UnresolvedType[] typeParams) {
- this.signature = signature;
- this.signatureErasure = signatureErasure;
- this.typeParameters = typeParams;
- if (typeParams != null) {
- this.typeKind = TypeKind.PARAMETERIZED;
- }
- }
-
- // The operations supported by an UnresolvedType are those that do not require a world
-
- /**
- * This is the size of this type as used in JVM.
- */
- public int getSize() {
- return size;
- }
-
- private int size = 1;
-
- /**
- * NOTE: Use forSignature() if you can, it'll be cheaper ! Constructs a UnresolvedType for a java language type name. For
- * example:
- *
- * <blockquote>
- *
- * <pre>
- * UnresolvedType.forName("java.lang.Thread[]")
- * UnresolvedType.forName("int")
- * </pre>
- *
- * </blockquote>
- *
- * Types may equivalently be produced by this or by {@link #forSignature(String)}.
- *
- * <blockquote>
- *
- * <pre>
- * UnresolvedType.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
- * UnresolvedType.forName("int").equals(Type.forSignature("I"))
- * </pre>
- *
- * </blockquote>
- *
- * @param name the java language type name in question.
- * @return a type object representing that java language type.
- */
- // OPTIMIZE change users of this to use forSignature, especially for simple cases
- public static UnresolvedType forName(String name) {
- return forSignature(nameToSignature(name));
- }
-
- /**
- * Constructs a UnresolvedType for each java language type name in an incoming array.
- *
- * @param names an array of java language type names.
- * @return an array of UnresolvedType objects.
- * @see #forName(String)
- */
- public static UnresolvedType[] forNames(String[] names) {
- UnresolvedType[] ret = new UnresolvedType[names.length];
- for (int i = 0, len = names.length; i < len; i++) {
- ret[i] = UnresolvedType.forName(names[i]);
- }
- return ret;
- }
-
- public static UnresolvedType forGenericType(String name, TypeVariable[] tvbs, String genericSig) {
- String sig = nameToSignature(name);
- UnresolvedType ret = UnresolvedType.forSignature(sig);
- ret.typeKind = TypeKind.GENERIC;
- ret.typeVariables = tvbs;
- ret.signatureErasure = sig;
- return ret;
- }
-
- public static UnresolvedType forGenericTypeSignature(String sig, String declaredGenericSig) {
- UnresolvedType ret = UnresolvedType.forSignature(sig);
- ret.typeKind = TypeKind.GENERIC;
-
- ClassSignature csig = new GenericSignatureParser().parseAsClassSignature(declaredGenericSig);
-
- GenericSignature.FormalTypeParameter[] ftps = csig.formalTypeParameters;
- ret.typeVariables = new TypeVariable[ftps.length];
- for (int i = 0; i < ftps.length; i++) {
- GenericSignature.FormalTypeParameter parameter = ftps[i];
- if (parameter.classBound instanceof GenericSignature.ClassTypeSignature) {
- GenericSignature.ClassTypeSignature cts = (GenericSignature.ClassTypeSignature) parameter.classBound;
- ret.typeVariables[i] = new TypeVariable(ftps[i].identifier, UnresolvedType.forSignature(cts.outerType.identifier
- + ";"));
- } else if (parameter.classBound instanceof GenericSignature.TypeVariableSignature) {
- GenericSignature.TypeVariableSignature tvs = (GenericSignature.TypeVariableSignature) parameter.classBound;
- UnresolvedTypeVariableReferenceType utvrt = new UnresolvedTypeVariableReferenceType(new TypeVariable(
- tvs.typeVariableName));
- ret.typeVariables[i] = new TypeVariable(ftps[i].identifier, utvrt);
- } else {
- throw new BCException(
- "UnresolvedType.forGenericTypeSignature(): Do not know how to process type variable bound of type '"
- + parameter.classBound.getClass() + "'. Full signature is '" + sig + "'");
- }
- }
- ret.signatureErasure = sig;
- ret.signature = ret.signatureErasure;
- return ret;
- }
-
- public static UnresolvedType forGenericTypeVariables(String sig, TypeVariable[] tVars) {
- UnresolvedType ret = UnresolvedType.forSignature(sig);
- ret.typeKind = TypeKind.GENERIC;
- ret.typeVariables = tVars;
- ret.signatureErasure = sig;
- ret.signature = ret.signatureErasure;
- return ret;
- }
-
- public static UnresolvedType forRawTypeName(String name) {
- UnresolvedType ret = UnresolvedType.forName(name);
- ret.typeKind = TypeKind.RAW;
- return ret;
- }
-
- public static UnresolvedType forPrimitiveType(String signature) {
- UnresolvedType ret = new UnresolvedType(signature);
- ret.typeKind = TypeKind.PRIMITIVE;
- if (signature.equals("J") || signature.equals("D")) {
- ret.size = 2;
- } else if (signature.equals("V")) {
- ret.size = 0;
- }
- return ret;
- }
-
- /**
- * Creates a new type array with a fresh type appended to the end.
- *
- * @param types the left hand side of the new array
- * @param end the right hand side of the new array
- */
- public static UnresolvedType[] add(UnresolvedType[] types, UnresolvedType end) {
- int len = types.length;
- UnresolvedType[] ret = new UnresolvedType[len + 1];
- System.arraycopy(types, 0, ret, 0, len);
- ret[len] = end;
- return ret;
- }
-
- /**
- * Creates a new type array with a fresh type inserted at the beginning.
- *
- *
- * @param start the left hand side of the new array
- * @param types the right hand side of the new array
- */
- public static UnresolvedType[] insert(UnresolvedType start, UnresolvedType[] types) {
- int len = types.length;
- UnresolvedType[] ret = new UnresolvedType[len + 1];
- ret[0] = start;
- System.arraycopy(types, 0, ret, 1, len);
- return ret;
- }
-
- /**
- * Constructs a Type for a JVM bytecode signature string. For example:
- *
- * <blockquote>
- *
- * <pre>
- * UnresolvedType.forSignature("[Ljava/lang/Thread;")
- * UnresolvedType.forSignature("I");
- * </pre>
- *
- * </blockquote>
- *
- * Types may equivalently be produced by this or by {@link #forName(String)}. This method should not be passed P signatures.
- *
- * <blockquote>
- *
- * <pre>
- * UnresolvedType.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
- * UnresolvedType.forName("int").equals(Type.forSignature("I"))
- * </pre>
- *
- * </blockquote>
- *
- * @param signature the JVM bytecode signature string for the desired type.
- * @return a type object represnting that JVM bytecode signature.
- */
- public static UnresolvedType forSignature(String signature) {
- assert !(signature.startsWith("L") && signature.contains("<"));
- switch (signature.charAt(0)) {
- case 'B':
- return UnresolvedType.BYTE;
- case 'C':
- return UnresolvedType.CHAR;
- case 'D':
- return UnresolvedType.DOUBLE;
- case 'F':
- return UnresolvedType.FLOAT;
- case 'I':
- return UnresolvedType.INT;
- case 'J':
- return UnresolvedType.LONG;
- case 'L':
- return TypeFactory.createTypeFromSignature(signature);
- case 'P':
- return TypeFactory.createTypeFromSignature(signature);
- case 'S':
- return UnresolvedType.SHORT;
- case 'V':
- return UnresolvedType.VOID;
- case 'Z':
- return UnresolvedType.BOOLEAN;
- case '[':
- return TypeFactory.createTypeFromSignature(signature);
- case '+':
- return TypeFactory.createTypeFromSignature(signature);
- case '-':
- return TypeFactory.createTypeFromSignature(signature);
- case '?':
- return TypeFactory.createTypeFromSignature(signature);
- case 'T':
- return TypeFactory.createTypeFromSignature(signature);
- default:
- throw new BCException("Bad type signature " + signature);
- }
- }
-
- /**
- * Constructs a UnresolvedType for each JVM bytecode type signature in an incoming array.
- *
- * @param names an array of JVM bytecode type signatures
- * @return an array of UnresolvedType objects.
- * @see #forSignature(String)
- */
- public static UnresolvedType[] forSignatures(String[] sigs) {
- UnresolvedType[] ret = new UnresolvedType[sigs.length];
- for (int i = 0, len = sigs.length; i < len; i++) {
- ret[i] = UnresolvedType.forSignature(sigs[i]);
- }
- return ret;
- }
-
- /**
- * Returns the name of this type in java language form (e.g. java.lang.Thread or boolean[]). This produces a more aesthetically
- * pleasing string than {@link java.lang.Class#getName()}.
- *
- * @return the java language name of this type.
- */
- public String getName() {
- return signatureToName(signature);
- }
-
- public String getSimpleName() {
- String name = getRawName();
- int lastDot = name.lastIndexOf('.');
- if (lastDot != -1) {
- name = name.substring(lastDot + 1);
- }
- if (isParameterizedType()) {
- StringBuffer sb = new StringBuffer(name);
- sb.append("<");
- for (int i = 0; i < (typeParameters.length - 1); i++) {
- sb.append(typeParameters[i].getSimpleName());
- sb.append(",");
- }
- sb.append(typeParameters[typeParameters.length - 1].getSimpleName());
- sb.append(">");
- name = sb.toString();
- }
- return name;
- }
-
- public String getRawName() {
- return signatureToName((signatureErasure == null ? signature : signatureErasure));
- }
-
- public String getBaseName() {
- String name = getName();
- if (isParameterizedType() || isGenericType()) {
- if (typeParameters == null) {
- return name;
- } else {
- return name.substring(0, name.indexOf("<"));
- }
- } else {
- return name;
- }
- }
-
- public String getSimpleBaseName() {
- String name = getBaseName();
- int lastDot = name.lastIndexOf('.');
- if (lastDot != -1) {
- name = name.substring(lastDot + 1);
- }
- return name;
- }
-
- /**
- * Returns an array of strings representing the java langauge names of an array of types.
- *
- * @param types an array of UnresolvedType objects
- * @return an array of Strings fo the java language names of types.
- * @see #getName()
- */
- public static String[] getNames(UnresolvedType[] types) {
- String[] ret = new String[types.length];
- for (int i = 0, len = types.length; i < len; i++) {
- ret[i] = types[i].getName();
- }
- return ret;
- }
-
- /**
- * Returns the name of this type in JVM signature form. For all UnresolvedType t:
- *
- * <blockquote>
- *
- * <pre>
- * UnresolvedType.forSignature(t.getSignature()).equals(t)
- * </pre>
- *
- * </blockquote>
- *
- * and for all String s where s is a lexically valid JVM type signature string:
- *
- * <blockquote>
- *
- * <pre>
- * UnresolvedType.forSignature(s).getSignature().equals(s)
- * </pre>
- *
- * </blockquote>
- *
- * @return the java JVM signature string for this type.
- */
- public String getSignature() {
- return signature;
- }
-
- /**
- * For parameterized types, return the signature for the raw type
- */
- public String getErasureSignature() {
- if (signatureErasure == null) {
- return signature;
- }
- return signatureErasure;
- }
-
- private boolean needsModifiableDelegate = false;
-
- public boolean needsModifiableDelegate() {
- return needsModifiableDelegate;
- }
-
- public void setNeedsModifiableDelegate(boolean b) {
- this.needsModifiableDelegate = b;
- }
-
- public UnresolvedType getRawType() {
- return UnresolvedType.forSignature(getErasureSignature());
- }
-
- /**
- * Returns a UnresolvedType object representing the effective outermost enclosing type for a name type. For all other types,
- * this will return the type itself.
- *
- * The only guarantee is given in JLS 13.1 where code generated according to those rules will have type names that can be split
- * apart in this way.
- *
- * @return the outermost enclosing UnresolvedType object or this.
- */
- public UnresolvedType getOutermostType() {
- if (isArray() || isPrimitiveType()) {
- return this;
- }
- String sig = getErasureSignature();
- int dollar = sig.indexOf('$');
- if (dollar != -1) {
- return UnresolvedType.forSignature(sig.substring(0, dollar) + ';');
- } else {
- return this;
- }
- }
-
- /**
- * Returns a UnresolvedType object representing the component type of this array, or null if this type does not represent an
- * array type.
- *
- * @return the component UnresolvedType object, or null.
- */
- public UnresolvedType getComponentType() {
- if (isArray()) {
- return forSignature(signature.substring(1));
- } else {
- return null;
- }
- }
-
- /**
- * Returns a java language string representation of this type.
- */
- @Override
- public String toString() {
- return getName(); // + " - " + getKind();
- }
-
- public String toDebugString() {
- return getName();
- }
-
- // ---- requires worlds
-
- /**
- * Returns a resolved version of this type according to a particular world.
- *
- * @param world the {@link World} within which to resolve.
- * @return a resolved type representing this type in the appropriate world.
- */
- public ResolvedType resolve(World world) {
- return world.resolve(this);
- }
-
- // ---- helpers
-
- private static String signatureToName(String signature) {
- switch (signature.charAt(0)) {
- case 'B':
- return "byte";
- case 'C':
- return "char";
- case 'D':
- return "double";
- case 'F':
- return "float";
- case 'I':
- return "int";
- case 'J':
- return "long";
- case 'L':
- String name = signature.substring(1, signature.length() - 1).replace('/', '.');
- return name;
- case 'T':
- StringBuffer nameBuff2 = new StringBuffer();
- int colon = signature.indexOf(";");
- String tvarName = signature.substring(1, colon);
- nameBuff2.append(tvarName);
- return nameBuff2.toString();
- case 'P': // it's one of our parameterized type sigs
- StringBuffer nameBuff = new StringBuffer();
- // signature for parameterized types is e.g.
- // List<String> -> Ljava/util/List<Ljava/lang/String;>;
- // Map<String,List<Integer>> -> Ljava/util/Map<java/lang/String;Ljava/util/List<Ljava/lang/Integer;>;>;
- int paramNestLevel = 0;
- for (int i = 1; i < signature.length(); i++) {
- char c = signature.charAt(i);
- switch (c) {
- case '/':
- nameBuff.append('.');
- break;
- case '<':
- nameBuff.append("<");
- paramNestLevel++;
- StringBuffer innerBuff = new StringBuffer();
- while (paramNestLevel > 0) {
- c = signature.charAt(++i);
- if (c == '<') {
- paramNestLevel++;
- }
- if (c == '>') {
- paramNestLevel--;
- }
- if (paramNestLevel > 0) {
- innerBuff.append(c);
- }
- if (c == ';' && paramNestLevel == 1) {
- nameBuff.append(signatureToName(innerBuff.toString()));
- if (signature.charAt(i + 1) != '>') {
- nameBuff.append(',');
- }
- innerBuff = new StringBuffer();
- }
- }
- nameBuff.append(">");
- break;
- case ';':
- break;
- default:
- nameBuff.append(c);
- }
- }
- return nameBuff.toString();
- case 'S':
- return "short";
- case 'V':
- return "void";
- case 'Z':
- return "boolean";
- case '[':
- return signatureToName(signature.substring(1, signature.length())) + "[]";
- // case '<':
- // // its a generic!
- // if (signature.charAt(1)=='>') return signatureToName(signature.substring(2));
- case '+':
- return "? extends " + signatureToName(signature.substring(1, signature.length()));
- case '-':
- return "? super " + signatureToName(signature.substring(1, signature.length()));
- case '*':
- return "?";
- default:
- throw new BCException("Bad type signature: " + signature);
- }
- }
-
- private static String nameToSignature(String name) {
- int len = name.length();
- if (len < 8) {
- if (name.equals("int")) {
- return "I";
- }
- if (name.equals("void")) {
- return "V";
- }
- if (name.equals("long")) {
- return "J";
- }
- if (name.equals("boolean")) {
- return "Z";
- }
- if (name.equals("double")) {
- return "D";
- }
- if (name.equals("float")) {
- return "F";
- }
- if (name.equals("byte")) {
- return "B";
- }
- if (name.equals("short")) {
- return "S";
- }
- if (name.equals("char")) {
- return "C";
- }
- if (name.equals("?")) {
- return name;
- }
- }
- if (len == 0) {
- throw new BCException("Bad type name: " + name);
- }
- if (name.endsWith("[]")) {
- return "[" + nameToSignature(name.substring(0, name.length() - 2));
- }
-
- // Sometimes the 'name' for an array is of the form: [Ljava.lang.String;
- if (name.charAt(0)=='[') {
- return name.replace('.','/');
- }
-
- if (!name.contains("<")) {
- // not parameterized
- return new StringBuilder("L").append(name.replace('.', '/')).append(';').toString();
- } else {
- StringBuffer nameBuff = new StringBuffer();
- int nestLevel = 0;
- nameBuff.append("P");
- for (int i = 0; i < len; i++) {
- char c = name.charAt(i);
- switch (c) {
- case '.':
- nameBuff.append('/');
- break;
- case '<':
- nameBuff.append("<");
- nestLevel++;
- StringBuffer innerBuff = new StringBuffer();
- while (nestLevel > 0) {
- c = name.charAt(++i);
- if (c == '<') {
- nestLevel++;
- } else if (c == '>') {
- nestLevel--;
- }
- if (c == ',' && nestLevel == 1) {
- nameBuff.append(nameToSignature(innerBuff.toString()));
- innerBuff = new StringBuffer();
- } else {
- if (nestLevel > 0) {
- innerBuff.append(c);
- }
- }
- }
- nameBuff.append(nameToSignature(innerBuff.toString()));
- nameBuff.append('>');
- break;
- // case '>':
- // throw new IllegalStateException("Should by matched by <");
- // case ',':
- // throw new IllegalStateException("Should only happen inside <...>");
- default:
- nameBuff.append(c);
- }
- }
- nameBuff.append(";");
- return nameBuff.toString();
- }
- }
-
- /**
- * Write out an UnresolvedType - the signature should be enough.
- */
- public final void write(CompressingDataOutputStream s) throws IOException {
- s.writeUTF(getSignature());
- }
-
- /**
- * Read in an UnresolvedType - just read the signature and rebuild the UnresolvedType.
- */
- public static UnresolvedType read(DataInputStream s) throws IOException {
- String sig = s.readUTF();
- if (sig.equals(MISSING_NAME)) {
- return ResolvedType.MISSING;
- } else {
- // TODO isn't it a shame to build these (this method is expensive) and then chuck them away on resolution?
- // TODO review callers and see if they are immediately resolving it, maybe we can do something more optimal if they are
- return UnresolvedType.forSignature(sig);
- }
- }
-
- public String getNameAsIdentifier() {
- return getName().replace('.', '_');
- }
-
- public String getPackageNameAsIdentifier() {
- String name = getName();
- int index = name.lastIndexOf('.');
- if (index == -1) {
- return "";
- } else {
- return name.substring(0, index).replace('.', '_');
- }
- }
-
- public UnresolvedType[] getTypeParameters() {
- return typeParameters == null ? UnresolvedType.NONE : typeParameters;
- }
-
- public TypeVariable[] getTypeVariables() {
- return typeVariables;
- }
-
- public static class TypeKind {
- // Note: It is not sufficient to say that a parameterized type with no type parameters in fact
- // represents a raw type - a parameterized type with no type parameters can represent
- // an inner type of a parameterized type that specifies no type parameters of its own.
- public final static TypeKind PRIMITIVE = new TypeKind("primitive");
- public final static TypeKind SIMPLE = new TypeKind("simple"); // a type with NO type parameters/vars
- public final static TypeKind RAW = new TypeKind("raw"); // the erasure of a generic type
- public final static TypeKind GENERIC = new TypeKind("generic"); // a generic type
- public final static TypeKind PARAMETERIZED = new TypeKind("parameterized"); // a parameterized type
- public final static TypeKind TYPE_VARIABLE = new TypeKind("type_variable"); // a type variable
- public final static TypeKind WILDCARD = new TypeKind("wildcard"); // a generic wildcard type
-
- @Override
- public String toString() {
- return type;
- }
-
- private TypeKind(String type) {
- this.type = type;
- }
-
- private final String type;
- }
-
- @Override
- public TypeVariable getTypeVariableNamed(String name) {
- TypeVariable[] vars = getTypeVariables();
- if (vars == null || vars.length == 0) {
- return null;
- }
- for (TypeVariable aVar : vars) {
- if (aVar.getName().equals(name)) {
- return aVar;
- }
- }
- return null;
- }
-
- @Override
- public String toTraceString() {
- return getClass().getName() + "[" + getName() + "]";
- }
-
- /**
- * Return a version of this parameterized type in which any type parameters that are type variable references are replaced by
- * their matching type variable binding.
- */
- // OPTIMIZE methods like this just allow callers to be lazy and not ensure they are working with the right (resolved) subtype
- public UnresolvedType parameterize(Map<String, UnresolvedType> typeBindings) {
- throw new UnsupportedOperationException("unable to parameterize unresolved type: " + signature);
- }
-
- /**
- * @return the class name (does not include the package name)
- */
- public String getClassName() {
- if (className == null) {
- String name = getName();
- if (name.contains("<")) {
- name = name.substring(0, name.indexOf("<"));
- }
- int index = name.lastIndexOf('.');
- if (index == -1) {
- className = name;
- } else {
- className = name.substring(index + 1);
- }
- }
- return className;
- }
-
- /**
- * @return the package name (no class name included)
- */
- public String getPackageName() {
- if (packageName == null) {
- String name = getName();
- int angly = name.indexOf('<');
- if (angly != -1) {
- name = name.substring(0, angly);
- }
- int index = name.lastIndexOf('.');
- if (index == -1) {
- packageName = "";
- } else {
- packageName = name.substring(0, index);
- }
- }
- return packageName;
- }
-
- public static void writeArray(UnresolvedType[] types, CompressingDataOutputStream stream) throws IOException {
- int len = types.length;
- stream.writeShort(len);
- for (UnresolvedType type : types) {
- type.write(stream);
- }
- }
-
- public static UnresolvedType[] readArray(DataInputStream s) throws IOException {
- int len = s.readShort();
- if (len == 0) {
- return UnresolvedType.NONE;
- }
- UnresolvedType[] types = new UnresolvedType[len];
- for (int i = 0; i < len; i++) {
- types[i] = UnresolvedType.read(s);
- }
- return types;
- }
-
- public static UnresolvedType makeArray(UnresolvedType base, int dims) {
- StringBuffer sig = new StringBuffer();
- for (int i = 0; i < dims; i++) {
- sig.append("[");
- }
- sig.append(base.getSignature());
- return UnresolvedType.forSignature(sig.toString());
- }
- }
|