@@ -118,17 +118,17 @@ public final class Iterators { | |||
}; | |||
} | |||
public static class ArrayIterator implements Iterator<ResolvedType> { | |||
public static class ResolvedTypeArrayIterator implements Iterator<ResolvedType> { | |||
private ResolvedType[] array; | |||
private int index; | |||
private int len; | |||
private boolean wantGenerics; | |||
private List<String> alreadySeen; // type signatures | |||
public ArrayIterator(ResolvedType[] array, List<String> alreadySeen, boolean genericsAware) { | |||
public ResolvedTypeArrayIterator(ResolvedType[] array, List<String> alreadySeen, boolean wantGenerics) { | |||
assert array != null; | |||
this.array = array; | |||
this.wantGenerics = genericsAware; | |||
this.wantGenerics = wantGenerics; | |||
this.len = array.length; | |||
this.index = 0; | |||
this.alreadySeen = alreadySeen; | |||
@@ -138,7 +138,7 @@ public final class Iterators { | |||
private void moveToNextNewOne() { | |||
while (index < len) { | |||
ResolvedType interfaceType = array[index]; | |||
if (!wantGenerics && (interfaceType.isGenericType() || interfaceType.isParameterizedType())) { | |||
if (!wantGenerics && interfaceType.isParameterizedOrGenericType()) { | |||
interfaceType = interfaceType.getRawType(); | |||
} | |||
String signature = interfaceType.getSignature(); |
@@ -21,8 +21,10 @@ import java.util.Collections; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Queue; | |||
import java.util.Set; | |||
import org.aspectj.bridge.IMessage; | |||
@@ -30,6 +32,7 @@ import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.Message; | |||
import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.util.FuzzyBoolean; | |||
import org.aspectj.weaver.Iterators.Getter; | |||
import org.aspectj.weaver.patterns.Declare; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
@@ -306,6 +309,155 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl | |||
}, Iterators.recur(this, ifaceGetter)), methodGetter); | |||
} | |||
/** | |||
* Return an iterator over the types in this types hierarchy - starting with this type first, then all superclasses up to Object | |||
* and then all interfaces (starting with those 'nearest' this type). | |||
* | |||
* @param wantGenerics true if the caller wants full generic information | |||
* @param wantDeclaredParents true if the caller even wants those parents introduced via declare parents | |||
* @return an iterator over all types in the hierarchy of this type | |||
*/ | |||
public Iterator<ResolvedType> getHierarchy(final boolean wantGenerics, final boolean wantDeclaredParents) { | |||
final Iterators.Getter<ResolvedType, ResolvedType> interfaceGetter = new Iterators.Getter<ResolvedType, ResolvedType>() { | |||
List<String> alreadySeen = new ArrayList<String>(); // Strings are signatures (ResolvedType.getSignature()) | |||
public Iterator<ResolvedType> get(ResolvedType type) { | |||
ResolvedType[] interfaces = type.getDeclaredInterfaces(); | |||
// remove interfaces introduced by declare parents | |||
// relatively expensive but hopefully uncommon | |||
if (!wantDeclaredParents && type.hasNewParentMungers()) { | |||
// Throw away interfaces from that array if they were decp'd onto here | |||
List<Integer> forRemoval = new ArrayList<Integer>(); | |||
for (ConcreteTypeMunger munger : type.interTypeMungers) { | |||
if (munger.getMunger() != null) { | |||
ResolvedTypeMunger m = munger.getMunger(); | |||
if (m.getKind() == ResolvedTypeMunger.Parent) { | |||
ResolvedType newType = ((NewParentTypeMunger) m).getNewParent(); | |||
if (!wantGenerics && newType.isParameterizedOrGenericType()) { | |||
newType = newType.getRawType(); | |||
} | |||
for (int ii = 0; ii < interfaces.length; ii++) { | |||
ResolvedType iface = interfaces[ii]; | |||
if (!wantGenerics && iface.isParameterizedOrGenericType()) { | |||
iface = iface.getRawType(); | |||
} | |||
if (newType.getSignature().equals(iface.getSignature())) { // pr171953 | |||
forRemoval.add(ii); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
// Found some to remove from those we are going to iterate over | |||
if (forRemoval.size() > 0) { | |||
ResolvedType[] interfaces2 = new ResolvedType[interfaces.length - forRemoval.size()]; | |||
int p = 0; | |||
for (int ii = 0; ii < interfaces.length; ii++) { | |||
if (!forRemoval.contains(ii)) { | |||
interfaces2[p++] = interfaces[ii]; | |||
} | |||
} | |||
interfaces = interfaces2; | |||
} | |||
} | |||
return new Iterators.ResolvedTypeArrayIterator(interfaces, alreadySeen, wantGenerics); | |||
} | |||
}; | |||
// If this type is an interface, there are only interfaces to walk | |||
if (this.isInterface()) { | |||
return new SuperInterfaceWalker(interfaceGetter, this); | |||
} else { | |||
SuperInterfaceWalker superInterfaceWalker = new SuperInterfaceWalker(interfaceGetter); | |||
Iterator<ResolvedType> superClassesIterator = new SuperClassWalker(this, superInterfaceWalker, wantGenerics); | |||
// append() will check if the second iterator is empty before appending - but the types which the superInterfaceWalker | |||
// needs to visit are only accumulated whilst the superClassesIterator is in progress | |||
return Iterators.append1(superClassesIterator, superInterfaceWalker); | |||
} | |||
} | |||
public static class SuperClassWalker implements Iterator<ResolvedType> { | |||
private ResolvedType curr; | |||
private SuperInterfaceWalker iwalker; | |||
private boolean wantGenerics; | |||
public SuperClassWalker(ResolvedType type, SuperInterfaceWalker iwalker, boolean genericsAware) { | |||
this.curr = type; | |||
this.iwalker = iwalker; | |||
this.wantGenerics = genericsAware; | |||
} | |||
public boolean hasNext() { | |||
return curr != null; | |||
} | |||
public ResolvedType next() { | |||
ResolvedType ret = curr; | |||
if (!wantGenerics && ret.isParameterizedOrGenericType()) { | |||
ret = ret.getRawType(); | |||
} | |||
iwalker.push(ret); // tell the interface walker about another class whose interfaces need visiting | |||
curr = curr.getSuperclass(); | |||
return ret; | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
} | |||
static class SuperInterfaceWalker implements Iterator<ResolvedType> { | |||
private Getter<ResolvedType, ResolvedType> ifaceGetter; | |||
Iterator<ResolvedType> delegate = null; | |||
public Queue<ResolvedType> toPersue = new LinkedList<ResolvedType>(); | |||
public Set<ResolvedType> visited = new HashSet<ResolvedType>(); | |||
SuperInterfaceWalker(Iterators.Getter<ResolvedType, ResolvedType> ifaceGetter) { | |||
this.ifaceGetter = ifaceGetter; | |||
} | |||
SuperInterfaceWalker(Iterators.Getter<ResolvedType, ResolvedType> ifaceGetter, ResolvedType interfaceType) { | |||
this.ifaceGetter = ifaceGetter; | |||
this.delegate = Iterators.one(interfaceType); | |||
} | |||
public boolean hasNext() { | |||
if (delegate == null || !delegate.hasNext()) { | |||
// either we set it up or we have run out, is there anything else to look at? | |||
if (toPersue.isEmpty()) { | |||
return false; | |||
} | |||
do { | |||
ResolvedType next = toPersue.remove(); | |||
visited.add(next); | |||
delegate = ifaceGetter.get(next); // retrieve interfaces from a class or another interface | |||
} while (!delegate.hasNext() && !toPersue.isEmpty()); | |||
} | |||
return delegate.hasNext(); | |||
} | |||
public void push(ResolvedType ret) { | |||
toPersue.add(ret); | |||
} | |||
public ResolvedType next() { | |||
ResolvedType next = delegate.next(); | |||
if (!visited.contains(next)) { | |||
visited.add(next); | |||
toPersue.add(next); // pushes on interfaces already visited? | |||
} | |||
return next; | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
} | |||
/** | |||
* 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) |
@@ -168,6 +168,10 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { | |||
return typeKind == TypeKind.PARAMETERIZED; | |||
} | |||
public boolean isParameterizedOrGenericType() { | |||
return typeKind == TypeKind.GENERIC || typeKind == TypeKind.PARAMETERIZED; | |||
} | |||
public boolean isTypeVariableReference() { | |||
return typeKind == TypeKind.TYPE_VARIABLE; | |||
} |
@@ -12,6 +12,7 @@ package org.aspectj.weaver.patterns; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.HashMap; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import java.util.Set; | |||
@@ -75,7 +76,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
return annotationType; | |||
} | |||
public Map getAnnotationValues() { | |||
public Map<String, String> getAnnotationValues() { | |||
return annotationValues; | |||
} | |||
@@ -99,7 +100,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) { | |||
if (!isForParameterAnnotationMatch()) { | |||
boolean checkSupers = false; | |||
if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) { | |||
if (getResolvedAnnotationType().isInheritedAnnotation()) { | |||
if (annotated instanceof ResolvedType) { | |||
checkSupers = true; | |||
} | |||
@@ -220,7 +221,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
// this version should be called for @this, @target, @args | |||
public FuzzyBoolean matchesRuntimeType(AnnotatedElement annotated) { | |||
if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) { | |||
if (getResolvedAnnotationType().isInheritedAnnotation()) { | |||
// a static match is good enough | |||
if (matches(annotated).alwaysTrue()) { | |||
return FuzzyBoolean.YES; | |||
@@ -234,8 +235,8 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
public void resolve(World world) { | |||
if (!resolved) { | |||
annotationType = annotationType.resolve(world); | |||
resolved = true; | |||
} | |||
resolved = true; | |||
} | |||
/* | |||
@@ -360,8 +361,9 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
s.writeInt(0); | |||
} else { | |||
s.writeInt(annotationValues.size()); | |||
Set<String> keys = annotationValues.keySet(); | |||
for (String k : keys) { | |||
Set<String> key = annotationValues.keySet(); | |||
for (Iterator<String> keys = key.iterator(); keys.hasNext();) { | |||
String k = keys.next(); | |||
s.writeUTF(k); | |||
s.writeUTF(annotationValues.get(k)); | |||
} |
@@ -32,6 +32,8 @@ import org.aspectj.weaver.World; | |||
public class ExactTypePattern extends TypePattern { | |||
protected UnresolvedType type; | |||
protected transient ResolvedType resolvedType; | |||
public boolean checked = false; | |||
public boolean isVoid = false; | |||
public static final Map<String, Class<?>> primitiveTypesMap; | |||
public static final Map<String, Class<?>> boxedPrimitivesMap; | |||
@@ -176,6 +178,15 @@ public class ExactTypePattern extends TypePattern { | |||
return resolvedType; | |||
} | |||
@Override | |||
public boolean isVoid() { | |||
if (!checked) { | |||
isVoid = this.type.getSignature().equals("V"); | |||
checked = true; | |||
} | |||
return isVoid; | |||
} | |||
// true if (matchType instanceof this.type) | |||
@Override | |||
public FuzzyBoolean matchesInstanceof(ResolvedType matchType) { |
@@ -90,9 +90,9 @@ public class HasMemberTypePattern extends TypePattern { | |||
} | |||
} | |||
// try itds before we give up | |||
List mungers = type.getInterTypeMungersIncludingSupers(); | |||
for (Iterator iter = mungers.iterator(); iter.hasNext();) { | |||
ConcreteTypeMunger munger = (ConcreteTypeMunger) iter.next(); | |||
List<ConcreteTypeMunger> mungers = type.getInterTypeMungersIncludingSupers(); | |||
for (Iterator<ConcreteTypeMunger> iter = mungers.iterator(); iter.hasNext();) { | |||
ConcreteTypeMunger munger = iter.next(); | |||
Member member = munger.getSignature(); | |||
if (signaturePattern.matches(member, type.getWorld(), false)) { | |||
if (!Modifier.isPublic(member.getModifiers())) { |
@@ -101,7 +101,6 @@ public class KindedPointcut extends Pointcut { | |||
@Override | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
long time = System.nanoTime(); | |||
if (shadow.getKind() != kind) { | |||
return FuzzyBoolean.NO; | |||
} | |||
@@ -116,7 +115,6 @@ public class KindedPointcut extends Pointcut { | |||
if (!signature.matches(shadow.getMatchingSignature(), shadow.getIWorld(), this.kind == Shadow.MethodCall)) { | |||
if (kind == Shadow.MethodCall) { | |||
long t2 = System.nanoTime(); | |||
warnOnConfusingSig(shadow); | |||
// warnOnBridgeMethod(shadow); | |||
} |
@@ -601,7 +601,7 @@ public class SignaturePattern extends PatternNode { | |||
return true; | |||
} | |||
Collection declaringTypes = member.getDeclaringTypes(world); | |||
Collection<ResolvedType> declaringTypes = member.getDeclaringTypes(world); | |||
boolean checkReturnType = true; | |||
// XXX Possible enhancement? Doesn't seem to speed things up | |||
@@ -614,8 +614,7 @@ public class SignaturePattern extends PatternNode { | |||
// Sometimes that list includes types that don't explicitly declare the member we are after - | |||
// they are on the list because their supertype is on the list, that's why we use | |||
// lookupMethod rather than lookupMemberNoSupers() | |||
for (Iterator i = declaringTypes.iterator(); i.hasNext();) { | |||
ResolvedType type = (ResolvedType) i.next(); | |||
for (ResolvedType type : declaringTypes) { | |||
if (declaringType.matchesStatically(type)) { | |||
if (!checkReturnType) { | |||
return true; |