* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
- * PARC initial implementation
+ * PARC initial implementation
+ * Alexandre Vasseur @AspectJ ITDs
* ******************************************************************/
package org.aspectj.weaver;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.bcel.BcelTypeMunger;
+import org.aspectj.weaver.patterns.Declare;
+import org.aspectj.weaver.patterns.PerClause;
+
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.Message;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.util.FuzzyBoolean;
-import org.aspectj.weaver.patterns.Declare;
-import org.aspectj.weaver.patterns.PerClause;
-
public abstract class ResolvedType extends UnresolvedType implements AnnotatedElement {
- private static final ResolvedType[] EMPTY_RESOLVED_TYPE_ARRAY = new ResolvedType[0];
- public static final String PARAMETERIZED_TYPE_IDENTIFIER = "P";
-
- private ResolvedType[] resolvedTypeParams;
-
+ private static final ResolvedType[] EMPTY_RESOLVED_TYPE_ARRAY = new ResolvedType[0];
+ public static final String PARAMETERIZED_TYPE_IDENTIFIER = "P";
+
+ private ResolvedType[] resolvedTypeParams;
+
protected World world;
-
+
protected ResolvedType(String signature, World world) {
super(signature);
this.world = world;
}
-
+
protected ResolvedType(String signature, String signatureErasure, World world) {
- super(signature,signatureErasure);
+ super(signature, signatureErasure);
this.world = world;
}
}
public abstract ResolvedMember[] getDeclaredFields();
+
public abstract ResolvedMember[] getDeclaredMethods();
+
public abstract ResolvedType[] getDeclaredInterfaces();
+
public abstract ResolvedMember[] getDeclaredPointcuts();
+
/**
* Returns a ResolvedType object representing the superclass of this type, or null.
* If this represents a java.lang.Object, a primitive type, or void, this
- * method returns null.
+ * method returns null.
*/
public abstract ResolvedType getSuperclass();
/**
- * Returns the modifiers for this type.
- *
- * See {@link java.lang.Class#getModifiers()} for a description
+ * Returns the modifiers for this type.
+ * <p/>
+ * See {@link Class#getModifiers()} for a description
* of the weirdness of this methods on primitives and arrays.
*
* @param world the {@link World} in which the lookup is made.
* @return an int representing the modifiers for this type
- * @see java.lang.reflect.Modifier
+ * @see java.lang.reflect.Modifier
*/
public abstract int getModifiers();
// return true if this resolved type couldn't be found (but we know it's name maybe)
- public boolean isMissing() { return false; }
-
+ public boolean isMissing() {
+ return false;
+ }
+
public ResolvedType[] getAnnotationTypes() {
- return EMPTY_RESOLVED_TYPE_ARRAY;
+ return EMPTY_RESOLVED_TYPE_ARRAY;
}
-
+
public final UnresolvedType getSuperclass(World world) {
return getSuperclass();
}
-
+
// This set contains pairs of types whose signatures are concatenated
// together, this means with a fast lookup we can tell if two types
// are equivalent.
static Set validBoxing = new HashSet();
-
+
static {
- validBoxing.add("Ljava/lang/Byte;B");
- validBoxing.add("Ljava/lang/Character;C");
- validBoxing.add("Ljava/lang/Double;D");
- validBoxing.add("Ljava/lang/Float;F");
- validBoxing.add("Ljava/lang/Integer;I");
- validBoxing.add("Ljava/lang/Long;J");
- validBoxing.add("Ljava/lang/Short;S");
- validBoxing.add("Ljava/lang/Boolean;Z");
- validBoxing.add("BLjava/lang/Byte;");
- validBoxing.add("CLjava/lang/Character;");
- validBoxing.add("DLjava/lang/Double;");
- validBoxing.add("FLjava/lang/Float;");
- validBoxing.add("ILjava/lang/Integer;");
- validBoxing.add("JLjava/lang/Long;");
- validBoxing.add("SLjava/lang/Short;");
- validBoxing.add("ZLjava/lang/Boolean;");
- }
-
-
-
- // utilities
+ validBoxing.add("Ljava/lang/Byte;B");
+ validBoxing.add("Ljava/lang/Character;C");
+ validBoxing.add("Ljava/lang/Double;D");
+ validBoxing.add("Ljava/lang/Float;F");
+ validBoxing.add("Ljava/lang/Integer;I");
+ validBoxing.add("Ljava/lang/Long;J");
+ validBoxing.add("Ljava/lang/Short;S");
+ validBoxing.add("Ljava/lang/Boolean;Z");
+ validBoxing.add("BLjava/lang/Byte;");
+ validBoxing.add("CLjava/lang/Character;");
+ validBoxing.add("DLjava/lang/Double;");
+ validBoxing.add("FLjava/lang/Float;");
+ validBoxing.add("ILjava/lang/Integer;");
+ validBoxing.add("JLjava/lang/Long;");
+ validBoxing.add("SLjava/lang/Short;");
+ validBoxing.add("ZLjava/lang/Boolean;");
+ }
+
+
+ // utilities
public ResolvedType getResolvedComponentType() {
- return null;
+ return null;
}
- public World getWorld() {
- return world;
- }
+ public World getWorld() {
+ return world;
+ }
// ---- things from object
return super.equals(other);
}
}
-
+
// ---- difficult things
-
+
/**
* returns an iterator through all of the fields of this type, in order
* for checking from JVM spec 2ed 5.4.3.2. This means that the order is
- *
+ * <p/>
* <ul><li> fields from current class </li>
- * <li> recur into direct superinterfaces </li>
- * <li> recur into superclass </li>
+ * <li> recur into direct superinterfaces </li>
+ * <li> recur into superclass </li>
* </ul>
- *
+ * <p/>
* We keep a hashSet of interfaces that we've visited so we don't spiral
* out into 2^n land.
*/
final Iterators.Filter dupFilter = Iterators.dupFilter();
Iterators.Getter typeGetter = new Iterators.Getter() {
public Iterator get(Object o) {
- return
- dupFilter.filter(
- ((ResolvedType)o).getDirectSupertypes());
+ return
+ dupFilter.filter(
+ ((ResolvedType) o).getDirectSupertypes());
}
};
Iterators.Getter fieldGetter = new Iterators.Getter() {
public Iterator get(Object o) {
- return Iterators.array(((ResolvedType)o).getDeclaredFields());
+ return Iterators.array(((ResolvedType) o).getDeclaredFields());
}
};
- return
- Iterators.mapOver(
- Iterators.recur(this, typeGetter),
- fieldGetter);
+ return
+ Iterators.mapOver(
+ Iterators.recur(this, typeGetter),
+ fieldGetter);
}
/**
* returns an iterator through all of the methods of this type, in order
* for checking from JVM spec 2ed 5.4.3.3. This means that the order is
- *
+ * <p/>
* <ul><li> methods from current class </li>
- * <li> recur into superclass, all the way up, not touching interfaces </li>
- * <li> recur into all superinterfaces, in some unspecified order </li>
+ * <li> recur into superclass, all the way up, not touching interfaces </li>
+ * <li> recur into all superinterfaces, in some unspecified order </li>
* </ul>
- *
+ * <p/>
* We keep a hashSet of interfaces that we've visited so we don't spiral
* out into 2^n land.
* NOTE: Take a look at the javadoc on getMethodsWithoutIterator() to see if
final Iterators.Filter dupFilter = Iterators.dupFilter();
Iterators.Getter ifaceGetter = new Iterators.Getter() {
public Iterator get(Object o) {
- return
- dupFilter.filter(
- Iterators.array(((ResolvedType)o).getDeclaredInterfaces())
- );
+ return
+ dupFilter.filter(
+ Iterators.array(((ResolvedType) o).getDeclaredInterfaces())
+ );
}
};
Iterators.Getter methodGetter = new Iterators.Getter() {
public Iterator get(Object o) {
- return Iterators.array(((ResolvedType)o).getDeclaredMethods());
+ return Iterators.array(((ResolvedType) o).getDeclaredMethods());
}
};
- return
- Iterators.mapOver(
- Iterators.append(
- new Iterator() {
- ResolvedType curr = ResolvedType.this;
- public boolean hasNext() {
- return curr != null;
- }
- public Object next() {
- ResolvedType ret = curr;
- curr = curr.getSuperclass();
- return ret;
- }
- public void remove() {
- throw new UnsupportedOperationException();
- }
- },
- Iterators.recur(this, ifaceGetter)),
- methodGetter);
+ return
+ Iterators.mapOver(
+ Iterators.append(
+ new Iterator() {
+ ResolvedType curr = ResolvedType.this;
+
+ public boolean hasNext() {
+ return curr != null;
+ }
+
+ public Object next() {
+ ResolvedType ret = curr;
+ curr = curr.getSuperclass();
+ return ret;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ },
+ Iterators.recur(this, ifaceGetter)),
+ methodGetter);
}
-
+
/**
* Return a list of methods, first those declared on this class, then those declared on the superclass (recurse) and then those declared
* on the superinterfaces. The getMethods() call above doesn't quite work the same as it will (through the iterator) return methods
public List getMethodsWithoutIterator(boolean includeITDs, boolean allowMissing) {
List methods = new ArrayList();
Set knowninterfaces = new HashSet();
- addAndRecurse(knowninterfaces,methods,this,includeITDs,allowMissing);
+ addAndRecurse(knowninterfaces, methods, this, includeITDs, allowMissing);
return methods;
}
-
- private void addAndRecurse(Set knowninterfaces,List collector, ResolvedType rtx, boolean includeITDs, boolean allowMissing) {
- collector.addAll(Arrays.asList(rtx.getDeclaredMethods())); // Add the methods declared on this type
- // now add all the inter-typed members too
- if (includeITDs && rtx.interTypeMungers != null) {
- for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
- ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
- ResolvedMember rm = tm.getSignature();
- if (rm != null) { // new parent type munger can have null signature...
- collector.add(tm.getSignature());
- }
- }
- }
- if (!rtx.equals(ResolvedType.OBJECT)) {
- ResolvedType superType = rtx.getSuperclass();
- if (superType != null && !superType.isMissing()) {
- addAndRecurse(knowninterfaces,collector,superType,includeITDs,allowMissing); // Recurse if we aren't at the top
- }
- }
- ResolvedType[] interfaces = rtx.getDeclaredInterfaces(); // Go through the interfaces on the way back down
- for (int i = 0; i < interfaces.length; i++) {
- ResolvedType iface = interfaces[i];
- if (!knowninterfaces.contains(iface)) { // Dont do interfaces more than once
- knowninterfaces.add(iface);
- if (allowMissing && iface.isMissing()) {
- if (iface instanceof MissingResolvedTypeWithKnownSignature) {
- ((MissingResolvedTypeWithKnownSignature)iface).raiseWarningOnMissingInterfaceWhilstFindingMethods();
- }
- } else {
- addAndRecurse(knowninterfaces,collector,iface,includeITDs,allowMissing);
- }
- }
- }
+
+ private void addAndRecurse(Set knowninterfaces, List collector, ResolvedType rtx, boolean includeITDs, boolean allowMissing) {
+ collector.addAll(Arrays.asList(rtx.getDeclaredMethods())); // Add the methods declared on this type
+ // now add all the inter-typed members too
+ if (includeITDs && rtx.interTypeMungers != null) {
+ for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+ ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
+ ResolvedMember rm = tm.getSignature();
+ if (rm != null) { // new parent type munger can have null signature...
+ collector.add(tm.getSignature());
+ }
+ }
+ }
+ if (!rtx.equals(ResolvedType.OBJECT)) {
+ ResolvedType superType = rtx.getSuperclass();
+ if (superType != null && !superType.isMissing()) {
+ addAndRecurse(knowninterfaces, collector, superType, includeITDs, allowMissing); // Recurse if we aren't at the top
+ }
+ }
+ ResolvedType[] interfaces = rtx.getDeclaredInterfaces(); // Go through the interfaces on the way back down
+ for (int i = 0; i < interfaces.length; i++) {
+ ResolvedType iface = interfaces[i];
+
+ // we need to know if it is an interface from Parent kind munger
+ // as those are used for @AJ ITD and we precisely want to skip those
+ boolean shouldSkip = false;
+ for (int j = 0; j < rtx.interTypeMungers.size(); j++) {
+ ConcreteTypeMunger munger = (ConcreteTypeMunger) rtx.interTypeMungers.get(j);
+ if (munger.getMunger().getKind() == ResolvedTypeMunger.Parent) {
+ shouldSkip = true;
+ break;
+ }
+ }
+
+ if (!shouldSkip && !knowninterfaces.contains(iface)) { // Dont do interfaces more than once
+ knowninterfaces.add(iface);
+ if (allowMissing && iface.isMissing()) {
+ if (iface instanceof MissingResolvedTypeWithKnownSignature) {
+ ((MissingResolvedTypeWithKnownSignature) iface).raiseWarningOnMissingInterfaceWhilstFindingMethods();
+ }
+ } else {
+ addAndRecurse(knowninterfaces, collector, iface, includeITDs, allowMissing);
+ }
+ }
+ }
}
public ResolvedType[] getResolvedTypeParameters() {
- if (resolvedTypeParams == null) {
- resolvedTypeParams = world.resolve(typeParameters);
- }
- return resolvedTypeParams;
+ if (resolvedTypeParams == null) {
+ resolvedTypeParams = world.resolve(typeParameters);
+ }
+ return resolvedTypeParams;
}
-
- /**
+
+ /**
* described in JVM spec 2ed 5.4.3.2
*/
public ResolvedMember lookupField(Member m) {
public ResolvedMember lookupMethod(Member m) {
return lookupMember(m, getMethods());
}
-
+
public ResolvedMember lookupMethodInITDs(Member m) {
- if (interTypeMungers != null) {
- for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
- ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
- if (matches(tm.getSignature(), m)) {
- return tm.getSignature();
- }
- }
- }
- return null;
- }
-
- /** return null if not found */
+ if (interTypeMungers != null) {
+ for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+ ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
+ if (matches(tm.getSignature(), m)) {
+ return tm.getSignature();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * return null if not found
+ */
private ResolvedMember lookupMember(Member m, Iterator i) {
while (i.hasNext()) {
ResolvedMember f = (ResolvedMember) i.next();
}
return null; //ResolvedMember.Missing;
//throw new BCException("can't find " + m);
- }
-
- /** return null if not found */
+ }
+
+ /**
+ * return null if not found
+ */
private ResolvedMember lookupMember(Member m, ResolvedMember[] a) {
- for (int i = 0; i < a.length; i++) {
- ResolvedMember f = a[i];
- if (matches(f, m)) return f;
- }
- return null;
- }
-
-
+ for (int i = 0; i < a.length; i++) {
+ ResolvedMember f = a[i];
+ if (matches(f, m)) return f;
+ }
+ return null;
+ }
+
+
/**
* Looks for the first member in the hierarchy matching aMember. This method
* differs from lookupMember(Member) in that it takes into account parameters
* which are type variables - which clearly an unresolved Member cannot do since
- * it does not know anything about type variables.
+ * it does not know anything about type variables.
*/
- public ResolvedMember lookupResolvedMember(ResolvedMember aMember,boolean allowMissing) {
- Iterator toSearch = null;
- ResolvedMember found = null;
- if ((aMember.getKind() == Member.METHOD) || (aMember.getKind() == Member.CONSTRUCTOR)) {
- toSearch = getMethodsWithoutIterator(true,allowMissing).iterator();
- } else {
- if (aMember.getKind() != Member.FIELD)
- throw new IllegalStateException("I didn't know you would look for members of kind " + aMember.getKind());
- toSearch = getFields();
- }
- while(toSearch.hasNext()) {
- ResolvedMemberImpl candidate = (ResolvedMemberImpl) toSearch.next();
- if (candidate.matches(aMember)) {
- found = candidate;
- break;
- }
- }
-
- return found;
- }
-
+ public ResolvedMember lookupResolvedMember(ResolvedMember aMember, boolean allowMissing) {
+ Iterator toSearch = null;
+ ResolvedMember found = null;
+ if ((aMember.getKind() == Member.METHOD) || (aMember.getKind() == Member.CONSTRUCTOR)) {
+ toSearch = getMethodsWithoutIterator(true, allowMissing).iterator();
+ } else {
+ if (aMember.getKind() != Member.FIELD)
+ throw new IllegalStateException("I didn't know you would look for members of kind " + aMember.getKind());
+ toSearch = getFields();
+ }
+ while (toSearch.hasNext()) {
+ ResolvedMemberImpl candidate = (ResolvedMemberImpl) toSearch.next();
+ if (candidate.matches(aMember)) {
+ found = candidate;
+ break;
+ }
+ }
+
+ return found;
+ }
+
public static boolean matches(Member m1, Member m2) {
if (m1 == null) return m2 == null;
if (m2 == null) return false;
-
+
// Check the names
boolean equalNames = m1.getName().equals(m2.getName());
if (!equalNames) return false;
-
+
// Check the signatures
boolean equalSignatures = m1.getSignature().equals(m2.getSignature());
if (equalSignatures) return true;
// the subsig might be ()LFastCar; - where FastCar is a subclass of Car
boolean equalCovariantSignatures = m1.getParameterSignature().equals(m2.getParameterSignature());
if (equalCovariantSignatures) return true;
-
+
return false;
}
-
+
public static boolean conflictingSignature(Member m1, Member m2) {
- if (m1 == null || m2 == null) return false;
-
- if (!m1.getName().equals(m2.getName())) { return false; }
- if (m1.getKind() != m2.getKind()) { return false; }
-
- if (m1.getKind() == Member.FIELD) {
- return m1.getDeclaringType().equals(m2.getDeclaringType());
- } else if (m1.getKind() == Member.POINTCUT) {
- return true;
- }
-
- UnresolvedType[] p1 = m1.getParameterTypes();
- UnresolvedType[] p2 = m2.getParameterTypes();
- int n = p1.length;
- if (n != p2.length) return false;
-
- for (int i=0; i < n; i++) {
- if (!p1[i].equals(p2[i])) return false;
- }
- return true;
- }
-
-
+ if (m1 == null || m2 == null) return false;
+
+ if (!m1.getName().equals(m2.getName())) {
+ return false;
+ }
+ if (m1.getKind() != m2.getKind()) {
+ return false;
+ }
+
+ if (m1.getKind() == Member.FIELD) {
+ return m1.getDeclaringType().equals(m2.getDeclaringType());
+ } else if (m1.getKind() == Member.POINTCUT) {
+ return true;
+ }
+
+ UnresolvedType[] p1 = m1.getParameterTypes();
+ UnresolvedType[] p2 = m2.getParameterTypes();
+ int n = p1.length;
+ if (n != p2.length) return false;
+
+ for (int i = 0; i < n; i++) {
+ if (!p1[i].equals(p2[i])) return false;
+ }
+ return true;
+ }
+
+
/**
* returns an iterator through all of the pointcuts of this type, in order
* for checking from JVM spec 2ed 5.4.3.2 (as for fields). This means that the order is
- *
+ * <p/>
* <ul><li> pointcuts from current class </li>
- * <li> recur into direct superinterfaces </li>
- * <li> recur into superclass </li>
+ * <li> recur into direct superinterfaces </li>
+ * <li> recur into superclass </li>
* </ul>
- *
+ * <p/>
* We keep a hashSet of interfaces that we've visited so we don't spiral
* out into 2^n land.
*/
// same order as fields
Iterators.Getter typeGetter = new Iterators.Getter() {
public Iterator get(Object o) {
- return
- dupFilter.filter(
- ((ResolvedType)o).getDirectSupertypes());
+ return
+ dupFilter.filter(
+ ((ResolvedType) o).getDirectSupertypes());
}
};
Iterators.Getter pointcutGetter = new Iterators.Getter() {
public Iterator get(Object o) {
//System.err.println("getting for " + o);
- return Iterators.array(((ResolvedType)o).getDeclaredPointcuts());
+ return Iterators.array(((ResolvedType) o).getDeclaredPointcuts());
}
};
- return
- Iterators.mapOver(
- Iterators.recur(this, typeGetter),
- pointcutGetter);
+ return
+ Iterators.mapOver(
+ Iterators.recur(this, typeGetter),
+ pointcutGetter);
}
-
+
public ResolvedPointcutDefinition findPointcut(String name) {
//System.err.println("looking for pointcuts " + this);
- for (Iterator i = getPointcuts(); i.hasNext(); ) {
+ for (Iterator i = getPointcuts(); i.hasNext();) {
ResolvedPointcutDefinition f = (ResolvedPointcutDefinition) i.next();
//System.err.println(f);
if (name.equals(f.getName())) {
}
return null; // should we throw an exception here?
}
-
-
+
// all about collecting CrosscuttingMembers
- //??? collecting data-structure, shouldn't really be a field
+ //??? collecting data-structure, shouldn't really be a field
public CrosscuttingMembers crosscuttingMembers;
- public CrosscuttingMembers collectCrosscuttingMembers() {
- crosscuttingMembers = new CrosscuttingMembers(this);
- crosscuttingMembers.setPerClause(getPerClause());
- crosscuttingMembers.addShadowMungers(collectShadowMungers());
- crosscuttingMembers.addTypeMungers(getTypeMungers());
+ public CrosscuttingMembers collectCrosscuttingMembers() {
+ crosscuttingMembers = new CrosscuttingMembers(this);
+ crosscuttingMembers.setPerClause(getPerClause());
+ crosscuttingMembers.addShadowMungers(collectShadowMungers());
+ crosscuttingMembers.addTypeMungers(getTypeMungers());
//FIXME AV - skip but needed ?? or ?? crosscuttingMembers.addLateTypeMungers(getLateTypeMungers());
- crosscuttingMembers.addDeclares(collectDeclares(!this.doesNotExposeShadowMungers()));
- crosscuttingMembers.addPrivilegedAccesses(getPrivilegedAccesses());
-
- //System.err.println("collected cc members: " + this + ", " + collectDeclares());
- return crosscuttingMembers;
- }
-
- public final Collection collectDeclares(boolean includeAdviceLike) {
- if (! this.isAspect() ) return Collections.EMPTY_LIST;
-
- ArrayList ret = new ArrayList();
- //if (this.isAbstract()) {
+ crosscuttingMembers.addDeclares(collectDeclares(!this.doesNotExposeShadowMungers()));
+ crosscuttingMembers.addPrivilegedAccesses(getPrivilegedAccesses());
+
+ //System.err.println("collected cc members: " + this + ", " + collectDeclares());
+ return crosscuttingMembers;
+ }
+
+ public final Collection collectDeclares(boolean includeAdviceLike) {
+ if (! this.isAspect()) return Collections.EMPTY_LIST;
+
+ ArrayList ret = new ArrayList();
+ //if (this.isAbstract()) {
// for (Iterator i = getDeclares().iterator(); i.hasNext();) {
// Declare dec = (Declare) i.next();
// if (!dec.isAdviceLike()) ret.add(dec);
// }
//
// if (!includeAdviceLike) return ret;
-
- if (!this.isAbstract()) {
- //ret.addAll(getDeclares());
- final Iterators.Filter dupFilter = Iterators.dupFilter();
- Iterators.Getter typeGetter = new Iterators.Getter() {
- public Iterator get(Object o) {
- return
- dupFilter.filter(
- ((ResolvedType)o).getDirectSupertypes());
- }
- };
- Iterator typeIterator = Iterators.recur(this, typeGetter);
-
- while (typeIterator.hasNext()) {
- ResolvedType ty = (ResolvedType) typeIterator.next();
- //System.out.println("super: " + ty + ", " + );
- for (Iterator i = ty.getDeclares().iterator(); i.hasNext();) {
- Declare dec = (Declare) i.next();
- if (dec.isAdviceLike()) {
- if (includeAdviceLike) ret.add(dec);
- } else {
- ret.add(dec);
- }
- }
- }
- }
-
- return ret;
- }
-
-
-
-
+
+ if (!this.isAbstract()) {
+ //ret.addAll(getDeclares());
+ final Iterators.Filter dupFilter = Iterators.dupFilter();
+ Iterators.Getter typeGetter = new Iterators.Getter() {
+ public Iterator get(Object o) {
+ return
+ dupFilter.filter(
+ ((ResolvedType) o).getDirectSupertypes());
+ }
+ };
+ Iterator typeIterator = Iterators.recur(this, typeGetter);
+
+ while (typeIterator.hasNext()) {
+ ResolvedType ty = (ResolvedType) typeIterator.next();
+ //System.out.println("super: " + ty + ", " + );
+ for (Iterator i = ty.getDeclares().iterator(); i.hasNext();) {
+ Declare dec = (Declare) i.next();
+ if (dec.isAdviceLike()) {
+ if (includeAdviceLike) ret.add(dec);
+ } else {
+ ret.add(dec);
+ }
+ }
+ }
+ }
+
+ return ret;
+ }
+
+
private final Collection collectShadowMungers() {
if (! this.isAspect() || this.isAbstract() || this.doesNotExposeShadowMungers()) return Collections.EMPTY_LIST;
- ArrayList acc = new ArrayList();
+ ArrayList acc = new ArrayList();
final Iterators.Filter dupFilter = Iterators.dupFilter();
Iterators.Getter typeGetter = new Iterators.Getter() {
public Iterator get(Object o) {
- return
- dupFilter.filter(
- ((ResolvedType)o).getDirectSupertypes());
+ return
+ dupFilter.filter(
+ ((ResolvedType) o).getDirectSupertypes());
}
};
Iterator typeIterator = Iterators.recur(this, typeGetter);
while (typeIterator.hasNext()) {
ResolvedType ty = (ResolvedType) typeIterator.next();
- acc.addAll(ty.getDeclaredShadowMungers());
+ acc.addAll(ty.getDeclaredShadowMungers());
}
-
+
return acc;
}
-
- protected boolean doesNotExposeShadowMungers() {
- return false;
- }
-
- public PerClause getPerClause() { return null; }
- protected Collection getDeclares() {
- return Collections.EMPTY_LIST;
- }
- protected Collection getTypeMungers() { return Collections.EMPTY_LIST; }
-
- protected Collection getPrivilegedAccesses() { return Collections.EMPTY_LIST; }
-
-
+
+ protected boolean doesNotExposeShadowMungers() {
+ return false;
+ }
+
+ public PerClause getPerClause() {
+ return null;
+ }
+
+ protected Collection getDeclares() {
+ return Collections.EMPTY_LIST;
+ }
+
+ protected Collection getTypeMungers() {
+ return Collections.EMPTY_LIST;
+ }
+
+ protected Collection getPrivilegedAccesses() {
+ return Collections.EMPTY_LIST;
+ }
// ---- useful things
-
- public final boolean isInterface() {
+
+ public final boolean isInterface() {
return Modifier.isInterface(getModifiers());
}
-
- public final boolean isAbstract() {
+
+ public final boolean isAbstract() {
return Modifier.isAbstract(getModifiers());
}
-
+
public boolean isClass() {
- return false;
+ return false;
}
-
+
public boolean isAspect() {
- return false;
+ return false;
}
public boolean isAnnotationStyleAspect() {
- return false;
+ return false;
}
/**
* Note: Only overridden by Name subtype.
*/
public boolean isEnum() {
- return false;
+ return false;
}
-
+
/**
* Note: Only overridden by Name subtype.
*/
public boolean isAnnotation() {
- return false;
+ return false;
}
-
+
+ /**
+ * Note: Only overridden by Name subtype
+ */
+ public void addAnnotation(AnnotationX annotationX) {
+ throw new RuntimeException("ResolvedType.addAnnotation() should never be called");
+ }
+
/**
* Note: Only overridden by Name subtype
*/
- public void addAnnotation(AnnotationX annotationX) {
- throw new RuntimeException("ResolvedType.addAnnotation() should never be called");
- }
-
- /**
- * Note: Only overridden by Name subtype
- */
- public AnnotationX[] getAnnotations() {
- throw new RuntimeException("ResolvedType.getAnnotations() should never be called");
- }
-
-
+ public AnnotationX[] getAnnotations() {
+ throw new RuntimeException("ResolvedType.getAnnotations() should never be called");
+ }
+
+
/**
* Note: Only overridden by Name subtype.
*/
public boolean isAnnotationWithRuntimeRetention() {
return false;
}
-
+
public boolean isSynthetic() {
- return signature.indexOf("$ajc") != -1;
+ return signature.indexOf("$ajc") != -1;
}
-
+
public final boolean isFinal() {
return Modifier.isFinal(getModifiers());
}
- protected Map /*Type variable name -> UnresolvedType*/ getMemberParameterizationMap() {
- if (!isParameterizedType()) return Collections.EMPTY_MAP;
- TypeVariable[] tvs = getGenericType().getTypeVariables();
- Map parameterizationMap = new HashMap();
- for (int i = 0; i < tvs.length; i++) {
- parameterizationMap.put(tvs[i].getName(), typeParameters[i]);
- }
- return parameterizationMap;
- }
-
-
- public Collection getDeclaredAdvice() {
- List l = new ArrayList();
- ResolvedMember[] methods = getDeclaredMethods();
- if (isParameterizedType()) methods = getGenericType().getDeclaredMethods();
- Map typeVariableMap = getMemberParameterizationMap();
- for (int i=0, len = methods.length; i < len; i++) {
- ShadowMunger munger = methods[i].getAssociatedShadowMunger();
- if (munger != null) {
- if (this.isParameterizedType()) {
- //munger.setPointcut(munger.getPointcut().parameterizeWith(typeVariableMap));
- munger = munger.parameterizeWith(typeVariableMap);
- if (munger instanceof Advice) {
- Advice advice = (Advice) munger;
- // update to use the parameterized signature...
- UnresolvedType[] ptypes = methods[i].getGenericParameterTypes() ;
- UnresolvedType[] newPTypes = new UnresolvedType[ptypes.length];
- for (int j = 0; j < ptypes.length; j++) {
- if (ptypes[j] instanceof TypeVariableReferenceType) {
- TypeVariableReferenceType tvrt = (TypeVariableReferenceType) ptypes[j];
- if (typeVariableMap.containsKey(tvrt.getTypeVariable().getName())) {
- newPTypes[j] = (UnresolvedType) typeVariableMap.get(tvrt.getTypeVariable().getName());
- } else {
- newPTypes[j] = ptypes[j];
- }
- } else {
- newPTypes[j] = ptypes[j];
- }
- }
- advice.setBindingParameterTypes(newPTypes);
- }
- }
- munger.setDeclaringType(this);
- l.add(munger);
- }
- }
- return l;
- }
-
- public Collection getDeclaredShadowMungers() {
- Collection c = getDeclaredAdvice();
- return c;
- }
-
- // ---- only for testing!
-
-
- public ResolvedMember[] getDeclaredJavaFields() {
- return filterInJavaVisible(getDeclaredFields());
- }
- public ResolvedMember[] getDeclaredJavaMethods() {
- return filterInJavaVisible(getDeclaredMethods());
- }
- public ShadowMunger[] getDeclaredShadowMungersArray() {
- List l = (List) getDeclaredShadowMungers();
- return (ShadowMunger[]) l.toArray(new ShadowMunger[l.size()]);
- }
- private ResolvedMember[] filterInJavaVisible(ResolvedMember[] ms) {
- List l = new ArrayList();
- for (int i=0, len = ms.length; i < len; i++) {
- if (! ms[i].isAjSynthetic() && ms[i].getAssociatedShadowMunger() == null) {
- l.add(ms[i]);
- }
- }
- return (ResolvedMember[]) l.toArray(new ResolvedMember[l.size()]);
- }
-
- public abstract ISourceContext getSourceContext();
+ protected Map /*Type variable name -> UnresolvedType*/ getMemberParameterizationMap() {
+ if (!isParameterizedType()) return Collections.EMPTY_MAP;
+ TypeVariable[] tvs = getGenericType().getTypeVariables();
+ Map parameterizationMap = new HashMap();
+ for (int i = 0; i < tvs.length; i++) {
+ parameterizationMap.put(tvs[i].getName(), typeParameters[i]);
+ }
+ return parameterizationMap;
+ }
+
+
+ public Collection getDeclaredAdvice() {
+ List l = new ArrayList();
+ ResolvedMember[] methods = getDeclaredMethods();
+ if (isParameterizedType()) methods = getGenericType().getDeclaredMethods();
+ Map typeVariableMap = getMemberParameterizationMap();
+ for (int i = 0, len = methods.length; i < len; i++) {
+ ShadowMunger munger = methods[i].getAssociatedShadowMunger();
+ if (munger != null) {
+ if (this.isParameterizedType()) {
+ //munger.setPointcut(munger.getPointcut().parameterizeWith(typeVariableMap));
+ munger = munger.parameterizeWith(typeVariableMap);
+ if (munger instanceof Advice) {
+ Advice advice = (Advice) munger;
+ // update to use the parameterized signature...
+ UnresolvedType[] ptypes = methods[i].getGenericParameterTypes();
+ UnresolvedType[] newPTypes = new UnresolvedType[ptypes.length];
+ for (int j = 0; j < ptypes.length; j++) {
+ if (ptypes[j] instanceof TypeVariableReferenceType) {
+ TypeVariableReferenceType tvrt = (TypeVariableReferenceType) ptypes[j];
+ if (typeVariableMap.containsKey(tvrt.getTypeVariable().getName())) {
+ newPTypes[j] = (UnresolvedType) typeVariableMap.get(tvrt.getTypeVariable().getName());
+ } else {
+ newPTypes[j] = ptypes[j];
+ }
+ } else {
+ newPTypes[j] = ptypes[j];
+ }
+ }
+ advice.setBindingParameterTypes(newPTypes);
+ }
+ }
+ munger.setDeclaringType(this);
+ l.add(munger);
+ }
+ }
+ return l;
+ }
+
+ public Collection getDeclaredShadowMungers() {
+ Collection c = getDeclaredAdvice();
+ return c;
+ }
+
+ // ---- only for testing!
+
+
+ public ResolvedMember[] getDeclaredJavaFields() {
+ return filterInJavaVisible(getDeclaredFields());
+ }
+
+ public ResolvedMember[] getDeclaredJavaMethods() {
+ return filterInJavaVisible(getDeclaredMethods());
+ }
+
+ public ShadowMunger[] getDeclaredShadowMungersArray() {
+ List l = (List) getDeclaredShadowMungers();
+ return (ShadowMunger[]) l.toArray(new ShadowMunger[l.size()]);
+ }
+
+ private ResolvedMember[] filterInJavaVisible(ResolvedMember[] ms) {
+ List l = new ArrayList();
+ for (int i = 0, len = ms.length; i < len; i++) {
+ if (! ms[i].isAjSynthetic() && ms[i].getAssociatedShadowMunger() == null) {
+ l.add(ms[i]);
+ }
+ }
+ return (ResolvedMember[]) l.toArray(new ResolvedMember[l.size()]);
+ }
+ public abstract ISourceContext getSourceContext();
// ---- fields
-
+
public static final ResolvedType[] NONE = new ResolvedType[0];
- public static final Primitive BYTE = new Primitive("B", 1, 0);
- public static final Primitive CHAR = new Primitive("C", 1, 1);
- public static final Primitive DOUBLE = new Primitive("D", 2, 2);
- public static final Primitive FLOAT = new Primitive("F", 1, 3);
- public static final Primitive INT = new Primitive("I", 1, 4);
- public static final Primitive LONG = new Primitive("J", 2, 5);
- public static final Primitive SHORT = new Primitive("S", 1, 6);
- public static final Primitive VOID = new Primitive("V", 0, 8);
+ public static final Primitive BYTE = new Primitive("B", 1, 0);
+ public static final Primitive CHAR = new Primitive("C", 1, 1);
+ public static final Primitive DOUBLE = new Primitive("D", 2, 2);
+ public static final Primitive FLOAT = new Primitive("F", 1, 3);
+ public static final Primitive INT = new Primitive("I", 1, 4);
+ public static final Primitive LONG = new Primitive("J", 2, 5);
+ public static final Primitive SHORT = new Primitive("S", 1, 6);
+ public static final Primitive VOID = new Primitive("V", 0, 8);
public static final Primitive BOOLEAN = new Primitive("Z", 1, 7);
- public static final Missing MISSING = new Missing();
-
+ public static final Missing MISSING = new Missing();
+
// ---- types
public static ResolvedType makeArray(ResolvedType type, int dim) {
- if (dim == 0) return type;
- ResolvedType array = new Array("[" + type.getSignature(),type.getWorld(),type);
- return makeArray(array,dim-1);
+ if (dim == 0) return type;
+ ResolvedType array = new Array("[" + type.getSignature(), type.getWorld(), type);
+ return makeArray(array, dim - 1);
}
-
+
static class Array extends ResolvedType {
ResolvedType componentType;
+
Array(String s, World world, ResolvedType componentType) {
super(s, world);
this.componentType = componentType;
}
+
public final ResolvedMember[] getDeclaredFields() {
return ResolvedMember.NONE;
}
+
public final ResolvedMember[] getDeclaredMethods() {
// ??? should this return clone? Probably not...
// If it ever does, here is the code:
// ResolvedMember cloneMethod =
// new ResolvedMember(Member.METHOD,this,Modifier.PUBLIC,UnresolvedType.OBJECT,"clone",new UnresolvedType[]{});
// return new ResolvedMember[]{cloneMethod};
- return ResolvedMember.NONE;
+ return ResolvedMember.NONE;
}
+
public final ResolvedType[] getDeclaredInterfaces() {
return
- new ResolvedType[] {
- world.getCoreType(CLONEABLE),
- world.getCoreType(SERIALIZABLE)
- };
+ new ResolvedType[]{
+ world.getCoreType(CLONEABLE),
+ world.getCoreType(SERIALIZABLE)
+ };
}
+
public final ResolvedMember[] getDeclaredPointcuts() {
return ResolvedMember.NONE;
}
-
+
public boolean hasAnnotation(UnresolvedType ofType) {
- return false;
+ return false;
}
-
+
public final ResolvedType getSuperclass() {
return world.getCoreType(OBJECT);
}
+
public final boolean isAssignableFrom(ResolvedType o) {
if (! o.isArray()) return false;
if (o.getComponentType().isPrimitiveType()) {
return getComponentType().resolve(world).isAssignableFrom(o.getComponentType().resolve(world));
}
}
-
+
public boolean isAssignableFrom(ResolvedType o, boolean allowMissing) {
- return isAssignableFrom(o);
+ return isAssignableFrom(o);
}
-
+
public final boolean isCoerceableFrom(ResolvedType o) {
- if (o.equals(UnresolvedType.OBJECT) ||
+ if (o.equals(UnresolvedType.OBJECT) ||
o.equals(UnresolvedType.SERIALIZABLE) ||
o.equals(UnresolvedType.CLONEABLE)) {
return true;
return getComponentType().resolve(world).isCoerceableFrom(o.getComponentType().resolve(world));
}
}
+
public final int getModifiers() {
int mask = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
return (componentType.getModifiers() & mask) | Modifier.FINAL;
}
+
public UnresolvedType getComponentType() {
return componentType;
}
+
public ResolvedType getResolvedComponentType() {
return componentType;
}
+
public ISourceContext getSourceContext() {
- return getResolvedComponentType().getSourceContext();
+ return getResolvedComponentType().getSourceContext();
}
}
-
+
static class Primitive extends ResolvedType {
private int size;
private int index;
+
Primitive(String signature, int size, int index) {
super(signature, null);
this.size = size;
this.index = index;
}
+
public final int getSize() {
return size;
}
+
public final int getModifiers() {
return Modifier.PUBLIC | Modifier.FINAL;
}
+
public final boolean isPrimitiveType() {
return true;
}
+
public boolean hasAnnotation(UnresolvedType ofType) {
- return false;
+ return false;
}
+
public final boolean isAssignableFrom(ResolvedType other) {
if (!other.isPrimitiveType()) {
- if (!world.isInJava5Mode()) return false;
- return validBoxing.contains(this.getSignature()+other.getSignature());
+ if (!world.isInJava5Mode()) return false;
+ return validBoxing.contains(this.getSignature() + other.getSignature());
}
- return assignTable[((Primitive)other).index][index];
+ return assignTable[((Primitive) other).index][index];
}
+
public final boolean isAssignableFrom(ResolvedType other, boolean allowMissing) {
- return isAssignableFrom(other);
- }
+ return isAssignableFrom(other);
+ }
+
public final boolean isCoerceableFrom(ResolvedType other) {
if (this == other) return true;
if (! other.isPrimitiveType()) return false;
- if (index > 6 || ((Primitive)other).index > 6) return false;
+ if (index > 6 || ((Primitive) other).index > 6) return false;
return true;
}
+
public ResolvedType resolve(World world) {
this.world = world;
return super.resolve(world);
}
+
public final boolean needsNoConversionFrom(ResolvedType other) {
if (! other.isPrimitiveType()) return false;
- return noConvertTable[((Primitive)other).index][index];
- }
- private static final boolean[][] assignTable =
- {// to: B C D F I J S V Z from
- { true , true , true , true , true , true , true , false, false }, // B
- { false, true , true , true , true , true , false, false, false }, // C
- { false, false, true , false, false, false, false, false, false }, // D
- { false, false, true , true , false, false, false, false, false }, // F
- { false, false, true , true , true , true , false, false, false }, // I
- { false, false, true , true , false, true , false, false, false }, // J
- { false, false, true , true , true , true , true , false, false }, // S
- { false, false, false, false, false, false, false, true , false }, // V
- { false, false, false, false, false, false, false, false, true }, // Z
- };
- private static final boolean[][] noConvertTable =
- {// to: B C D F I J S V Z from
- { true , true , false, false, true , false, true , false, false }, // B
- { false, true , false, false, true , false, false, false, false }, // C
- { false, false, true , false, false, false, false, false, false }, // D
- { false, false, false, true , false, false, false, false, false }, // F
- { false, false, false, false, true , false, false, false, false }, // I
- { false, false, false, false, false, true , false, false, false }, // J
- { false, false, false, false, true , false, true , false, false }, // S
- { false, false, false, false, false, false, false, true , false }, // V
- { false, false, false, false, false, false, false, false, true }, // Z
- };
-
+ return noConvertTable[((Primitive) other).index][index];
+ }
+
+ private static final boolean[][] assignTable =
+ {// to: B C D F I J S V Z from
+ {true, true, true, true, true, true, true, false, false}, // B
+ {false, true, true, true, true, true, false, false, false}, // C
+ {false, false, true, false, false, false, false, false, false}, // D
+ {false, false, true, true, false, false, false, false, false}, // F
+ {false, false, true, true, true, true, false, false, false}, // I
+ {false, false, true, true, false, true, false, false, false}, // J
+ {false, false, true, true, true, true, true, false, false}, // S
+ {false, false, false, false, false, false, false, true, false}, // V
+ {false, false, false, false, false, false, false, false, true}, // Z
+ };
+ private static final boolean[][] noConvertTable =
+ {// to: B C D F I J S V Z from
+ {true, true, false, false, true, false, true, false, false}, // B
+ {false, true, false, false, true, false, false, false, false}, // C
+ {false, false, true, false, false, false, false, false, false}, // D
+ {false, false, false, true, false, false, false, false, false}, // F
+ {false, false, false, false, true, false, false, false, false}, // I
+ {false, false, false, false, false, true, false, false, false}, // J
+ {false, false, false, false, true, false, true, false, false}, // S
+ {false, false, false, false, false, false, false, true, false}, // V
+ {false, false, false, false, false, false, false, false, true}, // Z
+ };
+
// ----
-
+
public final ResolvedMember[] getDeclaredFields() {
return ResolvedMember.NONE;
}
+
public final ResolvedMember[] getDeclaredMethods() {
return ResolvedMember.NONE;
}
+
public final ResolvedType[] getDeclaredInterfaces() {
return ResolvedType.NONE;
}
+
public final ResolvedMember[] getDeclaredPointcuts() {
return ResolvedMember.NONE;
}
public final ResolvedType getSuperclass() {
return null;
}
-
+
public ISourceContext getSourceContext() {
- return null;
+ return null;
}
-
+
}
static class Missing extends ResolvedType {
Missing() {
super(MISSING_NAME, null);
- }
+ }
// public final String toString() {
// return "<missing>";
// }
+
public final String getName() {
- return MISSING_NAME;
+ return MISSING_NAME;
+ }
+
+ public final boolean isMissing() {
+ return true;
}
-
- public final boolean isMissing() { return true; }
-
+
public boolean hasAnnotation(UnresolvedType ofType) {
- return false;
+ return false;
}
+
public final ResolvedMember[] getDeclaredFields() {
return ResolvedMember.NONE;
}
+
public final ResolvedMember[] getDeclaredMethods() {
return ResolvedMember.NONE;
}
+
public final ResolvedType[] getDeclaredInterfaces() {
return ResolvedType.NONE;
}
public final ResolvedMember[] getDeclaredPointcuts() {
return ResolvedMember.NONE;
}
+
public final ResolvedType getSuperclass() {
return null;
}
+
public final int getModifiers() {
return 0;
}
+
public final boolean isAssignableFrom(ResolvedType other) {
return false;
- }
+ }
+
public final boolean isAssignableFrom(ResolvedType other, boolean allowMissing) {
return false;
- }
+ }
+
public final boolean isCoerceableFrom(ResolvedType other) {
return false;
- }
+ }
+
public boolean needsNoConversionFrom(ResolvedType other) {
return false;
}
+
public ISourceContext getSourceContext() {
- return null;
+ return null;
}
}
- /**
+ /**
* Look up a member, takes into account any ITDs on this type.
- * return null if not found */
- public ResolvedMember lookupMemberNoSupers(Member member) {
- ResolvedMember ret = lookupDirectlyDeclaredMemberNoSupers(member);
- if (ret == null && interTypeMungers != null) {
- for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
- ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
- if (matches(tm.getSignature(), member)) {
- return tm.getSignature();
- }
- }
- }
- return ret;
- }
-
- public ResolvedMember lookupMemberWithSupersAndITDs(Member member) {
- ResolvedMember ret = lookupMemberNoSupers(member);
- if (ret != null) return ret;
-
- ResolvedType supert = getSuperclass();
- if (supert != null) {
- ret = supert.lookupMemberNoSupers(member);
- }
-
- return ret;
- }
-
- /**
- * as lookupMemberNoSupers, but does not include ITDs
- * @param member
- * @return
- */
- public ResolvedMember lookupDirectlyDeclaredMemberNoSupers(Member member) {
- ResolvedMember ret;
- if (member.getKind() == Member.FIELD) {
- ret = lookupMember(member, getDeclaredFields());
- } else {
- // assert member.getKind() == Member.METHOD || member.getKind() == Member.CONSTRUCTOR
- ret = lookupMember(member, getDeclaredMethods());
- }
- return ret;
- }
-
- /**
- * This lookup has specialized behaviour - a null result tells the
- * EclipseTypeMunger that it should make a default implementation of a
- * method on this type.
- * @param member
- * @return
- */
- public ResolvedMember lookupMemberIncludingITDsOnInterfaces(Member member) {
- return lookupMemberIncludingITDsOnInterfaces(member, this);
- }
-
- private ResolvedMember lookupMemberIncludingITDsOnInterfaces(Member member, ResolvedType onType) {
- ResolvedMember ret = onType.lookupMemberNoSupers(member);
- if (ret != null) {
- return ret;
- } else {
- ResolvedType superType = onType.getSuperclass();
- if (superType != null) {
- ret = lookupMemberIncludingITDsOnInterfaces(member,superType);
- }
- if (ret == null) {
- // try interfaces then, but only ITDs now...
- ResolvedType[] superInterfaces = onType.getDeclaredInterfaces();
- for (int i = 0; i < superInterfaces.length; i++) {
- ret = superInterfaces[i].lookupMethodInITDs(member);
- if (ret != null) return ret;
- }
- }
- }
- return ret;
- }
-
- protected List interTypeMungers = new ArrayList(0);
-
- public List getInterTypeMungers() {
- return interTypeMungers;
- }
-
- public List getInterTypeParentMungers() {
- List l = new ArrayList();
- for (Iterator iter = interTypeMungers.iterator(); iter.hasNext();) {
- ConcreteTypeMunger element = (ConcreteTypeMunger) iter.next();
- if (element.getMunger() instanceof NewParentTypeMunger) l.add(element);
- }
- return l;
- }
-
- /**
- * ??? This method is O(N*M) where N = number of methods and M is number of
- * inter-type declarations in my super
- */
- public List getInterTypeMungersIncludingSupers() {
- ArrayList ret = new ArrayList();
- collectInterTypeMungers(ret);
+ * return null if not found
+ */
+ public ResolvedMember lookupMemberNoSupers(Member member) {
+ ResolvedMember ret = lookupDirectlyDeclaredMemberNoSupers(member);
+ if (ret == null && interTypeMungers != null) {
+ for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+ ConcreteTypeMunger tm = (ConcreteTypeMunger) i.next();
+ if (matches(tm.getSignature(), member)) {
+ return tm.getSignature();
+ }
+ }
+ }
return ret;
}
-
- public List getInterTypeParentMungersIncludingSupers() {
- ArrayList ret = new ArrayList();
- collectInterTypeParentMungers(ret);
- return ret;
- }
-
- private void collectInterTypeParentMungers(List collector) {
- for (Iterator iter = getDirectSupertypes(); iter.hasNext();) {
+ public ResolvedMember lookupMemberWithSupersAndITDs(Member member) {
+ ResolvedMember ret = lookupMemberNoSupers(member);
+ if (ret != null) return ret;
+
+ ResolvedType supert = getSuperclass();
+ if (supert != null) {
+ ret = supert.lookupMemberNoSupers(member);
+ }
+
+ return ret;
+ }
+
+ /**
+ * as lookupMemberNoSupers, but does not include ITDs
+ *
+ * @param member
+ * @return
+ */
+ public ResolvedMember lookupDirectlyDeclaredMemberNoSupers(Member member) {
+ ResolvedMember ret;
+ if (member.getKind() == Member.FIELD) {
+ ret = lookupMember(member, getDeclaredFields());
+ } else {
+ // assert member.getKind() == Member.METHOD || member.getKind() == Member.CONSTRUCTOR
+ ret = lookupMember(member, getDeclaredMethods());
+ }
+ return ret;
+ }
+
+ /**
+ * This lookup has specialized behaviour - a null result tells the
+ * EclipseTypeMunger that it should make a default implementation of a
+ * method on this type.
+ *
+ * @param member
+ * @return
+ */
+ public ResolvedMember lookupMemberIncludingITDsOnInterfaces(Member member) {
+ return lookupMemberIncludingITDsOnInterfaces(member, this);
+ }
+
+ private ResolvedMember lookupMemberIncludingITDsOnInterfaces(Member member, ResolvedType onType) {
+ ResolvedMember ret = onType.lookupMemberNoSupers(member);
+ if (ret != null) {
+ return ret;
+ } else {
+ ResolvedType superType = onType.getSuperclass();
+ if (superType != null) {
+ ret = lookupMemberIncludingITDsOnInterfaces(member, superType);
+ }
+ if (ret == null) {
+ // try interfaces then, but only ITDs now...
+ ResolvedType[] superInterfaces = onType.getDeclaredInterfaces();
+ for (int i = 0; i < superInterfaces.length; i++) {
+ ret = superInterfaces[i].lookupMethodInITDs(member);
+ if (ret != null) return ret;
+ }
+ }
+ }
+ return ret;
+ }
+
+ protected List interTypeMungers = new ArrayList(0);
+
+ public List getInterTypeMungers() {
+ return interTypeMungers;
+ }
+
+ public List getInterTypeParentMungers() {
+ List l = new ArrayList();
+ for (Iterator iter = interTypeMungers.iterator(); iter.hasNext();) {
+ ConcreteTypeMunger element = (ConcreteTypeMunger) iter.next();
+ if (element.getMunger() instanceof NewParentTypeMunger) l.add(element);
+ }
+ return l;
+ }
+
+ /**
+ * ??? This method is O(N*M) where N = number of methods and M is number of
+ * inter-type declarations in my super
+ */
+ public List getInterTypeMungersIncludingSupers() {
+ ArrayList ret = new ArrayList();
+ collectInterTypeMungers(ret);
+ return ret;
+ }
+
+
+ public List getInterTypeParentMungersIncludingSupers() {
+ ArrayList ret = new ArrayList();
+ collectInterTypeParentMungers(ret);
+ return ret;
+ }
+
+ private void collectInterTypeParentMungers(List collector) {
+ for (Iterator iter = getDirectSupertypes(); iter.hasNext();) {
ResolvedType superType = (ResolvedType) iter.next();
superType.collectInterTypeParentMungers(collector);
}
collector.addAll(getInterTypeParentMungers());
}
-
-
+
+
protected void collectInterTypeMungers(List collector) {
for (Iterator iter = getDirectSupertypes(); iter.hasNext();) {
- ResolvedType superType = (ResolvedType) iter.next();
+ ResolvedType superType = (ResolvedType) iter.next();
superType.collectInterTypeMungers(collector);
- }
-
- outer: for (Iterator iter1 = collector.iterator(); iter1.hasNext(); ) {
+ }
+
+ outer:
+ for (Iterator iter1 = collector.iterator(); iter1.hasNext();) {
ConcreteTypeMunger superMunger = (ConcreteTypeMunger) iter1.next();
- if ( superMunger.getSignature() == null) continue;
-
- if ( !superMunger.getSignature().isAbstract()) continue;
-
+ if (superMunger.getSignature() == null) continue;
+
+ if (!superMunger.getSignature().isAbstract()) continue;
+
for (Iterator iter = getInterTypeMungers().iterator(); iter.hasNext();) {
- ConcreteTypeMunger myMunger = (ConcreteTypeMunger) iter.next();
+ ConcreteTypeMunger myMunger = (ConcreteTypeMunger) iter.next();
if (conflictingSignature(myMunger.getSignature(), superMunger.getSignature())) {
iter1.remove();
continue outer;
}
}
-
+
if (!superMunger.getSignature().isPublic()) continue;
-
- for (Iterator iter = getMethods(); iter.hasNext(); ) {
- ResolvedMember method = (ResolvedMember)iter.next();
+
+ for (Iterator iter = getMethods(); iter.hasNext();) {
+ ResolvedMember method = (ResolvedMember) iter.next();
if (conflictingSignature(method, superMunger.getSignature())) {
iter1.remove();
continue outer;
}
}
}
-
+
collector.addAll(getInterTypeMungers());
}
-
-
-
+
+
/**
* Check:
* 1) That we don't have any abstract type mungers unless this type is abstract.
*/
public void checkInterTypeMungers() {
if (isAbstract()) return;
-
+
boolean itdProblem = false;
-
+
for (Iterator iter = getInterTypeMungersIncludingSupers().iterator(); iter.hasNext();) {
- ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next();
- itdProblem = checkAbstractDeclaration(munger) || itdProblem; // Rule 2
+ ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next();
+ itdProblem = checkAbstractDeclaration(munger) || itdProblem; // Rule 2
}
-
+
if (itdProblem) return; // If the rules above are broken, return right now
-
- for (Iterator iter = getInterTypeMungersIncludingSupers().iterator(); iter.hasNext();) {
- ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next();
+
+ for (Iterator iter = getInterTypeMungersIncludingSupers().iterator(); iter.hasNext();) {
+ ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next();
if (munger.getSignature() != null && munger.getSignature().isAbstract()) { // Rule 1
- world.getMessageHandler().handleMessage(
- new Message("must implement abstract inter-type declaration: " + munger.getSignature(),
- "", IMessage.ERROR, getSourceLocation(), null,
- new ISourceLocation[] { getMungerLocation(munger) }));
+ if (munger.getMunger().getKind() == ResolvedTypeMunger.MethodDelegate) {
+ ;//ignore for @AJ ITD as munger.getSingature() is the interface method hence abstract
+ } else {
+ world.getMessageHandler().handleMessage(
+ new Message("must implement abstract inter-type declaration: " + munger.getSignature(),
+ "", IMessage.ERROR, getSourceLocation(), null,
+ new ISourceLocation[]{getMungerLocation(munger)}));
+ }
}
- }
+ }
}
-
+
/**
* See PR70794. This method checks that if an abstract inter-type method declaration is made on
* an interface then it must also be public.
* This is a compiler limitation that could be made to work in the future (if someone
* provides a worthwhile usecase)
- *
+ *
* @return indicates if the munger failed the check
*/
private boolean checkAbstractDeclaration(ConcreteTypeMunger munger) {
- if (munger.getMunger()!=null && (munger.getMunger() instanceof NewMethodTypeMunger)) {
- ResolvedMember itdMember = munger.getSignature();
- ResolvedType onType = itdMember.getDeclaringType().resolve(world);
- if (onType.isInterface() && itdMember.isAbstract() && !itdMember.isPublic()) {
- world.getMessageHandler().handleMessage(
- new Message(WeaverMessages.format(WeaverMessages.ITD_ABSTRACT_MUST_BE_PUBLIC_ON_INTERFACE,munger.getSignature(),onType),"",
- Message.ERROR,getSourceLocation(),null,
- new ISourceLocation[]{getMungerLocation(munger)})
- );
- return true;
- }
- }
- return false;
- }
-
+ if (munger.getMunger() != null && (munger.getMunger() instanceof NewMethodTypeMunger)) {
+ ResolvedMember itdMember = munger.getSignature();
+ ResolvedType onType = itdMember.getDeclaringType().resolve(world);
+ if (onType.isInterface() && itdMember.isAbstract() && !itdMember.isPublic()) {
+ world.getMessageHandler().handleMessage(
+ new Message(WeaverMessages.format(WeaverMessages.ITD_ABSTRACT_MUST_BE_PUBLIC_ON_INTERFACE, munger.getSignature(), onType), "",
+ Message.ERROR, getSourceLocation(), null,
+ new ISourceLocation[]{getMungerLocation(munger)})
+ );
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Get a source location for the munger.
* Until intertype mungers remember where they came from, the source location
* for the munger itself is null. In these cases use the
* source location for the aspect containing the ITD.
- *
*/
private ISourceLocation getMungerLocation(ConcreteTypeMunger munger) {
- ISourceLocation sloc = munger.getSourceLocation();
- if (sloc == null) {
- sloc = munger.getAspectType().getSourceLocation();
- }
- return sloc;
+ ISourceLocation sloc = munger.getSourceLocation();
+ if (sloc == null) {
+ sloc = munger.getAspectType().getSourceLocation();
+ }
+ return sloc;
}
-
+
/**
* Returns a ResolvedType object representing the declaring type of this type, or
* null if this type does not represent a non-package-level-type.
- *
+ * <p/>
* <strong>Warning</strong>: This is guaranteed to work for all member types.
* For anonymous/local types, the only guarantee is given in JLS 13.1, where
* it guarantees that if you call getDeclaringType() repeatedly, you will eventually
* @return the declaring UnresolvedType object, or null.
*/
public ResolvedType getDeclaringType() {
- if (isArray()) return null;
- String name = getName();
- int lastDollar = name.lastIndexOf('$');
- while (lastDollar != -1) {
- ResolvedType ret = world.resolve(UnresolvedType.forName(name.substring(0, lastDollar)), true);
- if (ret != ResolvedType.MISSING) return ret;
- lastDollar = name.lastIndexOf('$', lastDollar-1);
- }
- return null;
- }
-
-
- public static boolean isVisible(int modifiers, ResolvedType targetType, ResolvedType fromType) {
- //System.err.println("mod: " + modifiers + ", " + targetType + " and " + fromType);
-
- if (Modifier.isPublic(modifiers)) {
- return true;
- } else if (Modifier.isPrivate(modifiers)) {
- return targetType.getOutermostType().equals(fromType.getOutermostType());
- } else if (Modifier.isProtected(modifiers)) {
- return samePackage(targetType, fromType) || targetType.isAssignableFrom(fromType);
- } else { // package-visible
- return samePackage(targetType, fromType);
- }
- }
-
- public static boolean hasBridgeModifier(int modifiers) {
- return (modifiers & Constants.ACC_BRIDGE)!=0;
- }
-
- private static boolean samePackage(
- ResolvedType targetType,
- ResolvedType fromType)
- {
- String p1 = targetType.getPackageName();
- String p2 = fromType.getPackageName();
- if (p1 == null) return p2 == null;
- if (p2 == null) return false;
- return p1.equals(p2);
- }
-
- public void addInterTypeMunger(ConcreteTypeMunger munger) {
- ResolvedMember sig = munger.getSignature();
- if (sig == null || munger.getMunger() == null ||
- munger.getMunger().getKind() == ResolvedTypeMunger.PrivilegedAccess)
- {
- interTypeMungers.add(munger);
- return;
- }
-
- //System.err.println("add: " + munger + " to " + this.getClassName() + " with " + interTypeMungers);
- if (sig.getKind() == Member.METHOD) {
- if (!compareToExistingMembers(munger, getMethodsWithoutIterator(false,true) /*getMethods()*/)) return;
- if (this.isInterface()) {
- if (!compareToExistingMembers(munger,
- Arrays.asList(world.getCoreType(OBJECT).getDeclaredMethods()).iterator())) return;
- }
- } else if (sig.getKind() == Member.FIELD) {
- if (!compareToExistingMembers(munger, Arrays.asList(getDeclaredFields()).iterator())) return;
- } else {
- if (!compareToExistingMembers(munger, Arrays.asList(getDeclaredMethods()).iterator())) return;
- }
-
-
- // now compare to existingMungers
- for (Iterator i = interTypeMungers.iterator(); i.hasNext(); ) {
- ConcreteTypeMunger existingMunger = (ConcreteTypeMunger)i.next();
- if (conflictingSignature(existingMunger.getSignature(), munger.getSignature())) {
- //System.err.println("match " + munger + " with " + existingMunger);
- if (isVisible(munger.getSignature().getModifiers(),
- munger.getAspectType(), existingMunger.getAspectType()))
- {
- //System.err.println(" is visible");
- int c = compareMemberPrecedence(sig, existingMunger.getSignature());
- if (c == 0) {
- c = getWorld().compareByPrecedenceAndHierarchy(munger.getAspectType(), existingMunger.getAspectType());
- }
- //System.err.println(" compare: " + c);
- if (c < 0) {
- // the existing munger dominates the new munger
- checkLegalOverride(munger.getSignature(), existingMunger.getSignature());
- return;
- } else if (c > 0) {
- // the new munger dominates the existing one
- checkLegalOverride(existingMunger.getSignature(), munger.getSignature());
- i.remove();
- break;
- } else {
- interTypeConflictError(munger, existingMunger);
- interTypeConflictError(existingMunger, munger);
- return;
- }
- }
- }
- }
- //System.err.println("adding: " + munger + " to " + this);
- interTypeMungers.add(munger);
- }
-
- private boolean compareToExistingMembers(ConcreteTypeMunger munger, List existingMembersList) {
- return compareToExistingMembers(munger,existingMembersList.iterator());
- }
-
- //??? returning too soon
- private boolean compareToExistingMembers(ConcreteTypeMunger munger, Iterator existingMembers) {
- ResolvedMember sig = munger.getSignature();
- while (existingMembers.hasNext()) {
- ResolvedMember existingMember = (ResolvedMember)existingMembers.next();
- //System.err.println("Comparing munger: "+sig+" with member "+existingMember);
- if (conflictingSignature(existingMember, munger.getSignature())) {
- //System.err.println("conflict: existingMember=" + existingMember + " typeMunger=" + munger);
- //System.err.println(munger.getSourceLocation() + ", " + munger.getSignature() + ", " + munger.getSignature().getSourceLocation());
-
- if (isVisible(existingMember.getModifiers(), this, munger.getAspectType())) {
- int c = compareMemberPrecedence(sig, existingMember);
- //System.err.println(" c: " + c);
- if (c < 0) {
- // existingMember dominates munger
- checkLegalOverride(munger.getSignature(), existingMember);
- return false;
- } else if (c > 0) {
- // munger dominates existingMember
- checkLegalOverride(existingMember, munger.getSignature());
- //interTypeMungers.add(munger);
- //??? might need list of these overridden abstracts
- continue;
- } else {
- // bridge methods can differ solely in return type.
- // FIXME this whole method seems very hokey - unaware of covariance/varargs/bridging - it
- // could do with a rewrite !
- boolean sameReturnTypes = (existingMember.getReturnType().equals(sig.getReturnType()));
- if (sameReturnTypes)
- getWorld().getMessageHandler().handleMessage(
- MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT,munger.getAspectType().getName(),
- existingMember),
- munger.getSourceLocation())
- );
- }
- } else if (isDuplicateMemberWithinTargetType(existingMember,this,sig)) {
- getWorld().getMessageHandler().handleMessage(
- MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT,munger.getAspectType().getName(),
- existingMember),
- munger.getSourceLocation())
- );;
- }
- //return;
- }
- }
- return true;
- }
-
- // we know that the member signature matches, but that the member in the target type is not visible to the aspect.
- // this may still be disallowed if it would result in two members within the same declaring type with the same
- // signature AND more than one of them is concrete AND they are both visible within the target type.
- private boolean isDuplicateMemberWithinTargetType(ResolvedMember existingMember, ResolvedType targetType,ResolvedMember itdMember) {
- if ( (existingMember.isAbstract() || itdMember.isAbstract())) return false;
- UnresolvedType declaringType = existingMember.getDeclaringType();
- if (!targetType.equals(declaringType)) return false;
- // now have to test that itdMember is visible from targetType
- if (itdMember.isPrivate()) return false;
- if (itdMember.isPublic()) return true;
- // must be in same package to be visible then...
- if (!targetType.getPackageName().equals(itdMember.getDeclaringType().getPackageName())) return false;
-
- // trying to put two members with the same signature into the exact same type..., and both visible in that type.
- return true;
- }
-
- /**
- * @return true if the override is legal
- * note: calling showMessage with two locations issues TWO messages, not ONE message
- * with an additional source location.
- */
- public boolean checkLegalOverride(ResolvedMember parent, ResolvedMember child) {
- //System.err.println("check: " + child.getDeclaringType() + " overrides " + parent.getDeclaringType());
- if (Modifier.isFinal(parent.getModifiers())) {
- world.showMessage(Message.ERROR,
- WeaverMessages.format(WeaverMessages.CANT_OVERRIDE_FINAL_MEMBER,parent),
- child.getSourceLocation(),null);
- return false;
- }
-
- boolean incompatibleReturnTypes = false;
-
- // In 1.5 mode, allow for covariance on return type
- if (world.isInJava5Mode() && parent.getKind()==Member.METHOD) {
- ResolvedType rtParentReturnType = parent.getReturnType().resolve(world);
- ResolvedType rtChildReturnType = child.getReturnType().resolve(world);
- incompatibleReturnTypes = !rtParentReturnType.isAssignableFrom(rtChildReturnType);
- } else {
- incompatibleReturnTypes =!parent.getReturnType().equals(child.getReturnType());
- }
-
- if (incompatibleReturnTypes) {
- world.showMessage(IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.ITD_RETURN_TYPE_MISMATCH,parent,child),
- child.getSourceLocation(), parent.getSourceLocation());
- return false;
- }
- if (parent.getKind() == Member.POINTCUT) {
- UnresolvedType[] pTypes = parent.getParameterTypes();
- UnresolvedType[] cTypes = child.getParameterTypes();
- if (!Arrays.equals(pTypes, cTypes)) {
- world.showMessage(IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.ITD_PARAM_TYPE_MISMATCH,parent,child),
- child.getSourceLocation(), parent.getSourceLocation());
- return false;
- }
- }
- //System.err.println("check: " + child.getModifiers() + " more visible " + parent.getModifiers());
- if (isMoreVisible(parent.getModifiers(), child.getModifiers())) {
- world.showMessage(IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.ITD_VISIBILITY_REDUCTION,parent,child),
- child.getSourceLocation(), parent.getSourceLocation());
- return false;
- }
-
- // check declared exceptions
- ResolvedType[] childExceptions = world.resolve(child.getExceptions());
- ResolvedType[] parentExceptions = world.resolve(parent.getExceptions());
- ResolvedType runtimeException = world.resolve("java.lang.RuntimeException");
- ResolvedType error = world.resolve("java.lang.Error");
-
- outer: for (int i=0, leni = childExceptions.length; i < leni; i++) {
- //System.err.println("checking: " + childExceptions[i]);
- if (runtimeException.isAssignableFrom(childExceptions[i])) continue;
- if (error.isAssignableFrom(childExceptions[i])) continue;
-
- for (int j = 0, lenj = parentExceptions.length; j < lenj; j++) {
- if (parentExceptions[j].isAssignableFrom(childExceptions[i])) continue outer;
- }
-
- // this message is now better handled my MethodVerifier in JDT core.
+ if (isArray()) return null;
+ String name = getName();
+ int lastDollar = name.lastIndexOf('$');
+ while (lastDollar != -1) {
+ ResolvedType ret = world.resolve(UnresolvedType.forName(name.substring(0, lastDollar)), true);
+ if (ret != ResolvedType.MISSING) return ret;
+ lastDollar = name.lastIndexOf('$', lastDollar - 1);
+ }
+ return null;
+ }
+
+
+ public static boolean isVisible(int modifiers, ResolvedType targetType, ResolvedType fromType) {
+ //System.err.println("mod: " + modifiers + ", " + targetType + " and " + fromType);
+
+ if (Modifier.isPublic(modifiers)) {
+ return true;
+ } else if (Modifier.isPrivate(modifiers)) {
+ return targetType.getOutermostType().equals(fromType.getOutermostType());
+ } else if (Modifier.isProtected(modifiers)) {
+ return samePackage(targetType, fromType) || targetType.isAssignableFrom(fromType);
+ } else { // package-visible
+ return samePackage(targetType, fromType);
+ }
+ }
+
+ public static boolean hasBridgeModifier(int modifiers) {
+ return (modifiers & Constants.ACC_BRIDGE) != 0;
+ }
+
+ private static boolean samePackage(
+ ResolvedType targetType,
+ ResolvedType fromType) {
+ String p1 = targetType.getPackageName();
+ String p2 = fromType.getPackageName();
+ if (p1 == null) return p2 == null;
+ if (p2 == null) return false;
+ return p1.equals(p2);
+ }
+
+ public void addInterTypeMunger(ConcreteTypeMunger munger) {
+ ResolvedMember sig = munger.getSignature();
+ if (sig == null || munger.getMunger() == null ||
+ munger.getMunger().getKind() == ResolvedTypeMunger.PrivilegedAccess) {
+ interTypeMungers.add(munger);
+ return;
+ }
+
+ //System.err.println("add: " + munger + " to " + this.getClassName() + " with " + interTypeMungers);
+ if (sig.getKind() == Member.METHOD) {
+ if (!compareToExistingMembers(munger, getMethodsWithoutIterator(false, true) /*getMethods()*/)) return;
+ if (this.isInterface()) {
+ if (!compareToExistingMembers(munger,
+ Arrays.asList(world.getCoreType(OBJECT).getDeclaredMethods()).iterator())) return;
+ }
+ } else if (sig.getKind() == Member.FIELD) {
+ if (!compareToExistingMembers(munger, Arrays.asList(getDeclaredFields()).iterator())) return;
+ } else {
+ if (!compareToExistingMembers(munger, Arrays.asList(getDeclaredMethods()).iterator())) return;
+ }
+
+ // now compare to existingMungers
+ for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+ ConcreteTypeMunger existingMunger = (ConcreteTypeMunger) i.next();
+ if (conflictingSignature(existingMunger.getSignature(), munger.getSignature())) {
+ //System.err.println("match " + munger + " with " + existingMunger);
+ if (isVisible(munger.getSignature().getModifiers(),
+ munger.getAspectType(), existingMunger.getAspectType())) {
+ //System.err.println(" is visible");
+ int c = compareMemberPrecedence(sig, existingMunger.getSignature());
+ if (c == 0) {
+ c = getWorld().compareByPrecedenceAndHierarchy(munger.getAspectType(), existingMunger.getAspectType());
+ }
+ //System.err.println(" compare: " + c);
+ if (c < 0) {
+ // the existing munger dominates the new munger
+ checkLegalOverride(munger.getSignature(), existingMunger.getSignature());
+ return;
+ } else if (c > 0) {
+ // the new munger dominates the existing one
+ checkLegalOverride(existingMunger.getSignature(), munger.getSignature());
+ i.remove();
+ break;
+ } else {
+ interTypeConflictError(munger, existingMunger);
+ interTypeConflictError(existingMunger, munger);
+ return;
+ }
+ }
+ }
+ }
+ //System.err.println("adding: " + munger + " to " + this);
+ interTypeMungers.add(munger);
+ }
+
+ private boolean compareToExistingMembers(ConcreteTypeMunger munger, List existingMembersList) {
+ return compareToExistingMembers(munger, existingMembersList.iterator());
+ }
+
+ //??? returning too soon
+ private boolean compareToExistingMembers(ConcreteTypeMunger munger, Iterator existingMembers) {
+ ResolvedMember sig = munger.getSignature();
+ while (existingMembers.hasNext()) {
+ ResolvedMember existingMember = (ResolvedMember) existingMembers.next();
+ //System.err.println("Comparing munger: "+sig+" with member "+existingMember);
+ if (conflictingSignature(existingMember, munger.getSignature())) {
+ //System.err.println("conflict: existingMember=" + existingMember + " typeMunger=" + munger);
+ //System.err.println(munger.getSourceLocation() + ", " + munger.getSignature() + ", " + munger.getSignature().getSourceLocation());
+
+ if (isVisible(existingMember.getModifiers(), this, munger.getAspectType())) {
+ int c = compareMemberPrecedence(sig, existingMember);
+ //System.err.println(" c: " + c);
+ if (c < 0) {
+ // existingMember dominates munger
+ checkLegalOverride(munger.getSignature(), existingMember);
+ return false;
+ } else if (c > 0) {
+ // munger dominates existingMember
+ checkLegalOverride(existingMember, munger.getSignature());
+ //interTypeMungers.add(munger);
+ //??? might need list of these overridden abstracts
+ continue;
+ } else {
+ // bridge methods can differ solely in return type.
+ // FIXME this whole method seems very hokey - unaware of covariance/varargs/bridging - it
+ // could do with a rewrite !
+ boolean sameReturnTypes = (existingMember.getReturnType().equals(sig.getReturnType()));
+ if (sameReturnTypes)
+ getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT, munger.getAspectType().getName(),
+ existingMember),
+ munger.getSourceLocation())
+ );
+ }
+ } else if (isDuplicateMemberWithinTargetType(existingMember, this, sig)) {
+ getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_MEMBER_CONFLICT, munger.getAspectType().getName(),
+ existingMember),
+ munger.getSourceLocation())
+ );
+ ;
+ }
+ //return;
+ }
+ }
+ return true;
+ }
+
+ // we know that the member signature matches, but that the member in the target type is not visible to the aspect.
+ // this may still be disallowed if it would result in two members within the same declaring type with the same
+ // signature AND more than one of them is concrete AND they are both visible within the target type.
+ private boolean isDuplicateMemberWithinTargetType(ResolvedMember existingMember, ResolvedType targetType, ResolvedMember itdMember) {
+ if ((existingMember.isAbstract() || itdMember.isAbstract())) return false;
+ UnresolvedType declaringType = existingMember.getDeclaringType();
+ if (!targetType.equals(declaringType)) return false;
+ // now have to test that itdMember is visible from targetType
+ if (itdMember.isPrivate()) return false;
+ if (itdMember.isPublic()) return true;
+ // must be in same package to be visible then...
+ if (!targetType.getPackageName().equals(itdMember.getDeclaringType().getPackageName())) return false;
+
+ // trying to put two members with the same signature into the exact same type..., and both visible in that type.
+ return true;
+ }
+
+ /**
+ * @return true if the override is legal
+ * note: calling showMessage with two locations issues TWO messages, not ONE message
+ * with an additional source location.
+ */
+ public boolean checkLegalOverride(ResolvedMember parent, ResolvedMember child) {
+ //System.err.println("check: " + child.getDeclaringType() + " overrides " + parent.getDeclaringType());
+ if (Modifier.isFinal(parent.getModifiers())) {
+ world.showMessage(Message.ERROR,
+ WeaverMessages.format(WeaverMessages.CANT_OVERRIDE_FINAL_MEMBER, parent),
+ child.getSourceLocation(), null);
+ return false;
+ }
+
+ boolean incompatibleReturnTypes = false;
+
+ // In 1.5 mode, allow for covariance on return type
+ if (world.isInJava5Mode() && parent.getKind() == Member.METHOD) {
+ ResolvedType rtParentReturnType = parent.getReturnType().resolve(world);
+ ResolvedType rtChildReturnType = child.getReturnType().resolve(world);
+ incompatibleReturnTypes = !rtParentReturnType.isAssignableFrom(rtChildReturnType);
+ } else {
+ incompatibleReturnTypes = !parent.getReturnType().equals(child.getReturnType());
+ }
+
+ if (incompatibleReturnTypes) {
+ world.showMessage(IMessage.ERROR,
+ WeaverMessages.format(WeaverMessages.ITD_RETURN_TYPE_MISMATCH, parent, child),
+ child.getSourceLocation(), parent.getSourceLocation());
+ return false;
+ }
+ if (parent.getKind() == Member.POINTCUT) {
+ UnresolvedType[] pTypes = parent.getParameterTypes();
+ UnresolvedType[] cTypes = child.getParameterTypes();
+ if (!Arrays.equals(pTypes, cTypes)) {
+ world.showMessage(IMessage.ERROR,
+ WeaverMessages.format(WeaverMessages.ITD_PARAM_TYPE_MISMATCH, parent, child),
+ child.getSourceLocation(), parent.getSourceLocation());
+ return false;
+ }
+ }
+ //System.err.println("check: " + child.getModifiers() + " more visible " + parent.getModifiers());
+ if (isMoreVisible(parent.getModifiers(), child.getModifiers())) {
+ world.showMessage(IMessage.ERROR,
+ WeaverMessages.format(WeaverMessages.ITD_VISIBILITY_REDUCTION, parent, child),
+ child.getSourceLocation(), parent.getSourceLocation());
+ return false;
+ }
+
+ // check declared exceptions
+ ResolvedType[] childExceptions = world.resolve(child.getExceptions());
+ ResolvedType[] parentExceptions = world.resolve(parent.getExceptions());
+ ResolvedType runtimeException = world.resolve("java.lang.RuntimeException");
+ ResolvedType error = world.resolve("java.lang.Error");
+
+ outer:
+ for (int i = 0, leni = childExceptions.length; i < leni; i++) {
+ //System.err.println("checking: " + childExceptions[i]);
+ if (runtimeException.isAssignableFrom(childExceptions[i])) continue;
+ if (error.isAssignableFrom(childExceptions[i])) continue;
+
+ for (int j = 0, lenj = parentExceptions.length; j < lenj; j++) {
+ if (parentExceptions[j].isAssignableFrom(childExceptions[i])) continue outer;
+ }
+
+ // this message is now better handled my MethodVerifier in JDT core.
// world.showMessage(IMessage.ERROR,
// WeaverMessages.format(WeaverMessages.ITD_DOESNT_THROW,childExceptions[i].getName()),
// child.getSourceLocation(), null);
-
- return false;
- }
- if (parent.isStatic() && !child.isStatic()) {
- world.showMessage(IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.ITD_OVERRIDDEN_STATIC,child,parent),
- child.getSourceLocation(),null);
- return false;
- } else if (child.isStatic() && !parent.isStatic()) {
- world.showMessage(IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.ITD_OVERIDDING_STATIC,child,parent),
- child.getSourceLocation(),null);
- return false;
- }
- return true;
-
- }
-
- private int compareMemberPrecedence(ResolvedMember m1, ResolvedMember m2) {
- //if (!m1.getReturnType().equals(m2.getReturnType())) return 0;
-
- // need to allow for the special case of 'clone' - which is like abstract but is
- // not marked abstract. The code below this next line seems to make assumptions
- // about what will have gotten through the compiler based on the normal
- // java rules. clone goes against these...
- if (m2.isProtected() && m2.isNative() && m2.getName().equals("clone")) return +1;
-
- if (Modifier.isAbstract(m1.getModifiers())) return -1;
- if (Modifier.isAbstract(m2.getModifiers())) return +1;
-
- if (m1.getDeclaringType().equals(m2.getDeclaringType())) return 0;
-
- ResolvedType t1 = m1.getDeclaringType().resolve(world);
- ResolvedType t2 = m2.getDeclaringType().resolve(world);
- if (t1.isAssignableFrom(t2)) {
- return -1;
- }
- if (t2.isAssignableFrom(t1)) {
- return +1;
- }
- return 0;
- }
-
-
- public static boolean isMoreVisible(int m1, int m2) {
- if (Modifier.isPrivate(m1)) return false;
- if (isPackage(m1)) return Modifier.isPrivate(m2);
- if (Modifier.isProtected(m1)) return /* private package */ (Modifier.isPrivate(m2) || isPackage(m2));
- if (Modifier.isPublic(m1)) return /* private package protected */ ! Modifier.isPublic(m2);
- throw new RuntimeException("bad modifier: " + m1);
- }
-
- private static boolean isPackage(int i) {
- return (0 == (i & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)));
- }
-
- private void interTypeConflictError(
- ConcreteTypeMunger m1,
- ConcreteTypeMunger m2)
- {
- //XXX this works only if we ignore separate compilation issues
- //XXX dual errors possible if (this instanceof BcelObjectType) return;
-
- //System.err.println("conflict at " + m2.getSourceLocation());
- getWorld().showMessage(IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.ITD_CONFLICT,m1.getAspectType().getName(),
- m2.getSignature(),m2.getAspectType().getName()),
- m2.getSourceLocation(), getSourceLocation());
- }
-
-
- public ResolvedMember lookupSyntheticMember(Member member) {
- //??? horribly inefficient
- //for (Iterator i =
- //System.err.println("lookup " + member + " in " + interTypeMungers);
- for (Iterator i = interTypeMungers.iterator(); i.hasNext(); ) {
- ConcreteTypeMunger m = (ConcreteTypeMunger)i.next();
- ResolvedMember ret = m.getMatchingSyntheticMember(member);
- if (ret != null) {
- //System.err.println(" found: " + ret);
- return ret;
- }
- }
-
+
+ return false;
+ }
+ if (parent.isStatic() && !child.isStatic()) {
+ world.showMessage(IMessage.ERROR,
+ WeaverMessages.format(WeaverMessages.ITD_OVERRIDDEN_STATIC, child, parent),
+ child.getSourceLocation(), null);
+ return false;
+ } else if (child.isStatic() && !parent.isStatic()) {
+ world.showMessage(IMessage.ERROR,
+ WeaverMessages.format(WeaverMessages.ITD_OVERIDDING_STATIC, child, parent),
+ child.getSourceLocation(), null);
+ return false;
+ }
+ return true;
+
+ }
+
+ private int compareMemberPrecedence(ResolvedMember m1, ResolvedMember m2) {
+ //if (!m1.getReturnType().equals(m2.getReturnType())) return 0;
+
+ // need to allow for the special case of 'clone' - which is like abstract but is
+ // not marked abstract. The code below this next line seems to make assumptions
+ // about what will have gotten through the compiler based on the normal
+ // java rules. clone goes against these...
+ if (m2.isProtected() && m2.isNative() && m2.getName().equals("clone")) return +1;
+
+ if (Modifier.isAbstract(m1.getModifiers())) return -1;
+ if (Modifier.isAbstract(m2.getModifiers())) return +1;
+
+ if (m1.getDeclaringType().equals(m2.getDeclaringType())) return 0;
+
+ ResolvedType t1 = m1.getDeclaringType().resolve(world);
+ ResolvedType t2 = m2.getDeclaringType().resolve(world);
+ if (t1.isAssignableFrom(t2)) {
+ return -1;
+ }
+ if (t2.isAssignableFrom(t1)) {
+ return +1;
+ }
+ return 0;
+ }
+
+
+ public static boolean isMoreVisible(int m1, int m2) {
+ if (Modifier.isPrivate(m1)) return false;
+ if (isPackage(m1)) return Modifier.isPrivate(m2);
+ if (Modifier.isProtected(m1)) return /* private package */ (Modifier.isPrivate(m2) || isPackage(m2));
+ if (Modifier.isPublic(m1)) return /* private package protected */ ! Modifier.isPublic(m2);
+ throw new RuntimeException("bad modifier: " + m1);
+ }
+
+ private static boolean isPackage(int i) {
+ return (0 == (i & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)));
+ }
+
+ private void interTypeConflictError(
+ ConcreteTypeMunger m1,
+ ConcreteTypeMunger m2) {
+ //XXX this works only if we ignore separate compilation issues
+ //XXX dual errors possible if (this instanceof BcelObjectType) return;
+
+ //System.err.println("conflict at " + m2.getSourceLocation());
+ getWorld().showMessage(IMessage.ERROR,
+ WeaverMessages.format(WeaverMessages.ITD_CONFLICT, m1.getAspectType().getName(),
+ m2.getSignature(), m2.getAspectType().getName()),
+ m2.getSourceLocation(), getSourceLocation());
+ }
+
+
+ public ResolvedMember lookupSyntheticMember(Member member) {
+ //??? horribly inefficient
+ //for (Iterator i =
+ //System.err.println("lookup " + member + " in " + interTypeMungers);
+ for (Iterator i = interTypeMungers.iterator(); i.hasNext();) {
+ ConcreteTypeMunger m = (ConcreteTypeMunger) i.next();
+ ResolvedMember ret = m.getMatchingSyntheticMember(member);
+ if (ret != null) {
+ //System.err.println(" found: " + ret);
+ return ret;
+ }
+ }
+
// if (this.getSuperclass() != ResolvedType.OBJECT && this.getSuperclass() != null) {
// return getSuperclass().lookupSyntheticMember(member);
// }
-
- return null;
- }
-
- public void clearInterTypeMungers() {
- if (isRawType()) getGenericType().clearInterTypeMungers();
- interTypeMungers = new ArrayList();
- }
-
-
- public boolean isTopmostImplementor(ResolvedType interfaceType) {
- if (isInterface()) return false;
- if (!interfaceType.isAssignableFrom(this,true)) return false;
- // check that I'm truly the topmost implementor
- if (this.getSuperclass().isMissing()) return true; // we don't know anything about supertype, and it can't be exposed to weaver
- if (interfaceType.isAssignableFrom(this.getSuperclass(),true)) {
- return false;
- }
- return true;
- }
-
- public ResolvedType getTopmostImplementor(ResolvedType interfaceType) {
- if (isInterface()) return null;
- if (!interfaceType.isAssignableFrom(this)) return null;
- // Check if my super class is an implementor?
- ResolvedType higherType = this.getSuperclass().getTopmostImplementor(interfaceType);
- if (higherType!=null) return higherType;
- return this;
- }
-
- private ResolvedType findHigher(ResolvedType other) {
- if (this == other) return this;
- for(Iterator i = other.getDirectSupertypes(); i.hasNext(); ) {
- ResolvedType rtx = (ResolvedType)i.next();
- boolean b = this.isAssignableFrom(rtx);
- if (b) return rtx;
- }
- return null;
- }
-
- public List getExposedPointcuts() {
- List ret = new ArrayList();
- if (getSuperclass() != null) ret.addAll(getSuperclass().getExposedPointcuts());
-
- for (Iterator i = Arrays.asList(getDeclaredInterfaces()).iterator(); i.hasNext(); ) {
- ResolvedType t = (ResolvedType)i.next();
- addPointcutsResolvingConflicts(ret, Arrays.asList(t.getDeclaredPointcuts()), false);
- }
- addPointcutsResolvingConflicts(ret, Arrays.asList(getDeclaredPointcuts()), true);
- for (Iterator i = ret.iterator(); i.hasNext(); ) {
- ResolvedPointcutDefinition inherited = (ResolvedPointcutDefinition)i.next();
+
+ return null;
+ }
+
+ public void clearInterTypeMungers() {
+ if (isRawType()) getGenericType().clearInterTypeMungers();
+ interTypeMungers = new ArrayList();
+ }
+
+
+ public boolean isTopmostImplementor(ResolvedType interfaceType) {
+ if (isInterface()) return false;
+ if (!interfaceType.isAssignableFrom(this, true)) return false;
+ // check that I'm truly the topmost implementor
+ if (this.getSuperclass().isMissing()) return true; // we don't know anything about supertype, and it can't be exposed to weaver
+ if (interfaceType.isAssignableFrom(this.getSuperclass(), true)) {
+ return false;
+ }
+ return true;
+ }
+
+ public ResolvedType getTopmostImplementor(ResolvedType interfaceType) {
+ if (isInterface()) return null;
+ if (!interfaceType.isAssignableFrom(this)) return null;
+ // Check if my super class is an implementor?
+ ResolvedType higherType = this.getSuperclass().getTopmostImplementor(interfaceType);
+ if (higherType != null) return higherType;
+ return this;
+ }
+
+ private ResolvedType findHigher(ResolvedType other) {
+ if (this == other) return this;
+ for (Iterator i = other.getDirectSupertypes(); i.hasNext();) {
+ ResolvedType rtx = (ResolvedType) i.next();
+ boolean b = this.isAssignableFrom(rtx);
+ if (b) return rtx;
+ }
+ return null;
+ }
+
+ public List getExposedPointcuts() {
+ List ret = new ArrayList();
+ if (getSuperclass() != null) ret.addAll(getSuperclass().getExposedPointcuts());
+
+ for (Iterator i = Arrays.asList(getDeclaredInterfaces()).iterator(); i.hasNext();) {
+ ResolvedType t = (ResolvedType) i.next();
+ addPointcutsResolvingConflicts(ret, Arrays.asList(t.getDeclaredPointcuts()), false);
+ }
+ addPointcutsResolvingConflicts(ret, Arrays.asList(getDeclaredPointcuts()), true);
+ for (Iterator i = ret.iterator(); i.hasNext();) {
+ ResolvedPointcutDefinition inherited = (ResolvedPointcutDefinition) i.next();
// System.err.println("looking at: " + inherited + " in " + this);
// System.err.println(" " + inherited.isAbstract() + " in " + this.isAbstract());
- if (inherited.isAbstract()) {
- if (!this.isAbstract()) {
- getWorld().showMessage(IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.POINCUT_NOT_CONCRETE,inherited,this.getName()),
- inherited.getSourceLocation(), this.getSourceLocation());
- }
- }
- }
-
-
- return ret;
- }
-
- private void addPointcutsResolvingConflicts(List acc, List added, boolean isOverriding) {
- for (Iterator i = added.iterator(); i.hasNext();) {
- ResolvedPointcutDefinition toAdd =
- (ResolvedPointcutDefinition) i.next();
- //System.err.println("adding: " + toAdd);
- for (Iterator j = acc.iterator(); j.hasNext();) {
- ResolvedPointcutDefinition existing =
- (ResolvedPointcutDefinition) j.next();
- if (existing == toAdd) continue;
- if (!isVisible(existing.getModifiers(),
- existing.getDeclaringType().resolve(getWorld()),
- this)) {
- continue;
- }
- if (conflictingSignature(existing, toAdd)) {
- if (isOverriding) {
- checkLegalOverride(existing, toAdd);
- j.remove();
- } else {
- getWorld().showMessage(
- IMessage.ERROR,
- WeaverMessages.format(WeaverMessages.CONFLICTING_INHERITED_POINTCUTS,this.getName() + toAdd.getSignature()),
- existing.getSourceLocation(),
- toAdd.getSourceLocation());
- j.remove();
- }
- }
- }
- acc.add(toAdd);
- }
- }
-
- public ISourceLocation getSourceLocation() { return null; }
- public boolean isExposedToWeaver() { return false; }
- public WeaverStateInfo getWeaverState() {
- return null;
- }
-
- /**
- * Overridden by ReferenceType to return a sensible answer for parameterized and raw types.
- * @return
- */
- public ResolvedType getGenericType() {
- if (!(isParameterizedType() || isRawType()))
- throw new BCException("The type "+getBaseName()+" is not parameterized or raw - it has no generic type");
- return null;
- }
-
- public ResolvedType parameterizedWith(UnresolvedType[] typeParameters) {
- if (!(isGenericType() || isParameterizedType())) return this;
- return TypeFactory.createParameterizedType(this.getGenericType(), typeParameters, getWorld());
- }
-
- /**
- * Iff I am a parameterized type, and any of my parameters are type variable
- * references, return a version with those type parameters replaced in accordance
- * with the passed bindings.
- */
- public UnresolvedType parameterize(Map typeBindings) {
- if (!isParameterizedType()) throw new IllegalStateException("Can't parameterize a type that is not a parameterized type");
- boolean workToDo = false;
- for (int i = 0; i < typeParameters.length; i++) {
- if (typeParameters[i].isTypeVariableReference()) {
- workToDo = true;
- }
- }
- if (!workToDo) {
- return this;
- } else {
- UnresolvedType[] newTypeParams = new UnresolvedType[typeParameters.length];
- for (int i = 0; i < newTypeParams.length; i++) {
- newTypeParams[i] = typeParameters[i];
- if (newTypeParams[i].isTypeVariableReference()) {
- TypeVariableReferenceType tvrt = (TypeVariableReferenceType) newTypeParams[i];
- UnresolvedType binding = (UnresolvedType) typeBindings.get(tvrt.getTypeVariable().getName());
- if (binding != null) newTypeParams[i] = binding;
- }
- }
- return TypeFactory.createParameterizedType(getGenericType(), newTypeParams, getWorld());
- }
- }
-
- public boolean hasParameterizedSuperType() {
- getParameterizedSuperTypes();
- return parameterizedSuperTypes.length > 0;
- }
-
- public boolean hasGenericSuperType() {
- ResolvedType[] superTypes = getDeclaredInterfaces();
- for (int i = 0; i < superTypes.length; i++) {
- if (superTypes[i].isGenericType()) return true;
- }
- return false;
- }
-
- private ResolvedType[] parameterizedSuperTypes = null;
- /**
- * Similar to the above method, but accumulates the super types
- * @return
- */
- public ResolvedType[] getParameterizedSuperTypes() {
- if (parameterizedSuperTypes != null) return parameterizedSuperTypes;
- List accumulatedTypes = new ArrayList();
- accumulateParameterizedSuperTypes(this,accumulatedTypes);
- ResolvedType[] ret = new ResolvedType[accumulatedTypes.size()];
- parameterizedSuperTypes = (ResolvedType[]) accumulatedTypes.toArray(ret);
- return parameterizedSuperTypes;
- }
-
- private void accumulateParameterizedSuperTypes(ResolvedType forType, List parameterizedTypeList) {
- if (forType.isParameterizedType()) {
- parameterizedTypeList.add(forType);
- }
- if (forType.getSuperclass() != null) {
- accumulateParameterizedSuperTypes(forType.getSuperclass(), parameterizedTypeList);
- }
- ResolvedType[] interfaces = forType.getDeclaredInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- accumulateParameterizedSuperTypes(interfaces[i], parameterizedTypeList);
- }
- }
-
- /**
- * Types may have pointcuts just as they have methods and fields.
- */
- public ResolvedPointcutDefinition findPointcut(String name, World world) {
- throw new UnsupportedOperationException("Not yet implemenented");
- }
-
- /**
- * Determines if variables of this type could be assigned values of another
- * with lots of help.
- * java.lang.Object is convertable from all types.
- * A primitive type is convertable from X iff it's assignable from X.
- * A reference type is convertable from X iff it's coerceable from X.
- * In other words, X isConvertableFrom Y iff the compiler thinks that _some_ value of Y
- * could be assignable to a variable of type X without loss of precision.
- *
- * @param other the other type
- * @param world the {@link World} in which the possible assignment should be checked.
- * @return true iff variables of this type could be assigned values of other with possible conversion
- */
- public final boolean isConvertableFrom(ResolvedType other) {
+ if (inherited.isAbstract()) {
+ if (!this.isAbstract()) {
+ getWorld().showMessage(IMessage.ERROR,
+ WeaverMessages.format(WeaverMessages.POINCUT_NOT_CONCRETE, inherited, this.getName()),
+ inherited.getSourceLocation(), this.getSourceLocation());
+ }
+ }
+ }
+
+
+ return ret;
+ }
+
+ private void addPointcutsResolvingConflicts(List acc, List added, boolean isOverriding) {
+ for (Iterator i = added.iterator(); i.hasNext();) {
+ ResolvedPointcutDefinition toAdd =
+ (ResolvedPointcutDefinition) i.next();
+ //System.err.println("adding: " + toAdd);
+ for (Iterator j = acc.iterator(); j.hasNext();) {
+ ResolvedPointcutDefinition existing =
+ (ResolvedPointcutDefinition) j.next();
+ if (existing == toAdd) continue;
+ if (!isVisible(existing.getModifiers(),
+ existing.getDeclaringType().resolve(getWorld()),
+ this)) {
+ continue;
+ }
+ if (conflictingSignature(existing, toAdd)) {
+ if (isOverriding) {
+ checkLegalOverride(existing, toAdd);
+ j.remove();
+ } else {
+ getWorld().showMessage(
+ IMessage.ERROR,
+ WeaverMessages.format(WeaverMessages.CONFLICTING_INHERITED_POINTCUTS, this.getName() + toAdd.getSignature()),
+ existing.getSourceLocation(),
+ toAdd.getSourceLocation());
+ j.remove();
+ }
+ }
+ }
+ acc.add(toAdd);
+ }
+ }
+
+ public ISourceLocation getSourceLocation() {
+ return null;
+ }
+
+ public boolean isExposedToWeaver() {
+ return false;
+ }
+
+ public WeaverStateInfo getWeaverState() {
+ return null;
+ }
+
+ /**
+ * Overridden by ReferenceType to return a sensible answer for parameterized and raw types.
+ *
+ * @return
+ */
+ public ResolvedType getGenericType() {
+ if (!(isParameterizedType() || isRawType()))
+ throw new BCException("The type " + getBaseName() + " is not parameterized or raw - it has no generic type");
+ return null;
+ }
+
+ public ResolvedType parameterizedWith(UnresolvedType[] typeParameters) {
+ if (!(isGenericType() || isParameterizedType())) return this;
+ return TypeFactory.createParameterizedType(this.getGenericType(), typeParameters, getWorld());
+ }
+
+ /**
+ * Iff I am a parameterized type, and any of my parameters are type variable
+ * references, return a version with those type parameters replaced in accordance
+ * with the passed bindings.
+ */
+ public UnresolvedType parameterize(Map typeBindings) {
+ if (!isParameterizedType()) throw new IllegalStateException("Can't parameterize a type that is not a parameterized type");
+ boolean workToDo = false;
+ for (int i = 0; i < typeParameters.length; i++) {
+ if (typeParameters[i].isTypeVariableReference()) {
+ workToDo = true;
+ }
+ }
+ if (!workToDo) {
+ return this;
+ } else {
+ UnresolvedType[] newTypeParams = new UnresolvedType[typeParameters.length];
+ for (int i = 0; i < newTypeParams.length; i++) {
+ newTypeParams[i] = typeParameters[i];
+ if (newTypeParams[i].isTypeVariableReference()) {
+ TypeVariableReferenceType tvrt = (TypeVariableReferenceType) newTypeParams[i];
+ UnresolvedType binding = (UnresolvedType) typeBindings.get(tvrt.getTypeVariable().getName());
+ if (binding != null) newTypeParams[i] = binding;
+ }
+ }
+ return TypeFactory.createParameterizedType(getGenericType(), newTypeParams, getWorld());
+ }
+ }
+
+ public boolean hasParameterizedSuperType() {
+ getParameterizedSuperTypes();
+ return parameterizedSuperTypes.length > 0;
+ }
+
+ public boolean hasGenericSuperType() {
+ ResolvedType[] superTypes = getDeclaredInterfaces();
+ for (int i = 0; i < superTypes.length; i++) {
+ if (superTypes[i].isGenericType()) return true;
+ }
+ return false;
+ }
+
+ private ResolvedType[] parameterizedSuperTypes = null;
+
+ /**
+ * Similar to the above method, but accumulates the super types
+ *
+ * @return
+ */
+ public ResolvedType[] getParameterizedSuperTypes() {
+ if (parameterizedSuperTypes != null) return parameterizedSuperTypes;
+ List accumulatedTypes = new ArrayList();
+ accumulateParameterizedSuperTypes(this, accumulatedTypes);
+ ResolvedType[] ret = new ResolvedType[accumulatedTypes.size()];
+ parameterizedSuperTypes = (ResolvedType[]) accumulatedTypes.toArray(ret);
+ return parameterizedSuperTypes;
+ }
+
+ private void accumulateParameterizedSuperTypes(ResolvedType forType, List parameterizedTypeList) {
+ if (forType.isParameterizedType()) {
+ parameterizedTypeList.add(forType);
+ }
+ if (forType.getSuperclass() != null) {
+ accumulateParameterizedSuperTypes(forType.getSuperclass(), parameterizedTypeList);
+ }
+ ResolvedType[] interfaces = forType.getDeclaredInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ accumulateParameterizedSuperTypes(interfaces[i], parameterizedTypeList);
+ }
+ }
+
+ /**
+ * Types may have pointcuts just as they have methods and fields.
+ */
+ public ResolvedPointcutDefinition findPointcut(String name, World world) {
+ throw new UnsupportedOperationException("Not yet implemenented");
+ }
+
+ /**
+ * Determines if variables of this type could be assigned values of another
+ * with lots of help.
+ * java.lang.Object is convertable from all types.
+ * A primitive type is convertable from X iff it's assignable from X.
+ * A reference type is convertable from X iff it's coerceable from X.
+ * In other words, X isConvertableFrom Y iff the compiler thinks that _some_ value of Y
+ * could be assignable to a variable of type X without loss of precision.
+ *
+ * @param other the other type
+ * @param world the {@link World} in which the possible assignment should be checked.
+ * @return true iff variables of this type could be assigned values of other with possible conversion
+ */
+ public final boolean isConvertableFrom(ResolvedType other) {
// // version from TypeX
// if (this.equals(OBJECT)) return true;
// if (this.isPrimitiveType() || other.isPrimitiveType()) return this.isAssignableFrom(other);
// return this.isCoerceableFrom(other);
//
-
- // version from ResolvedTypeX
- if (this.equals(OBJECT)) return true;
- if (world.isInJava5Mode()) {
- if (this.isPrimitiveType()^other.isPrimitiveType()) { // If one is primitive and the other isnt
- if (validBoxing.contains(this.getSignature()+other.getSignature())) return true;
- }
- }
- if (this.isPrimitiveType() || other.isPrimitiveType()) return this.isAssignableFrom(other);
- return this.isCoerceableFrom(other);
- }
-
- /**
- * Determines if the variables of this type could be assigned values
- * of another type without casting. This still allows for assignment conversion
- * as per JLS 2ed 5.2. For object types, this means supertypeOrEqual(THIS, OTHER).
- *
- * @param other the other type
- * @param world the {@link World} in which the possible assignment should be checked.
- * @return true iff variables of this type could be assigned values of other without casting
- * @exception NullPointerException if other is null
- */
- public abstract boolean isAssignableFrom(ResolvedType other);
-
- public abstract boolean isAssignableFrom(ResolvedType other, boolean allowMissing);
-
- /**
- * Determines if values of another type could possibly be cast to
- * this type. The rules followed are from JLS 2ed 5.5, "Casting Conversion".
- *
- * <p> This method should be commutative, i.e., for all UnresolvedType a, b and all World w:
- *
- * <blockquote><pre>
- * a.isCoerceableFrom(b, w) == b.isCoerceableFrom(a, w)
- * </pre></blockquote>
- *
- * @param other the other type
- * @param world the {@link World} in which the possible coersion should be checked.
- * @return true iff values of other could possibly be cast to this type.
- * @exception NullPointerException if other is null.
- */
- public abstract boolean isCoerceableFrom(ResolvedType other);
-
- public boolean needsNoConversionFrom(ResolvedType o) {
- return isAssignableFrom(o);
- }
-
- /**
+
+ // version from ResolvedTypeX
+ if (this.equals(OBJECT)) return true;
+ if (world.isInJava5Mode()) {
+ if (this.isPrimitiveType() ^ other.isPrimitiveType()) { // If one is primitive and the other isnt
+ if (validBoxing.contains(this.getSignature() + other.getSignature())) return true;
+ }
+ }
+ if (this.isPrimitiveType() || other.isPrimitiveType()) return this.isAssignableFrom(other);
+ return this.isCoerceableFrom(other);
+ }
+
+ /**
+ * Determines if the variables of this type could be assigned values
+ * of another type without casting. This still allows for assignment conversion
+ * as per JLS 2ed 5.2. For object types, this means supertypeOrEqual(THIS, OTHER).
+ *
+ * @param other the other type
+ * @param world the {@link World} in which the possible assignment should be checked.
+ * @return true iff variables of this type could be assigned values of other without casting
+ * @throws NullPointerException if other is null
+ */
+ public abstract boolean isAssignableFrom(ResolvedType other);
+
+ public abstract boolean isAssignableFrom(ResolvedType other, boolean allowMissing);
+
+ /**
+ * Determines if values of another type could possibly be cast to
+ * this type. The rules followed are from JLS 2ed 5.5, "Casting Conversion".
+ * <p/>
+ * <p> This method should be commutative, i.e., for all UnresolvedType a, b and all World w:
+ * <p/>
+ * <blockquote><pre>
+ * a.isCoerceableFrom(b, w) == b.isCoerceableFrom(a, w)
+ * </pre></blockquote>
+ *
+ * @param other the other type
+ * @param world the {@link World} in which the possible coersion should be checked.
+ * @return true iff values of other could possibly be cast to this type.
+ * @throws NullPointerException if other is null.
+ */
+ public abstract boolean isCoerceableFrom(ResolvedType other);
+
+ public boolean needsNoConversionFrom(ResolvedType o) {
+ return isAssignableFrom(o);
+ }
+
+ /**
* Implemented by ReferenceTypes
*/
- public String getSignatureForAttribute() {
- throw new RuntimeException("Cannot ask this type "+this+" for a generic sig attribute");
- }
-
- private FuzzyBoolean parameterizedWithAMemberTypeVariable = FuzzyBoolean.MAYBE;
-
- /**
- * return true if the parameterization of this type includes a member type variable. Member
- * type variables occur in generic methods/ctors.
- */
- public boolean isParameterizedWithAMemberTypeVariable() {
- // MAYBE means we haven't worked it out yet...
- if (parameterizedWithAMemberTypeVariable==FuzzyBoolean.MAYBE) {
-
- // if there are no type parameters then we cant be...
- if (typeParameters==null || typeParameters.length==0) {
- parameterizedWithAMemberTypeVariable = FuzzyBoolean.NO;
- return false;
- }
-
- for (int i = 0; i < typeParameters.length; i++) {
- UnresolvedType aType = (ResolvedType)typeParameters[i];
- if (aType.isTypeVariableReference() && ((TypeVariableReference)aType).getTypeVariable().getDeclaringElementKind()==TypeVariable.METHOD) {
- parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
- return true;
- }
- if (aType.isParameterizedType()) {
- boolean b = aType.isParameterizedWithAMemberTypeVariable();
- if (b) {
- parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
- return true;
- }
- }
- if (aType.isGenericWildcard()) {
- if (aType.isExtends()) {
- boolean b = false;
- UnresolvedType upperBound = aType.getUpperBound();
- if (upperBound.isParameterizedType()) {
- b = upperBound.isParameterizedWithAMemberTypeVariable();
- } else if (upperBound.isTypeVariableReference() && ((TypeVariableReference)upperBound).getTypeVariable().getDeclaringElementKind()==TypeVariable.METHOD) {
- b = true;
- }
- if (b) {
- parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
- return true;
- }
- // FIXME asc need to check additional interface bounds
- }
- if (aType.isSuper()) {
- boolean b = false;
- UnresolvedType lowerBound = aType.getLowerBound();
- if (lowerBound.isParameterizedType()) {
- b = lowerBound.isParameterizedWithAMemberTypeVariable();
- } else if (lowerBound.isTypeVariableReference() && ((TypeVariableReference)lowerBound).getTypeVariable().getDeclaringElementKind()==TypeVariable.METHOD) {
- b = true;
- }
- if (b) {
- parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
- return true;
- }
- }
- }
- }
- parameterizedWithAMemberTypeVariable=FuzzyBoolean.NO;
- }
- return parameterizedWithAMemberTypeVariable.alwaysTrue();
- }
-
+ public String getSignatureForAttribute() {
+ throw new RuntimeException("Cannot ask this type " + this + " for a generic sig attribute");
+ }
+
+ private FuzzyBoolean parameterizedWithAMemberTypeVariable = FuzzyBoolean.MAYBE;
+
+ /**
+ * return true if the parameterization of this type includes a member type variable. Member
+ * type variables occur in generic methods/ctors.
+ */
+ public boolean isParameterizedWithAMemberTypeVariable() {
+ // MAYBE means we haven't worked it out yet...
+ if (parameterizedWithAMemberTypeVariable == FuzzyBoolean.MAYBE) {
+
+ // if there are no type parameters then we cant be...
+ if (typeParameters == null || typeParameters.length == 0) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.NO;
+ return false;
+ }
+
+ for (int i = 0; i < typeParameters.length; i++) {
+ UnresolvedType aType = (ResolvedType) typeParameters[i];
+ if (aType.isTypeVariableReference() && ((TypeVariableReference) aType).getTypeVariable().getDeclaringElementKind() == TypeVariable.METHOD) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
+ return true;
+ }
+ if (aType.isParameterizedType()) {
+ boolean b = aType.isParameterizedWithAMemberTypeVariable();
+ if (b) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
+ return true;
+ }
+ }
+ if (aType.isGenericWildcard()) {
+ if (aType.isExtends()) {
+ boolean b = false;
+ UnresolvedType upperBound = aType.getUpperBound();
+ if (upperBound.isParameterizedType()) {
+ b = upperBound.isParameterizedWithAMemberTypeVariable();
+ } else if (upperBound.isTypeVariableReference() && ((TypeVariableReference) upperBound).getTypeVariable().getDeclaringElementKind() == TypeVariable.METHOD) {
+ b = true;
+ }
+ if (b) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
+ return true;
+ }
+ // FIXME asc need to check additional interface bounds
+ }
+ if (aType.isSuper()) {
+ boolean b = false;
+ UnresolvedType lowerBound = aType.getLowerBound();
+ if (lowerBound.isParameterizedType()) {
+ b = lowerBound.isParameterizedWithAMemberTypeVariable();
+ } else if (lowerBound.isTypeVariableReference() && ((TypeVariableReference) lowerBound).getTypeVariable().getDeclaringElementKind() == TypeVariable.METHOD) {
+ b = true;
+ }
+ if (b) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
+ return true;
+ }
+ }
+ }
+ }
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.NO;
+ }
+ return parameterizedWithAMemberTypeVariable.alwaysTrue();
+ }
+
}