]> source.dussan.org Git - aspectj.git/commitdiff
fix for 169432 - allow @DeclareParents with no impl if the targets implement the...
authoraclement <aclement>
Thu, 8 Nov 2007 09:01:47 +0000 (09:01 +0000)
committeraclement <aclement>
Thu, 8 Nov 2007 09:01:47 +0000 (09:01 +0000)
weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java
weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java

index c62c07dbee103715eada329d61d2668bfd9d7de2..b8a5a9aeb625bbe1dd63ede92baf77c296dcdb73 100644 (file)
@@ -742,28 +742,27 @@ public class AtAjAttributes {
                     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;
-                            }
+                        // 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;
-
-                            struct.ajAttributes.add(
-                                    new AjAttribute.TypeMunger(
-                                            new MethodDelegateTypeMunger(
-                                                method,
-                                                struct.enclosingType,
-                                                defaultImplClassName,
-                                                typePattern
-                                            )
-                                    )
-                            );
+                            MethodDelegateTypeMunger mdtm = 
+                                new MethodDelegateTypeMunger(
+                                    method,
+                                    struct.enclosingType,
+                                    defaultImplClassName,
+                                    typePattern
+                                );
+                            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) {
+                    if (hasAtLeastOneMethod && defaultImplClassName!=null) {
                         struct.ajAttributes.add(
                                 new AjAttribute.TypeMunger(
                                         new MethodDelegateTypeMunger.FieldHostTypeMunger(
index 016bf8a683e2c69ba45a37177a9ac30d487b6882..fec373f0c68a569497eb188474187268f8a37649 100644 (file)
@@ -1087,6 +1087,27 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
                clazz.addMethodGen(bridgeMethod);
        }
        
+       // Unlike toString() on a member, this does not include the declaring type
+       private String stringifyMember(ResolvedMember member) {
+               StringBuffer buf = new StringBuffer();
+       buf.append(member.getReturnType().getName());
+       buf.append(' ');
+               buf.append(member.getName());
+       if (member.getKind() != Member.FIELD) {
+               buf.append("(");
+               UnresolvedType[] params = member.getParameterTypes();
+            if (params.length != 0) {
+                buf.append(params[0]);
+                       for (int i=1, len = params.length; i < len; i++) {
+                    buf.append(", ");
+                           buf.append(params[i].getName());
+                       }
+            }
+               buf.append(")");
+       }
+       return buf.toString();
+       }
+       
     private boolean mungeMethodDelegate(BcelClassWeaver weaver, MethodDelegateTypeMunger munger) {
         ResolvedMember introduced = munger.getSignature();
 
@@ -1102,6 +1123,34 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
 
         boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType);
         if (shouldApply) {
+               
+               // 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) {
+                       boolean isOK = false;
+                       List/*LazyMethodGen*/ existingMethods = gen.getMethodGens();
+                       for (Iterator i = existingMethods.iterator(); i.hasNext() && !isOK;) {
+                           LazyMethodGen m = (LazyMethodGen) i.next();
+                           if (m.getName().equals(introduced.getName()) &&  
+                               m.getParameterSignature().equals(introduced.getParameterSignature()) &&
+                               m.getReturnType().equals(introduced.getReturnType())) {
+                               isOK = true;
+                           }
+                       }        
+                       if (!isOK) {
+                               // the class does not implement this method, they needed to supply a default impl class
+                               IMessage msg = new Message("@DeclareParents: No defaultImpl was specified but the type '"+gen.getName()+
+                                               "' does not implement the method '"+stringifyMember(introduced)+"' defined on the interface '"+introduced.getDeclaringType()+"'",
+                                               weaver.getLazyClassGen().getType().getSourceLocation(),true,new ISourceLocation[]{munger.getSourceLocation()});
+                               weaver.getWorld().getMessageHandler().handleMessage(msg);
+                               return false;
+                       }
+                       
+                       return true;
+               }
+               
+               
+               
             LazyMethodGen mg = new LazyMethodGen(
                     introduced.getModifiers() - Modifier.ABSTRACT,
                     BcelWorld.makeBcelType(introduced.getReturnType()),