@@ -169,9 +169,12 @@ public class InterTypeFieldDeclaration extends InterTypeDeclaration { | |||
} | |||
//System.err.println("type: " + binding.returnType + ", " + returnType); | |||
ResolvedMember sig = | |||
new ResolvedMember(Member.FIELD, world.fromBinding(onTypeBinding), | |||
ResolvedType declaringType = world.fromBinding(onTypeBinding).resolve(world.getWorld()); | |||
if (declaringType.isRawType() || declaringType.isParameterizedType()) { | |||
declaringType = declaringType.getGenericType(); | |||
} | |||
ResolvedMember sig = | |||
new ResolvedMember(Member.FIELD, declaringType, | |||
declaredModifiers, world.fromBinding(binding.returnType), | |||
new String(declaredSelector), UnresolvedType.NONE); | |||
@@ -367,6 +367,8 @@ public class AjLookupEnvironment extends LookupEnvironment { | |||
private void weaveInterTypeDeclarations(SourceTypeBinding sourceType, Collection typeMungers, | |||
Collection declareParents, Collection declareAnnotationOnTypes, boolean skipInners) { | |||
ResolvedType onType = factory.fromEclipse(sourceType); | |||
// AMC we shouldn't need this when generic sigs are fixed?? | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
WeaverStateInfo info = onType.getWeaverState(); | |||
if (info != null && !info.isOldStyle()) { |
@@ -34,6 +34,7 @@ import org.aspectj.weaver.ReferenceType; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.Shadow; | |||
import org.aspectj.weaver.TypeFactory; | |||
import org.aspectj.weaver.TypeVariable; | |||
import org.aspectj.weaver.TypeVariableReferenceType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
@@ -212,7 +213,11 @@ public class EclipseFactory { | |||
} | |||
} | |||
} | |||
return UnresolvedType.forParameterizedTypes(UnresolvedType.forName(getName(binding)), arguments); | |||
ResolvedType baseType = UnresolvedType.forName(getName(binding)).resolve(getWorld()); | |||
return TypeFactory.createParameterizedType( | |||
baseType, | |||
arguments, | |||
getWorld()); | |||
} | |||
// Convert the source type binding for a generic type into a generic UnresolvedType | |||
@@ -232,9 +237,9 @@ public class EclipseFactory { | |||
//TODO asc generics - temporary guard.... | |||
if (!(binding instanceof SourceTypeBinding)) | |||
throw new RuntimeException("Cant get the generic sig for "+binding.debugName()); | |||
return ResolvedType.forGenericType(getName(binding),tVars, | |||
return UnresolvedType.forGenericType(getName(binding),tVars, | |||
CharOperation.charToString(((SourceTypeBinding)binding).genericSignature())); | |||
} | |||
} | |||
return UnresolvedType.forName(getName(binding)); | |||
} | |||
@@ -254,6 +259,7 @@ public class EclipseFactory { | |||
superinterfaces[i] = fromBinding(aTypeVariableBinding.superInterfaces[i]); | |||
} | |||
TypeVariable tv = new TypeVariable(name,superclassType,superinterfaces); | |||
tv.resolve(world); | |||
ret.setTypeVariable(tv); | |||
typeVariableBindingsInProgress.remove(aTypeVariableBinding); | |||
return ret; | |||
@@ -343,9 +349,12 @@ public class EclipseFactory { | |||
public ResolvedMember makeResolvedMember(MethodBinding binding, TypeBinding declaringType) { | |||
//System.err.println("member for: " + binding + ", " + new String(binding.declaringClass.sourceName)); | |||
// AMC these next two lines shouldn't be needed once we sort out generic types properly in the world map | |||
ResolvedType realDeclaringType = world.resolve(fromBinding(declaringType)); | |||
if (realDeclaringType.isRawType()) realDeclaringType = realDeclaringType.getGenericType(); | |||
ResolvedMember ret = new ResolvedMember( | |||
binding.isConstructor() ? Member.CONSTRUCTOR : Member.METHOD, | |||
world.resolve(fromBinding(declaringType)), | |||
realDeclaringType, | |||
binding.modifiers, | |||
world.resolve(fromBinding(binding.returnType)), | |||
new String(binding.selector), | |||
@@ -359,9 +368,12 @@ public class EclipseFactory { | |||
} | |||
public ResolvedMember makeResolvedMember(FieldBinding binding, TypeBinding receiverType) { | |||
// AMC these next two lines shouldn't be needed once we sort out generic types properly in the world map | |||
ResolvedType realDeclaringType = world.resolve(fromBinding(receiverType)); | |||
if (realDeclaringType.isRawType()) realDeclaringType = realDeclaringType.getGenericType(); | |||
return new ResolvedMember( | |||
Member.FIELD, | |||
world.resolve(fromBinding(receiverType)), | |||
realDeclaringType, | |||
binding.modifiers, | |||
world.resolve(fromBinding(binding.type)), | |||
new String(binding.name), | |||
@@ -521,6 +533,7 @@ public class EclipseFactory { | |||
ReferenceType complexName = new ReferenceType(complexTx,world);//getWorld().lookupOrCreateName(complexTx); | |||
name.setGenericType(complexName); | |||
complexName.setDelegate(t); | |||
complexName.setSourceContext(t.getResolvedTypeX().getSourceContext()); | |||
} | |||
name.setDelegate(t); |
@@ -458,8 +458,7 @@ public class EclipseSourceType extends AbstractReferenceTypeDelegate { | |||
} | |||
public boolean isGeneric() { | |||
char[] sig = binding.genericSignature(); | |||
return (sig==null?false:sig[0]=='<'); | |||
return binding.isGenericType(); | |||
} | |||
public TypeVariable[] getTypeVariables() { |
@@ -53,6 +53,8 @@ public class EclipseTypeMunger extends ConcreteTypeMunger { | |||
munger.setSourceLocation(sourceLocation); | |||
} | |||
targetTypeX = munger.getSignature().getDeclaringType().resolve(world.getWorld()); | |||
// AMC, needed until generic and raw have distinct sigs... | |||
if (targetTypeX.isParameterizedType() || targetTypeX.isRawType()) targetTypeX = targetTypeX.getGenericType(); | |||
//targetBinding = (ReferenceBinding)world.makeTypeBinding(targetTypeX); | |||
} | |||
@@ -71,7 +73,9 @@ public class EclipseTypeMunger extends ConcreteTypeMunger { | |||
* i.e. adds Method|FieldBindings, plays with inheritance, ... | |||
*/ | |||
public boolean munge(SourceTypeBinding sourceType) { | |||
if (!world.fromEclipse(sourceType).equals(targetTypeX)) return false; //??? move this test elsewhere | |||
ResolvedType rt = world.fromEclipse(sourceType); | |||
if (rt.isRawType() || rt.isParameterizedType()) rt = rt.getGenericType(); | |||
if (!rt.equals(targetTypeX)) return false; //??? move this test elsewhere | |||
//System.out.println("munging: " + sourceType); | |||
// System.out.println("match: " + world.fromEclipse(sourceType) + | |||
// " with " + targetTypeX); |
@@ -178,7 +178,7 @@ public class GenericsTests extends XMLBasedAjcTestCase { | |||
public void testPR96220_GenericDecp() { | |||
runTest("generic decp - simple"); | |||
verifyClassSignature("Basic","Ljava/lang/Object;LJ<Ljava/lang/Double;>;LI<Ljava/lang/Double;>;"); | |||
verifyClassSignature("Basic","Ljava/lang/Object;PJ<Ljava/lang/Double;>;PI<Ljava/lang/Double;>;"); | |||
} | |||
// Both the existing type decl and the one adding via decp are parameterized |
@@ -694,9 +694,12 @@ public class AjcMemberMaker { | |||
} | |||
} | |||
public static Member interfaceConstructor(ResolvedType resolvedTypeX) { | |||
// AMC next two lines should not be needed when sig for generic type is changed | |||
ResolvedType declaringType = resolvedTypeX; | |||
if (declaringType.isRawType()) declaringType = declaringType.getGenericType(); | |||
return new ResolvedMember( | |||
Member.CONSTRUCTOR, | |||
resolvedTypeX, | |||
declaringType, | |||
Modifier.PUBLIC, | |||
"<init>", | |||
"()V"); |
@@ -150,7 +150,13 @@ public class CrosscuttingMembers { | |||
public void exposeType(UnresolvedType typeToExpose) { | |||
if (typeToExpose == ResolvedType.MISSING) return; | |||
if (typeToExpose.isParameterizedType() || typeToExpose.isRawType()) { | |||
if (typeToExpose instanceof ResolvedType) { | |||
typeToExpose = ((ResolvedType)typeToExpose).getGenericType(); | |||
} else { | |||
typeToExpose = UnresolvedType.forSignature(typeToExpose.getRawTypeSignature()); | |||
} | |||
} | |||
ResolvedMember member = new ResolvedMember( | |||
Member.STATIC_INITIALIZATION, typeToExpose, 0, ResolvedType.VOID, "", UnresolvedType.NONE); | |||
addTypeMunger(world.concreteTypeMunger( |
@@ -27,7 +27,7 @@ import org.aspectj.util.TypeSafeEnum; | |||
public class Member implements Comparable, AnnotatedElement { | |||
private final Kind kind; | |||
private final UnresolvedType declaringType; | |||
protected UnresolvedType declaringType; | |||
protected final int modifiers; // protected because ResolvedMember uses it | |||
private final UnresolvedType returnType; | |||
private final String name; | |||
@@ -154,7 +154,7 @@ public class Member implements Comparable, AnnotatedElement { | |||
if (c == ')') break; // break out when the hit the ')' | |||
int start = i; | |||
while (c == '[') c = sig.charAt(++i); | |||
if (c == 'L') { | |||
if (c == 'L' || c == 'P') { | |||
int nextSemicolon = sig.indexOf(';',start); | |||
int firstAngly = sig.indexOf('<',start); | |||
if (firstAngly == -1 || firstAngly>nextSemicolon) { | |||
@@ -389,9 +389,9 @@ public class Member implements Comparable, AnnotatedElement { | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(returnType); | |||
buf.append(returnType.getName()); | |||
buf.append(' '); | |||
buf.append(declaringType); | |||
buf.append(declaringType.getName()); | |||
buf.append('.'); | |||
buf.append(name); | |||
if (kind != FIELD) { | |||
@@ -400,7 +400,7 @@ public class Member implements Comparable, AnnotatedElement { | |||
buf.append(parameterTypes[0]); | |||
for (int i=1, len = parameterTypes.length; i < len; i++) { | |||
buf.append(", "); | |||
buf.append(parameterTypes[i]); | |||
buf.append(parameterTypes[i].getName()); | |||
} | |||
} | |||
buf.append(")"); |
@@ -47,6 +47,7 @@ public class NewFieldTypeMunger extends ResolvedTypeMunger { | |||
public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) { | |||
//??? might give a field where a method is expected | |||
ResolvedType onType = aspectType.getWorld().resolve(getSignature().getDeclaringType()); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
ResolvedMember ret = AjcMemberMaker.interFieldGetDispatcher(getSignature(), aspectType); | |||
if (ResolvedType.matches(ret, member)) return getSignature(); |
@@ -57,6 +57,23 @@ public class ReferenceType extends ResolvedType { | |||
public ReferenceType(String signature, World world) { | |||
super(signature, world); | |||
} | |||
/** | |||
* Constructor used when creating a parameterized type. | |||
*/ | |||
public ReferenceType( | |||
ResolvedType theGenericType, | |||
ResolvedType[] theParameters, | |||
World aWorld) { | |||
super(makeParameterizedSignature(theGenericType,theParameters), | |||
theGenericType.signatureErasure, | |||
aWorld); | |||
ReferenceType genericReferenceType = (ReferenceType) theGenericType; | |||
this.typeParameters = theParameters; | |||
this.genericType = genericReferenceType; | |||
this.typeKind = PARAMETERIZED; | |||
this.delegate = genericReferenceType.getDelegate(); | |||
} | |||
/** | |||
* Create a reference type for a generic type | |||
@@ -72,7 +89,7 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
public final boolean isGenericType() { | |||
return delegate.isGeneric(); | |||
return !isParameterizedType() && !isRawType() && delegate.isGeneric(); | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
@@ -164,11 +181,11 @@ public class ReferenceType extends ResolvedType { | |||
public ResolvedMember[] getDeclaredFields() { | |||
if (parameterizedFields != null) return parameterizedFields; | |||
if (isParameterizedType()) { | |||
if (isParameterizedType() || isRawType()) { | |||
ResolvedMember[] delegateFields = delegate.getDeclaredFields(); | |||
parameterizedFields = new ResolvedMember[delegateFields.length]; | |||
for (int i = 0; i < delegateFields.length; i++) { | |||
parameterizedFields[i] = delegateFields[i].parameterizedWith(getTypeParameters()); | |||
parameterizedFields[i] = delegateFields[i].parameterizedWith(getTypesForMemberParameterization(),this); | |||
} | |||
return parameterizedFields; | |||
} else { | |||
@@ -183,11 +200,11 @@ public class ReferenceType extends ResolvedType { | |||
*/ | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
if (parameterizedInterfaces != null) return parameterizedInterfaces; | |||
if (isParameterizedType()) { | |||
if (isParameterizedType() || isRawType()) { | |||
ResolvedType[] delegateInterfaces = delegate.getDeclaredInterfaces(); | |||
parameterizedInterfaces = new ResolvedType[delegateInterfaces.length]; | |||
for (int i = 0; i < delegateInterfaces.length; i++) { | |||
parameterizedInterfaces[i] = delegateInterfaces[i].parameterizedWith(getTypeParameters()); | |||
parameterizedInterfaces[i] = delegateInterfaces[i].parameterizedWith(getTypesForMemberParameterization()); | |||
} | |||
return parameterizedInterfaces; | |||
} else { | |||
@@ -197,11 +214,12 @@ public class ReferenceType extends ResolvedType { | |||
public ResolvedMember[] getDeclaredMethods() { | |||
if (parameterizedMethods != null) return parameterizedMethods; | |||
if (isParameterizedType()) { | |||
if (isParameterizedType() || isRawType()) { | |||
ResolvedMember[] delegateMethods = delegate.getDeclaredMethods(); | |||
UnresolvedType[] parameters = getTypesForMemberParameterization(); | |||
parameterizedMethods = new ResolvedMember[delegateMethods.length]; | |||
for (int i = 0; i < delegateMethods.length; i++) { | |||
parameterizedMethods[i] = delegateMethods[i].parameterizedWith(getTypeParameters()); | |||
parameterizedMethods[i] = delegateMethods[i].parameterizedWith(parameters,this); | |||
} | |||
return parameterizedMethods; | |||
} else { | |||
@@ -211,17 +229,32 @@ public class ReferenceType extends ResolvedType { | |||
public ResolvedMember[] getDeclaredPointcuts() { | |||
if (parameterizedPointcuts != null) return parameterizedPointcuts; | |||
if (isParameterizedType()) { | |||
if (isParameterizedType() || isRawType()) { | |||
ResolvedMember[] delegatePointcuts = delegate.getDeclaredPointcuts(); | |||
parameterizedPointcuts = new ResolvedMember[delegatePointcuts.length]; | |||
for (int i = 0; i < delegatePointcuts.length; i++) { | |||
parameterizedPointcuts[i] = delegatePointcuts[i].parameterizedWith(getTypeParameters()); | |||
parameterizedPointcuts[i] = delegatePointcuts[i].parameterizedWith(getTypesForMemberParameterization(),this); | |||
} | |||
return parameterizedPointcuts; | |||
} else { | |||
return delegate.getDeclaredPointcuts(); | |||
} | |||
} | |||
private UnresolvedType[] getTypesForMemberParameterization() { | |||
UnresolvedType[] parameters = null; | |||
if (isParameterizedType()) { | |||
parameters = getTypeParameters(); | |||
} else if (isRawType()){ | |||
// raw type, use upper bounds of type variables on generic type | |||
TypeVariable[] tvs = getGenericType().getTypeVariables(); | |||
parameters = new UnresolvedType[tvs.length]; | |||
for (int i = 0; i < tvs.length; i++) { | |||
parameters[i] = tvs[i].getUpperBound(); | |||
} | |||
} | |||
return parameters; | |||
} | |||
public TypeVariable[] getTypeVariables() { | |||
return delegate.getTypeVariables(); | |||
@@ -293,7 +326,7 @@ public class ReferenceType extends ResolvedType { | |||
// makes sense if someone is specifying that it has a generic form | |||
if ( typeKind == UnresolvedType.SIMPLE ) { | |||
typeKind = UnresolvedType.RAW; | |||
rawTypeSignature = signature; | |||
signatureErasure = signature; | |||
} | |||
} | |||
@@ -301,4 +334,25 @@ public class ReferenceType extends ResolvedType { | |||
return genericType; | |||
} | |||
/** | |||
* a parameterized signature starts with a "P" in place of the "L", | |||
* see the comment on signatures in UnresolvedType. | |||
* @param aGenericType | |||
* @param someParameters | |||
* @return | |||
*/ | |||
private static String makeParameterizedSignature(ResolvedType aGenericType, ResolvedType[] someParameters) { | |||
String rawSignature = aGenericType.getRawTypeSignature(); | |||
String prefix = PARAMETERIZED_TYPE_IDENTIFIER + rawSignature.substring(1,rawSignature.length()-1); | |||
StringBuffer ret = new StringBuffer(); | |||
ret.append(prefix); | |||
ret.append("<"); | |||
for (int i = 0; i < someParameters.length; i++) { | |||
ret.append(someParameters[i].getSignature()); | |||
} | |||
ret.append(">;"); | |||
return ret.toString(); | |||
} | |||
} |
@@ -45,6 +45,7 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle | |||
// the case. It is up to the caller to work out where that is! | |||
// Once determined the caller may choose to stash the annotations in this member... | |||
private boolean isAnnotatedElsewhere = false; // this field is not serialized. | |||
private boolean isAjSynthetic = true; | |||
// these three fields hold the source location of this member | |||
@@ -90,6 +91,7 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle | |||
{ | |||
this(kind, declaringType, modifiers, returnType, name, parameterTypes,checkedExceptions); | |||
this.backingGenericMember = backingGenericMember; | |||
this.isAjSynthetic = backingGenericMember.isAjSynthetic(); | |||
} | |||
public ResolvedMember( | |||
@@ -130,7 +132,7 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle | |||
// ??? true or false? | |||
public boolean isAjSynthetic() { | |||
return true; | |||
return isAjSynthetic; | |||
} | |||
public boolean hasAnnotations() { | |||
@@ -232,6 +234,8 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle | |||
} | |||
annotationTypes = r; | |||
} | |||
declaringType = declaringType.resolve(world); | |||
if (declaringType.isRawType()) declaringType = ((ReferenceType)declaringType).getGenericType(); | |||
return this; | |||
} | |||
@@ -333,7 +337,7 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle | |||
// return a resolved member in which all type variables in the signature of this | |||
// member have been replaced with the given bindings. | |||
public ResolvedMember parameterizedWith(UnresolvedType[] typeParameters) { | |||
public ResolvedMember parameterizedWith(UnresolvedType[] typeParameters,ResolvedType newDeclaringType) { | |||
if (!this.getDeclaringType().isGenericType()) { | |||
throw new IllegalStateException("Can't ask to parameterize a member of a non-generic type"); | |||
} | |||
@@ -353,7 +357,7 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle | |||
} | |||
return new ResolvedMember( | |||
getKind(), | |||
getDeclaringType(), | |||
newDeclaringType, | |||
getModifiers(), | |||
parameterizedReturnType, | |||
getName(), |
@@ -33,28 +33,19 @@ import org.aspectj.weaver.patterns.PerClause; | |||
public abstract class ResolvedType extends UnresolvedType implements AnnotatedElement { | |||
private static final ResolvedType[] EMPTY_RESOLVED_TYPE_ARRAY = new ResolvedType[0]; | |||
public static final String PARAMETERIZED_TYPE_IDENTIFIER = "P"; | |||
protected World world; | |||
// Factory methods | |||
public static UnresolvedType forGenericType(String name,TypeVariable[] tvbs,String genericSig) { | |||
// TODO asc generics needs a declared sig | |||
UnresolvedType ret = UnresolvedType.forName(name); | |||
ret.typeKind=GENERIC; | |||
ret.typeVariables = tvbs; | |||
ret.rawTypeSignature = ret.signature; | |||
ret.genericSignature = genericSig; | |||
return ret; // this cast will fail at runtime, temp refactoring issue | |||
} | |||
protected ResolvedType(String signature, World world) { | |||
super(signature); | |||
this.world = world; | |||
} | |||
protected ResolvedType(String signature, String signatureErasure, World world) { | |||
super(signature,signatureErasure); | |||
this.world = world; | |||
} | |||
// ---- things that don't require a world | |||
@@ -135,9 +126,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl | |||
public ResolvedType getResolvedComponentType() { | |||
return null; | |||
} | |||
public ResolvedType resolve(World world) { | |||
return this; | |||
} | |||
public World getWorld() { | |||
return world; | |||
} | |||
@@ -1307,6 +1296,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl | |||
} | |||
public void clearInterTypeMungers() { | |||
if (isRawType()) getGenericType().clearInterTypeMungers(); | |||
interTypeMungers = new ArrayList(); | |||
} | |||
@@ -48,6 +48,11 @@ public abstract class ResolvedTypeMunger { | |||
public ResolvedTypeMunger(Kind kind, ResolvedMember signature) { | |||
this.kind = kind; | |||
this.signature = signature; | |||
UnresolvedType declaringType = signature != null ? signature.getDeclaringType() : null; | |||
if (declaringType != null) { | |||
if (declaringType.isRawType()) throw new IllegalStateException("Use generic type, not raw type"); | |||
if (declaringType.isParameterizedType()) throw new IllegalStateException("Use generic type, not parameterized type"); | |||
} | |||
} | |||
public void setSourceLocation(ISourceLocation isl) { | |||
@@ -62,6 +67,7 @@ public abstract class ResolvedTypeMunger { | |||
// fromType is guaranteed to be a non-abstract aspect | |||
public ConcreteTypeMunger concretize(World world, ResolvedType aspectType) { | |||
ConcreteTypeMunger munger = world.concreteTypeMunger(this, aspectType); | |||
return munger; | |||
} | |||
@@ -69,6 +75,7 @@ public abstract class ResolvedTypeMunger { | |||
public boolean matches(ResolvedType matchType, ResolvedType aspectType) { | |||
ResolvedType onType = matchType.getWorld().resolve(signature.getDeclaringType()); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
//System.err.println("matching: " + this + " to " + matchType + " onType = " + onType); | |||
if (matchType.equals(onType)) { | |||
if (!onType.isExposedToWeaver()) { |
@@ -0,0 +1,97 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 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://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
/** | |||
* @author colyer | |||
* | |||
*/ | |||
public class TypeFactory { | |||
/** | |||
* Create a parameterized version of a generic type. | |||
* @param aGenericType | |||
* @param someTypeParameters note, in the case of an inner type of a parameterized type, | |||
* this parameter may legitimately be null | |||
* @param inAWorld | |||
* @return | |||
*/ | |||
public static ReferenceType createParameterizedType( | |||
ResolvedType aBaseType, | |||
UnresolvedType[] someTypeParameters, | |||
World inAWorld | |||
) { | |||
ResolvedType baseType = aBaseType; | |||
if (!aBaseType.isGenericType()) { | |||
// try and find the generic type... | |||
if (someTypeParameters != null) { | |||
if (!aBaseType.isRawType()) throw new IllegalStateException("Expecting raw type"); | |||
baseType = baseType.getGenericType(); | |||
if (baseType == null) throw new IllegalStateException("Raw type does not have generic type set"); | |||
} // else if someTypeParameters is null, then the base type is allowed to be non-generic, it's an inner | |||
} | |||
ResolvedType[] resolvedParameters = inAWorld.resolve(someTypeParameters); | |||
ReferenceType pType = new ReferenceType(baseType,resolvedParameters,inAWorld); | |||
pType.setSourceContext(aBaseType.getSourceContext()); | |||
return (ReferenceType) pType.resolve(inAWorld); | |||
} | |||
/** | |||
* Used by UnresolvedType.read, creates a type from a full signature. | |||
* @param signature | |||
* @return | |||
*/ | |||
public static UnresolvedType createTypeFromSignature(String signature) { | |||
if (signature.equals(ResolvedType.MISSING_NAME)) return ResolvedType.MISSING; | |||
if (signature.startsWith(ResolvedType.PARAMETERIZED_TYPE_IDENTIFIER)) { | |||
// parameterized type, calculate signature erasure and type parameters | |||
int startOfParams = signature.indexOf('<'); | |||
int endOfParams = signature.lastIndexOf('>'); | |||
String signatureErasure = "L" + signature.substring(1,startOfParams) + ";"; | |||
UnresolvedType[] typeParams = createTypeParams(signature.substring(startOfParams +1, endOfParams)); | |||
return new UnresolvedType(signature,signatureErasure,typeParams); | |||
} else { | |||
return new UnresolvedType(signature); | |||
} | |||
} | |||
private static UnresolvedType[] createTypeParams(String typeParameterSpecification) { | |||
String remainingToProcess = typeParameterSpecification; | |||
List types = new ArrayList(); | |||
while(!remainingToProcess.equals("")) { | |||
int endOfSig = 0; | |||
int anglies = 0; | |||
boolean sigFound = false; | |||
for (endOfSig = 0; (endOfSig < remainingToProcess.length()) && !sigFound; endOfSig++) { | |||
char thisChar = remainingToProcess.charAt(endOfSig); | |||
switch(thisChar) { | |||
case '<' : anglies++; break; | |||
case '>' : anglies--; break; | |||
case ';' : | |||
if (anglies == 0) { | |||
sigFound = true; | |||
break; | |||
} | |||
} | |||
} | |||
types.add(createTypeFromSignature(remainingToProcess.substring(0,endOfSig))); | |||
remainingToProcess = remainingToProcess.substring(endOfSig); | |||
} | |||
UnresolvedType[] typeParams = new UnresolvedType[types.size()]; | |||
types.toArray(typeParams); | |||
return typeParams; | |||
} | |||
} |
@@ -117,7 +117,7 @@ public class UnresolvedType { | |||
public static final UnresolvedType AT_TARGET = forSignature("Ljava/lang/annotation/Target;"); | |||
// this doesn't belong here and will get moved to ResolvedType later in the refactoring | |||
public static final String MISSING_NAME = "<missing>"; | |||
public static final String MISSING_NAME = "@missing@"; | |||
// constants indicating the base kind of the type | |||
@@ -132,6 +132,18 @@ public class UnresolvedType { | |||
public final static int TYPE_VARIABLE = 5; // a type variable | |||
public final static int WILDCARD = 6; // a generic wildcard type | |||
public String getKind() { | |||
switch (typeKind) { | |||
case PRIMITIVE: return "PRIMITIVE"; | |||
case SIMPLE: return "SIMPLE"; | |||
case RAW: return "RAW"; | |||
case GENERIC: return "GENERIC"; | |||
case PARAMETERIZED: return "PARAMETERIZED"; | |||
case TYPE_VARIABLE: return "TYPE_VARIABLE"; | |||
case WILDCARD: return "WILDCARD"; | |||
default: return null; | |||
} | |||
} | |||
protected int typeKind = SIMPLE; // what kind of type am I? | |||
/** | |||
@@ -144,7 +156,7 @@ public class UnresolvedType { | |||
* with all supertype, superinterface, type variable, and parameter information | |||
* removed. | |||
*/ | |||
protected String signatureErasure; | |||
protected String signatureErasure; | |||
/** | |||
* Iff isParameterized(), then these are the type parameters | |||
@@ -225,13 +237,7 @@ public class UnresolvedType { | |||
// ----------------------------- | |||
// old stuff... | |||
/** | |||
* For parameterized types, this is the signature of the raw type (e.g. Ljava/util/List; ) | |||
* For non-parameterized types, it is null. | |||
*/ | |||
protected String rawTypeSignature; | |||
// For a generic type, this is the 'declared' signature | |||
// e.g. for Enum: <E:Ljava/lang/Enum<TE;>;>Ljava/lang/Object;Ljava/lang/Comparable<TE;>;Ljava/io/Serializable; | |||
// note: it doesnt include the name of the type! | |||
@@ -242,82 +248,24 @@ public class UnresolvedType { | |||
*/ | |||
protected UnresolvedType(String signature) { | |||
super(); | |||
// if (signature.indexOf('<') != -1) throw new IllegalStateException("Shouldn't be calling simple signature based type constructor with generic info in signature"); | |||
this.signature = signature; | |||
// avoid treating '<missing>' as a parameterized type ... | |||
if (signature.charAt(0)!='<' && signature.indexOf("<")!=-1 && !signature.startsWith("<missing>")) { | |||
// anglies alert - parameterized type | |||
processSignature(signature); | |||
} | |||
this.signatureErasure = signature; | |||
} | |||
/** | |||
* Called when processing a parameterized type, sets the raw type for this typeX and calls a subroutine | |||
* to handle sorting out the type parameters for the type. | |||
*/ | |||
private void processSignature(String sig) { | |||
// determine the raw type | |||
//TODO asc generics tidy this bit up? | |||
boolean skip=false; | |||
if (sig.charAt(0)=='+') {/*isExtends=true;*/skip=true;} | |||
if (sig.charAt(0)=='-') {/*isSuper=true;*/skip=true;} | |||
int parameterTypesStart = signature.indexOf("<"); | |||
int parameterTypesEnd = signature.lastIndexOf(">"); | |||
StringBuffer rawTypeSb = new StringBuffer(); | |||
String p = signature.substring(0,parameterTypesStart); | |||
if (skip) p = p.substring(1); | |||
rawTypeSb.append(p).append(";"); | |||
rawTypeSignature = rawTypeSb.toString(); | |||
typeParameters = processParameterization(signature,parameterTypesStart+1,parameterTypesEnd-1); | |||
typeKind = PARAMETERIZED; | |||
} | |||
/** | |||
* For a parameterized signature, e.g. <Ljava/lang/String;Ljava/util/List<Ljava/lang/String;>;>" | |||
* this routine will return an appropriate array of TypeXs representing the top level type parameters. | |||
* Where type parameters are themselves parameterized, we recurse. | |||
*/ | |||
public UnresolvedType[] processParameterization(String paramSig,int startpos,int endpos) { | |||
boolean debug = false; | |||
if (debug) { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(paramSig).append("\n"); | |||
for(int i=0;i<paramSig.length();i++) { | |||
if (i==startpos || i==endpos) sb.append("^"); | |||
else if (i<startpos || i>endpos) sb.append(" "); | |||
else sb.append("-"); | |||
} | |||
sb.append("\n"); | |||
System.err.println(sb.toString()); | |||
} | |||
int posn = startpos; | |||
List parameterTypes = new ArrayList(); | |||
while (posn<endpos && paramSig.charAt(posn)!='>') { | |||
int nextAngly = paramSig.indexOf("<",posn); | |||
int nextSemi = paramSig.indexOf(";",posn); | |||
if (nextAngly==-1 || nextSemi<nextAngly) { // the next type is not parameterized | |||
// simple type | |||
parameterTypes.add(UnresolvedType.forSignature(paramSig.substring(posn,nextSemi+1))); | |||
posn=nextSemi+1; // jump to the next type | |||
} else if (nextAngly!=-1 && nextSemi>nextAngly) { // parameterized type, e.g. Ljava/util/Set<Ljava/util/String;> | |||
int count=1; | |||
int pos=nextAngly+1; | |||
for (;count>0;pos++){ | |||
switch (paramSig.charAt(pos)) { | |||
case '<':count++;break; | |||
case '>':count--;break; | |||
default: | |||
} | |||
} | |||
String sub = paramSig.substring(posn,pos+1); | |||
parameterTypes.add(UnresolvedType.forSignature(sub)); | |||
posn=pos+1; | |||
} else { | |||
throw new BCException("What the hell do i do with this? ["+paramSig.substring(posn)+"]"); | |||
} | |||
} | |||
return (UnresolvedType[])parameterTypes.toArray(new UnresolvedType[]{}); | |||
} | |||
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 = PARAMETERIZED; | |||
} | |||
// ---- Things we can do without a world | |||
/** | |||
@@ -373,9 +321,19 @@ public class UnresolvedType { | |||
return ret; | |||
} | |||
public static UnresolvedType forGenericTypeSignature(String nameSig,String declaredGenericSig) { | |||
UnresolvedType ret = UnresolvedType.forSignature(nameSig); | |||
public static UnresolvedType forGenericType(String name,TypeVariable[] tvbs,String genericSig) { | |||
// TODO asc generics needs a declared sig | |||
String sig = nameToSignature(name); | |||
UnresolvedType ret = UnresolvedType.forSignature(sig); | |||
ret.typeKind=GENERIC; | |||
ret.typeVariables = tvbs; | |||
ret.signatureErasure = sig; | |||
ret.genericSignature = genericSig; | |||
return ret; | |||
} | |||
public static UnresolvedType forGenericTypeSignature(String sig,String declaredGenericSig) { | |||
UnresolvedType ret = UnresolvedType.forSignature(sig); | |||
ret.typeKind=GENERIC; | |||
ClassSignature csig = new GenericSignatureParser().parseAsClassSignature(declaredGenericSig); | |||
@@ -387,46 +345,12 @@ public class UnresolvedType { | |||
Signature.ClassTypeSignature cts = (Signature.ClassTypeSignature)parameter.classBound; | |||
ret.typeVariables[i]=new TypeVariable(ftps[i].identifier,UnresolvedType.forSignature(cts.outerType.identifier+";")); | |||
} | |||
ret.rawTypeSignature = ret.signature; | |||
ret.signature = ret.rawTypeSignature; | |||
ret.signatureErasure = sig; | |||
ret.signature = ret.signatureErasure; | |||
ret.genericSignature=declaredGenericSig; | |||
return ret; | |||
} | |||
/** | |||
* Makes a parameterized type with the given name | |||
* and parameterized type names. | |||
*/ | |||
public static UnresolvedType forParameterizedTypeNames(String name, String[] paramTypeNames) { | |||
UnresolvedType[] paramTypes = null; | |||
if (paramTypeNames!=null) { | |||
paramTypes = new UnresolvedType[paramTypeNames.length]; | |||
for (int i = 0; i < paramTypeNames.length; i++) { | |||
paramTypes[i] = UnresolvedType.forName(paramTypeNames[i]); | |||
} | |||
} | |||
return UnresolvedType.forParameterizedTypes(UnresolvedType.forName(name), paramTypes); | |||
} | |||
public static UnresolvedType forParameterizedTypes(UnresolvedType rawType, UnresolvedType[] paramTypes) { | |||
UnresolvedType ret = rawType; | |||
ret.typeKind=PARAMETERIZED; | |||
ret.typeParameters = paramTypes; | |||
ret.rawTypeSignature = ret.signature; | |||
// sig for e.g. List<String> is Ljava/util/List<Ljava/lang/String;>; | |||
if (ret.typeParameters!=null) { | |||
StringBuffer sigAddition = new StringBuffer(); | |||
sigAddition.append("<"); | |||
for (int i = 0; i < ret.typeParameters.length; i++) { | |||
sigAddition.append(ret.typeParameters[i].signature); | |||
} | |||
sigAddition.append(">"); | |||
sigAddition.append(";"); | |||
ret.signature = ret.signature.substring(0,ret.signature.length()-1) + sigAddition.toString(); | |||
} | |||
return ret; | |||
} | |||
public static UnresolvedType forRawTypeNames(String name) { | |||
UnresolvedType ret = UnresolvedType.forName(name); | |||
ret.typeKind = RAW; | |||
@@ -488,11 +412,12 @@ public class UnresolvedType { | |||
case 'F': return ResolvedType.FLOAT; | |||
case 'I': return ResolvedType.INT; | |||
case 'J': return ResolvedType.LONG; | |||
case 'L': return new UnresolvedType(signature); | |||
case 'L': return TypeFactory.createTypeFromSignature(signature); | |||
case 'P': return TypeFactory.createTypeFromSignature(signature); | |||
case 'S': return ResolvedType.SHORT; | |||
case 'V': return ResolvedType.VOID; | |||
case 'Z': return ResolvedType.BOOLEAN; | |||
case '[': return new UnresolvedType(signature); | |||
case '[': return TypeFactory.createTypeFromSignature(signature); | |||
case '+': return new UnresolvedType(signature); | |||
case '-' : return new UnresolvedType(signature); | |||
case '?' : return GenericsWildcardTypeX.GENERIC_WILDCARD; | |||
@@ -538,7 +463,7 @@ public class UnresolvedType { | |||
} | |||
public String getRawName() { | |||
return signatureToName((rawTypeSignature==null?signature:rawTypeSignature)); | |||
return signatureToName((signatureErasure==null?signature:signatureErasure)); | |||
} | |||
public String getBaseName() { | |||
@@ -595,8 +520,8 @@ public class UnresolvedType { | |||
* For parameterized types, return the signature for the raw type | |||
*/ | |||
public String getRawTypeSignature() { | |||
if (rawTypeSignature==null) return signature; | |||
return rawTypeSignature; | |||
if (signatureErasure==null) return signature; | |||
return signatureErasure; | |||
} | |||
public UnresolvedType getRawType() { | |||
@@ -642,7 +567,7 @@ public class UnresolvedType { | |||
* Returns a java language string representation of this type. | |||
*/ | |||
public String toString() { | |||
return getName(); | |||
return getName(); // + " - " + getKind(); | |||
} | |||
// ---- requires worlds | |||
@@ -669,59 +594,36 @@ public class UnresolvedType { | |||
case 'J': return "long"; | |||
case 'L': | |||
String name = signature.substring(1, signature.length() - 1).replace('/', '.'); | |||
if (name.indexOf("<") == -1) return name; | |||
return name; | |||
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;>;>; | |||
StringBuffer nameBuff = new StringBuffer(); | |||
boolean justSeenLeftArrowChar = false; | |||
boolean justSeenTypeParameter = false; | |||
boolean justSeenSemiColon= false; | |||
int paramNestLevel = 0; | |||
for (int i = 0 ; i < name.length(); i++) { | |||
char c = name.charAt(i); | |||
for (int i = 1 ; i < signature.length(); i++) { | |||
char c = signature.charAt(i); | |||
switch (c) { | |||
case '<' : | |||
justSeenLeftArrowChar = true; | |||
case '/' : nameBuff.append('.'); break; | |||
case '<' : | |||
nameBuff.append("<"); | |||
paramNestLevel++; | |||
nameBuff.append(c); | |||
break; | |||
case ';' : | |||
justSeenSemiColon = true; | |||
break; | |||
case '>' : | |||
paramNestLevel--; | |||
nameBuff.append(c); | |||
break; | |||
case 'L' : | |||
if (justSeenLeftArrowChar) { | |||
justSeenLeftArrowChar = false; | |||
break; | |||
} | |||
if (justSeenSemiColon) { | |||
nameBuff.append(","); | |||
} else { | |||
nameBuff.append("L"); | |||
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 'T': | |||
if (justSeenLeftArrowChar) { | |||
justSeenLeftArrowChar = false; | |||
justSeenTypeParameter = true; | |||
break; | |||
} | |||
if (justSeenSemiColon) { | |||
nameBuff.append(","); | |||
} else { | |||
nameBuff.append("T"); | |||
} | |||
justSeenTypeParameter = true; | |||
// type parameter | |||
break; | |||
case ';' : break; | |||
default: | |||
justSeenSemiColon = false; | |||
justSeenTypeParameter = false; | |||
justSeenLeftArrowChar = false; | |||
nameBuff.append(c); | |||
} | |||
} | |||
@@ -764,14 +666,34 @@ public class UnresolvedType { | |||
return "L" + name.replace('.', '/') + ";"; | |||
} else { | |||
StringBuffer nameBuff = new StringBuffer(); | |||
nameBuff.append("L"); | |||
int nestLevel = 0; | |||
nameBuff.append("P"); | |||
for (int i = 0; i < name.length(); i++) { | |||
char c = name.charAt(i); | |||
switch (c) { | |||
case '.' : nameBuff.append('/'); break; | |||
case '<' : nameBuff.append("<L"); break; | |||
case '>' : nameBuff.append(";>"); break; | |||
case ',' : nameBuff.append(";L"); break; | |||
case '<' : | |||
nameBuff.append("<"); | |||
nestLevel++; | |||
StringBuffer innerBuff = new StringBuffer(); | |||
while(nestLevel > 0) { | |||
c = name.charAt(++i); | |||
if (c == '<') nestLevel++; | |||
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); | |||
} | |||
} | |||
@@ -861,32 +783,6 @@ public class UnresolvedType { | |||
} | |||
public static UnresolvedType[] getInterfacesFromSignature(String sig) { | |||
// there is a declared signature - use it to work out the interfaces, rather than the stuff in the class file... | |||
ClassSignature cSig = new GenericSignatureParser().parseAsClassSignature(sig); | |||
Signature.ClassTypeSignature[] declaredInterfaces = cSig.superInterfaceSignatures; | |||
UnresolvedType[] retVal = new UnresolvedType[declaredInterfaces.length]; | |||
for (int i = 0; i < declaredInterfaces.length; i++) { | |||
Signature.ClassTypeSignature signature = declaredInterfaces[i]; | |||
retVal[i] = convertFromClassSignatureToTypeX(signature); | |||
} | |||
return retVal; | |||
} | |||
private static UnresolvedType convertFromClassSignatureToTypeX(Signature.ClassTypeSignature signature) { | |||
return new UnresolvedType(signature.classSignature); | |||
} | |||
public String getKind() { | |||
switch (typeKind) { | |||
case 0: return "SIMPLE"; | |||
case 1: return "RAW"; | |||
case 2: return "GENERIC"; | |||
case 3: return "PARAMETERIZED"; | |||
default: return null; | |||
} | |||
} | |||
} | |||
@@ -37,6 +37,7 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType { | |||
} | |||
public ResolvedType resolve(World world) { | |||
if (typeVariable == null) return ResolvedType.MISSING; | |||
typeVariable.resolve(world); | |||
return new TypeVariableReferenceType(typeVariable,world); | |||
} |
@@ -80,6 +80,7 @@ public abstract class World implements Dump.INode { | |||
} | |||
public ResolvedType[] resolve(UnresolvedType[] types) { | |||
if (types == null) return new ResolvedType[0]; | |||
int len = types.length; | |||
ResolvedType[] ret = new ResolvedType[len]; | |||
for (int i=0; i<len; i++) { | |||
@@ -113,7 +114,12 @@ public abstract class World implements Dump.INode { | |||
// if we already have an rtx, don't re-resolve it | |||
public ResolvedType resolve(ResolvedType ty) { | |||
return ty; | |||
ResolvedType resolved = typeMap.get(ty.getSignature()); | |||
if (resolved == null) { | |||
typeMap.put(ty.getSignature(), ty); | |||
resolved = ty; | |||
} | |||
return resolved; | |||
} | |||
public ResolvedType getCoreType(UnresolvedType tx) { | |||
@@ -158,6 +164,7 @@ public abstract class World implements Dump.INode { | |||
public ResolvedType resolve(UnresolvedType ty, boolean allowMissing) { | |||
if (ty instanceof ResolvedType) { | |||
ResolvedType rty = (ResolvedType) ty; | |||
rty = resolve(rty); | |||
rty.world = this; | |||
return rty; | |||
} | |||
@@ -212,9 +219,8 @@ public abstract class World implements Dump.INode { | |||
protected final ResolvedType resolveObjectType(UnresolvedType ty) { | |||
if (ty.isParameterizedType()) { | |||
ReferenceType genericType = (ReferenceType)resolveTheGenericType(ty,false); | |||
ReferenceType parameterizedType = new ReferenceType(ty.getSignature(),this); | |||
parameterizedType.setGenericType(genericType); | |||
parameterizedType.setDelegate(genericType.getDelegate()); // move into setgenerictype | |||
ReferenceType parameterizedType = | |||
TypeFactory.createParameterizedType(genericType, ty.typeParameters, this); | |||
return parameterizedType; | |||
} else if (ty.isGenericType()) { | |||
ReferenceType genericType = (ReferenceType)resolveTheGenericType(ty,false); | |||
@@ -564,6 +570,10 @@ public abstract class World implements Dump.INode { | |||
return ret; | |||
} | |||
public ReferenceType lookupBySignature(String signature) { | |||
return (ReferenceType) typeMap.get(signature); | |||
} | |||
// public void clearUnexposed() { | |||
// List toRemove = new ArrayList(); |
@@ -230,6 +230,8 @@ class BcelClassWeaver implements IClassWeaver { | |||
public void addInitializer(ConcreteTypeMunger cm) { | |||
NewFieldTypeMunger m = (NewFieldTypeMunger) cm.getMunger(); | |||
ResolvedType onType = m.getSignature().getDeclaringType().resolve(world); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
if (m.getSignature().isStatic()) { | |||
addedClassInitializers.add(cm); | |||
} else { |
@@ -22,6 +22,7 @@ import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.ReferenceType; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.TypeFactory; | |||
import org.aspectj.weaver.TypeVariable; | |||
import org.aspectj.weaver.TypeVariableReferenceType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
@@ -72,11 +73,21 @@ public class BcelGenericSignatureToTypeXConverter { | |||
if (innerType.typeArguments.length > 0) { | |||
// we have to create a parameterized type | |||
// type arguments may be array types, class types, or typevariable types | |||
UnresolvedType[] typeArgumentTypes = new UnresolvedType[innerType.typeArguments.length]; | |||
ResolvedType[] typeArgumentTypes = new ResolvedType[innerType.typeArguments.length]; | |||
for (int i = 0; i < typeArgumentTypes.length; i++) { | |||
typeArgumentTypes[i] = typeArgument2TypeX(innerType.typeArguments[i],typeParams,world,inProgressTypeVariableResolutions); | |||
} | |||
return world.resolve(UnresolvedType.forParameterizedTypes(UnresolvedType.forSignature(sig.toString()), typeArgumentTypes)); | |||
ResolvedType theBaseType = UnresolvedType.forSignature(sig.toString()).resolve(world); | |||
return | |||
TypeFactory.createParameterizedType( | |||
theBaseType, | |||
typeArgumentTypes, | |||
world); | |||
// world.resolve(UnresolvedType.forParameterizedTypes( | |||
// UnresolvedType.forSignature(sig.toString()).resolve(world), | |||
// typeArgumentTypes)); | |||
} else { | |||
// we have a non-parameterized type | |||
return world.resolve(UnresolvedType.forSignature(sig.toString())); |
@@ -181,6 +181,7 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
} | |||
public ResolvedMember[] getDeclaredMethods() { | |||
unpackGenericSignature(); | |||
if (methods == null) { | |||
Method[] ms = javaClass.getMethods(); | |||
ResolvedMember[] ret = new ResolvedMember[ms.length]; | |||
@@ -193,6 +194,7 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
} | |||
public ResolvedMember[] getDeclaredFields() { | |||
unpackGenericSignature(); | |||
if (fields == null) { | |||
Field[] fs = javaClass.getFields(); | |||
ResolvedMember[] ret = new ResolvedMember[fs.length]; | |||
@@ -529,6 +531,10 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { | |||
getResolvedTypeX().getWorld()); | |||
} | |||
} | |||
if (isGeneric()) { | |||
// update resolved typex to point at generic type not raw type. | |||
this.resolvedTypeX = (ReferenceType) this.resolvedTypeX.getGenericType(); | |||
} | |||
} | |||
private void ensureGenericInfoProcessed() { getDeclaredGenericSignature();} |
@@ -180,7 +180,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
List methods = newParent.getMethodsWithoutIterator(); | |||
for (Iterator iter = methods.iterator(); iter.hasNext();) { | |||
BcelMethod superMethod = (BcelMethod) iter.next(); | |||
ResolvedMember superMethod = (ResolvedMember) iter.next(); | |||
if (!superMethod.getName().equals("<init>")) { | |||
LazyMethodGen subMethod = findMatchingMethod(newParentTarget, superMethod); | |||
if (subMethod!=null) { | |||
@@ -211,7 +211,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
if (!(newParentTarget.isAbstract() || newParentTarget.isInterface())) { // Ignore abstract classes or interfaces | |||
List methods = newParent.getMethodsWithoutIterator(); | |||
for (Iterator i = methods.iterator(); i.hasNext();) { | |||
BcelMethod o = (BcelMethod)i.next(); | |||
ResolvedMember o = (ResolvedMember)i.next(); | |||
if (o.isAbstract() && !o.getName().startsWith("ajc$interField")) { // Ignore abstract methods of ajc$interField prefixed methods | |||
ResolvedMember discoveredImpl = null; | |||
List newParentTargetMethods = newParentTarget.getType().getMethodsWithoutIterator(); | |||
@@ -270,7 +270,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
/** | |||
* Rule 3. Can't narrow visibility of methods when overriding | |||
*/ | |||
private boolean enforceDecpRule3_visibilityChanges(BcelClassWeaver weaver, ResolvedType newParent, BcelMethod superMethod, LazyMethodGen subMethod) { | |||
private boolean enforceDecpRule3_visibilityChanges(BcelClassWeaver weaver, ResolvedType newParent, ResolvedMember superMethod, LazyMethodGen subMethod) { | |||
boolean cont = true; | |||
if (superMethod.isPublic()) { | |||
if (subMethod.isProtected() || subMethod.isDefault() || subMethod.isPrivate()) { | |||
@@ -300,7 +300,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
/** | |||
* Rule 4. Can't have incompatible return types | |||
*/ | |||
private boolean enforceDecpRule4_compatibleReturnTypes(BcelClassWeaver weaver, BcelMethod superMethod, LazyMethodGen subMethod) { | |||
private boolean enforceDecpRule4_compatibleReturnTypes(BcelClassWeaver weaver, ResolvedMember superMethod, LazyMethodGen subMethod) { | |||
boolean cont = true; | |||
String superReturnTypeSig = superMethod.getReturnType().getSignature(); | |||
String subReturnTypeSig = subMethod.getReturnType().getSignature(); | |||
@@ -323,7 +323,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
* Rule5. Method overrides can't change the staticality (word?) - you can't override and make an instance | |||
* method static or override and make a static method an instance method. | |||
*/ | |||
private boolean enforceDecpRule5_cantChangeFromStaticToNonstatic(BcelClassWeaver weaver,ISourceLocation mungerLoc,BcelMethod superMethod, LazyMethodGen subMethod ) { | |||
private boolean enforceDecpRule5_cantChangeFromStaticToNonstatic(BcelClassWeaver weaver,ISourceLocation mungerLoc,ResolvedMember superMethod, LazyMethodGen subMethod ) { | |||
if (superMethod.isStatic() && !subMethod.isStatic()) { | |||
error(weaver,"This instance method "+subMethod.getName()+subMethod.getParameterSignature()+ | |||
" cannot override the static method from "+superMethod.getDeclaringType().getName(), | |||
@@ -344,7 +344,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
} | |||
private LazyMethodGen findMatchingMethod(LazyClassGen newParentTarget, BcelMethod m) { | |||
private LazyMethodGen findMatchingMethod(LazyClassGen newParentTarget, ResolvedMember m) { | |||
LazyMethodGen found = null; | |||
// Search the type for methods overriding super methods (methods that come from the new parent) | |||
// Don't use the return value in the comparison as overriding doesnt | |||
@@ -456,6 +456,8 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
ResolvedMember member = munger.getMember(); | |||
ResolvedType onType = weaver.getWorld().resolve(member.getDeclaringType(),munger.getSourceLocation()); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
//System.out.println("munging: " + gen + " with " + member); | |||
if (onType.equals(gen.getType())) { | |||
if (member.getKind() == Member.FIELD) { | |||
@@ -713,6 +715,8 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
LazyClassGen gen = weaver.getLazyClassGen(); | |||
ResolvedType onType = weaver.getWorld().resolve(signature.getDeclaringType(),munger.getSourceLocation()); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
boolean onInterface = onType.isInterface(); | |||
if (onType.isAnnotation()) { | |||
@@ -898,14 +902,15 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
final InstructionFactory fact = currentClass.getFactory(); | |||
ResolvedMember newConstructorMember = newConstructorTypeMunger.getSyntheticConstructor(); | |||
UnresolvedType onType = newConstructorMember.getDeclaringType(); | |||
ResolvedType onType = newConstructorMember.getDeclaringType().resolve(weaver.getWorld()); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
if (onType.resolve(weaver.getWorld()).isAnnotation()) { | |||
if (onType.isAnnotation()) { | |||
signalError(WeaverMessages.ITDC_ON_ANNOTATION_NOT_ALLOWED,weaver,onType); | |||
return false; | |||
} | |||
if (onType.resolve(weaver.getWorld()).isEnum()) { | |||
if (onType.isEnum()) { | |||
signalError(WeaverMessages.ITDC_ON_ENUM_NOT_ALLOWED,weaver,onType); | |||
return false; | |||
} | |||
@@ -1044,6 +1049,8 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
ResolvedType onType = weaver.getWorld().resolve(field.getDeclaringType(),munger.getSourceLocation()); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
boolean onInterface = onType.isInterface(); | |||
if (onType.isAnnotation()) { |
@@ -1154,7 +1154,8 @@ public class BcelWeaver implements IWeaver { | |||
* FIXME asc confirm that algorithm is optimal ?? | |||
*/ | |||
public void weaveParentTypeMungers(ResolvedType onType) { | |||
onType.clearInterTypeMungers(); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
onType.clearInterTypeMungers(); | |||
List decpToRepeat = new ArrayList(); | |||
@@ -1312,6 +1313,7 @@ public class BcelWeaver implements IWeaver { | |||
} | |||
public void weaveNormalTypeMungers(ResolvedType onType) { | |||
if (onType.isRawType() || onType.isParameterizedType()) onType = onType.getGenericType(); | |||
for (Iterator i = typeMungerList.iterator(); i.hasNext(); ) { | |||
ConcreteTypeMunger m = (ConcreteTypeMunger)i.next(); | |||
if (m.matches(onType)) { |
@@ -100,7 +100,7 @@ public class DeclareSoft extends Declare { | |||
// ENH 42743 suggests that we don't soften runtime exceptions. | |||
if (scope.getWorld().getCoreType(UnresolvedType.RUNTIME_EXCEPTION).isAssignableFrom(excType)) { | |||
scope.getWorld().getLint().runtimeExceptionNotSoftened.signal( | |||
new String[]{exception.toString()}, | |||
new String[]{excType.getName()}, | |||
exception.getSourceLocation(),null); | |||
pointcut = Pointcut.makeMatchesNothing(Pointcut.RESOLVED); | |||
return; |
@@ -27,6 +27,7 @@ import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.TypeFactory; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.VersionedDataInputStream; | |||
import org.aspectj.weaver.WeaverMessages; | |||
@@ -509,11 +510,11 @@ public class WildTypePattern extends TypePattern { | |||
if (type == ResolvedType.MISSING) { | |||
return resolveBindingsForMissingType(resolvedTypeInTheWorld, originalName, scope, bindings, allowBinding, requireExactType); | |||
} else { | |||
return resolveBindingsForExactRawType(scope,type,fullyQualifiedName); | |||
return resolveBindingsForExactType(scope,type,fullyQualifiedName); | |||
} | |||
} | |||
private TypePattern resolveBindingsForExactRawType(IScope scope, UnresolvedType rawType, String fullyQualifiedName) { | |||
private TypePattern resolveBindingsForExactType(IScope scope, UnresolvedType aType, String fullyQualifiedName) { | |||
TypePattern ret = null; | |||
if (typeParameters.size()>0) { | |||
// Only if the type is exact *and* the type parameters are exact should we create an | |||
@@ -524,8 +525,9 @@ public class WildTypePattern extends TypePattern { | |||
for (int i = 0; i < typeParameterTypes.length; i++) { | |||
typeParameterTypes[i] = ((ExactTypePattern)typePats[i]).getExactType(); | |||
} | |||
UnresolvedType tx = UnresolvedType.forParameterizedTypes(rawType,typeParameterTypes); | |||
UnresolvedType type = scope.getWorld().resolve(tx,true); | |||
UnresolvedType type = TypeFactory.createParameterizedType(aType.resolve(scope.getWorld()), typeParameterTypes, scope.getWorld()); | |||
// UnresolvedType tx = UnresolvedType.forParameterizedTypes(aType,typeParameterTypes); | |||
// UnresolvedType type = scope.getWorld().resolve(tx,true); | |||
if (dim != 0) type = UnresolvedType.makeArray(type, dim); | |||
ret = new ExactTypePattern(type,includeSubtypes,isVarArgs); | |||
} else { | |||
@@ -537,8 +539,8 @@ public class WildTypePattern extends TypePattern { | |||
return this; | |||
} | |||
} else { | |||
if (dim != 0) rawType = UnresolvedType.makeArray(rawType, dim); | |||
ret = new ExactTypePattern(rawType,includeSubtypes,isVarArgs); | |||
if (dim != 0) aType = UnresolvedType.makeArray(aType, dim); | |||
ret = new ExactTypePattern(aType,includeSubtypes,isVarArgs); | |||
} | |||
ret.setAnnotationTypePattern(annotationPattern); | |||
ret.copyLocationFrom(this); |
@@ -40,7 +40,9 @@ public class MemberTestCase15 extends TestCase { | |||
public void testCanBeParameterizedGenericMethod() { | |||
BcelWorld world = new BcelWorld(); | |||
ResolvedType javaLangClass = world.resolve(UnresolvedType.forName("java/lang/Class")); | |||
ResolvedType javaLangClass = world.resolve(UnresolvedType.forName("java.lang.Class")); | |||
javaLangClass = javaLangClass.getGenericType(); | |||
if (javaLangClass == null) return; // for < 1.5 | |||
ResolvedMember[] methods = javaLangClass.getDeclaredMethods(); | |||
ResolvedMember asSubclass = null; | |||
for (int i = 0; i < methods.length; i++) { | |||
@@ -57,7 +59,9 @@ public class MemberTestCase15 extends TestCase { | |||
public void testCanBeParameterizedMethodInGenericType() { | |||
BcelWorld world = new BcelWorld(); | |||
ResolvedType javaUtilList = world.resolve(UnresolvedType.forName("java/util/List")); | |||
ResolvedType javaUtilList = world.resolve(UnresolvedType.forName("java.util.List")); | |||
javaUtilList = javaUtilList.getGenericType(); | |||
if (javaUtilList == null) return; // for < 1.5 | |||
ResolvedMember[] methods = javaUtilList.getDeclaredMethods(); | |||
ResolvedMember add = null; | |||
for (int i = 0; i < methods.length; i++) { |
@@ -62,7 +62,6 @@ public class ParameterizedReferenceTypeTestCase extends TestCase { | |||
super.setUp(); | |||
world = new BcelWorld(); | |||
listOfString = (ReferenceType) | |||
world.resolve(UnresolvedType.forParameterizedTypeNames("java/util/List", | |||
new String[] {"java/lang/String"})); | |||
TypeFactory.createTypeFromSignature("Ljava/util/List<Ljava/lang/String;>;").resolve(world); | |||
} | |||
} |
@@ -19,22 +19,36 @@ import junit.framework.TestCase; | |||
// XXX - couldn't find any unit test cases for the rest of the ReferenceType class | |||
public class ReferenceTypeTestCase extends TestCase { | |||
public void testIsGenericTrue() { | |||
public void testIsRawTrue() { | |||
BcelWorld world = new BcelWorld(); | |||
UnresolvedType javaLangClass = UnresolvedType.forName("java/lang/Class"); | |||
UnresolvedType javaLangClass = UnresolvedType.forName("java.lang.Class"); | |||
ResolvedType rtx = world.resolve(javaLangClass); | |||
assertTrue("Resolves to reference type",(rtx instanceof ReferenceType)); | |||
ReferenceType rt = (ReferenceType) rtx; | |||
assertTrue("java.lang.Class is generic",rt.isGenericType()); | |||
assertTrue("java.lang.Class is raw",rt.isRawType()); | |||
} | |||
public void testIsGenericFalse() { | |||
public void testIsRawFalse() { | |||
BcelWorld world = new BcelWorld(); | |||
UnresolvedType javaLangObject = UnresolvedType.forName("java/lang/Object"); | |||
UnresolvedType javaLangObject = UnresolvedType.forName("java.lang.Object"); | |||
ResolvedType rtx = world.resolve(javaLangObject); | |||
assertTrue("Resolves to reference type",(rtx instanceof ReferenceType)); | |||
ReferenceType rt = (ReferenceType) rtx; | |||
assertFalse("java.lang.Object is not generic",rt.isGenericType()); | |||
assertFalse("java.lang.Object is not raw",rt.isRawType()); | |||
} | |||
public void testIsGenericTrue() { | |||
BcelWorld world = new BcelWorld(); | |||
UnresolvedType javaLangClass = UnresolvedType.forName("java.lang.Class"); | |||
ResolvedType rtx = world.resolve(javaLangClass); | |||
assertTrue("java.lang.Class has underpinning generic type",rtx.getGenericType().isGenericType()); | |||
} | |||
public void testIsGenericFalse() { | |||
BcelWorld world = new BcelWorld(); | |||
UnresolvedType javaLangObject = UnresolvedType.forName("java.lang.Object"); | |||
ResolvedType rtx = world.resolve(javaLangObject); | |||
assertFalse(rtx.isGenericType()); | |||
} | |||
} |
@@ -16,6 +16,7 @@ package org.aspectj.weaver; | |||
import junit.framework.TestCase; | |||
import org.aspectj.testing.util.TestUtil; | |||
import org.aspectj.weaver.bcel.BcelWorld; | |||
/** | |||
* This is a test case for all the portions of UnresolvedType that don't require a world. | |||
@@ -65,16 +66,16 @@ public class TypeXTestCase extends TestCase { | |||
public void testNameAndSigWithParameters() { | |||
UnresolvedType t = UnresolvedType.forName("java.util.List<java.lang.String>"); | |||
assertEquals(t.getName(),"java.util.List<java.lang.String>"); | |||
assertEquals(t.getSignature(),"Ljava/util/List<Ljava/lang/String;>;"); | |||
t = new UnresolvedType("Ljava/util/List<Ljava/lang/String;>;"); | |||
assertEquals(t.getSignature(),"Pjava/util/List<Ljava/lang/String;>;"); | |||
t = UnresolvedType.forSignature("Pjava/util/List<Ljava/lang/String;>;"); | |||
assertEquals(t.getName(),"java.util.List<java.lang.String>"); | |||
assertEquals(t.getSignature(),"Ljava/util/List<Ljava/lang/String;>;"); | |||
assertEquals(t.getSignature(),"Pjava/util/List<Ljava/lang/String;>;"); | |||
t = UnresolvedType.forName("java.util.Map<java.util.String,java.util.List<java.lang.Integer>>"); | |||
assertEquals(t.getName(),"java.util.Map<java.util.String,java.util.List<java.lang.Integer>>"); | |||
assertEquals(t.getSignature(),"Ljava/util/Map<Ljava/util/String;Ljava/util/List<Ljava/lang/Integer;>;>;"); | |||
t = new UnresolvedType("Ljava/util/Map<Ljava/util/String;Ljava/util/List<Ljava/lang/Integer;>;>;"); | |||
assertEquals(t.getSignature(),"Pjava/util/Map<Ljava/util/String;Pjava/util/List<Ljava/lang/Integer;>;>;"); | |||
t = UnresolvedType.forSignature("Pjava/util/Map<Ljava/util/String;Pjava/util/List<Ljava/lang/Integer;>;>;"); | |||
assertEquals(t.getName(),"java.util.Map<java.util.String,java.util.List<java.lang.Integer>>"); | |||
assertEquals(t.getSignature(),"Ljava/util/Map<Ljava/util/String;Ljava/util/List<Ljava/lang/Integer;>;>;"); | |||
assertEquals(t.getSignature(),"Pjava/util/Map<Ljava/util/String;Pjava/util/List<Ljava/lang/Integer;>;>;"); | |||
} | |||
/** | |||
@@ -91,13 +92,13 @@ public class TypeXTestCase extends TestCase { | |||
public void testTypexGenericSignatureProcessing() { | |||
UnresolvedType tx = null; | |||
tx = new UnresolvedType("Ljava/util/Set<Ljava/lang/String;>;"); | |||
tx = UnresolvedType.forSignature("Pjava/util/Set<Ljava/lang/String;>;"); | |||
checkTX(tx,true,1); | |||
tx = new UnresolvedType("Ljava/util/Set<Ljava/util/List<Ljava/lang/String;>;>;"); | |||
tx = UnresolvedType.forSignature("Pjava/util/Set<Pjava/util/List<Ljava/lang/String;>;>;"); | |||
checkTX(tx,true,1); | |||
tx = new UnresolvedType("Ljava/util/Map<Ljava/util/List<Ljava/lang/String;>;Ljava/lang/String;>;"); | |||
tx = UnresolvedType.forSignature("Pjava/util/Map<Pjava/util/List<Ljava/lang/String;>;Ljava/lang/String;>;"); | |||
checkTX(tx,true,2); | |||
checkTX(tx.getTypeParameters()[0],true,1); | |||
checkTX(tx.getTypeParameters()[1],false,0); | |||
@@ -105,8 +106,13 @@ public class TypeXTestCase extends TestCase { | |||
} | |||
public void testTypeXForParameterizedTypes() { | |||
World world = new BcelWorld(); | |||
UnresolvedType stringType = UnresolvedType.forName("java/lang/String"); | |||
UnresolvedType listOfStringType = UnresolvedType.forParameterizedTypes(UnresolvedType.forName("java/util/List"), new UnresolvedType[] {stringType}); | |||
ResolvedType listOfStringType = | |||
TypeFactory.createParameterizedType( | |||
UnresolvedType.forName("java/util/List").resolve(world), | |||
new UnresolvedType[] {stringType}, | |||
world); | |||
assertEquals("1 type param",1,listOfStringType.typeParameters.length); | |||
assertEquals(stringType,listOfStringType.typeParameters[0]); | |||
assertTrue(listOfStringType.isParameterizedType()); |
@@ -45,7 +45,7 @@ public class BcelGenericSignatureToTypeXTestCase extends TestCase { | |||
cSig.formalTypeParameters, | |||
world | |||
); | |||
assertEquals("Ljava/lang/Comparable<Ljava/lang/Enum<Ljava/lang/Object;>;>;",comparable.getSignature()); | |||
assertEquals("Pjava/lang/Comparable<Pjava/lang/Enum<Ljava/lang/Object;>;>;",comparable.getSignature()); | |||
UnresolvedType serializable = | |||
BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX( | |||
cSig.superInterfaceSignatures[1], |