]> source.dussan.org Git - aspectj.git/commitdiff
declaremixin
authoraclement <aclement>
Wed, 4 Mar 2009 01:24:25 +0000 (01:24 +0000)
committeraclement <aclement>
Wed, 4 Mar 2009 01:24:25 +0000 (01:24 +0000)
weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java
weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java

index 7730103ed8932e31a64335d7a40ac3ebdc5b20fa..c2fb10049739eedb693d04aeb19b07e12c630da0 100644 (file)
@@ -30,8 +30,10 @@ import org.aspectj.apache.bcel.classfile.LocalVariable;
 import org.aspectj.apache.bcel.classfile.LocalVariableTable;
 import org.aspectj.apache.bcel.classfile.Method;
 import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
+import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValueGen;
 import org.aspectj.apache.bcel.classfile.annotation.ClassElementValueGen;
 import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen;
+import org.aspectj.apache.bcel.classfile.annotation.ElementValueGen;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnotations;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations;
 import org.aspectj.apache.bcel.generic.Type;
@@ -57,6 +59,7 @@ import org.aspectj.weaver.ResolvedPointcutDefinition;
 import org.aspectj.weaver.ResolvedType;
 import org.aspectj.weaver.UnresolvedType;
 import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
 import org.aspectj.weaver.patterns.Bindings;
 import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
 import org.aspectj.weaver.patterns.DeclareParents;
