]> source.dussan.org Git - aspectj.git/commitdiff
declareMixin
authoraclement <aclement>
Thu, 5 Mar 2009 22:54:12 +0000 (22:54 +0000)
committeraclement <aclement>
Thu, 5 Mar 2009 22:54:12 +0000 (22:54 +0000)
org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java
org.aspectj.matcher/src/org/aspectj/weaver/MethodDelegateTypeMunger.java
org.aspectj.matcher/src/org/aspectj/weaver/patterns/Declare.java
org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParents.java
org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParentsMixin.java [new file with mode: 0644]

index f5cec23cb3d7f0b695d2141469ceb861d71d10d2..f8a5e81cc6ec4423cf7cf7aef07fd226055bcc49 100644 (file)
@@ -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)) {
index e7b6625b596239c7c9822813b54a38fb4d62beec..fcfd0640e1ea8dbfe1def5564d8859cc31f75ac5 100644 (file)
@@ -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;
+       }
 }
index 174001047006658443b3d663aa3f7995d3a5ad3c..755e889196b2ed724dd2201f697388b17dbceea5 100644 (file)
@@ -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;
        }
index e21401222d63e04cc58ea204558bbfbb39cb8a92..ae373a87bee2ce0ee1e9fb9e15bedcc0c8063dcc 100644 (file)
@@ -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 (file)
index 0000000..2c4e727
--- /dev/null
@@ -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;
+       }
+
+}