diff options
author | aclement <aclement> | 2005-10-25 11:17:21 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-10-25 11:17:21 +0000 |
commit | e638a272e0d7e886bdcac33d7ca9fafa69c1b278 (patch) | |
tree | cfd4d38e96c9ca4e4f1598ed55d303a0e2b02775 | |
parent | 76ebbc76add2abd815b3a8b5ea0beb11c94c8c49 (diff) | |
download | aspectj-e638a272e0d7e886bdcac33d7ca9fafa69c1b278.tar.gz aspectj-e638a272e0d7e886bdcac33d7ca9fafa69c1b278.zip |
some bridge method testcases and impl for 108101
-rw-r--r-- | tests/java5/generics/itds/bridgeMethods/Sub4.java | 3 | ||||
-rw-r--r-- | tests/java5/generics/itds/bridgeMethods/Super4.java | 3 | ||||
-rw-r--r-- | tests/java5/generics/itds/bridgeMethods/X1.aj | 2 | ||||
-rw-r--r-- | tests/java5/generics/itds/bridgeMethods/X2.aj | 2 | ||||
-rw-r--r-- | tests/java5/generics/itds/bridgeMethods/X3.aj | 3 | ||||
-rw-r--r-- | tests/java5/generics/itds/bridgeMethods/X4.aj | 10 | ||||
-rw-r--r-- | tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java | 150 | ||||
-rw-r--r-- | tests/src/org/aspectj/systemtest/ajc150/ajc150.xml | 73 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java | 118 |
9 files changed, 282 insertions, 82 deletions
diff --git a/tests/java5/generics/itds/bridgeMethods/Sub4.java b/tests/java5/generics/itds/bridgeMethods/Sub4.java new file mode 100644 index 000000000..ceff1638c --- /dev/null +++ b/tests/java5/generics/itds/bridgeMethods/Sub4.java @@ -0,0 +1,3 @@ +public class Sub4 { + public Integer m() {return new Integer(42);} +} diff --git a/tests/java5/generics/itds/bridgeMethods/Super4.java b/tests/java5/generics/itds/bridgeMethods/Super4.java new file mode 100644 index 000000000..cd4237a41 --- /dev/null +++ b/tests/java5/generics/itds/bridgeMethods/Super4.java @@ -0,0 +1,3 @@ +public class Super4 { + public Object m() { return null;} +} diff --git a/tests/java5/generics/itds/bridgeMethods/X1.aj b/tests/java5/generics/itds/bridgeMethods/X1.aj index 2f085de6a..5c5df61e2 100644 --- a/tests/java5/generics/itds/bridgeMethods/X1.aj +++ b/tests/java5/generics/itds/bridgeMethods/X1.aj @@ -2,7 +2,5 @@ public aspect X1 { public static void main(String []argv) { Super1 s = new Sub1(); Integer i = (Integer)s.m(); - - Util.dumpMethods("Sub1"); } } diff --git a/tests/java5/generics/itds/bridgeMethods/X2.aj b/tests/java5/generics/itds/bridgeMethods/X2.aj index ce8f1a542..11ea07c5c 100644 --- a/tests/java5/generics/itds/bridgeMethods/X2.aj +++ b/tests/java5/generics/itds/bridgeMethods/X2.aj @@ -4,7 +4,5 @@ public aspect X2 { public static void main(String []argv) { Super2 s = new Sub2(); Integer i = (Integer)s.m(); - - Util.dumpMethods("Sub2"); } } diff --git a/tests/java5/generics/itds/bridgeMethods/X3.aj b/tests/java5/generics/itds/bridgeMethods/X3.aj index 5bd400d10..e83af6b26 100644 --- a/tests/java5/generics/itds/bridgeMethods/X3.aj +++ b/tests/java5/generics/itds/bridgeMethods/X3.aj @@ -5,7 +5,6 @@ public aspect X3 { public static void main(String []argv) { Super3 s = new Sub3(); Integer i = (Integer)s.m(); - - Util.dumpMethods("Sub3"); + if (i!=42) throw new RuntimeException("Should be 42 but is "+i); } } diff --git a/tests/java5/generics/itds/bridgeMethods/X4.aj b/tests/java5/generics/itds/bridgeMethods/X4.aj new file mode 100644 index 000000000..53333c875 --- /dev/null +++ b/tests/java5/generics/itds/bridgeMethods/X4.aj @@ -0,0 +1,10 @@ +public aspect X4 { + + declare parents: Sub4 extends Super4; + + public static void main(String []argv) { + Super4 s = new Sub4(); + Integer i = (Integer)s.m(); + if (i!=42) throw new RuntimeException("Should be 42 but is "+i); + } +} diff --git a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java index a3462950a..b61e75437 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java +++ b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java @@ -1,6 +1,12 @@ package org.aspectj.systemtest.ajc150; import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; import junit.framework.Test; @@ -405,12 +411,66 @@ public class GenericsTests extends XMLBasedAjcTestCase { public void testITDBridgeMethods2Itd() {runTest("basic bridging with type vars - 2 - itd");} public void testITDBridgeMethodsPr91381() {runTest("Abstract intertype method and covariant returns");} - public void testGenericITDsBridgeMethods1() {runTest("bridge methods - 1");} - public void testGenericITDsBridgeMethods1binary() {runTest("bridge methods - 1 - binary");} - public void testGenericITDsBridgeMethods2() {runTest("bridge methods - 2");} -// public void testGenericITDsBridgeMethods2binary() {runTest("bridge methods - 2 - binary");} // pr108101 - public void testGenericITDsBridgeMethods3() {runTest("bridge methods - 3");} -// public void testGenericITDsBridgeMethods3binary() {runTest("bridge methods - 3 - binary");} // pr108101 + + // Just normal source compile of two types with a method override between them + public void testGenericITDsBridgeMethods1() { + runTest("bridge methods - 1"); + checkMethodsExist("Sub1",new String[]{ + "java.lang.Integer Sub1.m()", + "java.lang.Object Sub1.m() [BridgeMethod]"}); + } + // Now the same thing but the aspect (which doesn't do much!) is binary woven in. + public void testGenericITDsBridgeMethods1binary() { + runTest("bridge methods - 1 - binary"); + checkMethodsExist("Sub1",new String[]{ + "java.lang.Integer Sub1.m()", + "java.lang.Object Sub1.m() [BridgeMethod]"}); + } + // Now the method is put into the superclass via ITD - there should be a bridge method in the subclass + public void testGenericITDsBridgeMethods2() { + runTest("bridge methods - 2"); + checkMethodsExist("Sub2",new String[]{ + "java.lang.Integer Sub2.m()", + "java.lang.Object Sub2.m() [BridgeMethod]"}); + } + // Now the superclass ITD is done with binary weaving so the weaver (rather than compiler) has to create the bridge method + public void testGenericITDsBridgeMethods2binary() { + runTest("bridge methods - 2 - binary"); + checkMethodsExist("Sub2",new String[]{ + "java.lang.Integer Sub2.m()", + "java.lang.Object Sub2.m() [BridgeMethod]"}); + } + // Now the method is put into the subclass via ITD - there should be a bridge method alongside it in the subclass + public void testGenericITDsBridgeMethods3() { + runTest("bridge methods - 3"); + checkMethodsExist("Sub3",new String[]{ + "java.lang.Integer Sub3.m()", + "java.lang.Object Sub3.m() [BridgeMethod]"}); + } + // Now the subclass ITD is done with binary weaving - the weaver should create the necessary bridge method +// public void testGenericITDsBridgeMethods3binary() { +// runTest("bridge methods - 3 - binary"); +// checkMethodsExist("Sub3",new String[]{ +// "java.lang.Integer Sub3.m()", +// "java.lang.Object Sub3.m() [BridgeMethod]"}); +// } + // Now the two types are disconnected until the aspect supplies a declare parents relationship - + // the bridge method should still be created in the subtype + public void testGenericITDSBridgeMethods4() { + runTest("bridge methods - 4"); + checkMethodsExist("Sub4",new String[]{ + "java.lang.Integer Sub4.m()", + "java.lang.Object Sub4.m() [BridgeMethod]"}); + } + // now the aspect doing the decp between the types is applied via binary weaving - weaver should create the bridge method +// public void testGenericITDSBridgeMethods4binary() { +// runTest("bridge methods - 4 - binary"); +// checkMethodsExist("Sub4",new String[]{ +// "java.lang.Integer Sub4.m()", +// "java.lang.Object Sub4.m() [BridgeMethod]"}); +// } + + // FIXME asc need a testcase for when a decp wires two classes together and causes the subtype to need bridge methods public void testGenericITDsBridgeMethodsPR91381() {runTest("abstract intertype methods and covariant returns");} public void testGenericITDsBridgeMethodsPR91381_2() {runTest("abstract intertype methods and covariant returns - error");} @@ -745,27 +805,77 @@ public class GenericsTests extends XMLBasedAjcTestCase { public void testMultiLevelGenericAspects() { runTest("multi-level generic abstract aspects"); } - // --- helpers + + /** + * When a class has been written to the sandbox directory, you can ask this method to + * verify it contains a particular set of methods. Typically this is used to verify that + * bridge methods have been created. + */ + public void checkMethodsExist(String classname,String[] methods) { + Set methodsFound = new HashSet(); + StringBuffer debugString = new StringBuffer(); + try { + ClassLoader cl = new URLClassLoader(new URL[]{ajc.getSandboxDirectory().toURL()}); + Class clz = Class.forName(classname,false,cl); + java.lang.reflect.Method[] ms = clz.getDeclaredMethods(); + if (ms!=null) { + for (int i =0;i<ms.length;i++) { + String methodString = ms[i].getReturnType().getName()+" "+ms[i].getDeclaringClass().getName()+"."+ + ms[i].getName()+"("+stringify(ms[i].getParameterTypes())+")"+ + (ms[i].isBridge()?" [BridgeMethod]":""); + methodsFound.add(methodString); + debugString.append("[").append(methodString).append("]"); + } + } + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } - public static Signature getClassSignature(Ajc ajc,String classname) { + // check the methods specified do exist + for (int i = 0; i < methods.length; i++) { + String string = methods[i]; + if (!methodsFound.remove(string)) { + fail("Couldn't find ["+string+"] in the set of methods in "+classname+" => "+debugString); + } + } + StringBuffer unexpectedMethods = new StringBuffer(); + if (!methodsFound.isEmpty()) { + for (Iterator iter = methodsFound.iterator(); iter.hasNext();) { + String element = (String) iter.next(); + unexpectedMethods.append("[").append(element).append("]"); + } + fail("These methods weren't expected: "+unexpectedMethods); + } + + } + + public static JavaClass getClass(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; + return clazz; } catch (ClassNotFoundException e) { fail("Couldn't find class "+classname+" in the sandbox directory."); } return null; } + + public static Signature getClassSignature(Ajc ajc,String classname) { + JavaClass clazz = getClass(ajc,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; + } + // Check the signature attribute on a class is correct public static void verifyClassSignature(Ajc ajc,String classname,String sig) { Signature sigAttr = getClassSignature(ajc,classname); @@ -774,5 +884,15 @@ public class GenericsTests extends XMLBasedAjcTestCase { sigAttr.getSignature().equals(sig)); } + private static String stringify(Class[] clazzes) { + if (clazzes==null) return ""; + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < clazzes.length; i++) { + Class class1 = clazzes[i]; + if (i>0) sb.append(","); + sb.append(clazzes[i].getName()); + } + return sb.toString(); + } } diff --git a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml index 32eadcb05..703204ab0 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml @@ -3892,72 +3892,45 @@ <!-- generics/itds and bridge methods --> <ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods - 1"> - <compile files="Sub1.java,Super1.java,X1.aj,Util.java" options="-1.5"/> - <run class="X1"> - <stderr> - <line text="Number of methods defined for Sub1 is 2"/> - <line text="java.lang.Integer Sub1.m()"/> - <line text="java.lang.Object Sub1.m() [BridgeMethod]"/> - </stderr> - </run> + <compile files="Sub1.java,Super1.java,X1.aj" options="-1.5"/> + <run class="X1"/> </ajc-test> - <ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods - 1 - binary"> <compile files="Sub1.java,Super1.java" outjar="code.jar" options="-1.5"/> - <compile files="X1.aj,Util.java" inpath="code.jar" options ="-1.5"/> - <run class="X1"> - <stderr> - <line text="Number of methods defined for Sub1 is 2"/> - <line text="java.lang.Integer Sub1.m()"/> - <line text="java.lang.Object Sub1.m() [BridgeMethod]"/> - </stderr> - </run> + <compile files="X1.aj" inpath="code.jar" options ="-1.5"/> + <run class="X1"/> </ajc-test> - <ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods - 2"> - <compile files="Sub2.java,Super2.java,X2.aj,Util.java" options="-1.5"/> - <run class="X2"> - <stderr> - <line text="Number of methods defined for Sub2 is 2"/> - <line text="java.lang.Integer Sub2.m()"/> - <line text="java.lang.Object Sub2.m() [BridgeMethod]"/> - </stderr> - </run> + <compile files="Sub2.java,Super2.java,X2.aj" options="-1.5"/> + <run class="X2"/> </ajc-test> <ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods - 2 - binary"> <compile files="Sub2.java,Super2.java" outjar="code.jar" options="-1.5"/> <compile files="X2.aj,Util.java" inpath="code.jar" options ="-1.5"/> - <run class="X2"> - <stderr> - <line text="Number of methods defined for Sub2 is 2"/> - <line text="java.lang.Integer Sub2.m()"/> - <line text="java.lang.Object Sub2.m() [BridgeMethod]"/> - </stderr> - </run> + <run class="X2"/> </ajc-test> <ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods - 3"> - <compile files="Sub3.java,Super3.java,X3.aj,Util.java" options="-1.5"/> - <run class="X3"> - <stderr> - <line text="Number of methods defined for Sub3 is 2"/> - <line text="java.lang.Integer Sub3.m()"/> - <line text="java.lang.Object Sub3.m() [BridgeMethod]"/> - </stderr> - </run> + <compile files="Sub3.java,Super3.java,X3.aj" options="-1.5"/> + <run class="X3"/> </ajc-test> - <ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods - 3 - binary"> <compile files="Sub3.java,Super3.java" outjar="code.jar" options="-1.5"/> - <compile files="X3.aj,Util.java" inpath="code.jar" options ="-1.5"/> - <run class="X3"> - <stderr> - <line text="Number of methods defined for Sub3 is 2"/> - <line text="java.lang.Integer Sub3.m()"/> - <line text="java.lang.Object Sub3.m() [BridgeMethod]"/> - </stderr> - </run> + <compile files="X3.aj" inpath="code.jar" options ="-1.5"/> + <run class="X3"/> + </ajc-test> + + <ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods - 4"> + <compile files="Sub4.java,Super4.java,X4.aj" options="-1.5"/> + <run class="X4"/> </ajc-test> + <ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="bridge methods - 4 - binary"> + <compile files="Sub4.java,Super4.java" outjar="code.jar" options="-1.5"/> + <compile files="X4.aj" inpath="code.jar" options ="-1.5"/> + <run class="X4"/> + </ajc-test> + + <ajc-test dir="java5/generics/itds/bridgeMethods" vm="1.5" title="abstract intertype methods and covariant returns"> <compile files="pr91381.aj" options="-1.5"/> diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index 36b65d381..3af5d3c98 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -735,13 +735,15 @@ public class BcelTypeMunger extends ConcreteTypeMunger { ResolvedMember memberHoldingAnyAnnotations = interMethodDispatcher; ResolvedType onType = weaver.getWorld().resolve(unMangledInterMethod.getDeclaringType(),munger.getSourceLocation()); - LazyClassGen gen = weaver.getLazyClassGen(); - boolean mungingInterface = gen.isInterface(); + LazyClassGen gen = weaver.getLazyClassGen(); + boolean mungingInterface = gen.isInterface(); if (onType.isRawType()) onType = onType.getGenericType(); boolean onInterface = onType.isInterface(); + + // Simple checks, can't ITD on annotations or enums if (onType.isAnnotation()) { signalError(WeaverMessages.ITDM_ON_ANNOTATION_NOT_ALLOWED,weaver,onType); return false; @@ -752,22 +754,26 @@ public class BcelTypeMunger extends ConcreteTypeMunger { return false; } + + if (onInterface && gen.getLazyMethodGen(unMangledInterMethod.getName(), unMangledInterMethod.getSignature(),true) != null) { // this is ok, we could be providing the default implementation of a method // that the target has already declared return false; } + // If we are processing the intended ITD target type (might be an interface) if (onType.equals(gen.getType())) { + + ResolvedMember mangledInterMethod = AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, onInterface); - - LazyMethodGen mg = makeMethodGen(gen, mangledInterMethod); + LazyMethodGen newMethod = makeMethodGen(gen, mangledInterMethod); if (mungingInterface) { // we want the modifiers of the ITD to be used for all *implementors* of the // interface, but the method itself we add to the interface must be public abstract - mg.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT); + newMethod.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT); } // pr98901 @@ -787,7 +793,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { AnnotationX annotationX = annotationsOnRealMember[i]; Annotation a = annotationX.getBcelAnnotation(); AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true); - mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld())); + newMethod.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld())); } } // the below loop fixes the very special (and very stupid) @@ -797,14 +803,15 @@ public class BcelTypeMunger extends ConcreteTypeMunger { for (Iterator i = allDecams.iterator(); i.hasNext();){ DeclareAnnotation decaMC = (DeclareAnnotation) i.next(); if (decaMC.matches(unMangledInterMethod,weaver.getWorld()) - && mg.getEnclosingClass().getType() == aspectType) { - mg.addAnnotation(decaMC.getAnnotationX()); + && newMethod.getEnclosingClass().getType() == aspectType) { + newMethod.addAnnotation(decaMC.getAnnotationX()); } } } + // If it doesn't target an interface and there is a body (i.e. it isnt abstract) if (!onInterface && !Modifier.isAbstract(mangledInterMethod.getModifiers())) { - InstructionList body = mg.getBody(); + InstructionList body = newMethod.getBody(); InstructionFactory fact = gen.getFactory(); int pos = 0; @@ -822,6 +829,11 @@ public class BcelTypeMunger extends ConcreteTypeMunger { body.append( InstructionFactory.createReturn( BcelWorld.makeBcelType(mangledInterMethod.getReturnType()))); + + if (weaver.getWorld().isInJava5Mode()) { // Don't need bridge methods if not in 1.5 mode. + createAnyBridgeMethodsForCovariance(weaver, munger, unMangledInterMethod, onType, gen, paramTypes); + } + } else { //??? this is okay //if (!(mg.getBody() == null)) throw new RuntimeException("bas"); @@ -829,8 +841,8 @@ public class BcelTypeMunger extends ConcreteTypeMunger { // XXX make sure to check that we set exceptions properly on this guy. - weaver.addLazyMethodGen(mg); - weaver.getLazyClassGen().warnOnAddedMethod(mg.getMethod(),getSignature().getSourceLocation()); + weaver.addLazyMethodGen(newMethod); + weaver.getLazyClassGen().warnOnAddedMethod(newMethod.getMethod(),getSignature().getSourceLocation()); addNeededSuperCallMethods(weaver, onType, munger.getSuperMethodsCalled()); @@ -896,6 +908,90 @@ public class BcelTypeMunger extends ConcreteTypeMunger { return false; } } + + /** + * Create any bridge method required because of covariant returns being used. This method is used in the case + * where an ITD is applied to some type and it may be in an override relationship with a method from the supertype - but + * due to covariance there is a mismatch in return values. + * Example of when required: + Super defines: Object m(String s) + Sub defines: String m(String s) + then we need a bridge method in Sub called 'Object m(String s)' that forwards to 'String m(String s)' + */ + private void createAnyBridgeMethodsForCovariance(BcelClassWeaver weaver, NewMethodTypeMunger munger, ResolvedMember unMangledInterMethod, ResolvedType onType, LazyClassGen gen, Type[] paramTypes) { + // PERFORMANCE BOTTLENECK? Might need investigating, method analysis between types in a hierarchy just seems expensive... + // COVARIANCE BRIDGING + // Algorithm: Step1. Check in this type - has someone already created the bridge method? + // Step2. Look above us - do we 'override' a method and yet differ in return type (i.e. covariance) + // Step3. Create a forwarding bridge method + ResolvedType superclass = onType.getSuperclass(); + boolean quitRightNow = false; + + String localMethodName = unMangledInterMethod.getName(); + String localParameterSig = unMangledInterMethod.getParameterSignature(); + String localReturnTypeESig = unMangledInterMethod.getReturnType().getErasureSignature(); + + // Step1 + boolean alreadyDone = false; // Compiler might have done it + ResolvedMember[] localMethods = onType.getDeclaredMethods(); + for (int i = 0; i < localMethods.length; i++) { + ResolvedMember member = localMethods[i]; + if (member.getName().equals(localMethodName)) { + // Check the params + if (member.getParameterSignature().equals(localParameterSig)) alreadyDone = true; + } + } + + // Step2 + if (!alreadyDone) { + // Use the iterator form of 'getMethods()' so we do as little work as necessary + for (Iterator iter = onType.getSuperclass().getMethods();iter.hasNext() && !quitRightNow;) { + ResolvedMember aMethod = (ResolvedMember) iter.next(); + if (aMethod.getName().equals(localMethodName) && aMethod.getParameterSignature().equals(localParameterSig)) { + // check the return types, if they are different we need a bridging method. + if (!aMethod.getReturnType().getErasureSignature().equals(localReturnTypeESig)) { + // Step3 + createBridgeMethod(weaver.getWorld(), munger, unMangledInterMethod, gen, paramTypes, aMethod); + quitRightNow = true; + } + } + } + } + } + + private void createBridgeMethod(BcelWorld world, NewMethodTypeMunger munger, + ResolvedMember unMangledInterMethod, LazyClassGen gen, Type[] paramTypes, ResolvedMember aMethod) { + InstructionList body; + InstructionFactory fact; + int pos = 0; + + LazyMethodGen bridgeMethod = makeMethodGen(gen,aMethod); // The bridge method in this type will have the same signature as the one in the supertype + bridgeMethod.setAccessFlags(bridgeMethod.getAccessFlags() | 0x00000040 /*BRIDGE = 0x00000040*/ ); + UnresolvedType[] newParams = munger.getSignature().getParameterTypes(); +// paramTypes = BcelWorld.makeBcelTypes(bridgingSetter.getParameterTypes()); +// Type[] bridgingToParms = BcelWorld.makeBcelTypes(unMangledInterMethod.getParameterTypes()); + Type returnType = BcelWorld.makeBcelType(aMethod.getReturnType()); + body = bridgeMethod.getBody(); + fact = gen.getFactory(); + + if (!unMangledInterMethod.isStatic()) { + body.append(InstructionFactory.createThis()); + pos++; + } + for (int i = 0, len = paramTypes.length; i < len; i++) { + Type paramType = paramTypes[i]; + body.append(InstructionFactory.createLoad(paramType, pos)); +// if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(unMangledInterMethod.getParameterTypes()[i].getErasureSignature())) { +// System.err.println("Putting in cast from "+paramType+" to "+bridgingToParms[i]); +// body.append(fact.createCast(paramType,bridgingToParms[i])); +// } + pos+=paramType.getSize(); + } + + body.append(Utility.createInvoke(fact, world,unMangledInterMethod)); + body.append(InstructionFactory.createReturn(returnType)); + gen.addMethodGen(bridgeMethod); + } private boolean mungeMethodDelegate(BcelClassWeaver weaver, MethodDelegateTypeMunger munger) { ResolvedMember introduced = munger.getSignature(); |