From 0ca15bb18dde892f599a1b2c8ae06cbcda847c7f Mon Sep 17 00:00:00 2001 From: aclement Date: Thu, 22 Apr 2010 02:24:45 +0000 Subject: [PATCH] 310043: override final rogue message --- .../aspectj/weaver/JoinPointSignature.java | 8 ++- .../src/org/aspectj/weaver/MemberImpl.java | 58 ++++++++++++------- .../org/aspectj/weaver/ResolvedMember.java | 4 +- .../src/org/aspectj/weaver/ResolvedType.java | 42 ++++++++++++-- .../aspectj/weaver/TemporaryTypeMunger.java | 4 +- 5 files changed, 85 insertions(+), 31 deletions(-) diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignature.java b/org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignature.java index 2377f91b7..da5927840 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignature.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/JoinPointSignature.java @@ -20,6 +20,8 @@ import java.util.Map; import org.aspectj.bridge.ISourceLocation; import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute; +import sun.security.krb5.Realm; + /** * @author colyer Instances of this class are created by ResolvedMember.getSignatures() when collating all of the signatures for a * member. We need to create entries in the set for the "gaps" in the hierarchy. For example: @@ -165,7 +167,7 @@ public class JoinPointSignature implements ResolvedMember { public boolean isPublic() { return realMember.isPublic(); } - + public boolean isDefault() { return realMember.isDefault(); } @@ -370,4 +372,8 @@ public class JoinPointSignature implements ResolvedMember { public boolean isDefaultConstructor() { return realMember.isDefaultConstructor(); } + + public boolean equalsApartFromDeclaringType(Object other) { + return realMember.equalsApartFromDeclaringType(other); + } } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java index 46e10a717..b34c34946 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java @@ -28,7 +28,7 @@ public class MemberImpl implements Member { protected UnresolvedType returnType; protected UnresolvedType[] parameterTypes; private final String erasedSignature; // eg. (Ljava/util/Set;V)Ljava/lang/String; - private String paramSignature; // eg. (Ljava/util/Set;V) // no return type + private String paramSignature; // eg. (Ljava/util/Set;V) // no return type // OPTIMIZE move out of the member! private boolean reportedCantFindDeclaringType = false; @@ -40,7 +40,8 @@ public class MemberImpl implements Member { private JoinPointSignatureIterator joinPointSignatures = null; /** - * Construct a MemberImpl using an erased signature for the parameters and return type (member method/ctor) or type (member field) + * Construct a MemberImpl using an erased signature for the parameters and return type (member method/ctor) or type (member + * field) */ public MemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, String name, String erasedSignature) { this.kind = kind; @@ -59,7 +60,8 @@ public class MemberImpl implements Member { } /** - * Construct a MemberImpl using real type information for the parameters and return type (member method/ctor) or type (member field) + * Construct a MemberImpl using real type information for the parameters and return type (member method/ctor) or type (member + * field) */ public MemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name, UnresolvedType[] parameterTypes) { @@ -73,19 +75,20 @@ public class MemberImpl implements Member { this.erasedSignature = returnType.getErasureSignature(); } else { this.erasedSignature = typesToSignature(returnType, parameterTypes, true); - + // Check parameter recovery by collapsing types to the string then rebuilding them from that // this will check we are capable of having WeakRefs to the parameter types -// String nonErasedSignature = getParameterSignature()+getReturnType().getSignature(); -// Object[] returnAndParams = signatureToTypes(nonErasedSignature); -// UnresolvedType[] recoveredParams = (UnresolvedType[]) returnAndParams[1]; -// for (int jj=0;jj;)V" - * or "(Ljava/util/Set;)V". The latter form shows what happens when the generics are erased + * Build a signature based on the return type and parameter types. For example: "(Ljava/util/Set;)V" or + * "(Ljava/util/Set;)V". The latter form shows what happens when the generics are erased */ public static String typesToSignature(UnresolvedType returnType, UnresolvedType[] paramTypes, boolean eraseGenerics) { StringBuilder buf = new StringBuilder(); buf.append("("); - for (UnresolvedType paramType: paramTypes) { + for (UnresolvedType paramType : paramTypes) { if (eraseGenerics && (paramType.isParameterizedType() || paramType.isTypeVariableReference())) { - buf.append(paramType.getErasureSignature()); + buf.append(paramType.getErasureSignature()); } else { - buf.append(paramType.getSignature()); + buf.append(paramType.getSignature()); } } buf.append(")"); if (eraseGenerics && (returnType.isParameterizedType() || returnType.isTypeVariableReference())) { - buf.append(returnType.getErasureSignature()); + buf.append(returnType.getErasureSignature()); } else { buf.append(returnType.getSignature()); } @@ -200,7 +203,7 @@ public class MemberImpl implements Member { } else if (c == 'T') { // assumed 'reference' to a type // variable, so just "Tname;" int nextSemicolon = sig.indexOf(';', start); - String nextbit = sig.substring(start, nextSemicolon+1); + String nextbit = sig.substring(start, nextSemicolon + 1); l.add(UnresolvedType.forSignature(nextbit)); i = nextSemicolon + 1; } else { @@ -251,7 +254,7 @@ public class MemberImpl implements Member { public static MemberImpl method(UnresolvedType declTy, int mods, UnresolvedType rTy, String name, UnresolvedType[] paramTys) { return new MemberImpl( // ??? this calls a method - name.equals("") ? CONSTRUCTOR : METHOD, declTy, mods, rTy, name, paramTys); + name.equals("") ? CONSTRUCTOR : METHOD, declTy, mods, rTy, name, paramTys); } private static Member pointcut(UnresolvedType declTy, int mods, UnresolvedType rTy, String name, UnresolvedType[] paramTys) { @@ -263,7 +266,7 @@ public class MemberImpl implements Member { } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { if (!(other instanceof Member)) { return false; } @@ -272,6 +275,17 @@ public class MemberImpl implements Member { .equals(o.getDeclaringType())); } + /** + * @return true if this member equals the one supplied in every respect other than the declaring type + */ + public final boolean equalsApartFromDeclaringType(Object other) { + if (!(other instanceof Member)) { + return false; + } + Member o = (Member) other; + return (getKind() == o.getKind() && getName().equals(o.getName()) && getSignature().equals(o.getSignature())); + } + /** * Equality is checked based on the underlying signature, so the hash code of a member is based on its kind, name, signature, * and declaring type. The algorithm for this was taken from page 38 of effective java. diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java index 1f82713e4..93d1361a5 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedMember.java @@ -81,7 +81,7 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe public ISourceLocation getSourceLocation(); public int getStart(); - + public int getEnd(); public ISourceContext getSourceContext(); @@ -123,6 +123,8 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe */ public UnresolvedType[] getGenericParameterTypes(); + public boolean equalsApartFromDeclaringType(Object other); + // return a resolved member in which all type variables in the signature of // this // member have been replaced with the given bindings. diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java index 0b7f27c08..7e4932f96 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java @@ -1771,11 +1771,11 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl // System.err.println(" compare: " + c); if (c < 0) { // the existing munger dominates the new munger - checkLegalOverride(munger.getSignature(), existingMunger.getSignature()); + checkLegalOverride(munger.getSignature(), existingMunger.getSignature(), 0x11, null); return; } else if (c > 0) { // the new munger dominates the existing one - checkLegalOverride(existingMunger.getSignature(), munger.getSignature()); + checkLegalOverride(existingMunger.getSignature(), munger.getSignature(), 0x11, null); i.remove(); break; } else { @@ -1841,11 +1841,11 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl // System.err.println(" c: " + c); if (c < 0) { // existingMember dominates munger - checkLegalOverride(typeTransformerSignature, existingMember); + checkLegalOverride(typeTransformerSignature, existingMember, 0x10, typeTransformer.getAspectType()); return true; } else if (c > 0) { // munger dominates existingMember - checkLegalOverride(existingMember, typeTransformerSignature); + checkLegalOverride(existingMember, typeTransformerSignature, 0x01, typeTransformer.getAspectType()); // interTypeMungers.add(munger); // ??? might need list of these overridden abstracts continue; @@ -1953,13 +1953,43 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl } /** + * @param transformerPosition which parameter is the type transformer (0x10 for first, 0x01 for second, 0x11 for both, 0x00 for + * neither) + * @param aspectType the declaring type of aspect defining the *first* type transformer * @return true if the override is legal note: calling showMessage with two locations issues TWO messages, not ONE message with * an additional source location. */ - public boolean checkLegalOverride(ResolvedMember parent, ResolvedMember child) { + public boolean checkLegalOverride(ResolvedMember parent, ResolvedMember child, int transformerPosition, ResolvedType aspectType) { // System.err.println("check: " + child.getDeclaringType() + // " overrides " + parent.getDeclaringType()); if (Modifier.isFinal(parent.getModifiers())) { + // If the ITD matching is occurring due to pulling in a BinaryTypeBinding then this check can incorrectly + // signal an error because the ITD transformer being examined here will exactly match the member it added + // during the first round of compilation. This situation can only occur if the ITD is on an interface whilst + // the class is the top most implementor. If the ITD is on the same type that received it during compilation, + // this method won't be called as the previous check for precedence level will return 0. + + if (transformerPosition == 0x10 && aspectType != null) { + ResolvedType nonItdDeclaringType = child.getDeclaringType().resolve(world); + WeaverStateInfo wsi = nonItdDeclaringType.getWeaverState(); + if (wsi != null) { + List transformersOnThisType = wsi.getTypeMungers(nonItdDeclaringType); + if (transformersOnThisType != null) { + for (ConcreteTypeMunger transformer : transformersOnThisType) { + // relatively crude check - is the ITD + // for the same as the existingmember + // and does it come + // from the same aspect + if (transformer.aspectType.equals(aspectType)) { + if (parent.equalsApartFromDeclaringType(transformer.getSignature())) { + return true; + } + } + } + } + } + } + world.showMessage(Message.ERROR, WeaverMessages.format(WeaverMessages.CANT_OVERRIDE_FINAL_MEMBER, parent), child .getSourceLocation(), null); return false; @@ -2332,7 +2362,7 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl } if (conflictingSignature(existing, toAdd)) { if (isOverriding) { - checkLegalOverride(existing, toAdd); + checkLegalOverride(existing, toAdd, 0x00, null); j.remove(); } else { getWorld().showMessage( diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/TemporaryTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/TemporaryTypeMunger.java index 2d31b597a..0e0a89fce 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/TemporaryTypeMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/TemporaryTypeMunger.java @@ -14,7 +14,7 @@ import java.util.Map; /** * Some methods need a temporary type munger (because ConcreteTypeMunger is abstract - dont ask...). * - * TODO ought to remove the need for this or at least sort out the two methods that are in it, they look wierd... + * TODO ought to remove the need for this or at least sort out the two methods that are in it, they look weird... * * @author AndyClement */ @@ -24,10 +24,12 @@ public class TemporaryTypeMunger extends ConcreteTypeMunger { super(munger, aspectType); } + @Override public ConcreteTypeMunger parameterizeWith(Map parameterizationMap, World world) { throw new UnsupportedOperationException("Cannot be called on a TemporaryTypeMunger"); } + @Override public ConcreteTypeMunger parameterizedFor(ResolvedType targetType) { throw new UnsupportedOperationException("Cannot be called on a TemporaryTypeMunger"); } -- 2.39.5