From 5aced374f29c70db5af2730672bc0d14dfa58df2 Mon Sep 17 00:00:00 2001 From: aclement Date: Thu, 8 Nov 2007 09:01:47 +0000 Subject: [PATCH] fix for 169432 - allow @DeclareParents with no impl if the targets implement the interface correctly --- .../aspectj/weaver/bcel/AtAjAttributes.java | 33 ++++++------- .../aspectj/weaver/bcel/BcelTypeMunger.java | 49 +++++++++++++++++++ 2 files changed, 65 insertions(+), 17 deletions(-) diff --git a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java index c62c07dbe..b8a5a9aeb 100644 --- a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java +++ b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java @@ -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( diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index 016bf8a68..fec373f0c 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -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()), -- 2.39.5