瀏覽代碼

genericitds: lots of new support for recursive type variables and ITD ctors.

tags/V1_5_0M3
aclement 19 年之前
父節點
當前提交
900a3e81d5

+ 18
- 8
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java 查看文件

@@ -13,6 +13,7 @@

package org.aspectj.ajdt.internal.compiler.ast;

import java.lang.reflect.Modifier;
import org.aspectj.ajdt.internal.compiler.lookup.*;
import org.aspectj.weaver.*;
import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
@@ -94,9 +95,16 @@ public class InterTypeConstructorDeclaration extends InterTypeDeclaration {
pre.scope = new MethodScope(scope, pre, true);
//??? do we need to do anything with scope???
pre.binding = world.makeMethodBinding(
AjcMemberMaker.preIntroducedConstructor(aspectTypeX, targetTypeX,
world.fromBindings(binding.parameters)));

// Use the factory to build a semi-correct resolvedmember - then patch it up with
// reset calls. This is SAFE
ResolvedMember preIntroducedConstructorRM = world.makeResolvedMember(binding);
preIntroducedConstructorRM.resetName(NameMangler.preIntroducedConstructor(aspectTypeX, targetTypeX));
preIntroducedConstructorRM.resetModifiers(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
preIntroducedConstructorRM.resetReturnTypeToObjectArray();
pre.binding = world.makeMethodBinding(preIntroducedConstructorRM);
pre.bindArguments();
pre.bindThrownExceptions();
@@ -218,12 +226,14 @@ public class InterTypeConstructorDeclaration extends InterTypeDeclaration {
ResolvedType declaringTypeX = world.fromEclipse(onTypeBinding);
ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding);
ResolvedMember bindingAsMember = world.makeResolvedMember(binding);
ResolvedMember signature =
new ResolvedMemberImpl(Member.CONSTRUCTOR, declaringTypeX, declaredModifiers,
ResolvedType.VOID, "<init>", bindingAsMember.getParameterTypes(),
world.fromEclipse(binding.thrownExceptions));

// This signature represents what we want consumers of the targetted type to 'see'
ResolvedMember signature = world.makeResolvedMember(binding,onTypeBinding);
signature.resetKind(Member.CONSTRUCTOR);
signature.resetName("<init>");
signature.resetModifiers(declaredModifiers);
ResolvedMember syntheticInterMember =
AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType);

+ 15
- 16
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java 查看文件

@@ -17,16 +17,6 @@ import java.lang.reflect.Modifier;

import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.NewMethodTypeMunger;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -39,6 +29,14 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.NewMethodTypeMunger;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.UnresolvedType;

/**
* An inter-type method declaration.
@@ -125,12 +123,13 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration {
if (isTargetAnnotation(classScope,"method")) return null; // Error message output in isTargetAnnotation
if (isTargetEnum(classScope,"method")) return null; // Error message output in isTargetEnum
ResolvedMemberImpl sig = new ResolvedMemberImpl(Member.METHOD, world.fromBinding(onTypeBinding),
declaredModifiers, world.fromBinding(binding.returnType), new String(declaredSelector),
world.fromBindings(binding.parameters),
world.fromEclipse(binding.thrownExceptions));
sig.setTypeVariables(world.fromBindings(binding.typeVariables));

// This signature represents what we want consumers of the targetted type to 'see'
// must use the factory method to build it since there may be typevariables from the binding
// referred to in the parameters/returntype
ResolvedMember sig = world.makeResolvedMember(binding,onTypeBinding);
sig.resetName(new String(declaredSelector));
sig.resetModifiers(declaredModifiers);
NewMethodTypeMunger myMunger = new NewMethodTypeMunger(sig, null);
setMunger(myMunger);

+ 110
- 61
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java 查看文件

@@ -24,26 +24,8 @@ import java.util.Map;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.AstUtil;
import org.aspectj.ajdt.internal.core.builder.AjBuildManager;
import org.aspectj.ajdt.internal.core.builder.AsmHierarchyBuilder;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.IMessage.Kind;
import org.aspectj.weaver.BoundedReferenceType;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.IHasPosition;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.TypeFactory;
import org.aspectj.weaver.TypeVariable;
import org.aspectj.weaver.TypeVariableDeclaringElement;
import org.aspectj.weaver.TypeVariableReference;
import org.aspectj.weaver.TypeVariableReferenceType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
import org.aspectj.weaver.World;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
@@ -64,9 +46,24 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
import org.aspectj.weaver.BoundedReferenceType;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.IHasPosition;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.TypeFactory;
import org.aspectj.weaver.TypeVariable;
import org.aspectj.weaver.TypeVariableDeclaringElement;
import org.aspectj.weaver.TypeVariableReference;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
import org.aspectj.weaver.World;
/**
* @author Jim Hugunin
@@ -231,10 +228,14 @@ public class EclipseFactory {
}
}
ResolvedType baseType = UnresolvedType.forName(getName(binding)).resolve(getWorld());
return TypeFactory.createParameterizedType(
baseType,
arguments,
getWorld());
// Create an unresolved parameterized type. We can't create a resolved one as the
// act of resolution here may cause recursion problems since the parameters may
// be type variables that we haven't fixed up yet.
if (!baseType.isGenericType() && arguments!=null) baseType = baseType.getGenericType();
if (arguments==null) arguments=new UnresolvedType[0];
String parameterizedSig = ResolvedType.PARAMETERIZED_TYPE_IDENTIFIER+CharOperation.charToString(binding.genericTypeSignature()).substring(1);
return TypeFactory.createUnresolvedParameterizedType(parameterizedSig,baseType.getErasureSignature(),arguments);
}
// Convert the source type binding for a generic type into a generic UnresolvedType
@@ -261,27 +262,47 @@ public class EclipseFactory {
return UnresolvedType.forName(getName(binding));
}

/**
* Some type variables refer to themselves recursively, this enables us to avoid
* recursion problems.
*/
private static Map typeVariableBindingsInProgress = new HashMap();
/**
* Convert from the eclipse form of type variable (TypeVariableBinding) to the AspectJ
* form (TypeVariable).
*/
private UnresolvedType fromTypeVariableBinding(TypeVariableBinding aTypeVariableBinding) {
// first, check for recursive call to this method for the same tvBinding
if (typeVariableBindingsInProgress.containsKey(aTypeVariableBinding)) {
return (UnresolvedType) typeVariableBindingsInProgress.get(aTypeVariableBinding);
}
if (typeVariablesForThisMember.containsKey(new Integer(aTypeVariableBinding.rank))) {
return (UnresolvedType)typeVariablesForThisMember.get(new Integer(aTypeVariableBinding.rank));
}
// Create the UnresolvedTypeVariableReferenceType for the type variable
String name = CharOperation.charToString(aTypeVariableBinding.sourceName());
UnresolvedTypeVariableReferenceType ret = new UnresolvedTypeVariableReferenceType();
typeVariableBindingsInProgress.put(aTypeVariableBinding,ret);
// Dont set any bounds here, you'll get in a recursive mess
// TODO -- what about lower bounds??
String name = new String(aTypeVariableBinding.sourceName());
UnresolvedType superclassType = fromBinding(aTypeVariableBinding.superclass());
UnresolvedType superclassType = fromBinding(aTypeVariableBinding.superclass());
UnresolvedType[] superinterfaces = new UnresolvedType[aTypeVariableBinding.superInterfaces.length];
for (int i = 0; i < superinterfaces.length; i++) {
superinterfaces[i] = fromBinding(aTypeVariableBinding.superInterfaces[i]);
}
TypeVariable tv = new TypeVariable(name,superclassType,superinterfaces);
tv.setUpperBound(superclassType);
tv.setAdditionalInterfaceBounds(superinterfaces);
tv.setRank(aTypeVariableBinding.rank);
// getting things right for method declaring elements is tricky...
if (!(aTypeVariableBinding.declaringElement instanceof MethodBinding)) {
tv.setDeclaringElement(fromBinding(aTypeVariableBinding.declaringElement));
}
tv.resolve(world);
// dont need the declaring element yet...
// if (aTypeVariableBinding.declaringElement instanceof MethodBinding) {
// tv.setDeclaringElement(fromBinding((MethodBinding)aTypeVariableBinding.declaringElement);
// } else {
// // tv.setDeclaringElement(fromBinding(aTypeVariableBinding.declaringElement));
// }
ret.setTypeVariable(tv);
typeVariableBindingsInProgress.remove(aTypeVariableBinding);
return ret;
@@ -369,8 +390,30 @@ public class EclipseFactory {
return makeResolvedMember(binding, binding.declaringClass);
}

/**
* Conversion from a methodbinding (eclipse) to a resolvedmember (aspectj) is now done
* in the scope of some type variables. Before converting the parts of a methodbinding
* (params, return type) we store the type variables in this structure, then should any
* component of the method binding refer to them, we grab them from the map.
*/
// FIXME asc convert to array, indexed by rank
private Map typeVariablesForThisMember = new HashMap();

public ResolvedMember makeResolvedMember(MethodBinding binding, TypeBinding declaringType) {
//System.err.println("member for: " + binding + ", " + new String(binding.declaringClass.sourceName));

// Convert the type variables and store them
UnresolvedType[] ajTypeRefs = null;
// This is the set of type variables available whilst building the resolved member...
if (binding.typeVariables!=null) {
ajTypeRefs = new UnresolvedType[binding.typeVariables.length];
for (int i = 0; i < binding.typeVariables.length; i++) {
ajTypeRefs[i] = fromBinding(binding.typeVariables[i]);
typeVariablesForThisMember.put(new Integer(binding.typeVariables[i].rank),ajTypeRefs[i]);
}
}
// 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();
@@ -378,10 +421,14 @@ public class EclipseFactory {
binding.isConstructor() ? Member.CONSTRUCTOR : Member.METHOD,
realDeclaringType,
binding.modifiers,
world.resolve(fromBinding(binding.returnType)),
fromBinding(binding.returnType),
new String(binding.selector),
world.resolve(fromBindings(binding.parameters)),
world.resolve(fromBindings(binding.thrownExceptions)));
fromBindings(binding.parameters),
fromBindings(binding.thrownExceptions)
);
if (ajTypeRefs!=null) ret.setTypeVariables(ajTypeRefs);
typeVariablesForThisMember.clear();
ret.resolve(world);
return ret;
}

@@ -407,7 +454,7 @@ public class EclipseFactory {
if (ret == null) {
ret = makeTypeBinding1(typeX);
// FIXME asc keep type variables *out* of the map for now, they go in typeVariableToTypeBinding
if (!(typeX instanceof TypeVariableReference))
if (!(typeX instanceof BoundedReferenceType))
typexToBinding.put(typeX, ret);
}
if (ret == null) {
@@ -457,8 +504,8 @@ public class EclipseFactory {
BoundedReferenceType brt = (BoundedReferenceType)typeX;
// Work out 'kind' for the WildcardBinding
int boundkind = Wildcard.UNBOUND;
if (brt.isGenericWildcardExtends()) boundkind = Wildcard.EXTENDS;
if (brt.isGenericWildcardSuper()) boundkind = Wildcard.SUPER;
if (brt.isExtends()) boundkind = Wildcard.EXTENDS;
if (brt.isSuper()) boundkind = Wildcard.SUPER;
// get the bound right
TypeBinding bound = null;
if (brt.isGenericWildcardExtends()) bound = makeTypeBinding(brt.getUpperBound());
@@ -518,46 +565,48 @@ public class EclipseFactory {

public MethodBinding makeMethodBinding(ResolvedMember member) {
typeVariableToTypeBinding.clear();
ReferenceBinding declaringType = (ReferenceBinding)makeTypeBinding(member.getDeclaringType());
MethodBinding mb = new MethodBinding(member.getModifiers(),
member.getName().toCharArray(),
makeTypeBinding(member.getReturnType()),
makeTypeBindings(member.getParameterTypes()),
makeReferenceBindings(member.getExceptions()),
declaringType);
TypeVariableBinding[] tvbs = null;
if (member.getTypeVariables()!=null) {
if (member.getTypeVariables().length==0) {
mb.typeVariables = MethodBinding.NoTypeVariables;
tvbs = MethodBinding.NoTypeVariables;
} else {
TypeVariableBinding[] tvbs = makeTypeVariableBindings(member.getTypeVariables());
tvbs = makeTypeVariableBindings(member.getTypeVariables());
// fixup the declaring element, we couldn't do it whilst processing the typevariables as we'll end up in recursion.
for (int i = 0; i < tvbs.length; i++) {
TypeVariableBinding binding = tvbs[i];
if (binding.declaringElement==null && ((TypeVariableReference)member.getTypeVariables()[i]).getTypeVariable().getDeclaringElement() instanceof Member) {
tvbs[i].declaringElement = mb;
} else {
tvbs[i].declaringElement = declaringType;
}
// if (binding.declaringElement==null && ((TypeVariableReference)member.getTypeVariables()[i]).getTypeVariable().getDeclaringElement() instanceof Member) {
// tvbs[i].declaringElement = mb;
// } else {
// tvbs[i].declaringElement = declaringType;
// }
}
mb.typeVariables = tvbs;
}
}
}
ReferenceBinding declaringType = (ReferenceBinding)makeTypeBinding(member.getDeclaringType());
MethodBinding mb = new MethodBinding(member.getModifiers(),
member.getName().toCharArray(),
makeTypeBinding(member.getReturnType()),
makeTypeBindings(member.getParameterTypes()),
makeReferenceBindings(member.getExceptions()),
declaringType);

if (tvbs!=null) mb.typeVariables = tvbs;
typeVariableToTypeBinding.clear();
return mb;
}


/**
* Convert a bunch of type variables in one go, from AspectJ form to Eclipse form.
*/
private TypeVariableBinding[] makeTypeVariableBindings(UnresolvedType[] typeVariables) {
int len = typeVariables.length;
TypeVariableBinding[] ret = new TypeVariableBinding[len];
for (int i = 0; i < len; i++) {
TypeVariableReference tvReference = (TypeVariableReference)typeVariables[i];
TypeVariableBinding tvb = (TypeVariableBinding)typeVariableToTypeBinding.get(tvReference.getTypeVariable().getName());
if (tvb==null) {
tvb = makeTypeVariableBinding(tvReference);
}
ret[i] = tvb;
ret[i] = makeTypeVariableBinding((TypeVariableReference)typeVariables[i]);
}
return ret;
}
@@ -575,7 +624,7 @@ public class EclipseFactory {
*/
private TypeVariableBinding makeTypeVariableBinding(TypeVariableReference tvReference) {
TypeVariable tVar = tvReference.getTypeVariable();
TypeVariableBinding tvBinding = (TypeVariableBinding)typeVariableToTypeBinding.get(tVar);
TypeVariableBinding tvBinding = (TypeVariableBinding)typeVariableToTypeBinding.get(tVar.getName());
if (tvBinding==null) {
Binding declaringElement = null;
// this will cause an infinite loop or NPE... not required yet luckily.
@@ -585,6 +634,7 @@ public class EclipseFactory {
// declaringElement = makeTypeBinding((UnresolvedType)tVar.getDeclaringElement());
// }
tvBinding = new TypeVariableBinding(tVar.getName().toCharArray(),declaringElement,tVar.getRank());
typeVariableToTypeBinding.put(tVar.getName(),tvBinding);
tvBinding.superclass=(ReferenceBinding)makeTypeBinding(tVar.getUpperBound());
tvBinding.firstBound=tvBinding.superclass; // FIXME asc is this correct? possibly it could be first superinterface
if (tVar.getAdditionalInterfaceBounds()==null) {
@@ -596,7 +646,6 @@ public class EclipseFactory {
rbs[i] = (ReferenceBinding)tbs[i];
}
tvBinding.superInterfaces=rbs;
typeVariableToTypeBinding.put(tVar.getName(),tvBinding);
}
}
return tvBinding;

+ 43
- 8
tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java 查看文件

@@ -99,6 +99,29 @@ public class GenericsTests extends XMLBasedAjcTestCase {
* - wait till we get there!
*/
/* ==========================================
* Generics test plan for ITDs.
*
* think about:
* - source/binary weaving
* - visibility default/private/public
* - static/nonstatic
* - parameterized ITDs (methods/ctors/fields)
* - ITD target: interface/class/aspect
* - multiple type variables
* - generic ITDs (like generic methods)
* - constructor ITDs, method ITDs
* - ITDs sharing type variables with generic types
* - relating to above point, this makes generic ITD fields possible
* - signature attributes for generic ITDs (required? required only for public ITDs?)
* - binary weaving when target type changes over time (might start out 'simple' then sometime later be 'generic')
* - bridge methods - when to create them
* - multiple 'separate' ITDs in a file that share a type variable by 'name'
* - wildcards '?' 'extends' 'super' '&'
* - do type variables assigned to members need to persist across serialization
* - recursive type variable definitions eg. <R extends Comparable<? super R>>
*/
public static Test suite() {
return XMLBasedAjcTestCase.loadSuite(GenericsTests.class);
}
@@ -182,12 +205,21 @@ public class GenericsTests extends XMLBasedAjcTestCase {
// non static

public void testGenericMethodITD1() {runTest("generic method itd - 1");} // <E> ... (List<? extends E>)
public void testGenericMethodITD2() {runTest("generic method itd - 2");} // <E extends Number> ... (List<? extends E>) called incorrectly
public void testGenericMethodITD3() {runTest("generic method itd - 3");} // <E> ... (List<E>,List<E>)
public void testGenericMethodITD4() {runTest("generic method itd - 4");} // <A,B> ... (List<A>,List<B>)
public void testGenericMethodITD5() {runTest("generic method itd - 5");} // <E> ... (List<E>,List<E>) called incorrectly
public void testGenericMethodITD6() {runTest("generic method itd - 6");} // <E extends Number> ... (List<? extends E>)
public void testGenericMethodITD1() {runTest("generic method itd - 1"); } // <E> ... (List<? extends E>)
public void testGenericMethodITD2() {runTest("generic method itd - 2"); } // <E extends Number> ... (List<? extends E>) called incorrectly
public void testGenericMethodITD3() {runTest("generic method itd - 3"); } // <E> ... (List<E>,List<E>)
public void testGenericMethodITD4() {runTest("generic method itd - 4"); } // <A,B> ... (List<A>,List<B>)
public void testGenericMethodITD5() {runTest("generic method itd - 5"); } // <E> ... (List<E>,List<E>) called incorrectly
public void testGenericMethodITD6() {runTest("generic method itd - 6"); } // <E extends Number> ... (List<? extends E>)
public void testGenericMethodITD7() {runTest("generic method itd - 7"); } // <E> ... (List<E>,List<? extends E>)
public void testGenericMethodITD8() {runTest("generic method itd - 8"); } // <E> ... (List<E>,List<? extends E>) called incorrectly
public void testGenericMethodITD9() {runTest("generic method itd - 9"); } // <R extends Comparable<? super R>> ... (List<R>)
public void testGenericMethodITD10() {runTest("generic method itd - 10");} // <R extends Comparable<? super R>> ... (List<R>) called incorrectly
public void testGenericMethodITD11() {runTest("generic method itd - 11");} // <R extends Comparable<? extends R>> ... (List<R>)
public void testGenericMethodITD12() {runTest("generic method itd - 12");} // <R extends Comparable<? extends R>> ... (List<R>) called incorrectly
public void testGenericMethodITD13() {runTest("generic method itd - 13");} // <R extends Comparable<? extends R>> ... (List<R>) called correctly in a clever way ;)
public void testGenericMethodITD14() {runTest("generic method itd - 14");} // <R extends Comparable<? super R>> ... (List<R>) called incorrectly in a clever way
public void testGenericMethodITD15() {runTest("generic method itd - 15");} // <R extends Comparable<? super R>> ... (List<R>) called correctly in a clever way

public void testParameterizedMethodITD1() {runTest("parameterized method itd - 1");} // (List<? extends Super>)
@@ -196,8 +228,11 @@ public class GenericsTests extends XMLBasedAjcTestCase {
public void testParameterizedMethodITD4() {runTest("parameterized method itd - 4");} // (List<? super B>)

// public void testNonStaticGenericCtorITD1() {runTest("generic ctor itd - 1");}
// public void testGenericITFSharingTypeVariable() {
public void testGenericCtorITD1() {runTest("generic ctor itd - 1");} // <T> new(List<T>)
public void testGenericCtorITD2() {runTest("generic ctor itd - 2");} // <T> new(List<T>,List<? extends T>)
public void testGenericCtorITD3() {runTest("generic ctor itd - 3");} // <T> new(List<T>,Comparator<? super T>)

// public void testGenericITFSharingTypeVariable() {
// runTest("generic intertype field declaration, sharing type variable");
// }


+ 62
- 3
tests/src/org/aspectj/systemtest/ajc150/ajc150.xml 查看文件

@@ -2386,9 +2386,19 @@
</run>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="non static generic ctor itd - 1">
<compile files="NonstaticGenericCtorITD1.aj" options="-1.5"/>
<run class="NonstaticGenericCtorITD1"/>
<ajc-test dir="java5/generics/itds" title="generic ctor itd - 1">
<compile files="GenericCtorITD1.aj" options="-1.5"/>
<run class="GenericCtorITD1"/>
</ajc-test>

<ajc-test dir="java5/generics/itds" title="generic ctor itd - 2">
<compile files="GenericCtorITD2.aj" options="-1.5"/>
<run class="GenericCtorITD2"/>
</ajc-test>

<ajc-test dir="java5/generics/itds" title="generic ctor itd - 3">
<compile files="GenericCtorITD3.aj" options="-1.5"/>
<run class="GenericCtorITD3"/>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="parameterized method itd - 1">
@@ -2447,6 +2457,55 @@
<run class="GenericMethodITD6"/>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="generic method itd - 7">
<compile files="GenericMethodITD7.aj" options="-1.5"/>
<run class="GenericMethodITD7"/>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="generic method itd - 8">
<compile files="GenericMethodITD8.aj" options="-1.5">
<message kind="error" line="10" text="The method simple(List&lt;E&gt;, List&lt;? extends E&gt;) in the type X is not applicable for the arguments (List&lt;Number&gt;, List&lt;String&gt;)"/>
</compile>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="generic method itd - 9">
<compile files="GenericMethodITD9.aj" options="-1.5"/>
<run class="GenericMethodITD9"/>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="generic method itd - 10">
<compile files="GenericMethodITD10.aj" options="-1.5">
<message kind="error" line="10" text="Bound mismatch: The generic method crazy(List&lt;R&gt;) of type X is not applicable for the arguments (List&lt;A&gt;) since the type A is not a valid substitute for the bounded parameter &lt;R extends Object &amp; Comparable&lt;? super R&gt;&gt;"/>
</compile>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="generic method itd - 11">
<compile files="GenericMethodITD11.aj" options="-1.5"/>
<run class="GenericMethodITD11"/>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="generic method itd - 12">
<compile files="GenericMethodITD12.aj" options="-1.5">
<message kind="error" line="10" text="Bound mismatch: The generic method crazy(List&lt;R&gt;) of type X is not applicable for the arguments (List&lt;A&gt;) since the type A is not a valid substitute for the bounded parameter &lt;R extends Object &amp; Foo&lt;? extends R&gt;&gt;"/>
</compile>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="generic method itd - 13">
<compile files="GenericMethodITD13.aj" options="-1.5"/>
<run class="GenericMethodITD13"/>
</ajc-test>

<ajc-test dir="java5/generics/itds" title="generic method itd - 14">
<compile files="GenericMethodITD14.aj" options="-1.5">
<message kind="error" line="10" text="Bound mismatch: The generic method crazy(List&lt;R&gt;) of type X is not applicable for the arguments (List&lt;A&gt;) since the type A is not a valid substitute for the bounded parameter &lt;R extends Object &amp; Foo&lt;? super R&gt;&gt;"/>
</compile>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="generic method itd - 15">
<compile files="GenericMethodITD15.aj" options="-1.5"/>
<run class="GenericMethodITD15"/>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="non static generic method itd - 2">
<compile files="NonstaticGenericCtorITD2.aj" options="-1.5"/>
<run class="NonstaticGenericCtorITD2"/>

+ 15
- 7
weaver/src/org/aspectj/weaver/BoundedReferenceType.java 查看文件

@@ -19,17 +19,23 @@ import org.aspectj.weaver.patterns.PerClause;
/**
* A BoundedReferenceType is the result of a generics wildcard expression
* ? extends String, ? super Foo etc..
*
* The "signature" for a bounded reference type follows the generic signature
* specification in section 4.4 of JVM spec: *,+,- plus signature strings
* specification in section 4.4 of JVM spec: *,+,- plus signature strings.
*
* The bound may be a type variable (e.g. ? super T)
*/
public class BoundedReferenceType extends ReferenceType {

protected ReferenceType[] additionalInterfaceBounds = new ReferenceType[0];
protected boolean isExtends = true;
protected boolean isSuper = false;
protected boolean isSuper = false;
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world) {
super((isExtends ? "+" : "-") + aBound.signature,world);
this.isExtends = isExtends; this.isSuper=!isExtends;
this.isExtends = isExtends;
this.isSuper = !isExtends;
if (isExtends) {
setUpperBound(aBound);
} else {
@@ -38,7 +44,7 @@ public class BoundedReferenceType extends ReferenceType {
}
setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)getUpperBound()));
}
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world, ReferenceType[] additionalInterfaces) {
this(aBound,isExtends,world);
this.additionalInterfaceBounds = additionalInterfaces;
@@ -51,20 +57,22 @@ public class BoundedReferenceType extends ReferenceType {
/**
* only for use when resolving GenericsWildcardTypeX or a TypeVariableReferenceType
*/
BoundedReferenceType(String sig, World world) {
protected BoundedReferenceType(String sig, World world) {
super(sig,world);
setUpperBound(world.resolve(UnresolvedType.OBJECT));
setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)getUpperBound()));
}
public ReferenceType[] getInterfaceBounds() { return additionalInterfaceBounds; }
public ReferenceType[] getInterfaceBounds() {
return additionalInterfaceBounds;
}
public boolean hasLowerBound() {
return getLowerBound() != null;
}
public boolean isExtends() { return isExtends; }
public boolean isSuper() { return isSuper; }
public boolean isSuper() { return isSuper; }
// override to include additional interface bounds...
public ResolvedType[] getDeclaredInterfaces() {

+ 17
- 0
weaver/src/org/aspectj/weaver/JoinPointSignature.java 查看文件

@@ -17,6 +17,7 @@ import java.util.Collection;

import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute;
import org.aspectj.weaver.Member.Kind;

/**
* @author colyer
@@ -351,4 +352,20 @@ public class JoinPointSignature implements ResolvedMember {
return buf.toString();
}

public void resetName(String newName) {
realMember.resetName(newName);
}

public void resetKind(Kind newKind) {
realMember.resetKind(newKind);
}
public void resetModifiers(int newModifiers) {
realMember.resetModifiers(newModifiers);
}
public void resetReturnTypeToObjectArray() {
realMember.resetReturnTypeToObjectArray();
}

}

+ 6
- 6
weaver/src/org/aspectj/weaver/MemberImpl.java 查看文件

@@ -21,14 +21,14 @@ import java.util.Iterator;
import java.util.List;


public class MemberImpl implements Comparable, AnnotatedElement, Member {
public class MemberImpl implements Comparable, AnnotatedElement,Member {
private final Kind kind;
protected Kind kind;
protected UnresolvedType declaringType;
protected final int modifiers; // protected because ResolvedMember uses it
private final UnresolvedType returnType;
private final String name;
private final UnresolvedType[] parameterTypes;
protected int modifiers;
protected UnresolvedType returnType;
protected String name;
protected UnresolvedType[] parameterTypes;
private final String signature;
private final String declaredSignature; // TODO asc Is this redundant? Is it needed for generics?
private String paramSignature;

+ 6
- 1
weaver/src/org/aspectj/weaver/ResolvedMember.java 查看文件

@@ -17,6 +17,7 @@ import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.Member.Kind;

public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDeclaringElement {

@@ -135,5 +136,9 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe
* variable to match any other type variable regardless of bounds.
*/
public boolean matches(ResolvedMember aCandidateMatch);

public void resetName(String newName);
public void resetKind(Kind newKind);
public void resetModifiers(int newModifiers);
public void resetReturnTypeToObjectArray();
}

+ 31
- 4
weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java 查看文件

@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Set;

import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.Member.Kind;

/**
* This is the declared member, i.e. it will always correspond to an
@@ -266,7 +267,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno
}

public boolean hasAnnotation(UnresolvedType ofType) {
// The ctors don't allow annotations to be specified ... yet - but
// The ctors don't allow annotations to be specified ... yet - but
// that doesn't mean it is an error to call this method.
// Normally the weaver will be working with subtypes of
// this type - BcelField/BcelMethod
@@ -372,7 +373,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno
public ResolvedMember resolve(World world) {
// FIXME asc guard with a check on resolution having happened !
// make sure all the pieces of a resolvedmember really are resolved
if (annotationTypes!=null) {
Set r = new HashSet();
for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) {
@@ -383,7 +384,20 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno
}
declaringType = declaringType.resolve(world);
if (declaringType.isRawType()) declaringType = ((ReferenceType)declaringType).getGenericType();
return this;
if (typeVariables!=null && typeVariables.length>0) {
for (int i = 0; i < typeVariables.length; i++) {
UnresolvedType array_element = typeVariables[i];
typeVariables[i] = typeVariables[i].resolve(world);
}
}
if (parameterTypes!=null && parameterTypes.length>0) {
for (int i = 0; i < parameterTypes.length; i++) {
UnresolvedType array_element = parameterTypes[i];
parameterTypes[i] = parameterTypes[i].resolve(world);
}
}
returnType = returnType.resolve(world);return this;
}
public ISourceContext getSourceContext(World world) {
@@ -587,7 +601,20 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno
private ResolvedMember myErasure = null;
private boolean calculatedMyErasure = false;


/**
* For ITDs, we use the default factory methods to build a resolved member, then alter a couple of characteristics
* using this method - this is safe.
*/
public void resetName(String newName) {this.name = newName;}
public void resetKind(Kind newKind) {this.kind=newKind; }
public void resetModifiers(int newModifiers) {this.modifiers=newModifiers;}

public void resetReturnTypeToObjectArray() {
returnType = UnresolvedType.OBJECTARRAY;
}
/**
* Returns a copy of this member but with the declaring type swapped.
* Copy only needs to be shallow.

+ 8
- 1
weaver/src/org/aspectj/weaver/TypeFactory.java 查看文件

@@ -38,7 +38,7 @@ public class TypeFactory {
ResolvedType baseType = aBaseType;
if (!aBaseType.isGenericType()) {
// try and find the generic type...
if (someTypeParameters != null) {
if (someTypeParameters != null && someTypeParameters.length>0) {
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");
@@ -50,6 +50,13 @@ public class TypeFactory {
return (ReferenceType) pType.resolve(inAWorld);
}
/**
* Create an *unresolved* parameterized version of a generic type.
*/
public static UnresolvedType createUnresolvedParameterizedType(String sig,String erasuresig,UnresolvedType[] arguments) {
return new UnresolvedType(sig,erasuresig,arguments);
}

public static ReferenceType createRawType(
ResolvedType aBaseType,
World inAWorld

+ 6
- 0
weaver/src/org/aspectj/weaver/TypeVariable.java 查看文件

@@ -25,6 +25,9 @@ public class TypeVariable {
*/
private boolean isResolved = false;
private boolean beingResolved = false;
/**
* the name of the type variable as recorded in the generic signature
*/
@@ -93,6 +96,8 @@ public class TypeVariable {
* resolve all the bounds of this type variable
*/
public void resolve(World inSomeWorld) {
if (beingResolved) { return; } // avoid spiral of death
beingResolved = true;
if (isResolved) return;
upperBound = upperBound.resolve(inSomeWorld);
@@ -103,6 +108,7 @@ public class TypeVariable {
}
isResolved = true;
beingResolved = false;
}
/**

+ 24
- 9
weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java 查看文件

@@ -23,18 +23,29 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T
World aWorld) {
super(aTypeVariable.getUpperBound().getSignature(),aWorld);
this.typeVariable = aTypeVariable;
this.isExtends = false;
this.isSuper = false;
setUpperBound(aTypeVariable.getUpperBound());
setLowerBound(aTypeVariable.getLowerBound());
UnresolvedType[] ifBounds = aTypeVariable.getAdditionalInterfaceBounds();
if (ifBounds.length > 0) {
this.additionalInterfaceBounds = new ReferenceType[ifBounds.length];
this.isExtends = false;
this.isSuper = false;
setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)aTypeVariable.getUpperBound()));
}
public UnresolvedType getUpperBound() {
if (typeVariable==null) return super.getUpperBound();
return typeVariable.getUpperBound();
}
public UnresolvedType getLowerBound() {
return typeVariable.getLowerBound();
}
public ReferenceType[] getAdditionalBounds() {
if (additionalInterfaceBounds ==null && typeVariable.getAdditionalInterfaceBounds()!=null) {
UnresolvedType [] ifBounds = typeVariable.getAdditionalInterfaceBounds();
additionalInterfaceBounds = new ReferenceType[ifBounds.length];
for (int i = 0; i < ifBounds.length; i++) {
this.additionalInterfaceBounds[i] = (ReferenceType) ifBounds[i];
additionalInterfaceBounds[i] = (ReferenceType) ifBounds[i];
}
}
setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)aTypeVariable.getUpperBound()));
return additionalInterfaceBounds;
}
public TypeVariable getTypeVariable() {
@@ -45,6 +56,10 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T
return true;
}
// public ResolvedType resolve(World world) {
// return super.resolve(world);
//}
/**
* return the signature for a *REFERENCE* to a type variable, which is simply:
* Tname;

+ 3
- 1
weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java 查看文件

@@ -37,7 +37,9 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen
}
public ResolvedType resolve(World world) {
if (typeVariable == null) return ResolvedType.MISSING;
if (typeVariable == null) {
throw new BCException("Cannot resolve this type variable reference, the type variable has not been set!");
}
typeVariable.resolve(world);
return new TypeVariableReferenceType(typeVariable,world);
}

+ 22
- 6
weaver/src/org/aspectj/weaver/World.java 查看文件

@@ -249,7 +249,7 @@ public abstract class World implements Dump.INode {
/**
* Resolve to a ReferenceType - simple, raw, parameterized, or generic.
* Raw, parmeterized, and generic versions of a type share a delegate.
* Raw, parameterized, and generic versions of a type share a delegate.
*/
private final ResolvedType resolveToReferenceType(UnresolvedType ty) {
if (ty.isParameterizedType()) {
@@ -309,6 +309,17 @@ public abstract class World implements Dump.INode {
// raw type from a source type, it won't if its been created just through
// being referenced, e.g. java.util.List
ResolvedType genericType = rawType.getGenericType();
// There is a special case to consider here (testGenericsBang_pr95993 highlights it)
// You may have an unresolvedType for a parameterized type but it
// is backed by a simple type rather than a generic type. This occurs for
// inner types of generic types that inherit their enclosing types
// type variables.
if (rawType.isSimpleType() && anUnresolvedType.typeParameters.length==0) {
rawType.world = this;
return rawType;
}
if (genericType != null) {
genericType.world = this;
return genericType;
@@ -324,18 +335,23 @@ public abstract class World implements Dump.INode {
}
}

// we have a generic wildcard with either extends or super, resolves to a
// BoundedReferenceType
/**
* Go from an unresolved generic wildcard (represented by UnresolvedType) to a resolved version (BoundedReferenceType).
*/
private ReferenceType resolveGenericWildcardFor(UnresolvedType aType) {
BoundedReferenceType ret = null;
// FIXME asc isExtends? isGenericWildcardExtends? I dont like having two
// FIXME asc doesnt take account of additional interface bounds (e.g. ? super R & Serializable - can you do that?)
if (aType.isGenericWildcardExtends()) {
ReferenceType upperBound = (ReferenceType) resolve(aType.getUpperBound());
ReferenceType upperBound = (ReferenceType)resolve(aType.getUpperBound());
ret = new BoundedReferenceType(upperBound,true,this);
} else {
} else {
ReferenceType lowerBound = (ReferenceType) resolve(aType.getLowerBound());
ret = new BoundedReferenceType(lowerBound,false,this);
}
typeMap.put(aType.getSignature(),ret);
// FIXME asc verify: I don't think these go in the typemap, it makes it potentially impossible to differentiate different uses of 'T',
// for example '? super T' where T is representing different things in two places would have the same sig (-TT;)
// typeMap.put(aType.getSignature(),ret);
return ret;
}

Loading…
取消
儲存