summaryrefslogtreecommitdiffstats
path: root/org.aspectj.matcher
diff options
context:
space:
mode:
authoraclement <aclement>2009-03-05 22:54:12 +0000
committeraclement <aclement>2009-03-05 22:54:12 +0000
commit49f8b5820a40d91dffad92d45d66d419d575cf23 (patch)
tree9ddec8036077d15a10a6714facead90200020083 /org.aspectj.matcher
parent9b4b39591fcf47c6fc22c078f014480ac9ab3e79 (diff)
downloadaspectj-49f8b5820a40d91dffad92d45d66d419d575cf23.tar.gz
aspectj-49f8b5820a40d91dffad92d45d66d419d575cf23.zip
declareMixin
Diffstat (limited to 'org.aspectj.matcher')
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java28
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/MethodDelegateTypeMunger.java7
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/Declare.java80
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParents.java328
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/DeclareParentsMixin.java83
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;
+ }
+
+}