Browse Source

390269: fix for multiple bridge candidates in hierarchy

tags/V1_7_2
Andy Clement 11 years ago
parent
commit
0bbb4f252a
1 changed files with 43 additions and 54 deletions
  1. 43
    54
      weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java

+ 43
- 54
weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java View File

@@ -14,6 +14,7 @@ package org.aspectj.weaver.bcel;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -345,8 +346,7 @@ class BcelClassWeaver implements IClassWeaver {
/**
* Create a single bridge method called 'theBridgeMethod' that bridges to 'whatToBridgeTo'
*/
private static void createBridgeMethod(BcelWorld world, LazyMethodGen whatToBridgeToMethodGen, LazyClassGen clazz,
ResolvedMember theBridgeMethod) {
private static void createBridgeMethod(BcelWorld world, LazyMethodGen whatToBridgeToMethodGen, LazyClassGen clazz, ResolvedMember theBridgeMethod) {
InstructionList body;
InstructionFactory fact;
int pos = 0;
@@ -563,6 +563,7 @@ class BcelClassWeaver implements IClassWeaver {
// FIXASC refactor into ResolvedType or even ResolvedMember?
/**
* Check if a particular method is overriding another - refactored into this helper so it can be used from multiple places.
* @return method that is overriding if it
*/
private static ResolvedMember isOverriding(ResolvedType typeToCheck, ResolvedMember methodThatMightBeGettingOverridden,
String mname, String mrettype, int mmods, boolean inSamePackage, UnresolvedType[] methodParamsArray) {
@@ -693,15 +694,16 @@ class BcelClassWeaver implements IClassWeaver {
*
* @return the method being overridden or null if none is found
*/
public static ResolvedMember checkForOverride(ResolvedType typeToCheck, String mname, String mparams, String mrettype,
int mmods, String mpkg, UnresolvedType[] methodParamsArray) {
public static void checkForOverride(ResolvedType typeToCheck, String mname, String mparams, String mrettype,
int mmods, String mpkg, UnresolvedType[] methodParamsArray, List<ResolvedMember> overriddenMethodsCollector) {

if (typeToCheck == null) {
return null;
return;
}
if (typeToCheck instanceof MissingResolvedTypeWithKnownSignature) {
return null; // we just can't tell !
return; // we just can't tell !
}

if (typeToCheck.getWorld().forDEBUG_bridgingCode) {
System.err.println(" Bridging:checking for override of " + mname + " in " + typeToCheck);
@@ -711,9 +713,8 @@ class BcelClassWeaver implements IClassWeaver {
if (packageName == null) {
packageName = "";
}
boolean inSamePackage = packageName.equals(mpkg); // used when looking
// at visibility
// rules
// used when looking at visibility rules
boolean inSamePackage = packageName.equals(mpkg);

ResolvedMember[] methods = typeToCheck.getDeclaredMethods();
for (int ii = 0; ii < methods.length; ii++) {
@@ -722,7 +723,7 @@ class BcelClassWeaver implements IClassWeaver {
ResolvedMember isOverriding = isOverriding(typeToCheck, methodThatMightBeGettingOverridden, mname, mrettype, mmods,
inSamePackage, methodParamsArray);
if (isOverriding != null) {
return isOverriding;
overriddenMethodsCollector.add(isOverriding);
}
}
// was: List l = typeToCheck.getInterTypeMungers();
@@ -742,31 +743,24 @@ class BcelClassWeaver implements IClassWeaver {
ResolvedMember isOverriding = isOverriding(typeToCheck, aMethod, mname, mrettype, mmods, inSamePackage,
methodParamsArray);
if (isOverriding != null) {
return isOverriding;
overriddenMethodsCollector.add(isOverriding);
}
}
}
}

if (typeToCheck.equals(UnresolvedType.OBJECT)) {
return null;
return;
}

ResolvedType superclass = typeToCheck.getSuperclass();
ResolvedMember overriddenMethod = checkForOverride(superclass, mname, mparams, mrettype, mmods, mpkg, methodParamsArray);
if (overriddenMethod != null) {
return overriddenMethod;
}

checkForOverride(superclass, mname, mparams, mrettype, mmods, mpkg, methodParamsArray,overriddenMethodsCollector);
ResolvedType[] interfaces = typeToCheck.getDeclaredInterfaces();
for (int i = 0; i < interfaces.length; i++) {
ResolvedType anInterface = interfaces[i];
overriddenMethod = checkForOverride(anInterface, mname, mparams, mrettype, mmods, mpkg, methodParamsArray);
if (overriddenMethod != null) {
return overriddenMethod;
}
checkForOverride(anInterface, mname, mparams, mrettype, mmods, mpkg, methodParamsArray,overriddenMethodsCollector);
}
return null;
}

/**
@@ -778,31 +772,30 @@ class BcelClassWeaver implements IClassWeaver {
*/
public static boolean calculateAnyRequiredBridgeMethods(BcelWorld world, LazyClassGen clazz) {
world.ensureAdvancedConfigurationProcessed();
if (!world.isInJava5Mode()) {
return false; // just double check... the caller should have already
}
// verified this
if (clazz.isInterface()) {
return false; // dont bother if we're an interface
return false; // dont bother if we are an interface
}
boolean didSomething = false; // set if we build any bridge methods

// So what methods do we have right now in this class?
List<LazyMethodGen> methods = clazz.getMethodGens();

// Keep a set of all methods from this type - it'll help us to check if
// bridge methods
// Keep a set of all methods from this type - it'll help us to check if bridge methods
// have already been created, we don't want to do it twice!
Set<String> methodsSet = new HashSet<String>();
for (int i = 0; i < methods.size(); i++) {
LazyMethodGen aMethod = methods.get(i);
methodsSet.add(aMethod.getName() + aMethod.getSignature()); // e.g.
// "foo(Ljava/lang/String;)V"
StringBuilder sb = new StringBuilder(aMethod.getName());
sb.append(aMethod.getSignature());
methodsSet.add(sb.toString()); // e.g. "foo(Ljava/lang/String;)V"
}

// Now go through all the methods in this type
for (int i = 0; i < methods.size(); i++) {

// This is the local method that we *might* have to bridge to
LazyMethodGen bridgeToCandidate = methods.get(i);
if (bridgeToCandidate.isBridgeMethod()) {
@@ -821,8 +814,7 @@ class BcelClassWeaver implements IClassWeaver {
}

if (world.forDEBUG_bridgingCode) {
System.err.println("Bridging: Determining if we have to bridge to " + clazz.getName() + "." + name + ""
+ bridgeToCandidate.getSignature());
System.err.println("Bridging: Determining if we have to bridge to " + clazz.getName() + "." + name + "" + bridgeToCandidate.getSignature());
}

// Let's take a look at the superclass
@@ -832,20 +824,20 @@ class BcelClassWeaver implements IClassWeaver {
}
String pkgName = clazz.getPackageName();
UnresolvedType[] bm = BcelWorld.fromBcel(bridgeToCandidate.getArgumentTypes());
ResolvedMember overriddenMethod = checkForOverride(theSuperclass, name, psig, rsig, bridgeToCandidate.getAccessFlags(),
pkgName, bm);
if (overriddenMethod != null) {
String key = new StringBuffer().append(overriddenMethod.getName()).append(overriddenMethod.getSignatureErased())
.toString(); // pr237419
boolean alreadyHaveABridgeMethod = methodsSet.contains(key);
if (!alreadyHaveABridgeMethod) {
if (world.forDEBUG_bridgingCode) {
System.err.println("Bridging:bridging to '" + overriddenMethod + "'");
List<ResolvedMember> overriddenMethodsCollector = new ArrayList<ResolvedMember>();
checkForOverride(theSuperclass, name, psig, rsig, bridgeToCandidate.getAccessFlags(), pkgName, bm, overriddenMethodsCollector);
if (overriddenMethodsCollector.size() != 0) {
for (ResolvedMember overriddenMethod: overriddenMethodsCollector) {
String key = new StringBuilder(overriddenMethod.getName()).append(overriddenMethod.getSignatureErased()).toString(); // pr237419
boolean alreadyHaveABridgeMethod = methodsSet.contains(key);
if (!alreadyHaveABridgeMethod) {
if (world.forDEBUG_bridgingCode) {
System.err.println("Bridging:bridging to '" + overriddenMethod + "'");
}
createBridgeMethod(world, bridgeToCandidate, clazz, overriddenMethod);
methodsSet.add(key);
didSomething = true;
}
createBridgeMethod(world, bridgeToCandidate, clazz, overriddenMethod);
methodsSet.add(key);
didSomething = true;
continue; // look at the next method
}
}

@@ -856,12 +848,11 @@ class BcelClassWeaver implements IClassWeaver {
System.err.println("Bridging:checking superinterface " + interfaces[j]);
}
ResolvedType interfaceType = world.resolve(interfaces[j]);
overriddenMethod = checkForOverride(interfaceType, name, psig, rsig, bridgeToCandidate.getAccessFlags(),
clazz.getPackageName(), bm);
if (overriddenMethod != null) {
String key = new StringBuffer().append(overriddenMethod.getName())
.append(overriddenMethod.getSignatureErased()).toString(); // pr
// 237419
overriddenMethodsCollector.clear();
checkForOverride(interfaceType, name, psig, rsig, bridgeToCandidate.getAccessFlags(),
clazz.getPackageName(), bm, overriddenMethodsCollector);
for (ResolvedMember overriddenMethod: overriddenMethodsCollector) {
String key = new StringBuffer().append(overriddenMethod.getName()).append(overriddenMethod.getSignatureErased()).toString(); // pr237419
boolean alreadyHaveABridgeMethod = methodsSet.contains(key);
if (!alreadyHaveABridgeMethod) {
createBridgeMethod(world, bridgeToCandidate, clazz, overriddenMethod);
@@ -870,7 +861,6 @@ class BcelClassWeaver implements IClassWeaver {
if (world.forDEBUG_bridgingCode) {
System.err.println("Bridging:bridging to " + overriddenMethod);
}
continue; // look at the next method
}
}
}
@@ -879,8 +869,7 @@ class BcelClassWeaver implements IClassWeaver {
return didSomething;
}

// **************************** end of bridge method creation code
// *****************
// **************************** end of bridge method creation code *****************

/**
* Weave any declare @method/@ctor statements into the members of the supplied class

Loading…
Cancel
Save