@@ -27,7 +27,7 @@ public @interface DeclareParents { | |||
* The target types expression | |||
*/ | |||
String value(); | |||
/** | |||
* Optional class defining default implementation | |||
* of interface members (equivalent to defining | |||
@@ -35,7 +35,7 @@ public @interface DeclareParents { | |||
* public methods of the interface). | |||
*/ | |||
Class defaultImpl() default DeclareParents.class; | |||
// note - a default of "null" is not allowed, | |||
// hence the strange default given above. | |||
} |
@@ -50,10 +50,11 @@ public class DeclareParentsImplementsTest extends TestCase { | |||
@Aspect | |||
static class TestAspect { | |||
@DeclareParents("ataspectj.DeclareParentsImplementsTest.Target") | |||
public static Introduced i = new Implementation();//see here control of instantiation | |||
@DeclareParents(value="ataspectj.DeclareParentsImplementsTest.Target", | |||
defaultImpl=Implementation.class) | |||
public static Introduced i; | |||
// will lead to: class Target implements Introduced { | |||
// void intro(args) { TestAspect.i.intro(args); } | |||
// void intro(args) { delegate to some hidden field, lazy initialized here for now } | |||
// } | |||
@Before("execution(* ataspectj.DeclareParentsImplementsTest.Introduced.intro())") |
@@ -15,6 +15,7 @@ import junit.framework.TestCase; | |||
import org.aspectj.lang.annotation.Aspect; | |||
import org.aspectj.lang.annotation.Before; | |||
import org.aspectj.lang.annotation.DeclareImplements; | |||
import org.aspectj.lang.annotation.DeclareParents; | |||
import java.util.Arrays; | |||
@@ -34,7 +35,7 @@ public class DeclareParentsInterfaceTest extends TestCase { | |||
@Aspect | |||
static class TestAspect { | |||
@DeclareImplements("ataspectj.DeclareParentsInterfaceTest.Target") | |||
@DeclareParents("ataspectj.DeclareParentsInterfaceTest.Target") | |||
Marker introduce; | |||
@Before("execution(* ataspectj.DeclareParentsInterfaceTest.Marker+.target())") |
@@ -5,4 +5,4 @@ | |||
<weaver options="-showWeaveInfo"/> | |||
</aspectj> | |||
@@ -499,8 +499,18 @@ public class AjcMemberMaker { | |||
NameMangler.postIntroducedConstructor(aspectType, targetType), | |||
UnresolvedType.insert(targetType, paramTypes)); | |||
} | |||
public static ResolvedMember interConstructor(ResolvedType targetType, ResolvedMember constructor, UnresolvedType aspectType) { | |||
public static ResolvedMember itdAtDeclareParentsField(ResolvedType targetType, UnresolvedType itdType, UnresolvedType aspectType) { | |||
return new ResolvedMemberImpl( | |||
Member.FIELD, | |||
targetType, | |||
Modifier.PRIVATE, | |||
itdType, | |||
NameMangler.itdAtDeclareParentsField(aspectType, itdType), | |||
null); | |||
} | |||
public static ResolvedMember interConstructor(ResolvedType targetType, ResolvedMember constructor, UnresolvedType aspectType) { | |||
// | |||
// ResolvedType targetType, | |||
// UnresolvedType[] argTypes, |
@@ -28,10 +28,12 @@ import org.aspectj.weaver.patterns.TypePattern; | |||
*/ | |||
public class MethodDelegateTypeMunger extends ResolvedTypeMunger { | |||
private final UnresolvedType aspect; | |||
/** | |||
* The field in the aspect that hosts the mixin instance | |||
* The mixin impl (no arg ctor) | |||
*/ | |||
private final ResolvedMember aspectFieldDelegate; | |||
private final String implClassName; | |||
/** | |||
* Type pattern this munger applies to | |||
@@ -43,52 +45,42 @@ public class MethodDelegateTypeMunger extends ResolvedTypeMunger { | |||
* | |||
* @param signature | |||
* @param aspect | |||
* @param fieldName | |||
* @param implClassName | |||
* @param typePattern | |||
*/ | |||
public MethodDelegateTypeMunger(ResolvedMember signature, ResolvedType aspect, String fieldName, TypePattern typePattern) { | |||
public MethodDelegateTypeMunger(ResolvedMember signature, UnresolvedType aspect, String implClassName, TypePattern typePattern) { | |||
super(MethodDelegate, signature); | |||
this.aspect = aspect; | |||
this.typePattern = typePattern; | |||
ResolvedMember[] fields = aspect.getDeclaredFields();//note: will unpack attributes | |||
ResolvedMember field = null; | |||
for (int i = 0; i < fields.length; i++) { | |||
if (fieldName.equals(fields[i].getName())) { | |||
field = fields[i]; | |||
break; | |||
} | |||
} | |||
if (field == null) { | |||
throw new RuntimeException("Should not happen: aspect field not found for @DeclareParents delegate"); | |||
} else { | |||
aspectFieldDelegate = field; | |||
} | |||
this.implClassName = implClassName; | |||
} | |||
private MethodDelegateTypeMunger(ResolvedMember signature, ResolvedMember fieldDelegate, TypePattern typePattern) { | |||
super(MethodDelegate, signature); | |||
this.aspectFieldDelegate = fieldDelegate; | |||
this.typePattern = typePattern; | |||
public ResolvedMember getDelegate(ResolvedType targetType) { | |||
return AjcMemberMaker.itdAtDeclareParentsField( | |||
targetType, | |||
signature.getDeclaringType(), | |||
aspect | |||
); | |||
} | |||
public ResolvedMember getDelegate() { | |||
return aspectFieldDelegate; | |||
public String getImplClassName() { | |||
return implClassName; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
signature.write(s); | |||
aspectFieldDelegate.write(s); | |||
aspect.write(s); | |||
s.writeUTF(implClassName); | |||
typePattern.write(s); | |||
} | |||
public static ResolvedTypeMunger readMethod(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context); | |||
ResolvedMemberImpl field = ResolvedMemberImpl.readResolvedMember(s, context); | |||
UnresolvedType aspect = UnresolvedType.read(s); | |||
String implClassName = s.readUTF(); | |||
TypePattern tp = TypePattern.read(s, context); | |||
return new MethodDelegateTypeMunger(signature, field, tp); | |||
return new MethodDelegateTypeMunger(signature, aspect, implClassName, tp); | |||
} | |||
/** | |||
@@ -115,4 +107,62 @@ public class MethodDelegateTypeMunger extends ResolvedTypeMunger { | |||
public boolean changesPublicSignature() { | |||
return true; | |||
} | |||
public static class FieldHostTypeMunger extends ResolvedTypeMunger { | |||
private UnresolvedType aspect; | |||
/** | |||
* Type pattern this munger applies to | |||
*/ | |||
private final TypePattern typePattern; | |||
/** | |||
* Construct a new type munger for @AspectJ ITD | |||
* | |||
* @param field | |||
* @param aspect | |||
* @param typePattern | |||
*/ | |||
public FieldHostTypeMunger(ResolvedMember field, UnresolvedType aspect, TypePattern typePattern) { | |||
super(FieldHost, field); | |||
this.aspect = aspect; | |||
this.typePattern = typePattern; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
signature.write(s); | |||
aspect.write(s); | |||
typePattern.write(s); | |||
} | |||
public static ResolvedTypeMunger readFieldHost(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context); | |||
UnresolvedType aspect = UnresolvedType.read(s); | |||
TypePattern tp = TypePattern.read(s, context); | |||
return new FieldHostTypeMunger(signature, aspect, tp); | |||
} | |||
/** | |||
* Match based on given type pattern, only classes can be matched | |||
* | |||
* @param matchType | |||
* @param aspectType | |||
* @return true if match | |||
*/ | |||
public boolean matches(ResolvedType matchType, ResolvedType aspectType) { | |||
// match only on class | |||
if (matchType.isEnum() || matchType.isInterface() || matchType.isAnnotation()) { | |||
return false; | |||
} | |||
return typePattern.matchesStatically(matchType); | |||
} | |||
public boolean changesPublicSignature() { | |||
return false; | |||
} | |||
} | |||
} |
@@ -64,16 +64,17 @@ public class NameMangler { | |||
// PTWIMPL method names that must include aspect type | |||
public static String perTypeWithinFieldForTarget(UnresolvedType aspectType) { | |||
String s = makeName(aspectType.getNameAsIdentifier(), "ptwAspectInstance"); | |||
return s; | |||
return makeName(aspectType.getNameAsIdentifier(), "ptwAspectInstance"); | |||
} | |||
public static String perTypeWithinLocalAspectOf(UnresolvedType aspectType) { | |||
public static String perTypeWithinLocalAspectOf(UnresolvedType aspectType) { | |||
return makeName(aspectType.getNameAsIdentifier(), "localAspectOf"); | |||
} | |||
public static String itdAtDeclareParentsField(UnresolvedType aspectType, UnresolvedType itdType) { | |||
return makeName(aspectType.getNameAsIdentifier(), itdType.getNameAsIdentifier()); | |||
} | |||
public static String privilegedAccessMethodForMethod(String name, UnresolvedType objectType, UnresolvedType aspectType) { | |||
return makeName("privMethod", aspectType.getNameAsIdentifier(), | |||
objectType.getNameAsIdentifier(), name); |
@@ -135,6 +135,8 @@ public abstract class ResolvedTypeMunger { | |||
return NewConstructorTypeMunger.readConstructor(s, context); | |||
} else if (kind == MethodDelegate) { | |||
return MethodDelegateTypeMunger.readMethod(s, context); | |||
} else if (kind == FieldHost) { | |||
return MethodDelegateTypeMunger.FieldHostTypeMunger.readFieldHost(s, context); | |||
} else { | |||
throw new RuntimeException("unimplemented"); | |||
} | |||
@@ -237,12 +239,14 @@ public abstract class ResolvedTypeMunger { | |||
case 2: return Method; | |||
case 5: return Constructor; | |||
case 9: return MethodDelegate; | |||
case 10: return FieldHost; | |||
} | |||
throw new BCException("bad kind: " + key); | |||
} | |||
public String toString() { | |||
// we want MethodDelegate to appear as Method in WeaveInfo messages | |||
//TODO we may want something for fieldhost ? | |||
if (MethodDelegate.getName().equals(getName())) { | |||
return Method.toString(); | |||
} else { | |||
@@ -267,6 +271,7 @@ public abstract class ResolvedTypeMunger { | |||
public static final Kind AnnotationOnType = new Kind("AnnotationOnType",8); // not serialized | |||
public static final Kind MethodDelegate = new Kind("MethodDelegate", 9);// serialized, @AJ ITDs | |||
public static final Kind FieldHost = new Kind("FieldHost", 10);// serialized, @AJ ITDs | |||
public static final String SUPER_DISPATCH_NAME = "superDispatch"; | |||
@@ -17,6 +17,7 @@ import java.util.Collections; | |||
import java.util.Comparator; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.lang.reflect.Modifier; | |||
import org.aspectj.apache.bcel.Constants; | |||
import org.aspectj.apache.bcel.classfile.Attribute; | |||
@@ -31,6 +32,7 @@ import org.aspectj.apache.bcel.classfile.annotation.Annotation; | |||
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair; | |||
import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnotations; | |||
import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations; | |||
import org.aspectj.apache.bcel.classfile.annotation.ClassElementValue; | |||
import org.aspectj.apache.bcel.generic.Type; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.IMessageHandler; | |||
@@ -50,6 +52,9 @@ import org.aspectj.weaver.ResolvedPointcutDefinition; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.WeaverMessages; | |||
import org.aspectj.weaver.NewFieldTypeMunger; | |||
import org.aspectj.weaver.ResolvedMemberImpl; | |||
import org.aspectj.weaver.Member; | |||
import org.aspectj.weaver.patterns.AndPointcut; | |||
import org.aspectj.weaver.patterns.DeclareErrorOrWarning; | |||
import org.aspectj.weaver.patterns.DeclareParents; | |||
@@ -317,7 +322,6 @@ public class AtAjAttributes { | |||
if (acceptAttribute(fattribute)) { | |||
RuntimeAnnotations frvs = (RuntimeAnnotations) fattribute; | |||
if (handleDeclareErrorOrWarningAnnotation(frvs, fstruct) | |||
|| handleDeclareImplementsAnnotation(frvs, fstruct) | |||
|| handleDeclareParentsAnnotation(frvs, fstruct)) { | |||
// semantic check - must be in an @Aspect [remove if previous block bypassed in advance] | |||
if (!type.isAnnotationStyleAspect()) { | |||
@@ -338,7 +342,7 @@ public class AtAjAttributes { | |||
} | |||
struct.ajAttributes.addAll(fstruct.ajAttributes); | |||
} | |||
return struct.ajAttributes; | |||
} | |||
@@ -463,8 +467,8 @@ public class AtAjAttributes { | |||
// Note: field annotation are for ITD and DEOW - processed at class level directly | |||
return Collections.EMPTY_LIST; | |||
} | |||
/** | |||
* Read @Aspect | |||
* | |||
@@ -518,12 +522,12 @@ public class AtAjAttributes { | |||
struct.context, | |||
bindings | |||
); | |||
// // we can't resolve here since the perclause typically refers to pointcuts | |||
// // defined in the aspect that we haven't told the BcelObjectType about yet. | |||
// | |||
// | |||
// perClause.resolve(binding); | |||
// so we prepare to do it later... | |||
aspectAttribute.setResolutionScope(binding); | |||
return true; | |||
@@ -607,47 +611,47 @@ public class AtAjAttributes { | |||
return false; | |||
} | |||
/** | |||
* Read @DeclareImplements | |||
* | |||
* @param runtimeAnnotations | |||
* @param struct | |||
* @return true if found | |||
*/ | |||
private static boolean handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) {//, ResolvedPointcutDefinition preResolvedPointcut) { | |||
Annotation deci = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION); | |||
if (deci != null) { | |||
ElementNameValuePair deciPatternNVP = getAnnotationElement(deci, VALUE); | |||
String deciPattern = deciPatternNVP.getValue().stringifyValue(); | |||
if (deciPattern != null) { | |||
TypePattern typePattern = parseTypePattern(deciPattern, struct); | |||
ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld()); | |||
if (fieldType.isPrimitiveType()) { | |||
return false; | |||
} else if (fieldType.isInterface()) { | |||
TypePattern parent = new ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()), false, false); | |||
parent.resolve(struct.enclosingType.getWorld()); | |||
List parents = new ArrayList(1); | |||
parents.add(parent); | |||
//TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ?? | |||
struct.ajAttributes.add( | |||
new AjAttribute.DeclareAttribute( | |||
new DeclareParents( | |||
typePattern, | |||
parents, | |||
false | |||
) | |||
) | |||
); | |||
return true; | |||
} else { | |||
reportError("@DeclareImplements: can only be used on field whose type is an interface", struct); | |||
return false; | |||
} | |||
} | |||
} | |||
return false; | |||
} | |||
// /** | |||
// * Read @DeclareImplements | |||
// * | |||
// * @param runtimeAnnotations | |||
// * @param struct | |||
// * @return true if found | |||
// */ | |||
// private static boolean handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) {//, ResolvedPointcutDefinition preResolvedPointcut) { | |||
// Annotation deci = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION); | |||
// if (deci != null) { | |||
// ElementNameValuePair deciPatternNVP = getAnnotationElement(deci, VALUE); | |||
// String deciPattern = deciPatternNVP.getValue().stringifyValue(); | |||
// if (deciPattern != null) { | |||
// TypePattern typePattern = parseTypePattern(deciPattern, struct); | |||
// ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld()); | |||
// if (fieldType.isPrimitiveType()) { | |||
// return false; | |||
// } else if (fieldType.isInterface()) { | |||
// TypePattern parent = new ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()), false, false); | |||
// parent.resolve(struct.enclosingType.getWorld()); | |||
// List parents = new ArrayList(1); | |||
// parents.add(parent); | |||
// //TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ?? | |||
// struct.ajAttributes.add( | |||
// new AjAttribute.DeclareAttribute( | |||
// new DeclareParents( | |||
// typePattern, | |||
// parents, | |||
// false | |||
// ) | |||
// ) | |||
// ); | |||
// return true; | |||
// } else { | |||
// reportError("@DeclareImplements: can only be used on field whose type is an interface", struct); | |||
// return false; | |||
// } | |||
// } | |||
// } | |||
// return false; | |||
// } | |||
/** | |||
* Read @DeclareParents | |||
@@ -664,9 +668,7 @@ public class AtAjAttributes { | |||
if (decpPattern != null) { | |||
TypePattern typePattern = parseTypePattern(decpPattern, struct); | |||
ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld()); | |||
if (fieldType.isPrimitiveType()) { | |||
return false; | |||
} else if (fieldType.isInterface() && (struct.field.isPublic() && struct.field.isStatic())) { | |||
if (fieldType.isInterface()) { | |||
TypePattern parent = new ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()), false, false); | |||
parent.resolve(struct.enclosingType.getWorld()); | |||
//TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ?? | |||
@@ -681,25 +683,66 @@ public class AtAjAttributes { | |||
) | |||
) | |||
); | |||
// do we have a defaultImpl=xxx.class (ie implementation) | |||
String defaultImplClassName = null; | |||
ElementNameValuePair defaultImplNVP = getAnnotationElement(decp, "defaultImpl"); | |||
if (defaultImplNVP != null) { | |||
ClassElementValue defaultImpl = (ClassElementValue) defaultImplNVP.getValue(); | |||
defaultImplClassName = UnresolvedType.forSignature(defaultImpl.getClassString()).getName(); | |||
if (defaultImplClassName.equals("org.aspectj.lang.annotation.DeclareParents")) { | |||
defaultImplClassName = null; | |||
} | |||
//TODO check public no arg ctor | |||
} | |||
// then iterate on field interface hierarchy (not object) | |||
for (Iterator it = fieldType.getMethods(); it.hasNext();) { | |||
ResolvedMember method = (ResolvedMember)it.next(); | |||
boolean hasAtLeastOneMethod = false; | |||
ResolvedMember[] methods = (ResolvedMember[])fieldType.getMethodsWithoutIterator(true, false).toArray(new ResolvedMember[0]); | |||
for (int i = 0; i < methods.length; i++) { | |||
ResolvedMember method = (ResolvedMember)methods[i]; | |||
if (method.isAbstract()) { | |||
if (defaultImplClassName == null) { | |||
// non marker interface with no default impl provided | |||
reportError("@DeclareParents: used with a non marker interface and no defaultImpl=\"...\" provided", struct); | |||
return false; | |||
} | |||
hasAtLeastOneMethod = true; | |||
struct.ajAttributes.add( | |||
new AjAttribute.TypeMunger( | |||
new MethodDelegateTypeMunger( | |||
method, | |||
struct.enclosingType, | |||
struct.field.getName(), | |||
defaultImplClassName, | |||
typePattern | |||
) | |||
) | |||
); | |||
} | |||
} | |||
// successfull so far, we thus need a bcel type munger to have | |||
// a field hosting the mixin in the target type | |||
if (hasAtLeastOneMethod) { | |||
struct.ajAttributes.add( | |||
new AjAttribute.TypeMunger( | |||
new MethodDelegateTypeMunger.FieldHostTypeMunger( | |||
AjcMemberMaker.itdAtDeclareParentsField( | |||
null,//prototyped | |||
fieldType, | |||
struct.enclosingType | |||
), | |||
struct.enclosingType, | |||
typePattern | |||
) | |||
) | |||
); | |||
} | |||
return true; | |||
} else { | |||
reportError("@DeclareParents: can only be used on a public static field whose type is an interface", struct); | |||
reportError("@DeclareParents: can only be used on a field whose type is an interface", struct); | |||
return false; | |||
} | |||
} |
@@ -29,6 +29,7 @@ import org.aspectj.apache.bcel.generic.InstructionFactory; | |||
import org.aspectj.apache.bcel.generic.InstructionHandle; | |||
import org.aspectj.apache.bcel.generic.InstructionList; | |||
import org.aspectj.apache.bcel.generic.Type; | |||
import org.aspectj.apache.bcel.generic.BranchInstruction; | |||
import org.aspectj.apache.bcel.generic.annotation.AnnotationGen; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.ISourceLocation; | |||
@@ -63,7 +64,7 @@ import org.aspectj.weaver.WeaverStateInfo; | |||
import org.aspectj.weaver.World; | |||
import org.aspectj.weaver.patterns.DeclareAnnotation; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
import org.aspectj.lang.Signature; | |||
//XXX addLazyMethodGen is probably bad everywhere | |||
public class BcelTypeMunger extends ConcreteTypeMunger { | |||
@@ -87,6 +88,8 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
changed = mungeNewMethod(weaver, (NewMethodTypeMunger)munger); | |||
} else if (munger.getKind() == ResolvedTypeMunger.MethodDelegate) { | |||
changed = mungeMethodDelegate(weaver, (MethodDelegateTypeMunger)munger); | |||
} else if (munger.getKind() == ResolvedTypeMunger.FieldHost) { | |||
changed = mungeFieldHost(weaver, (MethodDelegateTypeMunger.FieldHostTypeMunger)munger); | |||
} else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) { | |||
changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger); | |||
worthReporting = false; | |||
@@ -147,7 +150,9 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
// reportDeclareParentsMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent); | |||
} | |||
} else { | |||
} else if (munger.getKind().equals(ResolvedTypeMunger.FieldHost)) { | |||
;//hidden | |||
} else { | |||
ResolvedMember declaredSig = munger.getDeclaredSignature(); | |||
if (declaredSig==null) declaredSig= munger.getSignature(); | |||
weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ITD, | |||
@@ -1103,11 +1108,23 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
InstructionList body = new InstructionList(); | |||
InstructionFactory fact = gen.getFactory(); | |||
// getstatic field from aspect | |||
body.append(Utility.createGet(fact, munger.getDelegate())); | |||
// getfield | |||
body.append(InstructionConstants.ALOAD_0); | |||
body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType()))); | |||
BranchInstruction ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null); | |||
body.append(ifNonNull); | |||
InstructionHandle ifNonNullElse = body.append(InstructionConstants.ALOAD_0); | |||
body.append(fact.createNew(munger.getImplClassName())); | |||
body.append(InstructionConstants.DUP); | |||
body.append(fact.createInvoke(munger.getImplClassName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); | |||
body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType()))); | |||
ifNonNull.setTarget(ifNonNullElse); | |||
body.append(InstructionConstants.ALOAD_0); | |||
body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType()))); | |||
//args | |||
int pos = 0; | |||
if (!introduced.isStatic()) { // skip 'this' | |||
if (!introduced.isStatic()) { // skip 'this' (?? can this really happen) | |||
//body.append(InstructionFactory.createThis()); | |||
pos++; | |||
} | |||
@@ -1133,7 +1150,25 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
return false; | |||
} | |||
private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor,boolean isCtorRelated) { | |||
private boolean mungeFieldHost(BcelClassWeaver weaver, MethodDelegateTypeMunger.FieldHostTypeMunger munger) { | |||
LazyClassGen gen = weaver.getLazyClassGen(); | |||
if (gen.getType().isAnnotation() || gen.getType().isEnum()) { | |||
// don't signal error as it could be a consequence of a wild type pattern | |||
return false; | |||
} | |||
boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType); | |||
ResolvedMember host = AjcMemberMaker.itdAtDeclareParentsField( | |||
weaver.getLazyClassGen().getType(), | |||
munger.getSignature().getType(), | |||
aspectType); | |||
weaver.getLazyClassGen().addField(makeFieldGen( | |||
weaver.getLazyClassGen(), | |||
host).getField(), null); | |||
return true; | |||
} | |||
private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor,boolean isCtorRelated) { | |||
World world = aspectType.getWorld(); | |||
boolean debug = false; | |||
if (debug) { |