diff options
author | aclement <aclement> | 2005-10-11 08:25:03 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-10-11 08:25:03 +0000 |
commit | 0a69e42808527ec7daa32ec2d4bbf183ca8b4f4b (patch) | |
tree | 7c0602405c4b5297996255190dcf3a47423c5acc | |
parent | 074261689aede2fdb288e2fe2615bca466cfc098 (diff) | |
download | aspectj-0a69e42808527ec7daa32ec2d4bbf183ca8b4f4b.tar.gz aspectj-0a69e42808527ec7daa32ec2d4bbf183ca8b4f4b.zip |
generic itds - see pr112105
24 files changed, 473 insertions, 104 deletions
diff --git a/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/AjTypeTestsWithAspects.java b/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/AjTypeTestsWithAspects.java index d2fad06b0..7b15d3e64 100644 --- a/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/AjTypeTestsWithAspects.java +++ b/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/AjTypeTestsWithAspects.java @@ -17,7 +17,6 @@ import java.lang.reflect.Modifier; import junit.framework.TestCase; import org.aspectj.internal.lang.annotation.ajcDeclareEoW; -import org.aspectj.internal.lang.annotation.ajcITD; import org.aspectj.internal.lang.annotation.ajcPrivileged; import org.aspectj.lang.annotation.AdviceName; import org.aspectj.lang.annotation.After; diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java index a9776e410..58e650286 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java @@ -47,7 +47,6 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.PackageBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits; @@ -57,7 +56,6 @@ import org.aspectj.weaver.AsmRelationshipProvider; import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.ReferenceType; import org.aspectj.weaver.ResolvedType; -import org.aspectj.weaver.ResolvedTypeMunger; import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.WeaverStateInfo; @@ -543,6 +541,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC needOldStyleWarning = false; } onType.addInterTypeMunger(munger); + /* //TODO: Andy Should be done at weave time. // Unfortunately we can't do it at weave time unless the type mungers remember where // they came from. Thats why we do it here during complation because at this time @@ -554,6 +553,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC // AsmRelationshipProvider (see BCELTypeMunger) if (!ResolvedTypeMunger.persistSourceLocation) // Do it up front if we bloody have to AsmInterTypeRelationshipProvider.getDefault().addRelationship(onType, munger); + */ } } @@ -863,7 +863,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC needFieldsAndMethods, accessRestriction); factory.getWorld().validateType(factory.fromBinding(ret)); - // if you need the bytes to pass to validate, here they are:ClassFileReader)binaryType).getReferenceBytes() + // if you need the bytes to pass to validate, here they are:((ClassFileReader)binaryType).getReferenceBytes() weaveInterTypeDeclarations(ret); return ret; } finally { diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java index ac65d16ec..2c49f86ee 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java @@ -464,10 +464,11 @@ public class EclipseFactory { ret.setVarargsMethod(); } if (typeVariablesForThisMember.size()!=0) { - UnresolvedType[] tvars = new UnresolvedType[typeVariablesForThisMember.size()]; + // SAUSAGES this might be broken with the change for resolved members to own type variables + TypeVariable[] tvars = new TypeVariable[typeVariablesForThisMember.size()]; int i =0; for (Iterator iter = typeVariablesForThisMember.values().iterator(); iter.hasNext();) { - tvars[i++] = (UnresolvedType)iter.next(); + tvars[i++] = ((TypeVariableReference)((UnresolvedType)iter.next())).getTypeVariable(); } ret.setTypeVariables(tvars); } @@ -621,7 +622,7 @@ public class EclipseFactory { if (member.getTypeVariables().length==0) { tvbs = MethodBinding.NoTypeVariables; } else { - tvbs = makeTypeVariableBindings(member.getTypeVariables()); + tvbs = makeTypeVariableBindingsFromAJTypeVariables(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]; @@ -661,6 +662,15 @@ public class EclipseFactory { } return ret; } + + private TypeVariableBinding[] makeTypeVariableBindingsFromAJTypeVariables(TypeVariable[] typeVariables) { + int len = typeVariables.length; + TypeVariableBinding[] ret = new TypeVariableBinding[len]; + for (int i = 0; i < len; i++) { + ret[i] = makeTypeVariableBindingFromAJTypeVariable(typeVariables[i]); + } + return ret; + } // only accessed through private methods in this class. Ensures all type variables we encounter // map back to the same type binding - this is important later when Eclipse code is processing @@ -705,6 +715,38 @@ public class EclipseFactory { } return tvBinding; } + + private TypeVariableBinding makeTypeVariableBindingFromAJTypeVariable(TypeVariable tv) { + TypeVariableBinding tvBinding = (TypeVariableBinding)typeVariableToTypeBinding.get(tv.getName()); + if (currentType!=null) { + TypeVariableBinding tvb = currentType.getTypeVariable(tv.getName().toCharArray()); + if (tvb!=null) return tvb; + } + if (tvBinding==null) { + Binding declaringElement = null; + // this will cause an infinite loop or NPE... not required yet luckily. +// if (tVar.getDeclaringElement() instanceof Member) { +// declaringElement = makeMethodBinding((ResolvedMember)tVar.getDeclaringElement()); +// } else { +// declaringElement = makeTypeBinding((UnresolvedType)tVar.getDeclaringElement()); +// } + tvBinding = new TypeVariableBinding(tv.getName().toCharArray(),declaringElement,tv.getRank()); + typeVariableToTypeBinding.put(tv.getName(),tvBinding); + tvBinding.superclass=(ReferenceBinding)makeTypeBinding(tv.getUpperBound()); + tvBinding.firstBound=tvBinding.superclass; // FIXME asc is this correct? possibly it could be first superinterface + if (tv.getAdditionalInterfaceBounds()==null) { + tvBinding.superInterfaces=TypeVariableBinding.NoSuperInterfaces; + } else { + TypeBinding tbs[] = makeTypeBindings(tv.getAdditionalInterfaceBounds()); + ReferenceBinding[] rbs= new ReferenceBinding[tbs.length]; + for (int i = 0; i < tbs.length; i++) { + rbs[i] = (ReferenceBinding)tbs[i]; + } + tvBinding.superInterfaces=rbs; + } + } + return tvBinding; + } public MethodBinding makeMethodBindingForCall(Member member) { return new MethodBinding(member.getCallsiteModifiers(), diff --git a/tests/.classpath b/tests/.classpath index 042f58fb3..3d4d909eb 100644 --- a/tests/.classpath +++ b/tests/.classpath @@ -14,5 +14,6 @@ <classpathentry kind="lib" path="/lib/ant/lib/ant-launcher.jar"/> <classpathentry kind="src" path="testsrc"/> <classpathentry kind="var" path="JAVA_HOME/lib/tools.jar"/> + <classpathentry combineaccessrules="false" kind="src" path="/weaver"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/tests/java5/generics/itds/design/DesignA.java b/tests/java5/generics/itds/design/DesignA.java new file mode 100644 index 000000000..9d7b4056b --- /dev/null +++ b/tests/java5/generics/itds/design/DesignA.java @@ -0,0 +1,6 @@ +class C { +} + +aspect X { + <T> void C.m(T t) {} +} diff --git a/tests/java5/generics/itds/design/DesignB.java b/tests/java5/generics/itds/design/DesignB.java new file mode 100644 index 000000000..5b86a11c3 --- /dev/null +++ b/tests/java5/generics/itds/design/DesignB.java @@ -0,0 +1,12 @@ +class C {} + +interface I {} + +aspect X { + + <T extends Number> void C.m0(T t) {} // L7 + + <Q extends I> void C.m1(Q q) {} // L9 + + <R extends Number,I> void C.m2(R r) {} // L11 +} diff --git a/tests/java5/generics/itds/design/DesignC.java b/tests/java5/generics/itds/design/DesignC.java new file mode 100644 index 000000000..8e25e9f56 --- /dev/null +++ b/tests/java5/generics/itds/design/DesignC.java @@ -0,0 +1,10 @@ +class C {} + +interface I {} + +aspect X { + + <T extends Number,Q extends I> void C.m0(T t,Q q) {} // L7 + + <A,B,C> List<A> C.m1(B b,Collection<C> cs) {} // L9 +} diff --git a/tests/multiIncremental/PR111779/inc1/Bar.aj b/tests/multiIncremental/PR111779/inc1/Bar.aj index 3372a5428..804d562bf 100644 --- a/tests/multiIncremental/PR111779/inc1/Bar.aj +++ b/tests/multiIncremental/PR111779/inc1/Bar.aj @@ -1,6 +1,7 @@ import java.util.*; public aspect Bar { + private List<String> Foo.l; diff --git a/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java b/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java index a3366f74d..0f457c739 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java +++ b/tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java @@ -47,6 +47,7 @@ public class AllTestsAspectJ150 { suite.addTest(SuppressedWarnings.suite()); suite.addTest(DeclareAnnotationTests.suite()); suite.addTest(GenericsTests.suite()); + suite.addTest(GenericITDsDesign.suite()); suite.addTest(AtAjSyntaxTests.suite()); suite.addTest(AtAjMisuseTests.suite()); suite.addTest(AtAjLTWTests.suite()); diff --git a/tests/src/org/aspectj/systemtest/ajc150/GenericITDsDesign.java b/tests/src/org/aspectj/systemtest/ajc150/GenericITDsDesign.java new file mode 100644 index 000000000..a2cf92c07 --- /dev/null +++ b/tests/src/org/aspectj/systemtest/ajc150/GenericITDsDesign.java @@ -0,0 +1,167 @@ +package org.aspectj.systemtest.ajc150; + +import java.io.File; +import java.util.Iterator; +import java.util.List; + +import junit.framework.Test; + +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.classfile.Signature; +import org.aspectj.apache.bcel.util.ClassPath; +import org.aspectj.apache.bcel.util.SyntheticRepository; +import org.aspectj.testing.XMLBasedAjcTestCase; +import org.aspectj.tools.ajc.Ajc; +import org.aspectj.weaver.CrosscuttingMembers; +import org.aspectj.weaver.ReferenceType; +import org.aspectj.weaver.ResolvedMember; +import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.ResolvedTypeMunger; +import org.aspectj.weaver.TypeVariable; +import org.aspectj.weaver.TypeVariableReference; +import org.aspectj.weaver.World; +import org.aspectj.weaver.bcel.BcelTypeMunger; +import org.aspectj.weaver.bcel.BcelWorld; + +public class GenericITDsDesign extends XMLBasedAjcTestCase { + + private World recentWorld; + + public static Test suite() { + return XMLBasedAjcTestCase.loadSuite(GenericITDsDesign.class); + } + + protected File getSpecFile() { + return new File("../tests/src/org/aspectj/systemtest/ajc150/ajc150.xml"); + } + + public static Signature getClassSignature(Ajc ajc,String classname) { + try { + ClassPath cp = + new ClassPath(ajc.getSandboxDirectory() + File.pathSeparator + System.getProperty("java.class.path")); + SyntheticRepository sRepos = SyntheticRepository.getInstance(cp); + JavaClass clazz = sRepos.loadClass(classname); + Signature sigAttr = null; + Attribute[] attrs = clazz.getAttributes(); + for (int i = 0; i < attrs.length; i++) { + Attribute attribute = attrs[i]; + if (attribute.getName().equals("Signature")) sigAttr = (Signature)attribute; + } + return sigAttr; + } catch (ClassNotFoundException e) { + fail("Couldn't find class "+classname+" in the sandbox directory."); + } + return null; + } + // Check the signature attribute on a class is correct + public static void verifyClassSignature(Ajc ajc,String classname,String sig) { + Signature sigAttr = getClassSignature(ajc,classname); + assertTrue("Failed to find signature attribute for class "+classname,sigAttr!=null); + assertTrue("Expected signature to be '"+sig+"' but was '"+sigAttr.getSignature()+"'", + sigAttr.getSignature().equals(sig)); + } + + public List /*BcelTypeMunger*/ getTypeMunger(String classname) { + ClassPath cp = + new ClassPath(ajc.getSandboxDirectory() + File.pathSeparator + + System.getProperty("java.class.path")); + recentWorld = new BcelWorld(cp.toString()); + ReferenceType resolvedType = (ReferenceType)recentWorld.resolve(classname); + CrosscuttingMembers cmembers = resolvedType.collectCrosscuttingMembers(); + List tmungers = cmembers.getTypeMungers(); + return tmungers; + } + + private BcelTypeMunger getMungerFromLine(String classname,int linenumber) { + List allMungers = getTypeMunger(classname); + for (Iterator iter = allMungers.iterator(); iter.hasNext();) { + BcelTypeMunger element = (BcelTypeMunger) iter.next(); + if (element.getMunger().getSourceLocation().getLine()==linenumber) return element; + } + for (Iterator iter = allMungers.iterator(); iter.hasNext();) { + BcelTypeMunger element = (BcelTypeMunger) iter.next(); + System.err.println("Line: "+element.getMunger().getSourceLocation().getLine()+" > "+element); + } + fail("Couldn't find a type munger from line "+linenumber+" in class "+classname); + return null; + } + /* + test plan: + 1. Serializing and recovering 'default bounds' type variable info: + a. methods + b. fields + c. ctors + 2. Serializing and recovering 'extends' with a class bounded type variable info: + a. methods + b. fields + c. ctors + 3. Serializing and recovering 'extends' with an interface bounded type variable info: + a. methods + b. fields + c. ctors + 4. Multiple interface bounds + a. methods + b. fields + c. ctors + 5. wildcard bounds '? extends/? super' + a. methods + b. fields + c. ctors + 6. using type variables in an ITD from the containing aspect, no bounds + a. methods + b. fields + c. ctors + + + */ + + + // Verify: a) After storing it in a class file and recovering it (through deserialization), we can see the type + // variable and that the parameter refers to the type variable. + public void testDesignA() { + runTest("generic itds - design A"); + BcelTypeMunger theBcelMunger = getMungerFromLine("X",5); + ResolvedType typeC = recentWorld.resolve("C"); + ResolvedTypeMunger rtMunger = theBcelMunger.getMunger(); + ResolvedMember theMember = rtMunger.getSignature(); + // Let's check all parts of the member + assertTrue("Declaring type should be C: "+theMember, + theMember.getDeclaringType().equals(typeC)); + + TypeVariable tVar = theMember.getTypeVariables()[0]; + TypeVariableReference tvrt = (TypeVariableReference)theMember.getParameterTypes()[0]; + + theMember.resolve(recentWorld); // resolution will join the type variables together (i.e. make them refer to the same instance) + + tVar = theMember.getTypeVariables()[0]; + tvrt = (TypeVariableReference)theMember.getParameterTypes()[0]; + + assertTrue("Post resolution, the type variable in the parameter should be identical to the type variable declared on the member", + tVar==tvrt.getTypeVariable()); + } + + // Verify: bounds are preserved and accessible after serialization + public void xtestDesignB() { + runTest("generic itds - design B"); + BcelTypeMunger theBcelMunger = getMungerFromLine("X",7); + } + + // Verify: a) multiple type variables work. + // b) type variables below the 'top level' (e.g. List<A>) are preserved. + public void xtestDesignC() { + runTest("generic itds - design B"); + BcelTypeMunger theBcelMunger = getMungerFromLine("X",7); + } + + + /* + * broken stuff: + * + * When generic signatures are unpacked from members, the typevariables attached to the bcelmethod/field won't + * be the same instances as those held in the TypeVariableReferenceTypes for anything that occurs in the + * return type or parameterset - we should perhaps fix that up. + */ + + +} diff --git a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml index db6fb07c2..703c1b3fc 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml @@ -5024,4 +5024,19 @@ </stdout> </run> </ajc-test> + + <!-- generic ITDs --> + + <ajc-test dir="java5/generics/itds/design" title="generic itds - design A"> + <compile files="DesignA.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="java5/generics/itds/design" title="generic itds - design B"> + <compile files="DesignB.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="java5/generics/itds/design" title="generic itds - design C"> + <compile files="DesignC.java" options="-1.5"/> + </ajc-test> + </suite>
\ No newline at end of file diff --git a/tests/src/org/aspectj/systemtest/incremental/tools/AjdeInteractionTestbed.java b/tests/src/org/aspectj/systemtest/incremental/tools/AjdeInteractionTestbed.java index 571d04ba0..902028862 100644 --- a/tests/src/org/aspectj/systemtest/incremental/tools/AjdeInteractionTestbed.java +++ b/tests/src/org/aspectj/systemtest/incremental/tools/AjdeInteractionTestbed.java @@ -663,7 +663,7 @@ public class AjdeInteractionTestbed extends TestCase { } public String getSourceCompatibilityLevel() { - return null; + return "1.5"; } public Set getWarnings() { diff --git a/tests/src/org/aspectj/systemtest/incremental/tools/MultiProjectIncrementalTests.java b/tests/src/org/aspectj/systemtest/incremental/tools/MultiProjectIncrementalTests.java index 7043a40a4..706410f40 100644 --- a/tests/src/org/aspectj/systemtest/incremental/tools/MultiProjectIncrementalTests.java +++ b/tests/src/org/aspectj/systemtest/incremental/tools/MultiProjectIncrementalTests.java @@ -289,12 +289,14 @@ public class MultiProjectIncrementalTests extends AjdeInteractionTestbed { } /* public void testPr111779() { + super.VERBOSE=true; initialiseProject("PR111779"); build("PR111779"); alter("PR111779","inc1"); build("PR111779"); } */ + // other possible tests: // - memory usage (freemem calls?) diff --git a/weaver/src/org/aspectj/weaver/JoinPointSignature.java b/weaver/src/org/aspectj/weaver/JoinPointSignature.java index 92b7fadf0..7b3689173 100644 --- a/weaver/src/org/aspectj/weaver/JoinPointSignature.java +++ b/weaver/src/org/aspectj/weaver/JoinPointSignature.java @@ -202,13 +202,17 @@ public class JoinPointSignature implements ResolvedMember { return realMember.parameterizedWith(typeParameters, newDeclaringType, isParameterized); } - public void setTypeVariables(UnresolvedType[] types) { + public void setTypeVariables(TypeVariable[] types) { realMember.setTypeVariables(types); } - public UnresolvedType[] getTypeVariables() { + public TypeVariable[] getTypeVariables() { return realMember.getTypeVariables(); } + + public TypeVariable getTypeVariableNamed(String name) { + return realMember.getTypeVariableNamed(name); + } public ResolvedMember getErasure() { throw new UnsupportedOperationException("Adrian doesn't think you should be asking for the erasure of one of these..."); diff --git a/weaver/src/org/aspectj/weaver/ResolvedMember.java b/weaver/src/org/aspectj/weaver/ResolvedMember.java index 44507e5c1..24736d403 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedMember.java +++ b/weaver/src/org/aspectj/weaver/ResolvedMember.java @@ -113,9 +113,9 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe UnresolvedType[] typeParameters, ResolvedType newDeclaringType, boolean isParameterized); - public void setTypeVariables(UnresolvedType[] types); + public void setTypeVariables(TypeVariable[] types); - public UnresolvedType[] getTypeVariables(); + public TypeVariable[] getTypeVariables(); /** * If this member is defined by a parameterized super-type, return the erasure diff --git a/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java b/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java index 23a2e57c4..855d6bf75 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java +++ b/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java @@ -50,7 +50,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno private boolean isAjSynthetic = true; // generic methods have type variables - private UnresolvedType[] typeVariables; + private TypeVariable[] typeVariables; // these three fields hold the source location of this member protected int start, end; @@ -385,9 +385,10 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno int tvcount = s.readInt(); if (tvcount!=0) { - m.typeVariables = new UnresolvedType[tvcount]; + m.typeVariables = new TypeVariable[tvcount]; for (int i=0;i<tvcount;i++) { - m.typeVariables[i]=UnresolvedType.read(s); + m.typeVariables[i]=TypeVariable.read(s); + m.typeVariables[i].setDeclaringElement(m); } } } @@ -407,30 +408,37 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno public ResolvedMember resolve(World world) { // 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();) { - UnresolvedType element = (UnresolvedType) iter.next(); - r.add(world.resolve(element)); - } - annotationTypes = r; - } - declaringType = declaringType.resolve(world); - if (declaringType.isRawType()) declaringType = ((ReferenceType)declaringType).getGenericType(); - 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); + try { + if (typeVariables!=null && typeVariables.length>0) { + for (int i = 0; i < typeVariables.length; i++) { + typeVariables[i] = typeVariables[i].resolve(world); + } } + world.setTypeVariableLookupScope(this); + if (annotationTypes!=null) { + Set r = new HashSet(); + for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) { + UnresolvedType element = (UnresolvedType) iter.next(); + r.add(world.resolve(element)); + } + annotationTypes = r; + } + declaringType = declaringType.resolve(world); + if (declaringType.isRawType()) declaringType = ((ReferenceType)declaringType).getGenericType(); + + 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); + parameterTypes[i] = parameterTypes[i].resolve(world); + } + } + + returnType = returnType.resolve(world); + } finally { + world.setTypeVariableLookupScope(null); } - - returnType = returnType.resolve(world);return this; + return this; } public ISourceContext getSourceContext(World world) { @@ -567,11 +575,11 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno } - public void setTypeVariables(UnresolvedType[] types) { - typeVariables = types; + public void setTypeVariables(TypeVariable[] tvars) { + typeVariables = tvars; } - public UnresolvedType[] getTypeVariables() { + public TypeVariable[] getTypeVariables() { return typeVariables; } @@ -758,5 +766,20 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno } return buf.toString(); } + + + + public TypeVariable getTypeVariableNamed(String name) { + // Check locally... + if (typeVariables!=null) { + for (int i = 0; i < typeVariables.length; i++) { + if (typeVariables[i].getName().equals(name)) return typeVariables[i]; + } + } + // Bugger, check the declaring type! + return declaringType.getTypeVariableNamed(name); + + // Do generic aspects with ITDs that share type variables with the aspect and the target type and have their own tvars cause this to be messier? + } } diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java index 8b0de53a4..125e436f4 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java @@ -47,8 +47,6 @@ public abstract class ResolvedTypeMunger { // might need serializing the class file for binary weaving. protected List /*String*/ typeVariableToGenericTypeVariableIndex; - public static transient boolean persistSourceLocation = true; - private Set /* resolvedMembers */ superMethodsCalled = Collections.EMPTY_SET; private ISourceLocation location; // Lost during serialize/deserialize ! @@ -138,6 +136,7 @@ public abstract class ResolvedTypeMunger { Set ret = new HashSet(); int n = s.readInt(); + if (n<0) throw new BCException("Problem deserializing type munger"); for (int i=0; i < n; i++) { ret.add(ResolvedMemberImpl.readResolvedMember(s, null)); } @@ -146,7 +145,7 @@ public abstract class ResolvedTypeMunger { protected void writeSuperMethodsCalled(DataOutputStream s) throws IOException { - if (superMethodsCalled == null) { + if (superMethodsCalled == null || superMethodsCalled.size()==0) { s.writeInt(0); return; } @@ -163,7 +162,6 @@ public abstract class ResolvedTypeMunger { } protected static ISourceLocation readSourceLocation(VersionedDataInputStream s) throws IOException { - if (!persistSourceLocation) return null; // Location persistence for type mungers was added after 1.2.1 was shipped... if (s.getMajorVersion()<AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) return null; SourceLocation ret = null; @@ -196,7 +194,6 @@ public abstract class ResolvedTypeMunger { } protected void writeSourceLocation(DataOutputStream s) throws IOException { - if (!persistSourceLocation) return; ObjectOutputStream oos = new ObjectOutputStream(s); // oos.writeObject(location); oos.writeObject(new Boolean(location!=null)); diff --git a/weaver/src/org/aspectj/weaver/TypeVariable.java b/weaver/src/org/aspectj/weaver/TypeVariable.java index 9718179ab..1488bb25b 100644 --- a/weaver/src/org/aspectj/weaver/TypeVariable.java +++ b/weaver/src/org/aspectj/weaver/TypeVariable.java @@ -11,6 +11,8 @@ * ******************************************************************/ package org.aspectj.weaver; +import java.io.DataOutputStream; +import java.io.IOException; import java.util.HashSet; import java.util.Set; @@ -106,10 +108,10 @@ public class TypeVariable { /** * resolve all the bounds of this type variable */ - public void resolve(World inSomeWorld) { - if (beingResolved) { return; } // avoid spiral of death + public TypeVariable resolve(World inSomeWorld) { + if (beingResolved) { return this; } // avoid spiral of death beingResolved = true; - if (isResolved) return; + if (isResolved) return this; TypeVariable resolvedTVar = null; @@ -128,13 +130,14 @@ public class TypeVariable { } else { // look for type variable on method... ResolvedMember declaring = (ResolvedMember) declaringElement; - UnresolvedType[] tvrts = declaring.getTypeVariables(); + TypeVariable[] tvrts = declaring.getTypeVariables(); for (int i = 0; i < tvrts.length; i++) { - if (tvrts[i].isTypeVariableReference()) { - TypeVariableReferenceType tvrt = (TypeVariableReferenceType) tvrts[i].resolve(inSomeWorld); - TypeVariable tv = tvrt.getTypeVariable(); - if (tv.getName().equals(getName())) resolvedTVar = tv; - } + if (tvrts[i].getName().equals(getName())) resolvedTVar = tvrts[i]; +// if (tvrts[i].isTypeVariableReference()) { +// TypeVariableReferenceType tvrt = (TypeVariableReferenceType) tvrts[i].resolve(inSomeWorld); +// TypeVariable tv = tvrt.getTypeVariable(); +// if (tv.getName().equals(getName())) resolvedTVar = tv; +// } } } @@ -155,12 +158,14 @@ public class TypeVariable { upperBound = upperBound.resolve(inSomeWorld); if (lowerBound != null) lowerBound = lowerBound.resolve(inSomeWorld); - for (int i = 0; i < additionalInterfaceBounds.length; i++) { - additionalInterfaceBounds[i] = additionalInterfaceBounds[i].resolve(inSomeWorld); + if (additionalInterfaceBounds!=null) { + for (int i = 0; i < additionalInterfaceBounds.length; i++) { + additionalInterfaceBounds[i] = additionalInterfaceBounds[i].resolve(inSomeWorld); + } } - isResolved = true; beingResolved = false; + return this; } /** @@ -320,4 +325,37 @@ public class TypeVariable { return declaringElementKind; } + public void write(DataOutputStream s) throws IOException { + // name, upperbound, additionalInterfaceBounds, lowerbound + s.writeUTF(name); + upperBound.write(s); + if (additionalInterfaceBounds==null || additionalInterfaceBounds.length==0) { + s.writeInt(0); + } else { + s.writeInt(additionalInterfaceBounds.length); + for (int i = 0; i < additionalInterfaceBounds.length; i++) { + UnresolvedType ibound = additionalInterfaceBounds[i]; + ibound.write(s); + } + } + } + + public static TypeVariable read(VersionedDataInputStream s) throws IOException { + + //if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) { + + String name = s.readUTF(); + UnresolvedType ubound = UnresolvedType.read(s); + int iboundcount = s.readInt(); + UnresolvedType[] ibounds = null; + if (iboundcount>0) { + ibounds = new UnresolvedType[iboundcount]; + for (int i=0; i<iboundcount; i++) { + ibounds[i] = UnresolvedType.read(s); + } + } + + TypeVariable newVariable = new TypeVariable(name,ubound,ibounds); + return newVariable; + } } diff --git a/weaver/src/org/aspectj/weaver/TypeVariableDeclaringElement.java b/weaver/src/org/aspectj/weaver/TypeVariableDeclaringElement.java index 618c87dba..6a4a17ac8 100644 --- a/weaver/src/org/aspectj/weaver/TypeVariableDeclaringElement.java +++ b/weaver/src/org/aspectj/weaver/TypeVariableDeclaringElement.java @@ -19,5 +19,5 @@ package org.aspectj.weaver; * the declaring element */ public interface TypeVariableDeclaringElement { - + public TypeVariable getTypeVariableNamed(String name); } diff --git a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java index f5e5e3306..59b3b1b19 100644 --- a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java +++ b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java @@ -22,6 +22,12 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T private TypeVariable typeVariable; private boolean resolvedIfBounds = false; + // If 'fixedUp' then the type variable in here is a reference to the real one that may + // exist either on a member or a type. Not fixedUp means that we unpacked a generic + // signature and weren't able to fix it up during resolution (didn't quite know enough + // at the right time). Wonder if we can fix it up late? + boolean fixedUp = false; + public TypeVariableReferenceType( TypeVariable aTypeVariable, World aWorld) { @@ -62,6 +68,7 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T } public TypeVariable getTypeVariable() { + // if (!fixedUp) throw new BCException("ARGH"); // SAUSAGES - fix it up now? return typeVariable; } @@ -104,17 +111,17 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T public void write(DataOutputStream s) throws IOException { super.write(s); - TypeVariableDeclaringElement tvde = typeVariable.getDeclaringElement(); - if (tvde == null) { - s.writeInt(TypeVariable.UNKNOWN); - } else { - s.writeInt(typeVariable.getDeclaringElementKind()); - if (typeVariable.getDeclaringElementKind() == TypeVariable.TYPE) { - ((UnresolvedType)tvde).write(s); - } else if (typeVariable.getDeclaringElementKind() == TypeVariable.METHOD){ - // it's a method - ((ResolvedMember)tvde).write(s); - } - } +// TypeVariableDeclaringElement tvde = typeVariable.getDeclaringElement(); +// if (tvde == null) { +// s.writeInt(TypeVariable.UNKNOWN); +// } else { +// s.writeInt(typeVariable.getDeclaringElementKind()); +// if (typeVariable.getDeclaringElementKind() == TypeVariable.TYPE) { +// ((UnresolvedType)tvde).write(s); +// } else if (typeVariable.getDeclaringElementKind() == TypeVariable.METHOD){ +// // it's a method +// ((ResolvedMember)tvde).write(s); +// } +// } } } diff --git a/weaver/src/org/aspectj/weaver/UnresolvedType.java b/weaver/src/org/aspectj/weaver/UnresolvedType.java index e40867c8a..7b0ef3972 100644 --- a/weaver/src/org/aspectj/weaver/UnresolvedType.java +++ b/weaver/src/org/aspectj/weaver/UnresolvedType.java @@ -779,10 +779,6 @@ public class UnresolvedType implements TypeVariableDeclaringElement { return ResolvedType.MISSING; } else { UnresolvedType ret = UnresolvedType.forSignature(sig); - // ugh, this is horrid, we shouldn't know about this subclass. - if (ret instanceof UnresolvedTypeVariableReferenceType) { - UnresolvedTypeVariableReferenceType.readDeclaringElement(s, (UnresolvedTypeVariableReferenceType)ret); - } return ret; } } @@ -883,5 +879,14 @@ public class UnresolvedType implements TypeVariableDeclaringElement { throw new RuntimeException("I dont know - you should ask a resolved version of me: "+this); } + public TypeVariable getTypeVariableNamed(String name) { + if (typeVariables==null || typeVariables.length==0) return null; + for (int i = 0; i < typeVariables.length; i++) { + TypeVariable aVar = typeVariables[i]; + if (aVar.getName().equals(name)) return aVar; + } + return null; + } + } diff --git a/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java b/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java index 75eaa9710..e9db34508 100644 --- a/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java +++ b/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java @@ -11,7 +11,6 @@ * ******************************************************************/ package org.aspectj.weaver; -import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; @@ -41,13 +40,56 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen } public ResolvedType resolve(World world) { - if (typeVariable == null) { - throw new BCException("Cannot resolve this type variable reference, the type variable has not been set!"); + TypeVariableDeclaringElement typeVariableScope = world.getTypeVariableLookupScope(); + TypeVariable resolvedTypeVariable = null; + TypeVariableReferenceType tvrt = null; + if (typeVariableScope == null) { + // throw new BCException("There is no scope in which to lookup type variables!"); + // SAUSAGES correct thing to do is go bang, but to limp along, lets cope with the scope missing + resolvedTypeVariable = typeVariable.resolve(world); + tvrt = new TypeVariableReferenceType(resolvedTypeVariable,world); + } else { + boolean foundOK = false; + resolvedTypeVariable = typeVariableScope.getTypeVariableNamed(typeVariable.getName()); + // SAUSAGES remove this when the shared type var stuff is sorted + if (resolvedTypeVariable == null) { + resolvedTypeVariable = typeVariable.resolve(world); + } else { + foundOK = true; + } + tvrt = new TypeVariableReferenceType(resolvedTypeVariable,world); + tvrt.fixedUp = foundOK; } - typeVariable.resolve(world); - return new TypeVariableReferenceType(typeVariable,world); + + return tvrt; +// // SAUSAGES should really be resolved in a scope, or you won't get the type variable you really want! +// //throw new BCException("NO - UnresolvedTypeVariableReferenceTypes must be resolved in a type variable scope"); +// 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); } +// public ResolvedType resolve(World world,TypeVariableDeclaringElement tvde) { +// if (typeVariable == null) { +// throw new BCException("Cannot resolve this type variable reference, the type variable has not been set!"); +// } +// +// // SAUSAGES temporary whilst the ITD logic gets sorted out +// if (tvde == null) return new TypeVariableReferenceType(typeVariable.resolve(world),world); +// +// TypeVariable resolvedTypeVariable = tvde.getTypeVariableNamed(typeVariable.getName()); +// if (resolvedTypeVariable == null) { +// resolvedTypeVariable = typeVariable.resolve(world); +// // SAUSAGES put this in once ITDs remember the complex shared type var stuff +// // throw new BCException("Could not locate type variable '"+typeVariable.getName()+"' during resolution, scope was: "+tvde); +// } +// TypeVariableReferenceType tvrt = new TypeVariableReferenceType(resolvedTypeVariable,world); +// tvrt.fixedUp = true; +// return tvrt; +// } + public boolean isTypeVariableReference() { return true; } @@ -71,20 +113,8 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen public void write(DataOutputStream s) throws IOException { super.write(s); - TypeVariableDeclaringElement tvde = typeVariable.getDeclaringElement(); - if (tvde == null) { - s.writeInt(TypeVariable.UNKNOWN); - } else { - s.writeInt(typeVariable.getDeclaringElementKind()); - if (typeVariable.getDeclaringElementKind() == TypeVariable.TYPE) { - ((UnresolvedType)tvde).write(s); - } else if (typeVariable.getDeclaringElementKind() == TypeVariable.METHOD){ - // it's a method - ((ResolvedMember)tvde).write(s); - } - } } - + /* public static void readDeclaringElement(DataInputStream s, UnresolvedTypeVariableReferenceType utv) throws IOException { int kind = s.readInt(); @@ -97,5 +127,5 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen utv.typeVariable.setDeclaringElement(rm); } } - +*/ } diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java index 1d42e44d2..e68bcaf25 100644 --- a/weaver/src/org/aspectj/weaver/World.java +++ b/weaver/src/org/aspectj/weaver/World.java @@ -45,6 +45,9 @@ public abstract class World implements Dump.INode { /** handler for cross-reference information produced during the weaving process */ private ICrossReferenceHandler xrefHandler = null; + /** Currently 'active' scope in which to lookup (resolve) typevariable references */ + private TypeVariableDeclaringElement typeVariableLookupScope; + /** The heart of the world, a map from type signatures to resolved types */ protected TypeMap typeMap = new TypeMap(); // Signature to ResolvedType @@ -329,7 +332,7 @@ public abstract class World implements Dump.INode { // 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) { + if (rawType.isSimpleType() && (anUnresolvedType.typeParameters==null || anUnresolvedType.typeParameters.length==0)) { rawType.world = this; return rawType; } @@ -546,6 +549,15 @@ public abstract class World implements Dump.INode { public ICrossReferenceHandler getCrossReferenceHandler() { return this.xrefHandler; } + + public void setTypeVariableLookupScope(TypeVariableDeclaringElement scope) { + this.typeVariableLookupScope = scope; + } + + public TypeVariableDeclaringElement getTypeVariableLookupScope() { + return typeVariableLookupScope; + } + public List getDeclareParents() { return crosscuttingMembersSet.getDeclareParents(); diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index 0205d0a08..3d7455fb1 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -106,15 +106,12 @@ public class BcelTypeMunger extends ConcreteTypeMunger { weaver.getLazyClassGen().getOrCreateWeaverStateInfo(weaver.getReweavableMode()); info.addConcreteMunger(this); } - // Whilst type mungers aren't persisting their source locations, we add this relationship during - // compilation time (see other reference to ResolvedTypeMunger.persist) - if (ResolvedTypeMunger.persistSourceLocation) { - if (changed && worthReporting) { - if (munger.getKind().equals(ResolvedTypeMunger.Parent)) { - AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType()); - } else { - AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType()); - } + + if (changed && worthReporting) { + if (munger.getKind().equals(ResolvedTypeMunger.Parent)) { + AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType()); + } else { + AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType()); } } @@ -894,7 +891,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { boolean matchOK = true; for (int j = 0; j < memberParams.length && matchOK; j++){ UnresolvedType memberParam = memberParams[j]; - UnresolvedType lookingForParam = lookingForParams[j].resolve(aspectType.getWorld()); + UnresolvedType lookingForParam = lookingForParams[j].resolve(aspectType.getWorld()); if (lookingForParam.isTypeVariableReference()) lookingForParam = lookingForParam.getUpperBound(); if (!memberParam.equals(lookingForParam)){ matchOK=false; |