diff options
author | aclement <aclement> | 2009-03-05 22:54:12 +0000 |
---|---|---|
committer | aclement <aclement> | 2009-03-05 22:54:12 +0000 |
commit | 49f8b5820a40d91dffad92d45d66d419d575cf23 (patch) | |
tree | 9ddec8036077d15a10a6714facead90200020083 /org.aspectj.matcher | |
parent | 9b4b39591fcf47c6fc22c078f014480ac9ab3e79 (diff) | |
download | aspectj-49f8b5820a40d91dffad92d45d66d419d575cf23.tar.gz aspectj-49f8b5820a40d91dffad92d45d66d419d575cf23.zip |
declareMixin
Diffstat (limited to 'org.aspectj.matcher')
5 files changed, 321 insertions, 205 deletions
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java b/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java index f5cec23cb..f8a5e81cc 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java @@ -401,8 +401,32 @@ public class CrosscuttingMembers { } if (!declareParents.equals(other.declareParents)) { - changed = true; - declareParents = other.declareParents; + // Are the differences just because of a mixin? These are not created until weave time so should be gotten rid of for + // the up front comparison + if (!careAboutShadowMungers) { + // this means we are in front end compilation and if the differences are purely mixin parents, we can continue OK + Set trimmedThis = new HashSet(); + for (Iterator iterator = declareParents.iterator(); iterator.hasNext();) { + DeclareParents decp = (DeclareParents) iterator.next(); + if (!decp.isMixin()) { + trimmedThis.add(decp); + } + } + Set trimmedOther = new HashSet(); + for (Iterator iterator = other.declareParents.iterator(); iterator.hasNext();) { + DeclareParents decp = (DeclareParents) iterator.next(); + if (!decp.isMixin()) { + trimmedOther.add(decp); + } + } + if (!trimmedThis.equals(trimmedOther)) { + changed = true; + declareParents = other.declareParents; + } + } else { + changed = true; + declareParents = other.declareParents; + } } if (!declareSofts.equals(other.declareSofts)) { diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/MethodDelegateTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/MethodDelegateTypeMunger.java index e7b6625b5..fcfd0640e 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/MethodDelegateTypeMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/MethodDelegateTypeMunger.java @@ -252,6 +252,9 @@ public class MethodDelegateTypeMunger extends ResolvedTypeMunger { return false; } + public boolean existsToSupportShadowMunging() { + return true; + } } public void setFieldType(UnresolvedType fieldType) { @@ -273,4 +276,8 @@ public class MethodDelegateTypeMunger extends ResolvedTypeMunger { public UnresolvedType getAspect() { return aspect; } + + public boolean existsToSupportShadowMunging() { + return true; + } } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Declare.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Declare.java index 174001047..755e88919 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Declare.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/Declare.java @@ -10,7 +10,6 @@ * PARC initial implementation * ******************************************************************/ - package org.aspectj.weaver.patterns; import java.io.IOException; @@ -27,60 +26,59 @@ public abstract class Declare extends PatternNode { public static final byte SOFT = 3; public static final byte DOMINATES = 4; public static final byte ANNOTATION = 5; - - // set when reading declare from aspect + public static final byte PARENTSMIXIN = 6; + + // set when reading declare from aspect private ResolvedType declaringType; public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException { byte kind = s.readByte(); switch (kind) { - case ERROR_OR_WARNING: - return DeclareErrorOrWarning.read(s, context); - case DOMINATES: - return DeclarePrecedence.read(s, context); - case PARENTS: - return DeclareParents.read(s, context); - case SOFT: - return DeclareSoft.read(s, context); - case ANNOTATION: - return DeclareAnnotation.read(s,context); - default: - throw new RuntimeException("unimplemented"); + case ERROR_OR_WARNING: + return DeclareErrorOrWarning.read(s, context); + case DOMINATES: + return DeclarePrecedence.read(s, context); + case PARENTS: + return DeclareParents.read(s, context); + case SOFT: + return DeclareSoft.read(s, context); + case ANNOTATION: + return DeclareAnnotation.read(s, context); + case PARENTSMIXIN: + return DeclareParentsMixin.read(s, context); + default: + throw new RuntimeException("unimplemented"); } } - - /** - * Returns this declare mutated - */ - public abstract void resolve(IScope scope); - - /** - * Returns a version of this declare element in which all references to type variables - * are replaced with their bindings given in the map. - */ - public abstract Declare parameterizeWith(Map typeVariableBindingMap,World w); - - /** - * Indicates if this declare should be treated like advice. If true, the - * declare will have no effect in an abstract aspect. It will be inherited by - * any concrete aspects and will have an effect for each concrete aspect it - * is ultimately inherited by. - */ - public abstract boolean isAdviceLike(); /** - * Declares have methods in the .class file against which info can be stored - * (for example, the annotation in the case of declare annotation). The - * name is of the form ajc$declare_XXX_NNN where XXX can optionally be set in - * this 'getNameSuffix()' method - depending on whether, at weave time, we - * want to easily differentiate between the declare methods. + * Returns this declare mutated + */ + public abstract void resolve(IScope scope); + + /** + * Returns a version of this declare element in which all references to type variables are replaced with their bindings given in + * the map. + */ + public abstract Declare parameterizeWith(Map typeVariableBindingMap, World w); + + /** + * Indicates if this declare should be treated like advice. If true, the declare will have no effect in an abstract aspect. It + * will be inherited by any concrete aspects and will have an effect for each concrete aspect it is ultimately inherited by. + */ + public abstract boolean isAdviceLike(); + + /** + * Declares have methods in the .class file against which info can be stored (for example, the annotation in the case of declare + * annotation). The name is of the form ajc$declare_XXX_NNN where XXX can optionally be set in this 'getNameSuffix()' method - + * depending on whether, at weave time, we want to easily differentiate between the declare methods. */ public abstract String getNameSuffix(); - + public void setDeclaringType(ResolvedType aType) { this.declaringType = aType; } - + public ResolvedType getDeclaringType() { return declaringType; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParents.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParents.java index e21401222..ae373a87b 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParents.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParents.java @@ -10,7 +10,6 @@ * PARC initial implementation * ******************************************************************/ - package org.aspectj.weaver.patterns; import java.io.DataOutputStream; @@ -32,130 +31,130 @@ import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.World; public class DeclareParents extends Declare { - private TypePattern child; - private TypePatternList parents; + protected TypePattern child; + protected TypePatternList parents; private boolean isWildChild = false; - private boolean isExtends = true; -// private String[] typeVariablesInScope = new String[0]; // AspectJ 5 extension for generic types - + protected boolean isExtends = true; + + // private String[] typeVariablesInScope = new String[0]; // AspectJ 5 extension for generic types public DeclareParents(TypePattern child, List parents, boolean isExtends) { - this(child, new TypePatternList(parents),isExtends); + this(child, new TypePatternList(parents), isExtends); } - - private DeclareParents(TypePattern child, TypePatternList parents, boolean isExtends) { + + protected DeclareParents(TypePattern child, TypePatternList parents, boolean isExtends) { this.child = child; this.parents = parents; this.isExtends = isExtends; - if (child instanceof WildTypePattern) isWildChild = true; + if (child instanceof WildTypePattern) + isWildChild = true; } - -// public String[] getTypeParameterNames() { -// return this.typeVariablesInScope; -// } -// -// public void setTypeParametersInScope(String[] typeParameters) { -// this.typeVariablesInScope = typeParameters; -// } - + + // public String[] getTypeParameterNames() { + // return this.typeVariablesInScope; + // } + // + // public void setTypeParametersInScope(String[] typeParameters) { + // this.typeVariablesInScope = typeParameters; + // } + public boolean match(ResolvedType typeX) { - if (!child.matchesStatically(typeX)) return false; - if (typeX.getWorld().getLint().typeNotExposedToWeaver.isEnabled() && - !typeX.isExposedToWeaver()) - { + if (!child.matchesStatically(typeX)) + return false; + if (typeX.getWorld().getLint().typeNotExposedToWeaver.isEnabled() && !typeX.isExposedToWeaver()) { typeX.getWorld().getLint().typeNotExposedToWeaver.signal(typeX.getName(), getSourceLocation()); } - + return true; } - + public Object accept(PatternNodeVisitor visitor, Object data) { - return visitor.visit(this,data); + return visitor.visit(this, data); } - - public Declare parameterizeWith(Map typeVariableBindingMap,World w) { - DeclareParents ret = - new DeclareParents( - child.parameterizeWith(typeVariableBindingMap,w), - parents.parameterizeWith(typeVariableBindingMap,w), - isExtends); + + public Declare parameterizeWith(Map typeVariableBindingMap, World w) { + DeclareParents ret = new DeclareParents(child.parameterizeWith(typeVariableBindingMap, w), parents.parameterizeWith( + typeVariableBindingMap, w), isExtends); ret.copyLocationFrom(this); return ret; } - + public String toString() { StringBuffer buf = new StringBuffer(); buf.append("declare parents: "); buf.append(child); - buf.append(isExtends ? " extends " : " implements "); //extends and implements are treated equivalently + buf.append(isExtends ? " extends " : " implements "); // extends and implements are treated equivalently buf.append(parents); buf.append(";"); return buf.toString(); } - - public boolean equals(Object other) { - if (!(other instanceof DeclareParents)) return false; - DeclareParents o = (DeclareParents)other; + + public boolean equals(Object other) { + if (!(other instanceof DeclareParents)) + return false; + DeclareParents o = (DeclareParents) other; return o.child.equals(child) && o.parents.equals(parents); } - - //??? cache this - public int hashCode() { - int result = 23; - result = 37*result + child.hashCode(); - result = 37*result + parents.hashCode(); - return result; - } + // ??? cache this + public int hashCode() { + int result = 23; + result = 37 * result + child.hashCode(); + result = 37 * result + parents.hashCode(); + return result; + } public void write(DataOutputStream s) throws IOException { s.writeByte(Declare.PARENTS); child.write(s); parents.write(s); -// s.writeInt(typeVariablesInScope.length); -// for (int i = 0; i < typeVariablesInScope.length; i++) { -// s.writeUTF(typeVariablesInScope[i]); -// } + // s.writeInt(typeVariablesInScope.length); + // for (int i = 0; i < typeVariablesInScope.length; i++) { + // s.writeUTF(typeVariablesInScope[i]); + // } writeLocation(s); } public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException { - DeclareParents ret = new DeclareParents(TypePattern.read(s, context), TypePatternList.read(s, context),true); -// if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) { -// int numTypeVariablesInScope = s.readInt(); -// ret.typeVariablesInScope = new String[numTypeVariablesInScope]; -// for (int i = 0; i < numTypeVariablesInScope; i++) { -// ret.typeVariablesInScope[i] = s.readUTF(); -// } -// } + DeclareParents ret = new DeclareParents(TypePattern.read(s, context), TypePatternList.read(s, context), true); + // if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) { + // int numTypeVariablesInScope = s.readInt(); + // ret.typeVariablesInScope = new String[numTypeVariablesInScope]; + // for (int i = 0; i < numTypeVariablesInScope; i++) { + // ret.typeVariablesInScope[i] = s.readUTF(); + // } + // } ret.readLocation(context, s); return ret; } - + public boolean parentsIncludeInterface(World w) { for (int i = 0; i < parents.size(); i++) { - if (parents.get(i).getExactType().resolve(w).isInterface()) return true; + if (parents.get(i).getExactType().resolve(w).isInterface()) + return true; } - return false; + return false; } + public boolean parentsIncludeClass(World w) { for (int i = 0; i < parents.size(); i++) { - if (parents.get(i).getExactType().resolve(w).isClass()) return true; + if (parents.get(i).getExactType().resolve(w).isClass()) + return true; } - return false; + return false; } - - public void resolve(IScope scope) { -// ScopeWithTypeVariables resolutionScope = new ScopeWithTypeVariables(typeVariablesInScope,scope); - child = child.resolveBindings(scope, Bindings.NONE, false, false); + + public void resolve(IScope scope) { + // ScopeWithTypeVariables resolutionScope = new ScopeWithTypeVariables(typeVariablesInScope,scope); + child = child.resolveBindings(scope, Bindings.NONE, false, false); isWildChild = (child instanceof WildTypePattern); - parents = parents.resolveBindings(scope, Bindings.NONE, false, true); + parents = parents.resolveBindings(scope, Bindings.NONE, false, true); -// Could assert this ... -// for (int i=0; i < parents.size(); i++) { -// parents.get(i).assertExactType(scope.getMessageHandler()); -// } - } + // Could assert this ... + // for (int i=0; i < parents.size(); i++) { + // parents.get(i).assertExactType(scope.getMessageHandler()); + // } + } public TypePatternList getParents() { return parents; @@ -164,192 +163,197 @@ public class DeclareParents extends Declare { public TypePattern getChild() { return child; } - + // note - will always return true after deserialization, this doesn't affect weaver public boolean isExtends() { return this.isExtends; } - + public boolean isAdviceLike() { return false; } - - private ResolvedType maybeGetNewParent(ResolvedType targetType, TypePattern typePattern, World world,boolean reportErrors) { - if (typePattern == TypePattern.NO) return null; // already had an error here -// isWildChild = (child instanceof WildTypePattern); + private ResolvedType maybeGetNewParent(ResolvedType targetType, TypePattern typePattern, World world, boolean reportErrors) { + if (typePattern == TypePattern.NO) + return null; // already had an error here + + // isWildChild = (child instanceof WildTypePattern); UnresolvedType iType = typePattern.getExactType(); ResolvedType parentType = iType.resolve(world); - + if (targetType.equals(world.getCoreType(UnresolvedType.OBJECT))) { - world.showMessage(IMessage.ERROR, - WeaverMessages.format(WeaverMessages.DECP_OBJECT), - this.getSourceLocation(), null); + world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.DECP_OBJECT), this.getSourceLocation(), null); return null; } - - // Ensure the target doesn't already have an + + // Ensure the target doesn't already have an // alternate parameterization of the generic type on it if (parentType.isParameterizedType() || parentType.isRawType()) { // Let's take a look at the parents we already have - boolean isOK = verifyNoInheritedAlternateParameterization(targetType,parentType,world); - if (!isOK) return null; + boolean isOK = verifyNoInheritedAlternateParameterization(targetType, parentType, world); + if (!isOK) + return null; } - if (parentType.isAssignableFrom(targetType)) return null; // already a parent - - // Enum types that are targetted for decp through a wild type pattern get linted + if (parentType.isAssignableFrom(targetType)) + return null; // already a parent + + // Enum types that are targetted for decp through a wild type pattern get linted if (reportErrors && isWildChild && targetType.isEnum()) { - world.getLint().enumAsTargetForDecpIgnored.signal(targetType.toString(),getSourceLocation()); + world.getLint().enumAsTargetForDecpIgnored.signal(targetType.toString(), getSourceLocation()); } - - // Annotation types that are targetted for decp through a wild type pattern get linted + + // Annotation types that are targetted for decp through a wild type pattern get linted if (reportErrors && isWildChild && targetType.isAnnotation()) { - world.getLint().annotationAsTargetForDecpIgnored.signal(targetType.toString(),getSourceLocation()); + world.getLint().annotationAsTargetForDecpIgnored.signal(targetType.toString(), getSourceLocation()); } // 1. Can't use decp to make an enum/annotation type implement an interface if (targetType.isEnum() && parentType.isInterface()) { - if (reportErrors && !isWildChild) { - world.showMessage(IMessage.ERROR, - WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ENUM_TO_IMPL_INTERFACE,targetType),getSourceLocation(),null); - } + if (reportErrors && !isWildChild) { + world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ENUM_TO_IMPL_INTERFACE, + targetType), getSourceLocation(), null); + } return null; } if (targetType.isAnnotation() && parentType.isInterface()) { - if (reportErrors && !isWildChild) { - world.showMessage(IMessage.ERROR,WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ANNOTATION_TO_IMPL_INTERFACE,targetType),getSourceLocation(),null); - } + if (reportErrors && !isWildChild) { + world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ANNOTATION_TO_IMPL_INTERFACE, + targetType), getSourceLocation(), null); + } return null; } - + // 2. Can't use decp to change supertype of an enum/annotation if (targetType.isEnum() && parentType.isClass()) { if (reportErrors && !isWildChild) { - world.showMessage(IMessage.ERROR,WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ENUM_TO_EXTEND_CLASS,targetType),getSourceLocation(),null); + world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ENUM_TO_EXTEND_CLASS, + targetType), getSourceLocation(), null); } return null; } if (targetType.isAnnotation() && parentType.isClass()) { if (reportErrors && !isWildChild) { - world.showMessage(IMessage.ERROR,WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ANNOTATION_TO_EXTEND_CLASS,targetType),getSourceLocation(),null); + world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_DECP_ON_ANNOTATION_TO_EXTEND_CLASS, + targetType), getSourceLocation(), null); } return null; } - + // 3. Can't use decp to declare java.lang.Enum/java.lang.annotation.Annotation as the parent of a type if (parentType.getSignature().equals(UnresolvedType.ENUM.getSignature())) { if (reportErrors && !isWildChild) { - world.showMessage(IMessage.ERROR, - WeaverMessages.format(WeaverMessages.CANT_DECP_TO_MAKE_ENUM_SUPERTYPE,targetType),getSourceLocation(),null); + world.showMessage(IMessage.ERROR, WeaverMessages + .format(WeaverMessages.CANT_DECP_TO_MAKE_ENUM_SUPERTYPE, targetType), getSourceLocation(), null); } return null; - } + } if (parentType.getSignature().equals(UnresolvedType.ANNOTATION.getSignature())) { if (reportErrors && !isWildChild) { - world.showMessage(IMessage.ERROR, - WeaverMessages.format(WeaverMessages.CANT_DECP_TO_MAKE_ANNOTATION_SUPERTYPE,targetType),getSourceLocation(),null); + world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_DECP_TO_MAKE_ANNOTATION_SUPERTYPE, + targetType), getSourceLocation(), null); } return null; - } - - if (parentType.isAssignableFrom(targetType)) return null; // already a parent + } + + if (parentType.isAssignableFrom(targetType)) + return null; // already a parent if (targetType.isAssignableFrom(parentType)) { - world.showMessage(IMessage.ERROR, - WeaverMessages.format(WeaverMessages.CANT_EXTEND_SELF,targetType.getName()), - this.getSourceLocation(), null - ); + world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_EXTEND_SELF, targetType.getName()), this + .getSourceLocation(), null); return null; } - + if (parentType.isClass()) { if (targetType.isInterface()) { - world.showMessage(IMessage.ERROR, - WeaverMessages.format(WeaverMessages.INTERFACE_CANT_EXTEND_CLASS), - this.getSourceLocation(), null - ); + world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.INTERFACE_CANT_EXTEND_CLASS), this + .getSourceLocation(), null); return null; // how to handle xcutting errors??? } - + if (!targetType.getSuperclass().isAssignableFrom(parentType)) { - world.showMessage(IMessage.ERROR, - WeaverMessages.format(WeaverMessages.DECP_HIERARCHY_ERROR, - iType.getName(), - targetType.getSuperclass().getName()), - this.getSourceLocation(), null - ); + world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.DECP_HIERARCHY_ERROR, iType.getName(), + targetType.getSuperclass().getName()), this.getSourceLocation(), null); return null; } else { return parentType; - } + } } else { return parentType; } } - + /** - * This method looks through the type hierarchy for some target type - it is attempting to - * find an existing parameterization that clashes with the new parent that the user - * wants to apply to the type. If it finds an existing parameterization that matches the - * new one, it silently completes, if it finds one that clashes (e.g. a type already has - * A<String> when the user wants to add A<Number>) then it will produce an error. + * This method looks through the type hierarchy for some target type - it is attempting to find an existing parameterization + * that clashes with the new parent that the user wants to apply to the type. If it finds an existing parameterization that + * matches the new one, it silently completes, if it finds one that clashes (e.g. a type already has A<String> when the user + * wants to add A<Number>) then it will produce an error. * * It uses recursion and exits recursion on hitting 'jlObject' - * + * * Related bugzilla entries: pr110788 */ - private boolean verifyNoInheritedAlternateParameterization(ResolvedType typeToVerify,ResolvedType newParent,World world) { - + private boolean verifyNoInheritedAlternateParameterization(ResolvedType typeToVerify, ResolvedType newParent, World world) { - if (typeToVerify.equals(ResolvedType.OBJECT)) return true; + if (typeToVerify.equals(ResolvedType.OBJECT)) + return true; ResolvedType newParentGenericType = newParent.getGenericType(); Iterator iter = typeToVerify.getDirectSupertypes(); while (iter.hasNext()) { - ResolvedType supertype = (ResolvedType)iter.next(); - if ( ((supertype.isRawType() && newParent.isParameterizedType()) || - (supertype.isParameterizedType() && newParent.isRawType())) && newParentGenericType.equals(supertype.getGenericType())) { + ResolvedType supertype = (ResolvedType) iter.next(); + if (((supertype.isRawType() && newParent.isParameterizedType()) || (supertype.isParameterizedType() && newParent + .isRawType())) + && newParentGenericType.equals(supertype.getGenericType())) { // new parent is a parameterized type, but this is a raw type - world.getMessageHandler().handleMessage(new Message( - WeaverMessages.format(WeaverMessages.CANT_DECP_MULTIPLE_PARAMETERIZATIONS,newParent.getName(),typeToVerify.getName(),supertype.getName()), - getSourceLocation(), true, new ISourceLocation[]{typeToVerify.getSourceLocation()})); + world.getMessageHandler().handleMessage( + new Message(WeaverMessages.format(WeaverMessages.CANT_DECP_MULTIPLE_PARAMETERIZATIONS, newParent.getName(), + typeToVerify.getName(), supertype.getName()), getSourceLocation(), true, + new ISourceLocation[] { typeToVerify.getSourceLocation() })); return false; } if (supertype.isParameterizedType()) { ResolvedType generictype = supertype.getGenericType(); - + // If the generic types are compatible but the parameterizations aren't then we have a problem - if (generictype.isAssignableFrom(newParentGenericType) && - !supertype.isAssignableFrom(newParent)) { - world.getMessageHandler().handleMessage(new Message( - WeaverMessages.format(WeaverMessages.CANT_DECP_MULTIPLE_PARAMETERIZATIONS,newParent.getName(),typeToVerify.getName(),supertype.getName()), - getSourceLocation(), true, new ISourceLocation[]{typeToVerify.getSourceLocation()})); + if (generictype.isAssignableFrom(newParentGenericType) && !supertype.isAssignableFrom(newParent)) { + world.getMessageHandler().handleMessage( + new Message(WeaverMessages.format(WeaverMessages.CANT_DECP_MULTIPLE_PARAMETERIZATIONS, newParent + .getName(), typeToVerify.getName(), supertype.getName()), getSourceLocation(), true, + new ISourceLocation[] { typeToVerify.getSourceLocation() })); return false; } } - if (!verifyNoInheritedAlternateParameterization(supertype,newParent,world)) { + if (!verifyNoInheritedAlternateParameterization(supertype, newParent, world)) { return false; } } return true; } - public List/*<ResolvedType>*/ findMatchingNewParents(ResolvedType onType,boolean reportErrors) { - if (onType.isRawType()) onType = onType.getGenericType(); - if (!match(onType)) return Collections.EMPTY_LIST; - + public List/* <ResolvedType> */findMatchingNewParents(ResolvedType onType, boolean reportErrors) { + if (onType.isRawType()) + onType = onType.getGenericType(); + if (!match(onType)) + return Collections.EMPTY_LIST; + List ret = new ArrayList(); - for (int i=0; i < parents.size(); i++) { - ResolvedType t = maybeGetNewParent(onType, parents.get(i), onType.getWorld(),reportErrors); - if (t != null) ret.add(t); + for (int i = 0; i < parents.size(); i++) { + ResolvedType t = maybeGetNewParent(onType, parents.get(i), onType.getWorld(), reportErrors); + if (t != null) + ret.add(t); } - + return ret; } public String getNameSuffix() { return "parents"; } + + public boolean isMixin() { + return false; + } } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParentsMixin.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParentsMixin.java new file mode 100644 index 000000000..2c4e727ca --- /dev/null +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParentsMixin.java @@ -0,0 +1,83 @@ +/* ******************************************************************* + * Copyright (c) 2009 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * initial implementation Andy Clement + * ******************************************************************/ +package org.aspectj.weaver.patterns; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; + +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.VersionedDataInputStream; + +/** + * Constructed based on an @DeclareMixin being found in an aspect. + * + * @author Andy Clement + */ +public class DeclareParentsMixin extends DeclareParents { + private int bitflags = 0x0000; // for future expansion + + public DeclareParentsMixin(TypePattern child, List parents) { + super(child, parents, true); + } + + public DeclareParentsMixin(TypePattern child, TypePatternList parents) { + super(child, parents, true); + } + + public boolean equals(Object other) { + if (!(other instanceof DeclareParentsMixin)) { + return false; + } + DeclareParentsMixin o = (DeclareParentsMixin) other; + return o.child.equals(child) && o.parents.equals(parents) && o.bitflags == bitflags; + } + + public int hashCode() { + int result = 23; + result = 37 * result + child.hashCode(); + result = 37 * result + parents.hashCode(); + result = 37 * result + bitflags; + return result; + } + + public void write(DataOutputStream s) throws IOException { + s.writeByte(Declare.PARENTSMIXIN); + child.write(s); + parents.write(s); + writeLocation(s); + s.writeInt(bitflags); + } + + public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException { + DeclareParentsMixin ret = new DeclareParentsMixin(TypePattern.read(s, context), TypePatternList.read(s, context)); + ret.readLocation(context, s); + ret.bitflags = s.readInt(); + return ret; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("declare parents mixin: "); + buf.append(child); + buf.append(" implements "); + buf.append(parents); + buf.append(";"); + buf.append("bits=0x").append(Integer.toHexString(bitflags)); + return buf.toString(); + } + + public boolean isMixin() { + return true; + } + +} |