@@ -124,7 +127,9 @@ public class AtAjAttributes {
 
                // argument names used for formal binding
                private String[] m_argumentNamesLazy = null;
-               public String unparsedArgumentNames = null; // Set only if discovered as argNames attribute of annotation
+               public String unparsedArgumentNames = null; // Set only if discovered as
+               // argNames attribute of
+               // annotation
 
                final Method method;
                final BcelMethod bMethod;
@@ -220,10 +225,12 @@ public class AtAjAttributes {
                        Attribute attribute = attributes[i];
                        if (acceptAttribute(attribute)) {
                                RuntimeAnnotations rvs = (RuntimeAnnotations) attribute;
-                               // we don't need to look for several attribute occurrences since it cannot happen as per JSR175
+                               // we don't need to look for several attribute occurrences since
+                               // it cannot happen as per JSR175
                                if (!isCodeStyleAspect && !javaClass.isInterface()) {
                                        hasAtAspectAnnotation = handleAspectAnnotation(rvs, struct);
-                                       // TODO AV - if put outside the if isCodeStyleAspect then we would enable mix style
+                                       // TODO AV - if put outside the if isCodeStyleAspect then we
+                                       // would enable mix style
                                        hasAtPrecedenceAnnotation = handlePrecedenceAnnotation(rvs, struct);
                                }
                                // there can only be one RuntimeVisible bytecode attribute
@@ -239,7 +246,8 @@ public class AtAjAttributes {
                        return EMPTY_LIST;
                }
 
-               // the following block will not detect @Pointcut in non @Aspect types for optimization purpose
+               // the following block will not detect @Pointcut in non @Aspect types
+               // for optimization purpose
                if (!(hasAtAspectAnnotation || isCodeStyleAspect) && !containsPointcut) {
                        return EMPTY_LIST;
                }
@@ -263,7 +271,8 @@ public class AtAjAttributes {
                // if (hasAtAspectAnnotation && !javaClass.isPublic()) {
                // msgHandler.handleMessage(
                // new Message(
-               // "Found @Aspect annotation on a non public class '" + javaClass.getClassName() + "'",
+               // "Found @Aspect annotation on a non public class '" +
+               // javaClass.getClassName() + "'",
                // IMessage.ERROR,
                // null,
                // type.getSourceLocation()
@@ -273,46 +282,53 @@ public class AtAjAttributes {
                // }
 
                // code style pointcuts are class attributes
-               // we need to gather the @AJ pointcut right now and not at method level annotation extraction time
+               // we need to gather the @AJ pointcut right now and not at method level
+               // annotation extraction time
                // in order to be able to resolve the pointcut references later on
-               // we don't need to look in super class, the pointcut reference in the grammar will do it
+               // we don't need to look in super class, the pointcut reference in the
+               // grammar will do it
 
                for (int i = 0; i < javaClass.getMethods().length; i++) {
                        Method method = javaClass.getMethods()[i];
                        if (method.getName().startsWith(NameMangler.PREFIX))
                                continue; // already dealt with by ajc...
-                       // FIXME alex optimize, this method struct will gets recreated for advice extraction
+                       // FIXME alex optimize, this method struct will gets recreated for
+                       // advice extraction
                        AjAttributeMethodStruct mstruct = null;
                        boolean processedPointcut = false;
                        Attribute[] mattributes = method.getAttributes();
                        for (int j = 0; j < mattributes.length; j++) {
                                Attribute mattribute = mattributes[j];
                                if (acceptAttribute(mattribute)) {
-                                       // TODO speed all this nonsense up rather than looking through all the annotations every time
+                                       // TODO speed all this nonsense up rather than looking
+                                       // through all the annotations every time
                                        // same for fields
                                        mstruct = new AjAttributeMethodStruct(method, null, type, context, msgHandler);
                                        processedPointcut = handlePointcutAnnotation((RuntimeAnnotations) mattribute, mstruct);
-//                                     if (!processedPointcut) {
-//                                             handleDeclareMixinAnnotation((RuntimeAnnotations) mattribute, mstruct);
-//                                     }
+                                       if (!processedPointcut) {
+                                               processedPointcut = handleDeclareMixinAnnotation((RuntimeAnnotations) mattribute, mstruct);
+                                       }
                                        // there can only be one RuntimeVisible bytecode attribute
                                        break;
                                }
                        }
                        if (processedPointcut) {
-                               // FIXME asc should check we aren't adding multiple versions... will do once I get the tests passing again...
+                               // FIXME asc should check we aren't adding multiple versions...
+                               // will do once I get the tests passing again...
                                struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo());
                                struct.ajAttributes.addAll(mstruct.ajAttributes);
                        }
                }
 
-               // code style declare error / warning / implements / parents are field attributes
+               // code style declare error / warning / implements / parents are field
+               // attributes
                Field[] fs = javaClass.getFields();
                for (int i = 0; i < fs.length; i++) {
                        Field field = fs[i];
                        if (field.getName().startsWith(NameMangler.PREFIX))
                                continue; // already dealt with by ajc...
-                       // FIXME alex optimize, this method struct will gets recreated for advice extraction
+                       // FIXME alex optimize, this method struct will gets recreated for
+                       // advice extraction
                        AjAttributeFieldStruct fstruct = new AjAttributeFieldStruct(field, null, type, context, msgHandler);
                        Attribute[] fattributes = field.getAttributes();
 
@@ -322,7 +338,8 @@ public class AtAjAttributes {
                                        RuntimeAnnotations frvs = (RuntimeAnnotations) fattribute;
                                        if (handleDeclareErrorOrWarningAnnotation(model, frvs, fstruct)
                                                        || handleDeclareParentsAnnotation(frvs, fstruct)) {
-                                               // semantic check - must be in an @Aspect [remove if previous block bypassed in advance]
+                                               // semantic check - must be in an @Aspect [remove if
+                                               // previous block bypassed in advance]
                                                if (!type.isAnnotationStyleAspect() && !isCodeStyleAspect) {
                                                        msgHandler.handleMessage(new Message("Found @AspectJ annotations in a non @Aspect type '"
                                                                        + type.getName() + "'", IMessage.WARNING, null, type.getSourceLocation()));
@@ -356,12 +373,16 @@ public class AtAjAttributes {
                AjAttributeMethodStruct struct = new AjAttributeMethodStruct(method, bMethod, type, context, msgHandler);
                Attribute[] attributes = method.getAttributes();
 
-               // we remember if we found one @AJ annotation for minimal semantic error reporting
-               // the real reporting beeing done thru AJDT and the compiler mapping @AJ to AjAtttribute
+               // we remember if we found one @AJ annotation for minimal semantic error
+               // reporting
+               // the real reporting beeing done thru AJDT and the compiler mapping @AJ
+               // to AjAtttribute
                // or thru APT
                //
-               // Note: we could actually skip the whole thing if type is not itself an @Aspect
-               // but then we would not see any warning. We do bypass for pointcut but not for advice since it would
+               // Note: we could actually skip the whole thing if type is not itself an
+               // @Aspect
+               // but then we would not see any warning. We do bypass for pointcut but
+               // not for advice since it would
                // be too silent.
                boolean hasAtAspectJAnnotation = false;
                boolean hasAtAspectJAnnotationMustReturnVoid = false;
@@ -392,8 +413,10 @@ public class AtAjAttributes {
                }
                hasAtAspectJAnnotation = hasAtAspectJAnnotation || hasAtAspectJAnnotationMustReturnVoid;
 
-               // semantic check - must be in an @Aspect [remove if previous block bypassed in advance]
-               if (hasAtAspectJAnnotation && !type.isAspect()) { // isAnnotationStyleAspect()) {
+               // semantic check - must be in an @Aspect [remove if previous block
+               // bypassed in advance]
+               if (hasAtAspectJAnnotation && !type.isAspect()) { // isAnnotationStyleAspect())
+                       // {
                        msgHandler.handleMessage(new Message("Found @AspectJ annotations in a non @Aspect type '" + type.getName() + "'",
                                        IMessage.WARNING, null, type.getSourceLocation()));
                        // go ahead
@@ -410,7 +433,8 @@ public class AtAjAttributes {
                        msgHandler.handleMessage(MessageUtil.error("Advice cannot be declared static '" + methodToString(struct.method) + "'",
                                        type.getSourceLocation()));
                        // new Message(
-                       // "Advice cannot be declared static '" + methodToString(struct.method) + "'",
+                       // "Advice cannot be declared static '" +
+                       // methodToString(struct.method) + "'",
                        // IMessage.ERROR,
                        // null,
                        // type.getSourceLocation()
@@ -440,7 +464,8 @@ public class AtAjAttributes {
         */
        public static List readAj5FieldAttributes(Field field, BcelField bField, ResolvedType type, ISourceContext context,
                        IMessageHandler msgHandler) {
-               // Note: field annotation are for ITD and DEOW - processed at class level directly
+               // Note: field annotation are for ITD and DEOW - processed at class
+               // level directly
                return Collections.EMPTY_LIST;
        }
 
@@ -485,7 +510,8 @@ public class AtAjAttributes {
                                // could not parse it, ignore the aspect
                                return false;
                        } else {
-                               perClause.setLocation(struct.context, -1, -1);// struct.context.getOffset(), struct.context.getOffset()+1);//FIXME
+                               perClause.setLocation(struct.context, -1, -1);// struct.context.getOffset(),
+                               // struct.context.getOffset()+1);//FIXME
                                // AVASM
                                // FIXME asc see related comment way about about the version...
                                struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo());
@@ -495,8 +521,10 @@ public class AtAjAttributes {
                                final IScope binding;
                                binding = new BindingScope(struct.enclosingType, 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.
+                               // // 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);
 
@@ -543,7 +571,8 @@ public class AtAjAttributes {
                } else if (perClauseString.equalsIgnoreCase(PerClause.SINGLETON.getName() + "()")) {
                        perClause = new PerSingleton();
                } else {
-                       // could not parse the @AJ perclause - fallback to singleton and issue an error
+                       // could not parse the @AJ perclause - fallback to singleton and
+                       // issue an error
                        reportError("@Aspect per clause cannot be read '" + perClauseString + "'", struct);
                        return null;
                }
@@ -589,19 +618,26 @@ public class AtAjAttributes {
        // * @param struct
        // * @return true if found
        // */
-       // private static boolean handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct
+       // private static boolean
+       // handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations,
+       // AjAttributeFieldStruct
        // struct) {//, ResolvedPointcutDefinition preResolvedPointcut) {
-       // Annotation deci = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION);
+       // Annotation deci = getAnnotation(runtimeAnnotations,
+       // AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION);
        // if (deci != null) {
-       // ElementNameValuePairGen deciPatternNVP = getAnnotationElement(deci, VALUE);
+       // ElementNameValuePairGen 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());
+       // 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);
+       // TypePattern parent = new
+       // ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()),
+       // false, false);
        // parent.resolve(struct.enclosingType.getWorld());
        // List parents = new ArrayList(1);
        // parents.add(parent);
@@ -617,7 +653,8 @@ public class AtAjAttributes {
        // );
        // return true;
        // } else {
-       // reportError("@DeclareImplements: can only be used on field whose type is an interface", struct);
+       // reportError("@DeclareImplements: can only be used on field whose type is an interface",
+       // struct);
        // return false;
        // }
        // }
@@ -652,13 +689,17 @@ public class AtAjAttributes {
                                        List parents = new ArrayList(1);
                                        parents.add(parent);
                                        DeclareParents dp = new DeclareParents(typePattern, parents, false);
-                                       dp.resolve(binding); // resolves the parent and child parts of the decp
+                                       dp.resolve(binding); // resolves the parent and child parts
+                                       // of the decp
 
-                                       // resolve this so that we can use it for the MethodDelegateMungers below.
-                                       // eg. '@Coloured *' will change from a WildTypePattern to an 'AnyWithAnnotationTypePattern' after this
+                                       // resolve this so that we can use it for the
+                                       // MethodDelegateMungers below.
+                                       // eg. '@Coloured *' will change from a WildTypePattern to
+                                       // an 'AnyWithAnnotationTypePattern' after this
                                        // resolution
                                        typePattern = typePattern.resolveBindings(binding, Bindings.NONE, false, false);
-                                       // TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ??
+                                       // TODO kick ISourceLocation sl =
+                                       // struct.bField.getSourceLocation(); ??
                                        // dp.setLocation(dp.getDeclaringType().getSourceContext(),
                                        // dp.getDeclaringType().getSourceLocation().getOffset(),
                                        // dp.getDeclaringType().getSourceLocation().getOffset());
@@ -688,13 +729,16 @@ public class AtAjAttributes {
                                                                        hasNoCtorOrANoArgOne = false;
 
                                                                        if (resolvedMember.getParameterTypes().length == 0) {
-                                                                               if (defaultVisibilityImpl) { // default visibility implementation
+                                                                               if (defaultVisibilityImpl) { // default
+                                                                                       // visibility
+                                                                                       // implementation
                                                                                        if (resolvedMember.isPublic() || resolvedMember.isDefault()) {
                                                                                                hasNoCtorOrANoArgOne = true;
                                                                                        } else {
                                                                                                foundOneOfIncorrectVisibility = resolvedMember;
                                                                                        }
-                                                                               } else if (Modifier.isPublic(implModifiers)) { // public implementation
+                                                                               } else if (Modifier.isPublic(implModifiers)) { // public
+                                                                                       // implementation
                                                                                        if (resolvedMember.isPublic()) {
                                                                                                hasNoCtorOrANoArgOne = true;
                                                                                        } else {
@@ -734,21 +778,29 @@ public class AtAjAttributes {
                                        for (int i = 0; i < methods.length; i++) {
                                                ResolvedMember method = methods[i];
                                                if (method.isAbstract()) {
-                                                       // moved to be detected at weave time if the target doesnt implement the methods
+                                                       // moved to be detected at weave time if the target
+                                                       // doesnt implement the methods
                                                        // if (defaultImplClassName == null) {
-                                                       // // non marker interface with no default impl provided
+                                                       // // 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;
                                                        // What we are saying here:
-                                                       // We have this method 'method' and we want to put a forwarding method into a type that matches
-                                                       // typePattern that should delegate to the version of the method in 'defaultImplClassName'
-
-                                                       // Now the method may be from a supertype but the declaring type of the method we pass into the type
-                                                       // munger is what is used to determine the type of the field that hosts the delegate instance.
-                                                       // So here we create a modified method with an alternative declaring type so that we lookup
+                                                       // We have this method 'method' and we want to put a
+                                                       // forwarding method into a type that matches
+                                                       // typePattern that should delegate to the version
+                                                       // of the method in 'defaultImplClassName'
+
+                                                       // Now the method may be from a supertype but the
+                                                       // declaring type of the method we pass into the
+                                                       // type
+                                                       // munger is what is used to determine the type of
+                                                       // the field that hosts the delegate instance.
+                                                       // So here we create a modified method with an
+                                                       // alternative declaring type so that we lookup
                                                        // the right field. See pr164016.
                                                        MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType,
                                                                        defaultImplClassName, typePattern);
@@ -757,7 +809,8 @@ public class AtAjAttributes {
                                                        struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm));
                                                }
                                        }
-                                       // successfull so far, we thus need a bcel type munger to have
+                                       // successfull so far, we thus need a bcel type munger to
+                                       // have
                                        // a field hosting the mixin in the target type
                                        if (hasAtLeastOneMethod && defaultImplClassName != null) {
                                                ResolvedMember fieldHost = AjcMemberMaker.itdAtDeclareParentsField(null, fieldType, struct.enclosingType);
@@ -778,155 +831,235 @@ public class AtAjAttributes {
        /**
         * Process any @DeclareMixin annotation.
         * 
+        * Example Declaration <br>
+        * 
+        * @DeclareMixin("Foo+") public I createImpl(Object o) { return new Impl(o); }
+        * 
+        * <br>
         * @param runtimeAnnotations
         * @param struct
         * @return true if found
         */
        private static boolean handleDeclareMixinAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct) {
                AnnotationGen declareMixinAnnotation = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREMIXIN_ANNOTATION);
-               if (declareMixinAnnotation != null) {
-                       ElementNameValuePairGen declareMixinPatternNameValuePair = getAnnotationElement(declareMixinAnnotation, VALUE);
-                       String declareMixinPattern = declareMixinPatternNameValuePair.getValue().stringifyValue();
-                       if (declareMixinPattern != null) {
-                               TypePattern typePattern = parseTypePattern(declareMixinPattern, struct);
-                               ResolvedType methodType = UnresolvedType.forSignature(struct.method.getSignature()).resolve(
-                                               struct.enclosingType.getWorld());
-                               // For @DeclareMixin:
-                               // methodType - might be a class or an interface. If a class then the interfaces value of the
-                               // annotation will subset it
-                               if (methodType.isInterface()) {
-                                       // TODO DECLAREMIXIN set the location more accurately than this
-                                       // TODO DECLAREMIXIN check for interfaces specified and if they aren't it is an error
-                                       TypePattern parent = parseTypePattern(methodType.getName(), struct);
-                                       FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
-                                       IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
-                                       // first add the declare implements like
-                                       List parents = new ArrayList(1);
-                                       parents.add(parent);
-                                       // how do we mark this as a decp due to decmixin?
-                                       DeclareParents dp = new DeclareParents(typePattern, parents, false);
-                                       dp.resolve(binding); // resolves the parent and child parts of the decp
+               if (declareMixinAnnotation == null) {
+                       // No annotation found
+                       return false;
+               }
 
-                                       // resolve this so that we can use it for the MethodDelegateMungers below.
-                                       // eg. '@Coloured *' will change from a WildTypePattern to an 'AnyWithAnnotationTypePattern' after this
-                                       // resolution
-                                       typePattern = typePattern.resolveBindings(binding, Bindings.NONE, false, false);
-                                       // TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ??
-                                       // dp.setLocation(dp.getDeclaringType().getSourceContext(),
-                                       // dp.getDeclaringType().getSourceLocation().getOffset(),
-                                       // dp.getDeclaringType().getSourceLocation().getOffset());
-                                       dp.setLocation(struct.context, -1, -1); // not ideal...
-                                       struct.ajAttributes.add(new AjAttribute.DeclareAttribute(dp));
+               Method annotatedMethod = struct.method;
+               World world = struct.enclosingType.getWorld();
+               ElementNameValuePairGen declareMixinPatternNameValuePair = getAnnotationElement(declareMixinAnnotation, VALUE);
+
+               // declareMixinPattern could be of the form "Bar*" or "A || B" or "Foo+"
+               String declareMixinPattern = declareMixinPatternNameValuePair.getValue().stringifyValue();
+               TypePattern targetTypePattern = parseTypePattern(declareMixinPattern, struct);
+
+               // Return value of the annotated method is the interface or class that the mixin delegate should have
+               ResolvedType methodReturnType = UnresolvedType.forSignature(annotatedMethod.getReturnType().getSignature()).resolve(world);
+
+               // The set of interfaces to be mixed in is either:
+               // supplied as a list in the 'Class[] interfaces' value in the annotation value
+               // supplied as just the interface return value of the annotated method
+               // supplied as just the class return value of the annotated method
+               ElementNameValuePairGen interfaceListSpecified = getAnnotationElement(declareMixinAnnotation, "interfaces");
+
+               List newParents = new ArrayList(1);
+               List newParentTypes = new ArrayList(1);
+               if (interfaceListSpecified != null) {
+                       ArrayElementValueGen arrayOfInterfaceTypes = (ArrayElementValueGen) interfaceListSpecified.getValue();
+                       int numberOfTypes = arrayOfInterfaceTypes.getElementValuesArraySize();
+                       ElementValueGen[] theTypes = arrayOfInterfaceTypes.getElementValuesArray();
+                       for (int i = 0; i < numberOfTypes; i++) {
+                               ClassElementValueGen interfaceType = (ClassElementValueGen) theTypes[i];
+                               // Check: needs to be resolvable
+                               // TODO crappy replace required
+                               ResolvedType ajInterfaceType = UnresolvedType.forSignature(interfaceType.getClassString().replace("/", "."))
+                                               .resolve(world);
+                               newParentTypes.add(ajInterfaceType);
+                               if (ajInterfaceType.isMissing() || !ajInterfaceType.isInterface()) {
+                                       reportError(
+                                                       "Types listed in the 'interfaces' DeclareMixin annotation value must be valid interfaces. This is invalid: "
+                                                                       + ajInterfaceType.getName(), struct); // TODO better error location, use the method position
+                                       return false;
+                               }
+                               // Checking that it is a superinterface of the methods return value is done at weave time
+                               TypePattern newParent = parseTypePattern(ajInterfaceType.getName(), struct);
+                               newParents.add(newParent);
+                       }
+               } else {
+                       // Use the method return type: this might be a class or an interface
+                       TypePattern newParent = parseTypePattern(methodReturnType.getName(), struct);
+                       newParentTypes.add(methodReturnType);
+                       newParents.add(newParent);
+               }
+               if (newParents.size() == 0) {
+                       // Warning: did they foolishly put @DeclareMixin(value="Bar+",interfaces={})
+                       // TODO output warning
+                       return false;
+               }
+               // TODO DECLAREMIXIN set the location more accurately than
+               // this
+               FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
+               IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
+               // first add the declare implements like
+               // how do we mark this as a decp due to decmixin?
+               DeclareParents dp = new DeclareParents(targetTypePattern, newParents, false);
+               dp.resolve(binding); // resolves the parent and child parts
+               // of the decp
+
+               // resolve this so that we can use it for the
+               // MethodDelegateMungers below.
+               // eg. '@Coloured *' will change from a WildTypePattern to
+               // an 'AnyWithAnnotationTypePattern' after this
+               // resolution
+               targetTypePattern = dp.getChild();// targetTypePattern.resolveBindings(binding, Bindings.NONE, false, false);
+               // TODO kick ISourceLocation sl =
+               // struct.bField.getSourceLocation(); ??
+               // dp.setLocation(dp.getDeclaringType().getSourceContext(),
+               // dp.getDeclaringType().getSourceLocation().getOffset(),
+               // dp.getDeclaringType().getSourceLocation().getOffset());
+               dp.setLocation(struct.context, -1, -1); // not ideal...
+               struct.ajAttributes.add(new AjAttribute.DeclareAttribute(dp));
+
+               // The factory method for building the implementation is the
+               // one attached to the annotation:
+               Method implementationFactory = struct.method;
+               // do we have a defaultImpl=xxx.class (ie implementation)
+               // String defaultImplClassName = null;
+               // ElementNameValuePairGen defaultImplNVP =
+               // getAnnotationElement(declareMixinAnnotation,
+               // "defaultImpl");
+               // if (defaultImplNVP != null) {
+               // ClassElementValueGen defaultImpl = (ClassElementValueGen)
+               // defaultImplNVP.getValue();
+               // defaultImplClassName =
+               // UnresolvedType.forSignature(defaultImpl.getClassString()).getName();
+               // if
+               // (defaultImplClassName.equals("org.aspectj.lang.annotation.DeclareParents"))
+               // {
+               // defaultImplClassName = null;
+               // } else {
+               // // check public no arg ctor
+               // ResolvedType impl =
+               // struct.enclosingType.getWorld().resolve(defaultImplClassName,
+               // false);
+               // ResolvedMember[] mm = impl.getDeclaredMethods();
+               // int implModifiers = impl.getModifiers();
+               // boolean defaultVisibilityImpl =
+               // !(Modifier.isPrivate(implModifiers)
+               // || Modifier.isProtected(implModifiers) ||
+               // Modifier.isPublic(implModifiers));
+               // boolean hasNoCtorOrANoArgOne = true;
+               // ResolvedMember foundOneOfIncorrectVisibility = null;
+               // for (int i = 0; i < mm.length; i++) {
+               // ResolvedMember resolvedMember = mm[i];
+               // if (resolvedMember.getName().equals("<init>")) {
+               // hasNoCtorOrANoArgOne = false;
+               //
+               // if (resolvedMember.getParameterTypes().length == 0) {
+               // if (defaultVisibilityImpl) { // default visibility
+               // implementation
+               // if (resolvedMember.isPublic() ||
+               // resolvedMember.isDefault()) {
+               // hasNoCtorOrANoArgOne = true;
+               // } else {
+               // foundOneOfIncorrectVisibility = resolvedMember;
+               // }
+               // } else if (Modifier.isPublic(implModifiers)) { // public
+               // implementation
+               // if (resolvedMember.isPublic()) {
+               // hasNoCtorOrANoArgOne = true;
+               // } else {
+               // foundOneOfIncorrectVisibility = resolvedMember;
+               // }
+               // }
+               // }
+               // }
+               // if (hasNoCtorOrANoArgOne) {
+               // break;
+               // }
+               // }
+               // if (!hasNoCtorOrANoArgOne) {
+               // if (foundOneOfIncorrectVisibility != null) {
+               // reportError(
+               // "@DeclareParents: defaultImpl=\""
+               // + defaultImplClassName
+               // +
+               // "\" has a no argument constructor, but it is of incorrect visibility.  It must be at least as visible as the type.",
+               // struct);
+               // } else {
+               // reportError("@DeclareParents: defaultImpl=\"" +
+               // defaultImplClassName
+               // + "\" has no public no-arg constructor", struct);
+               // }
+               // }
+               // if (!methodType.isAssignableFrom(impl)) {
+               // reportError("@DeclareParents: defaultImpl=\"" +
+               // defaultImplClassName
+               // + "\" does not implement the interface '" +
+               // methodType.toString() + "'", struct);
+               // }
+               // }
+               //
+               // }
 
-                                       // do we have a defaultImpl=xxx.class (ie implementation)
-                                       String defaultImplClassName = null;
-                                       ElementNameValuePairGen defaultImplNVP = getAnnotationElement(declareMixinAnnotation, "defaultImpl");
-                                       // if (defaultImplNVP != null) {
-                                       // ClassElementValueGen defaultImpl = (ClassElementValueGen) defaultImplNVP.getValue();
-                                       // defaultImplClassName = UnresolvedType.forSignature(defaultImpl.getClassString()).getName();
-                                       // if (defaultImplClassName.equals("org.aspectj.lang.annotation.DeclareParents")) {
-                                       // defaultImplClassName = null;
-                                       // } else {
-                                       // // check public no arg ctor
-                                       // ResolvedType impl = struct.enclosingType.getWorld().resolve(defaultImplClassName, false);
-                                       // ResolvedMember[] mm = impl.getDeclaredMethods();
-                                       // int implModifiers = impl.getModifiers();
-                                       // boolean defaultVisibilityImpl = !(Modifier.isPrivate(implModifiers)
-                                       // || Modifier.isProtected(implModifiers) || Modifier.isPublic(implModifiers));
-                                       // boolean hasNoCtorOrANoArgOne = true;
-                                       // ResolvedMember foundOneOfIncorrectVisibility = null;
-                                       // for (int i = 0; i < mm.length; i++) {
-                                       // ResolvedMember resolvedMember = mm[i];
-                                       // if (resolvedMember.getName().equals("<init>")) {
-                                       // hasNoCtorOrANoArgOne = false;
-                                       //
-                                       // if (resolvedMember.getParameterTypes().length == 0) {
-                                       // if (defaultVisibilityImpl) { // default visibility implementation
-                                       // if (resolvedMember.isPublic() || resolvedMember.isDefault()) {
-                                       // hasNoCtorOrANoArgOne = true;
-                                       // } else {
-                                       // foundOneOfIncorrectVisibility = resolvedMember;
-                                       // }
-                                       // } else if (Modifier.isPublic(implModifiers)) { // public implementation
-                                       // if (resolvedMember.isPublic()) {
-                                       // hasNoCtorOrANoArgOne = true;
-                                       // } else {
-                                       // foundOneOfIncorrectVisibility = resolvedMember;
-                                       // }
-                                       // }
-                                       // }
-                                       // }
-                                       // if (hasNoCtorOrANoArgOne) {
-                                       // break;
-                                       // }
-                                       // }
-                                       // if (!hasNoCtorOrANoArgOne) {
-                                       // if (foundOneOfIncorrectVisibility != null) {
-                                       // reportError(
-                                       // "@DeclareParents: defaultImpl=\""
-                                       // + defaultImplClassName
-                                       // +
-                                       // "\" has a no argument constructor, but it is of incorrect visibility.  It must be at least as visible as the type.",
+               // then iterate on field interface hierarchy (not object)
+               boolean hasAtLeastOneMethod = false;
+
+               for (Iterator iterator = newParentTypes.iterator(); iterator.hasNext();) {
+                       ResolvedType typeForDelegation = (ResolvedType) iterator.next();
+                       // TODO check for overlapping interfaces. Eg. A implements I, I extends J - if they specify interfaces={I,J} we dont
+                       // want to do any methods twice
+                       ResolvedMember[] methods = (ResolvedMember[]) typeForDelegation.getMethodsWithoutIterator(true, false).toArray(
+                                       new ResolvedMember[0]);
+                       for (int i = 0; i < methods.length; i++) {
+                               ResolvedMember method = methods[i];
+                               if (method.isAbstract()) {
+                                       // moved to be detected at weave time if the target
+                                       // doesnt implement the methods
+                                       // if (defaultImplClassName == null) {
+                                       // // non marker interface with no default impl
+                                       // provided
+                                       // reportError("@DeclareParents: used with a non marker interface and no defaultImpl=\"...\" provided",
                                        // struct);
-                                       // } else {
-                                       // reportError("@DeclareParents: defaultImpl=\"" + defaultImplClassName
-                                       // + "\" has no public no-arg constructor", struct);
-                                       // }
-                                       // }
-                                       // if (!methodType.isAssignableFrom(impl)) {
-                                       // reportError("@DeclareParents: defaultImpl=\"" + defaultImplClassName
-                                       // + "\" does not implement the interface '" + methodType.toString() + "'", struct);
+                                       // return false;
                                        // }
-                                       // }
-                                       //
-                                       // }
-
-                                       // then iterate on field interface hierarchy (not object)
-                                       boolean hasAtLeastOneMethod = false;
-                                       ResolvedMember[] methods = (ResolvedMember[]) methodType.getMethodsWithoutIterator(true, false).toArray(
-                                                       new ResolvedMember[0]);
-                                       for (int i = 0; i < methods.length; i++) {
-                                               ResolvedMember method = methods[i];
-                                               if (method.isAbstract()) {
-                                                       // moved to be detected at weave time if the target doesnt implement the methods
-                                                       // 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;
-                                                       // What we are saying here:
-                                                       // We have this method 'method' and we want to put a forwarding method into a type that matches
-                                                       // typePattern that should delegate to the version of the method in 'defaultImplClassName'
-
-                                                       // Now the method may be from a supertype but the declaring type of the method we pass into the type
-                                                       // munger is what is used to determine the type of the field that hosts the delegate instance.
-                                                       // So here we create a modified method with an alternative declaring type so that we lookup
-                                                       // the right field. See pr164016.
-                                                       MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType,
-                                                                       defaultImplClassName, typePattern);
-                                                       mdtm.setFieldType(methodType);
-                                                       mdtm.setSourceLocation(struct.enclosingType.getSourceLocation());
-                                                       struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm));
-                                               }
-                                       }
-                                       // successfull so far, we thus need a bcel type munger to have
-                                       // a field hosting the mixin in the target type
-                                       if (hasAtLeastOneMethod && defaultImplClassName != null) {
-                                               ResolvedMember fieldHost = AjcMemberMaker.itdAtDeclareParentsField(null, methodType, struct.enclosingType);
-                                               struct.ajAttributes.add(new AjAttribute.TypeMunger(new MethodDelegateTypeMunger.FieldHostTypeMunger(
-                                                               fieldHost, struct.enclosingType, typePattern)));
-                                       }
-
-                                       return true;
-                               } else {
-                                       reportError("@DeclareParents: can only be used on a field whose type is an interface", struct);
-                                       return false;
+                                       hasAtLeastOneMethod = true;
+                                       // What we are saying here:
+                                       // We have this method 'method' and we want to put a
+                                       // forwarding method into a type that matches
+                                       // typePattern that should delegate to the version
+                                       // of the method in 'defaultImplClassName'
+
+                                       // Now the method may be from a supertype but the
+                                       // declaring type of the method we pass into the
+                                       // type
+                                       // munger is what is used to determine the type of
+                                       // the field that hosts the delegate instance.
+                                       // So here we create a modified method with an
+                                       // alternative declaring type so that we lookup
+                                       // the right field. See pr164016.
+                                       MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType, "",
+                                                       targetTypePattern, struct.method.getName(), struct.method.getSignature());
+                                       mdtm.setFieldType(methodReturnType);
+                                       mdtm.setSourceLocation(struct.enclosingType.getSourceLocation());
+                                       struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm));
                                }
                        }
                }
-               return false;
+               // successfull so far, we thus need a bcel type munger to
+               // have
+               // a field hosting the mixin in the target type
+               if (hasAtLeastOneMethod) {
+                       ResolvedMember fieldHost = AjcMemberMaker.itdAtDeclareParentsField(null, methodReturnType, struct.enclosingType);
+                       struct.ajAttributes.add(new AjAttribute.TypeMunger(new MethodDelegateTypeMunger.FieldHostTypeMunger(fieldHost,
+                                       struct.enclosingType, targetTypePattern)));
+               } else {
+                       return false;
+               }
+
+               return true;
        }
 
        /**
@@ -1069,7 +1202,8 @@ public class AtAjAttributes {
                                if (isNullOrEmpty(returned)) {
                                        returned = null;
                                } else {
-                                       // check that thrownFormal exists as the last parameter in the advice
+                                       // check that thrownFormal exists as the last parameter in
+                                       // the advice
                                        String[] pNames = owningMethod.getParameterNames();
                                        if (pNames == null || pNames.length == 0 || !Arrays.asList(pNames).contains(returned)) {
                                                throw new ReturningFormalNotDeclaredInAdviceSignatureException(returned);
@@ -1081,7 +1215,8 @@ public class AtAjAttributes {
                                struct.unparsedArgumentNames = argumentNames;
                        }
                        // this/target/args binding
-                       // exclude the return binding from the pointcut binding since it is an extraArg binding
+                       // exclude the return binding from the pointcut binding since it is
+                       // an extraArg binding
                        FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
                        try {
                                bindings = (returned == null ? extractBindings(struct) : extractBindings(struct, returned));
@@ -1156,7 +1291,8 @@ public class AtAjAttributes {
                                if (isNullOrEmpty(thrownFormal)) {
                                        thrownFormal = null;
                                } else {
-                                       // check that thrownFormal exists as the last parameter in the advice
+                                       // check that thrownFormal exists as the last parameter in
+                                       // the advice
                                        String[] pNames = owningMethod.getParameterNames();
                                        if (pNames == null || pNames.length == 0 || !Arrays.asList(pNames).contains(thrownFormal)) {
                                                throw new ThrownFormalNotDeclaredInAdviceSignatureException(thrownFormal);
@@ -1168,7 +1304,8 @@ public class AtAjAttributes {
                                struct.unparsedArgumentNames = argumentNames;
                        }
                        // this/target/args binding
-                       // exclude the throwned binding from the pointcut binding since it is an extraArg binding
+                       // exclude the throwned binding from the pointcut binding since it
+                       // is an extraArg binding
                        FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
                        try {
                                bindings = (thrownFormal == null ? extractBindings(struct) : extractBindings(struct, thrownFormal));
@@ -1269,7 +1406,8 @@ public class AtAjAttributes {
                        return false;
                ElementNameValuePairGen pointcutExpr = getAnnotationElement(pointcut, VALUE);
 
-               // semantic check: the method must return void, or be "public static boolean" for if() support
+               // semantic check: the method must return void, or be
+               // "public static boolean" for if() support
                if (!(Type.VOID.equals(struct.method.getReturnType()) || (Type.BOOLEAN.equals(struct.method.getReturnType())
                                && struct.method.isStatic() && struct.method.isPublic()))) {
                        reportWarning("Found @Pointcut on a method not returning 'void' or not 'public static boolean'", struct);
@@ -1314,17 +1452,22 @@ public class AtAjAttributes {
                        }
                } else {
                        if (pointcutExpr == null || isNullOrEmpty(pointcutExpr.getValue().stringifyValue())) {
-                               // the matches nothing pointcut (125475/125480) - perhaps not as cleanly supported as it could be.
+                               // the matches nothing pointcut (125475/125480) - perhaps not as
+                               // cleanly supported as it could be.
                        } else {
                                // if (pointcutExpr != null) {
-                               // use a LazyResolvedPointcutDefinition so that the pointcut is resolved lazily
-                               // since for it to be resolved, we will need other pointcuts to be registered as well
+                               // use a LazyResolvedPointcutDefinition so that the pointcut is
+                               // resolved lazily
+                               // since for it to be resolved, we will need other pointcuts to
+                               // be registered as well
                                pc = parsePointcut(pointcutExpr.getValue().stringifyValue(), struct, true);
                                if (pc == null)
                                        return false;// parse error
-                               pc.setLocation(struct.context, -1, -1);// FIXME AVASM !! bMethod is null here..
+                               pc.setLocation(struct.context, -1, -1);// FIXME AVASM !! bMethod
+                               // is null here..
                                // } else {
-                               // reportError("Found undefined @Pointcut on a non-abstract method", struct);
+                               // reportError("Found undefined @Pointcut on a non-abstract method",
+                               // struct);
                                // return false;
                                // }
                        }
@@ -1332,7 +1475,12 @@ public class AtAjAttributes {
                // do not resolve binding now but lazily
                struct.ajAttributes.add(new AjAttribute.PointcutDeclarationAttribute(new LazyResolvedPointcutDefinition(
                                struct.enclosingType, struct.method.getModifiers(), struct.method.getName(), argumentTypes, UnresolvedType
-                                               .forSignature(struct.method.getReturnType().getSignature()), pc,// can be null for abstract pointcut
+                                               .forSignature(struct.method.getReturnType().getSignature()), pc,// can
+                               // be
+                               // null
+                               // for
+                               // abstract
+                               // pointcut
                                binding // can be null for abstract pointcut
                                )));
                return true;
@@ -1454,8 +1602,10 @@ public class AtAjAttributes {
                        String argumentName = argumentNames[i];
                        UnresolvedType argumentType = UnresolvedType.forSignature(method.getArgumentTypes()[i].getSignature());
 
-                       // do not bind JoinPoint / StaticJoinPoint / EnclosingStaticJoinPoint
-                       // TODO solve me : this means that the JP/SJP/ESJP cannot appear as binding
+                       // do not bind JoinPoint / StaticJoinPoint /
+                       // EnclosingStaticJoinPoint
+                       // TODO solve me : this means that the JP/SJP/ESJP cannot appear as
+                       // binding
                        // f.e. when applying advice on advice etc
                        if ((AjcMemberMaker.TYPEX_JOINPOINT.equals(argumentType)
                                        || AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.equals(argumentType)
@@ -1488,13 +1638,15 @@ public class AtAjAttributes {
                return bindings;
                //
                // if (excludeIndex >= 0) {
-               // FormalBinding[] bindingsFiltered = new FormalBinding[bindings.length-1];
+               // FormalBinding[] bindingsFiltered = new
+               // FormalBinding[bindings.length-1];
                // int k = 0;
                // for (int i = 0; i < bindings.length; i++) {
                // if (i == excludeIndex) {
                // ;
                // } else {
-               // bindingsFiltered[k] = new FormalBinding(bindings[i].getType(), bindings[i].getName(), k);
+               // bindingsFiltered[k] = new FormalBinding(bindings[i].getType(),
+               // bindings[i].getName(), k);
                // k++;
                // }
                // }
@@ -1703,7 +1855,8 @@ public class AtAjAttributes {
         * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
         */
        public static class LazyResolvedPointcutDefinition extends ResolvedPointcutDefinition {
-               private final Pointcut m_pointcutUnresolved; // null for abstract pointcut
+               private final Pointcut m_pointcutUnresolved; // null for abstract
+               // pointcut
                private final IScope m_binding;
 
                private Pointcut m_lazyPointcut = null;
@@ -1771,6 +1924,12 @@ public class AtAjAttributes {
                }
        }
 
+       private static void reportError(String message, IMessageHandler handler, ISourceLocation sourceLocation) {
+               if (!handler.isIgnoring(IMessage.ERROR)) {
+                       handler.handleMessage(new Message(message, sourceLocation, true));
+               }
+       }
+
        /**
         * Report a warning
         * 
@@ -1801,7 +1960,8 @@ public class AtAjAttributes {
                                reportError("if() pointcut is not allowed at this pointcut location '" + pointcutString + "'", struct);
                                return null;
                        }
-                       pointcut.setLocation(struct.context, -1, -1);// FIXME -1,-1 is not good enough
+                       pointcut.setLocation(struct.context, -1, -1);// FIXME -1,-1 is not
+                       // good enough
                        return pointcut;
                } catch (ParserException e) {
                        reportError("Invalid pointcut '" + pointcutString + "': " + e.toString()
@@ -1826,7 +1986,9 @@ public class AtAjAttributes {
        private static TypePattern parseTypePattern(String patternString, AjAttributeStruct location) {
                try {
                        TypePattern typePattern = new PatternParser(patternString).parseTypePattern();
-                       typePattern.setLocation(location.context, -1, -1);// FIXME -1,-1 is not good enough
+                       typePattern.setLocation(location.context, -1, -1);// FIXME -1,-1 is
+                       // not good
+                       // enough
                        return typePattern;
                } catch (ParserException e) {
                        reportError("Invalid type pattern'" + patternString + "' : " + e.getLocation(), location);
index 9975791adcc2db85d0b6f105db9f9e10acc4a5e3..eb3c1dd8d3b797e505758fdf24104b6f8f664597 100644 (file)
@@ -1140,7 +1140,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
         * @param unMangledInterMethod the method to bridge 'to' that we have already created in the 'subtype'
         * @param clazz the class in which to put the bridge method
         * @param paramTypes Parameter types for the bridge method, passed in as an optimization since the caller is likely to have
-        *        already created them.
+        *            already created them.
         * @param theBridgeMethod
         */
        private void createBridgeMethod(BcelWorld world, NewMethodTypeMunger munger, ResolvedMember unMangledInterMethod,
@@ -1240,7 +1240,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                        // If no implementation class was specified, the intention was that
                        // the types matching the pattern
                        // already implemented the interface, let's check that now!
-                       if (munger.getImplClassName() == null) {
+                       if (munger.getImplClassName() == null && !munger.specifiesDelegateFactoryMethod()) {
                                boolean isOK = false;
                                List/* LazyMethodGen */existingMethods = gen.getMethodGens();
                                for (Iterator i = existingMethods.iterator(); i.hasNext() && !isOK;) {
@@ -1303,11 +1303,41 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                        body.append(ifNonNull);
 
                        // Create and store a new instance
-                       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())));
+                       body.append(InstructionConstants.ALOAD_0); // 'this' is where we'll store the field value
+
+                       // TODO for non-static case, call aspectOf() then call the factory method on the retval
+                       // TODO decide whether the value can really be cached
+
+                       // locate the aspect and call the static method in it
+                       if (munger.specifiesDelegateFactoryMethod()) {
+                               ResolvedMember rm = munger.getDelegateFactoryMethod(weaver.getWorld());
+
+                               if (rm.isStatic()) {
+                                       if (rm.getArity() != 0) {
+                                               body.append(InstructionConstants.ALOAD_0);
+                                       }
+                                       body.append(fact.createInvoke(rm.getDeclaringType().getName(), rm.getName(), rm.getSignature(),
+                                                       Constants.INVOKESTATIC));
+                                       body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
+                               } else {
+                                       // Need to call aspectOf() to obtain the aspect instance then call the factory method upon that
+                                       UnresolvedType theAspect = munger.getAspect();
+                                       body.append(fact.createInvoke(theAspect.getName(), "aspectOf", "()" + theAspect.getSignature(),
+                                                       Constants.INVOKESTATIC));
+                                       if (rm.getArity() != 0) {
+                                               body.append(InstructionConstants.ALOAD_0);
+                                       }
+                                       body.append(fact.createInvoke(rm.getDeclaringType().getName(), rm.getName(), rm.getSignature(),
+                                                       Constants.INVOKEVIRTUAL));
+                                       body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
+                               }
+                       } else {
+                               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())));
+                       }
 
                        // if not null use the instance we've got
                        InstructionHandle ifNonNullElse = body.append(InstructionConstants.ALOAD_0);