declarations just like we have from calls to super methodstags/V_1_1_b2
public void fixSuperCallsInBody() { | public void fixSuperCallsInBody() { | ||||
SuperFixerVisitor v = new SuperFixerVisitor(this, onTypeBinding); | SuperFixerVisitor v = new SuperFixerVisitor(this, onTypeBinding); | ||||
this.traverse(v, (ClassScope)null); | this.traverse(v, (ClassScope)null); | ||||
HashSet set = new HashSet(); | |||||
for (Iterator i = v.superMethodsCalled.iterator(); i.hasNext(); ) { | |||||
MethodBinding b = (MethodBinding)i.next(); | |||||
set.add(EclipseWorld.makeResolvedMember(b)); | |||||
} | |||||
munger.setSuperMethodsCalled(set); | |||||
munger.setSuperMethodsCalled(v.superMethodsCalled); | |||||
// HashSet set = new HashSet(); | |||||
// for (Iterator i = v.superMethodsCalled.iterator(); i.hasNext(); ) { | |||||
// MethodBinding b = (MethodBinding)i.next(); | |||||
// set.add(EclipseWorld.makeResolvedMember(b)); | |||||
// } | |||||
// | |||||
// munger.setSuperMethodsCalled(set); | |||||
} | } | ||||
protected void resolveOnType(ClassScope classScope) { | protected void resolveOnType(ClassScope classScope) { |
import java.util.*; | import java.util.*; | ||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import org.aspectj.ajdt.internal.compiler.lookup.EclipseWorld; | |||||
import org.aspectj.weaver.*; | import org.aspectj.weaver.*; | ||||
import org.aspectj.weaver.ShadowMunger; | import org.aspectj.weaver.ShadowMunger; | ||||
import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter; | import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter; | ||||
// an error has already occurred | // an error has already occurred | ||||
if (call.codegenBinding == null) return; | if (call.codegenBinding == null) return; | ||||
if (!call.isSuperAccess() || call.binding.isStatic()) return; | |||||
call.receiver = new ThisReference(); | |||||
MethodBinding superBinding = call.codegenBinding; | MethodBinding superBinding = call.codegenBinding; | ||||
char[] accessName = AstUtil.makeAjcMangledName( | |||||
ResolvedTypeMunger.SUPER_DISPATCH_NAME.toCharArray(), targetClass, superBinding.selector | |||||
); | |||||
char[] accessName; | |||||
boolean isSuper; | |||||
if (call.isSuperAccess() && !call.binding.isStatic()) { | |||||
call.receiver = new ThisReference(); | |||||
accessName = | |||||
NameMangler.superDispatchMethod(EclipseWorld.fromBinding(targetClass), | |||||
new String(superBinding.selector)).toCharArray(); | |||||
} else if (call.receiver.isThis() && call.binding.isProtected() && !call.binding.isStatic()) { | |||||
//XXX this is a hack that violates some binary compatibility rules | |||||
if (superBinding.declaringClass.equals(targetClass)) { | |||||
accessName = | |||||
NameMangler.protectedDispatchMethod(EclipseWorld.fromBinding(targetClass), | |||||
new String(superBinding.selector)).toCharArray(); | |||||
} else { | |||||
accessName = | |||||
NameMangler.superDispatchMethod(EclipseWorld.fromBinding(targetClass), | |||||
new String(superBinding.selector)).toCharArray(); | |||||
} | |||||
} else { | |||||
return; | |||||
} | |||||
//??? do we want these to be unique | //??? do we want these to be unique | ||||
MethodBinding superAccessBinding = | MethodBinding superAccessBinding = | ||||
call.codegenBinding = superAccessBinding; | call.codegenBinding = superAccessBinding; | ||||
superMethodsCalled.add(superBinding); | |||||
ResolvedMember targetMember = EclipseWorld.makeResolvedMember(superBinding); | |||||
superMethodsCalled.add(targetMember); | |||||
} | } | ||||
} | } |
// ---- | // ---- | ||||
/** | /** | ||||
* This static method goes on the declaring aspect of the inter-type method. | |||||
* This static method goes on the target class of the inter-type method. | |||||
*/ | */ | ||||
public static String superDispatcher(TypeX classType, String name) | |||||
public static String superDispatchMethod(TypeX classType, String name) | |||||
{ | { | ||||
return makeName("superDispatch", | return makeName("superDispatch", | ||||
classType.getNameAsIdentifier(), name); | classType.getNameAsIdentifier(), name); | ||||
} | } | ||||
/** | |||||
* This static method goes on the target class of the inter-type method. | |||||
*/ | |||||
public static String protectedDispatchMethod(TypeX classType, String name) | |||||
{ | |||||
return makeName("protectedDispatch", | |||||
classType.getNameAsIdentifier(), name); | |||||
} | |||||
// ---- | // ---- | ||||
private static TypeX getOutermostType(TypeX type) { | private static TypeX getOutermostType(TypeX type) { |
for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext(); ) { | for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext(); ) { | ||||
ResolvedMember superMethod = (ResolvedMember) iter.next(); | ResolvedMember superMethod = (ResolvedMember) iter.next(); | ||||
if (weaver.addDispatchTarget(superMethod)) { | if (weaver.addDispatchTarget(superMethod)) { | ||||
String dispatchName = genSuperDispatchName(onType, superMethod); | |||||
LazyMethodGen dispatcher = makeDispatcher(gen, dispatchName, superMethod, weaver.getWorld()); | |||||
//System.err.println("super type: " + superMethod.getDeclaringType() + ", " + gen.getType()); | |||||
boolean isSuper = !superMethod.getDeclaringType().equals(gen.getType()); | |||||
String dispatchName; | |||||
if (isSuper) dispatchName = NameMangler.superDispatchMethod(onType, superMethod.getName()); | |||||
else dispatchName = NameMangler.protectedDispatchMethod(onType, superMethod.getName()); | |||||
LazyMethodGen dispatcher = makeDispatcher(gen, dispatchName, superMethod, weaver.getWorld(), isSuper); | |||||
weaver.addLazyMethodGen(dispatcher); | weaver.addLazyMethodGen(dispatcher); | ||||
} | } | ||||
LazyClassGen onGen, | LazyClassGen onGen, | ||||
String dispatchName, | String dispatchName, | ||||
ResolvedMember superMethod, | ResolvedMember superMethod, | ||||
BcelWorld world) | |||||
BcelWorld world, | |||||
boolean isSuper) | |||||
{ | { | ||||
Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes()); | Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes()); | ||||
Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType()); | Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType()); | ||||
body.append(fact.createLoad(paramType, pos)); | body.append(fact.createLoad(paramType, pos)); | ||||
pos+=paramType.getSize(); | pos+=paramType.getSize(); | ||||
} | } | ||||
body.append(Utility.createSuperInvoke(fact, world, superMethod)); | |||||
if (isSuper) { | |||||
body.append(Utility.createSuperInvoke(fact, world, superMethod)); | |||||
} else { | |||||
body.append(Utility.createInvoke(fact, world, superMethod)); | |||||
} | |||||
body.append(fact.createReturn(returnType)); | body.append(fact.createReturn(returnType)); | ||||
return mg; | return mg; | ||||
} | |||||
private static String genSuperDispatchName( | |||||
ResolvedTypeX onType, | |||||
ResolvedMember superMethod) | |||||
{ | |||||
return "ajc$" + ResolvedTypeMunger.SUPER_DISPATCH_NAME + "$" + onType.getNameAsIdentifier() + "$" + superMethod.getName(); | |||||
} | |||||
} | |||||
private boolean mungeNewField(BcelClassWeaver weaver, NewFieldTypeMunger munger) { | private boolean mungeNewField(BcelClassWeaver weaver, NewFieldTypeMunger munger) { | ||||
ResolvedMember initMethod = munger.getInitMethod(aspectType); | ResolvedMember initMethod = munger.getInitMethod(aspectType); |
LazyClassGen clazz = null; | LazyClassGen clazz = null; | ||||
if (shadowMungers.size() > 0 || typeMungers.size() > 0) { | |||||
if (shadowMungers.size() > 0 || typeMungers.size() > 0 || classType.isAspect()) { | |||||
clazz = classType.getLazyClassGen(); | clazz = classType.getLazyClassGen(); | ||||
try { | try { | ||||
boolean isChanged = BcelClassWeaver.weave(world, clazz, shadowMungers, typeMungers); | boolean isChanged = BcelClassWeaver.weave(world, clazz, shadowMungers, typeMungers); |