From 34b6b7ea43e739b9e70fb3f64e94e50f420f095a Mon Sep 17 00:00:00 2001 From: aclement Date: Fri, 30 Jul 2010 03:51:56 +0000 Subject: [PATCH] 320358: type signature changes --- .../org/aspectj/weaver/AjcMemberMaker.java | 6 +- .../aspectj/weaver/ConcreteTypeMunger.java | 14 +- .../src/org/aspectj/weaver/MemberImpl.java | 16 +- .../src/org/aspectj/weaver/MemberUtils.java | 25 ++ .../aspectj/weaver/NewFieldTypeMunger.java | 2 +- .../aspectj/weaver/NewMethodTypeMunger.java | 6 +- .../aspectj/weaver/ResolvedMemberImpl.java | 16 +- .../src/org/aspectj/weaver/ResolvedType.java | 2 +- .../aspectj/weaver/ResolvedTypeMunger.java | 2 +- .../src/org/aspectj/weaver/TypeFactory.java | 69 +++- .../org/aspectj/weaver/UnresolvedType.java | 303 ++++++++---------- .../UnresolvedTypeVariableReferenceType.java | 4 +- .../patterns/WildAnnotationTypePattern.java | 2 +- .../aspectj/weaver/MatcherModuleTests.java | 1 + .../org/aspectj/weaver/TypeFactoryTests.java | 76 +++++ 15 files changed, 334 insertions(+), 210 deletions(-) create mode 100644 org.aspectj.matcher/src/org/aspectj/weaver/MemberUtils.java create mode 100644 org.aspectj.matcher/testsrc/org/aspectj/weaver/TypeFactoryTests.java diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java b/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java index 1e533918d..918572bcd 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java @@ -109,7 +109,7 @@ public class AjcMemberMaker { if (!isSerializableAspect(aspectType)) { modifiers |= Modifier.TRANSIENT; } - return new ResolvedMemberImpl(Member.FIELD, declaringType, modifiers, UnresolvedType.JAVA_LANG_STRING, + return new ResolvedMemberImpl(Member.FIELD, declaringType, modifiers, UnresolvedType.JL_STRING, NameMangler.PERTYPEWITHIN_WITHINTYPEFIELD, UnresolvedType.NONE); } @@ -126,7 +126,7 @@ public class AjcMemberMaker { public static ResolvedMember perTypeWithinGetInstance(UnresolvedType declaringType) { // private static a.X ajc$getInstance(java.lang.Class) ResolvedMemberImpl rm = new ResolvedMemberImpl(Member.METHOD, declaringType, PRIVATE_STATIC, declaringType, // return value - NameMangler.PERTYPEWITHIN_GETINSTANCE_METHOD, new UnresolvedType[] { UnresolvedType.JAVA_LANG_CLASS }); + NameMangler.PERTYPEWITHIN_GETINSTANCE_METHOD, new UnresolvedType[] { UnresolvedType.JL_CLASS }); return rm; } @@ -134,7 +134,7 @@ public class AjcMemberMaker { public static ResolvedMember perTypeWithinGetWithinTypeNameMethod(UnresolvedType declaringType, boolean inJava5Mode) { // public String getWithinTypeName() ResolvedMemberImpl rm = new ResolvedMemberImpl(Member.METHOD, declaringType, Modifier.PUBLIC, - UnresolvedType.JAVA_LANG_STRING, // return value + UnresolvedType.JL_STRING, // return value NameMangler.PERTYPEWITHIN_GETWITHINTYPENAME_METHOD, UnresolvedType.NONE); return rm; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ConcreteTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/ConcreteTypeMunger.java index a51de77c9..8f8687622 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ConcreteTypeMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ConcreteTypeMunger.java @@ -69,14 +69,16 @@ public abstract class ConcreteTypeMunger implements PartialOrder.PartialComparab } public ISourceLocation getSourceLocation() { - if (munger == null) + if (munger == null) { return null; + } return munger.getSourceLocation(); // XXX } public boolean matches(ResolvedType onType) { - if (munger == null) + if (munger == null) { throw new RuntimeException("huh: " + this); + } return munger.matches(onType, aspectType); } @@ -119,8 +121,9 @@ public abstract class ConcreteTypeMunger implements PartialOrder.PartialComparab * */ public boolean isTargetTypeParameterized() { - if (munger == null) + if (munger == null) { return false; + } return munger.sharesTypeVariablesWithGenericType(); } @@ -131,12 +134,13 @@ public abstract class ConcreteTypeMunger implements PartialOrder.PartialComparab public abstract ConcreteTypeMunger parameterizedFor(ResolvedType targetType); public boolean isLateMunger() { - if (munger == null) + if (munger == null) { return false; + } return munger.isLateMunger(); } - public abstract ConcreteTypeMunger parameterizeWith(Map parameterizationMap, World world); + public abstract ConcreteTypeMunger parameterizeWith(Map parameterizationMap, World world); /** * Some type mungers are created purely to help with the implementation of shadow mungers. For example to support the cflow() diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java index 64ae458d2..fda448d5e 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java @@ -381,17 +381,13 @@ public class MemberImpl implements Member { } public String getParameterSignature() { - if (paramSignature != null) { - return paramSignature; - } - StringBuffer sb = new StringBuffer(); - sb.append("("); - for (int i = 0; i < parameterTypes.length; i++) { - UnresolvedType tx = parameterTypes[i]; - sb.append(tx.getSignature()); + if (paramSignature == null) { + StringBuilder sb = new StringBuilder("("); + for (UnresolvedType parameterType : parameterTypes) { + sb.append(parameterType.getSignature()); + } + paramSignature = sb.append(")").toString(); } - sb.append(")"); - paramSignature = sb.toString(); return paramSignature; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/MemberUtils.java b/org.aspectj.matcher/src/org/aspectj/weaver/MemberUtils.java new file mode 100644 index 000000000..201eb758f --- /dev/null +++ b/org.aspectj.matcher/src/org/aspectj/weaver/MemberUtils.java @@ -0,0 +1,25 @@ +/* ******************************************************************* + * Copyright (c) 2010 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: + * Andy Clement, SpringSource + * ******************************************************************/ +package org.aspectj.weaver; + +/** + * Common utility methods for members. + * + * @author Andy Clement + */ +public class MemberUtils { + + public static boolean isConstructor(ResolvedMember member) { + return member.getName().equals(""); + } + +} diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java index bb2cacbb1..ed8afc1e0 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java @@ -128,7 +128,7 @@ public class NewFieldTypeMunger extends ResolvedTypeMunger { return nftm; } - public ResolvedTypeMunger parameterizeWith(Map m, World w) { + public ResolvedTypeMunger parameterizeWith(Map m, World w) { ResolvedMember parameterizedSignature = getSignature().parameterizedWith(m, w); NewFieldTypeMunger nftm = new NewFieldTypeMunger(parameterizedSignature, getSuperMethodsCalled(), typeVariableAliases); nftm.setDeclaredSignature(getSignature()); diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/NewMethodTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/NewMethodTypeMunger.java index da5c3b1f4..a6e0ffce7 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/NewMethodTypeMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/NewMethodTypeMunger.java @@ -69,9 +69,9 @@ public class NewMethodTypeMunger extends ResolvedTypeMunger { public static ResolvedTypeMunger readMethod(VersionedDataInputStream s, ISourceContext context) throws IOException { ISourceLocation sloc = null; ResolvedMemberImpl rmImpl = ResolvedMemberImpl.readResolvedMember(s, context); - Set superMethodsCalled = readSuperMethodsCalled(s); + Set superMethodsCalled = readSuperMethodsCalled(s); sloc = readSourceLocation(s); - List typeVarAliases = readInTypeAliases(s); + List typeVarAliases = readInTypeAliases(s); ResolvedTypeMunger munger = new NewMethodTypeMunger(rmImpl, superMethodsCalled, typeVarAliases); if (sloc != null) { @@ -138,7 +138,7 @@ public class NewMethodTypeMunger extends ResolvedTypeMunger { return result; } - public ResolvedTypeMunger parameterizeWith(Map m, World w) { + public ResolvedTypeMunger parameterizeWith(Map m, World w) { ResolvedMember parameterizedSignature = getSignature().parameterizedWith(m, w); NewMethodTypeMunger nmtm = new NewMethodTypeMunger(parameterizedSignature, getSuperMethodsCalled(), typeVariableAliases); nmtm.setDeclaredSignature(getSignature()); diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMemberImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMemberImpl.java index 963490118..749a9bbff 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMemberImpl.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMemberImpl.java @@ -1039,17 +1039,13 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno * getParam */ public String getParameterSignatureErased() { - if (myParameterSignatureErasure != null) { - return myParameterSignatureErasure; - } - StringBuffer sig = new StringBuffer(); - UnresolvedType[] myParameterTypes = getParameterTypes(); - for (int i = 0; i < myParameterTypes.length; i++) { - UnresolvedType thisParameter = myParameterTypes[i]; - // type vars will be erased to first bound - sig.append(thisParameter.getErasureSignature()); + if (myParameterSignatureErasure == null) { + StringBuilder sig = new StringBuilder(); + for (UnresolvedType parameter : getParameterTypes()) { + sig.append(parameter.getErasureSignature()); + } + myParameterSignatureErasure = sig.toString(); } - myParameterSignatureErasure = sig.toString(); return myParameterSignatureErasure; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java index 0bdb6953e..b500076e8 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java @@ -2499,7 +2499,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl * @return true if assignable to java.lang.Exception */ public boolean isException() { - return (world.getCoreType(UnresolvedType.JAVA_LANG_EXCEPTION).isAssignableFrom(this)); + return (world.getCoreType(UnresolvedType.JL_EXCEPTION).isAssignableFrom(this)); } /** diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java index e08fe2f2e..2ba3cbc36 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java @@ -488,7 +488,7 @@ public abstract class ResolvedTypeMunger { return false; } - public ResolvedTypeMunger parameterizeWith(Map m, World w) { + public ResolvedTypeMunger parameterizeWith(Map m, World w) { throw new BCException("Dont call parameterizeWith() on a type munger of this kind: " + this.getClass()); } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/TypeFactory.java b/org.aspectj.matcher/src/org/aspectj/weaver/TypeFactory.java index 7cdbe230b..c81e23133 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/TypeFactory.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/TypeFactory.java @@ -69,7 +69,7 @@ public class TypeFactory { * Creates a sensible unresolvedtype from some signature, for example: signature = LIGuard; bound = toString=IGuard * sig=PIGuard; sigErasure=LIGuard; kind=parameterized */ - private static UnresolvedType convertSigToType(String aSignature) { + static UnresolvedType convertSigToType(String aSignature) { UnresolvedType bound = null; int startOfParams = aSignature.indexOf('<'); if (startOfParams == -1) { @@ -132,6 +132,15 @@ public class TypeFactory { endOfParams = locateMatchingEndAngleBracket(lastType, startOfParams); typeParams = createTypeParams(lastType.substring(startOfParams + 1, endOfParams)); } + StringBuilder s = new StringBuilder(); + int firstAngleBracket = signature.indexOf('<'); + s.append("P").append(signature.substring(1, firstAngleBracket)); + s.append('<'); + for (UnresolvedType typeParameter : typeParams) { + s.append(typeParameter.getSignature()); + } + s.append(">;"); + signature = s.toString();//'P' + signature.substring(1); return new UnresolvedType(signature, signatureErasure, typeParams); } // can't replace above with convertSigToType - leads to stackoverflow @@ -185,6 +194,54 @@ public class TypeFactory { } else if (firstChar == '@') { // missing type return ResolvedType.MISSING; + } else if (firstChar == 'L') { + // only an issue if there is also an angle bracket + int leftAngleBracket = signature.indexOf('<'); + + if (leftAngleBracket == -1) { + return new UnresolvedType(signature); + } else { + int endOfParams = locateMatchingEndAngleBracket(signature, leftAngleBracket); + StringBuffer erasureSig = new StringBuffer(signature); + erasureSig.setCharAt(0, 'L'); + while (leftAngleBracket != -1) { + erasureSig.delete(leftAngleBracket, endOfParams + 1); + leftAngleBracket = locateFirstBracket(erasureSig); + if (leftAngleBracket != -1) { + endOfParams = locateMatchingEndAngleBracket(erasureSig, leftAngleBracket); + } + } + + String signatureErasure = erasureSig.toString(); + + // TODO should consider all the intermediate parameterizations as well! + // the type parameters of interest are only those that apply to the 'last type' in the signature + // if the signature is 'PMyInterface$MyOtherType;' then there are none... + String lastType = null; + int nestedTypePosition = signature.indexOf("$", endOfParams); // don't look for $ INSIDE the parameters + if (nestedTypePosition != -1) { + lastType = signature.substring(nestedTypePosition + 1); + } else { + lastType = new String(signature); + } + leftAngleBracket = lastType.indexOf("<"); + UnresolvedType[] typeParams = UnresolvedType.NONE; + if (leftAngleBracket != -1) { + endOfParams = locateMatchingEndAngleBracket(lastType, leftAngleBracket); + typeParams = createTypeParams(lastType.substring(leftAngleBracket + 1, endOfParams)); + } + StringBuilder s = new StringBuilder(); + int firstAngleBracket = signature.indexOf('<'); + s.append("P").append(signature.substring(1, firstAngleBracket)); + s.append('<'); + for (UnresolvedType typeParameter : typeParams) { + s.append(typeParameter.getSignature()); + } + s.append(">;"); + signature = s.toString();//'P' + signature.substring(1); + return new UnresolvedType(signature, signatureErasure, typeParams); + } + } return new UnresolvedType(signature); } @@ -224,16 +281,18 @@ public class TypeFactory { private static UnresolvedType[] createTypeParams(String typeParameterSpecification) { String remainingToProcess = typeParameterSpecification; - List types = new ArrayList(); + List types = new ArrayList(); while (remainingToProcess.length() != 0) { int endOfSig = 0; int anglies = 0; + boolean hadAnglies = false; boolean sigFound = false; // OPTIMIZE can this be done better? for (endOfSig = 0; (endOfSig < remainingToProcess.length()) && !sigFound; endOfSig++) { char thisChar = remainingToProcess.charAt(endOfSig); switch (thisChar) { case '<': anglies++; + hadAnglies = true; break; case '>': anglies--; @@ -260,7 +319,11 @@ public class TypeFactory { } } } - types.add(createTypeFromSignature(remainingToProcess.substring(0, endOfSig))); + String forProcessing = remainingToProcess.substring(0, endOfSig); + if (hadAnglies && forProcessing.charAt(0) == 'L') { + forProcessing = "P" + forProcessing.substring(1); + } + types.add(createTypeFromSignature(forProcessing)); remainingToProcess = remainingToProcess.substring(endOfSig); } UnresolvedType[] typeParams = new UnresolvedType[types.size()]; diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java b/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java index 992e38548..1193eff17 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java @@ -19,66 +19,22 @@ 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.util.GenericSignature.ClassSignature; import org.aspectj.weaver.tools.Traceable; /** - * A UnresolvedType represents a type to the weaver. It has a basic signature that knows nothing about type variables, type - * parameters, etc.. UnresolvedTypes are resolved in some World (a repository of types). 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 (currently either BCEL or an EclipseSourceType, but in the future we probably need to support java.lang.reflect - * based delegates too). - * + * 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). + *

* Every UnresolvedType has a signature, the unique key for the type in the world. - * - * - * TypeXs are fully aware of their complete type information (there is no erasure in the UnresolvedType world). To achieve this, the - * signature of TypeXs combines the basic Java signature and the generic signature information into one complete signature. - * - * The format of a UnresolvedType signature is as follows: - * - * a simple (non-generic, non-parameterized) type has the as its signature the Java signature. e.g. Ljava/lang/String; - * - * a generic type has signature: TypeParamsOpt ClassSig SuperClassSig SuperIntfListOpt - * - * following the Generic signature grammar in the JVM spec., but with the addition of the ClassSignature (which is not in the - * generic signature). In addition type variable names are replaced by a simple number which represents their declaration order in - * the type declaration. - * - * e.g. public class Foo would have signature: <1:Ljava/lang/Number>Lorg.xyz.Foo;Ljava/lang/Object; - * - * A parameterized type is a distinct type in the world with its own signature following the grammar: - * - * TypeParamsOpt ClassSig; - * - * but with the L for the class sig replaced by "P". For example List has signature - * - * Pjava/util/List; - * - * and List in the following class : class Foo { List lt; } - * - * has signature: <1:>Pjava/util/List; - * - * A typex that represents a type variable has its own unique signature, following the grammar for a FormalTypeParameter in the JVM - * spec. - * - * A generic typex has its true signature and also an erasure signature. Both of these are keys pointing to the same UnresolvedType - * in the world. For example List has signature: - * - * <1:>Ljava/util/List;Ljava/lang/Object; - * - * and the erasure signature - * - * Ljava/util/List; - * - * Generics wildcards introduce their own special signatures for type parameters. The wildcard ? has signature * The wildcard ? - * extends Foo has signature +LFoo; The wildcard ? super Foo has signature -LFoo; */ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { - // common types referred to by the weaver + // 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;"); @@ -91,10 +47,10 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { 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 JAVA_LANG_CLASS = forSignature("Ljava/lang/Class;"); + 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 JAVA_LANG_STRING = forSignature("Ljava/lang/String;"); - public static final UnresolvedType JAVA_LANG_EXCEPTION = forSignature("Ljava/lang/Exception;"); + 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;"); @@ -106,18 +62,20 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { public static final UnresolvedType JOINPOINT_STATICPART = forSignature("Lorg/aspectj/lang/JoinPoint$StaticPart;"); public static final UnresolvedType JOINPOINT_ENCLOSINGSTATICPART = forSignature("Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;"); - // this doesn't belong here and will get moved to ResolvedType later in the refactoring + // 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 + // 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 SIGNATURE - see the comments above for how this is defined + * 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 signature; + protected String signatureErasure; /** * Calculated on first request - the package name (java.lang for type java.lang.String) @@ -129,12 +87,6 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { */ private String className; - /** - * 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; - /** * Iff isParameterized(), then these are the type parameters */ @@ -198,7 +150,7 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { } /** - * Equality is checked based on the underlying signature. {@link ResolvedType} objects' equals is by reference. + * Equality is checked based on the underlying signature. */ @Override public boolean equals(Object other) { @@ -237,7 +189,7 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { } } - // ---- Things we can do without a world + // 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. @@ -246,15 +198,6 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { return 1; } - 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()); - } - /** * NOTE: Use forSignature() if you can, it'll be cheaper ! Constructs a UnresolvedType for a java language type name. For * example: @@ -398,7 +341,7 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { * * * - * Types may equivalently be produced by this or by {@link #forName(String)}. + * Types may equivalently be produced by this or by {@link #forName(String)}. This method should not be passed P signatures. * *

* @@ -413,6 +356,7 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { * @return a type object represnting that JVM bytecode signature. */ public static UnresolvedType forSignature(String signature) { + assert !(signature.startsWith("L") && signature.indexOf("<") != -1); switch (signature.charAt(0)) { case 'B': return ResolvedType.BYTE; @@ -740,51 +684,49 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { } private static String nameToSignature(String name) { - if (name.equals("byte")) { - return "B"; - } - if (name.equals("char")) { - return "C"; - } - if (name.equals("double")) { - return "D"; - } - if (name.equals("float")) { - return "F"; - } - if (name.equals("int")) { - return "I"; - } - if (name.equals("long")) { - return "J"; - } - if (name.equals("short")) { - return "S"; - } - if (name.equals("boolean")) { - return "Z"; - } - if (name.equals("void")) { - return "V"; - } - if (name.equals("?")) { - return name; + int len = name.length(); + if (len < 8) { + if (name.equals("byte")) { + return "B"; + } + if (name.equals("char")) { + return "C"; + } + if (name.equals("double")) { + return "D"; + } + if (name.equals("float")) { + return "F"; + } + if (name.equals("int")) { + return "I"; + } + if (name.equals("long")) { + return "J"; + } + if (name.equals("short")) { + return "S"; + } + if (name.equals("boolean")) { + return "Z"; + } + if (name.equals("void")) { + return "V"; + } + if (name.equals("?")) { + return name; + } } if (name.endsWith("[]")) { return "[" + nameToSignature(name.substring(0, name.length() - 2)); } - if (name.length() != 0) { - // lots more tests could be made here... - + if (len != 0) { // check if someone is calling us with something that is a signature already - if (name.charAt(0) == '[') { - throw new BCException("Do not call nameToSignature with something that looks like a signature (descriptor): '" - + name + "'"); - } + assert name.charAt(0) != '['; if (name.indexOf("<") == -1) { - // not parameterised - return "L" + name.replace('.', '/') + ";"; + // not parameterized + return new StringBuilder("L").append(name.replace('.', '/')).append(';').toString(); } else { StringBuffer nameBuff = new StringBuffer(); int nestLevel = 0; @@ -835,40 +777,27 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { } } + /** + * 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 { - UnresolvedType ret = UnresolvedType.forSignature(sig); - return ret; + // 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 static void writeArray(UnresolvedType[] types, CompressingDataOutputStream s) throws IOException { - int len = types.length; - s.writeShort(len); - for (int i = 0; i < len; i++) { - types[i].write(s); - } - } - - 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 String getNameAsIdentifier() { return getName().replace('.', '_'); } @@ -883,42 +812,10 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { } } - public String getPackageName() { - if (packageName == null) { - String name = getName(); - if (name.indexOf("<") != -1) { - name = name.substring(0, name.indexOf("<")); - } - int index = name.lastIndexOf('.'); - if (index == -1) { - packageName = ""; - } else { - packageName = name.substring(0, index); - } - } - return packageName; - } - public UnresolvedType[] getTypeParameters() { return typeParameters == null ? UnresolvedType.NONE : typeParameters; } - /** - * Doesn't include the package - */ - public String getClassName() { - if (className == null) { - String name = getName(); - int index = name.lastIndexOf('.'); - if (index == -1) { - className = name; - } else { - className = name.substring(index + 1); - } - } - return className; - } - public TypeVariable[] getTypeVariables() { return typeVariables; } @@ -973,4 +870,70 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { public UnresolvedType parameterize(Map 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(); + 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(); + if (name.indexOf("<") != -1) { + name = name.substring(0, name.indexOf("<")); + } + int index = name.lastIndexOf('.'); + if (index == -1) { + packageName = ""; + } else { + packageName = name.substring(0, index); + } + } + return packageName; + } + + // TODO these move to a TypeUtils class + + 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()); + } } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java b/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java index 2dcbbd91a..5510c29d5 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java @@ -8,7 +8,6 @@ * ******************************************************************/ package org.aspectj.weaver; - /** * @author Adrian Colyer * @author Andy Clement @@ -23,13 +22,14 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen } public UnresolvedTypeVariableReferenceType(TypeVariable aTypeVariable) { - super(aTypeVariable.getFirstBound().getSignature()); + super("T" + aTypeVariable.getName() + ";", aTypeVariable.getFirstBound().getErasureSignature());//aTypeVariable.getFirstBound().getSignature()); this.typeVariable = aTypeVariable; } // only used when resolving circular refs... public void setTypeVariable(TypeVariable aTypeVariable) { this.signature = "T" + aTypeVariable.getName() + ";"; // aTypeVariable.getUpperBound().getSignature(); + this.signatureErasure = aTypeVariable.getFirstBound().getErasureSignature(); this.typeVariable = aTypeVariable; this.typeKind = TypeKind.TYPE_VARIABLE; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java index 8934a7512..56492c3f2 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java @@ -181,7 +181,7 @@ public class WildAnnotationTypePattern extends AnnotationTypePattern { } else { throw new RuntimeException("Not implemented for " + t); } - } else if (t.equals(ResolvedType.JAVA_LANG_STRING)) { + } else if (t.equals(ResolvedType.JL_STRING)) { // nothing to do, it will be OK } else { throw new RuntimeException("Compiler limitation: annotation value support not implemented for type " + t); diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/MatcherModuleTests.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/MatcherModuleTests.java index 5b646c5df..234e387de 100644 --- a/org.aspectj.matcher/testsrc/org/aspectj/weaver/MatcherModuleTests.java +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/MatcherModuleTests.java @@ -33,6 +33,7 @@ public class MatcherModuleTests extends TestCase { suite.addTestSuite(ReflectionWorldSpecificTest.class); suite.addTestSuite(ReflectionWorldBasicTest.class); suite.addTestSuite(ReflectionWorldPointcutExpressionTests.class); + suite.addTestSuite(TypeFactoryTests.class); suite.addTest(PatternsTests.suite()); return suite; } diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/TypeFactoryTests.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/TypeFactoryTests.java new file mode 100644 index 000000000..40fed411a --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/TypeFactoryTests.java @@ -0,0 +1,76 @@ +/* ******************************************************************* + * Copyright (c) 2010 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://eclipse.org/legal/epl-v10.html + * ******************************************************************/ +package org.aspectj.weaver; + +import junit.framework.TestCase; + +/** + * Check signature to type mapping. + * + * @author Andy Clement + */ +public class TypeFactoryTests extends TestCase { + + public void testParameterizedSig() { + UnresolvedType t = null; + t = UnresolvedType.forSignature("Pjava/util/List;"); + assertEquals("Ljava/util/List;", t.getErasureSignature()); + assertEquals("Ljava/lang/String;", t.getTypeParameters()[0].signature); + assertEquals("Ljava/lang/String;", t.getTypeParameters()[0].signatureErasure); + assertEquals("Pjava/util/List;", t.getSignature()); + + t = TypeFactory.createTypeFromSignature("Ljava/util/List;"); + assertEquals("Ljava/util/List;", t.getErasureSignature()); + assertEquals("Ljava/lang/String;", t.getTypeParameters()[0].signature); + assertEquals("Ljava/lang/String;", t.getTypeParameters()[0].signatureErasure); + assertEquals("Pjava/util/List;", t.getSignature()); + + t = UnresolvedType.forName("java.util.List"); + assertEquals("Ljava/util/List;", t.getErasureSignature()); + assertEquals("Ljava/lang/String;", t.getTypeParameters()[0].signature); + assertEquals("Ljava/lang/String;", t.getTypeParameters()[0].signatureErasure); + assertEquals("Pjava/util/List;", t.getSignature()); + + t = UnresolvedType.forSignature("Pjava/util/Map;>;"); + assertEquals("Ljava/util/Map;", t.getErasureSignature()); + assertEquals("TS;", t.getTypeParameters()[0].signature); + assertEquals("Ljava/lang/Object;", t.getTypeParameters()[0].signatureErasure); + assertEquals("S", ((UnresolvedTypeVariableReferenceType) t.getTypeParameters()[0]).getTypeVariable().getName()); + assertEquals("Pjava/util/Map;>;", t.getSignature()); + assertEquals("Pjava/util/List;", t.getTypeParameters()[1].signature); + assertEquals("Ljava/util/List;", t.getTypeParameters()[1].signatureErasure); + + t = UnresolvedType.forSignature("Pjava/util/List<+Pnl/ZoekFoo;>;>;"); + assertEquals("Ljava/util/List;", t.getErasureSignature()); + WildcardedUnresolvedType wut = (WildcardedUnresolvedType) t.getTypeParameters()[0]; + assertEquals("+Pnl/ZoekFoo;>;", wut.signature); + assertEquals("Lnl/ZoekFoo;", wut.signatureErasure); + assertTrue(wut.isExtends()); + assertEquals("Pnl/ZoekFoo;>;", wut.getUpperBound().signature); + assertEquals("Lnl/ZoekFoo;", wut.getUpperBound().signatureErasure); + UnresolvedTypeVariableReferenceType tvar = (UnresolvedTypeVariableReferenceType) wut.getUpperBound().getTypeParameters()[0]; + assertEquals("Pnl/ZoekFoo;>;", wut.getUpperBound().signature); + assertEquals("Lnl/ZoekFoo;", wut.getUpperBound().signatureErasure); + assertEquals("S", tvar.getTypeVariable().getName()); + UnresolvedType t2 = wut.getUpperBound().getTypeParameters()[1]; + assertEquals("Pnl/ZoekCopy;", t2.getSignature()); + assertEquals("Lnl/ZoekCopy;", t2.getErasureSignature()); + + // // t = UnresolvedType.forSignature("Ljava/util/List<+Lnl/ZoekFoo;>;>;"); + // t = TypeFactory.createTypeFromSignature("Ljava/util/List<+Lnl/ZoekFoo;>;>;"); + // System.out.println(t.getSignature()); + // + // t = TypeFactory.createTypeFromSignature("Ljava/util/List;>;"); + // System.out.println(t.getSignature()); // Pjava/util/List;>; + + // TODO should be able to cope with nested parameterizations + // Foo.Bar>> + // both components Foo and Bar of that are parameterized + } +} -- 2.39.5