public static final ResolvedType[] EMPTY_RESOLVED_TYPE_ARRAY = new ResolvedType[0];
public static final String PARAMETERIZED_TYPE_IDENTIFIER = "P";
+ // Set during a type pattern match call - this currently used to hold the annotations
+ // that may be attached to a type when it used as a parameter
+ public ResolvedType[] temporaryAnnotationTypes;
private ResolvedType[] resolvedTypeParams;
private String binaryPath;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
/**
* Matches an annotation of a given type
}
public FuzzyBoolean matches(AnnotatedElement annotated) {
- boolean checkSupers = false;
- if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) {
- if (annotated instanceof ResolvedType) {
- checkSupers = true;
- }
- }
-
- if (annotated.hasAnnotation(annotationType)) {
- if (annotationType instanceof ReferenceType) {
- ReferenceType rt = (ReferenceType)annotationType;
- if (rt.getRetentionPolicy()!=null && rt.getRetentionPolicy().equals("SOURCE")) {
- rt.getWorld().getMessageHandler().handleMessage(
- MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,annotationType,annotated),getSourceLocation()));
- return FuzzyBoolean.NO;
+ return matches(annotated,null);
+ }
+
+ public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+ if (!isForParameterAnnotationMatch()) {
+ boolean checkSupers = false;
+ if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) {
+ if (annotated instanceof ResolvedType) {
+ checkSupers = true;
}
}
- return FuzzyBoolean.YES;
- } else if (checkSupers) {
- ResolvedType toMatchAgainst = ((ResolvedType) annotated).getSuperclass();
- while (toMatchAgainst != null) {
- if (toMatchAgainst.hasAnnotation(annotationType)) return FuzzyBoolean.YES;
- toMatchAgainst = toMatchAgainst.getSuperclass();
+
+ if (annotated.hasAnnotation(annotationType)) {
+ if (annotationType instanceof ReferenceType) {
+ ReferenceType rt = (ReferenceType)annotationType;
+ if (rt.getRetentionPolicy()!=null && rt.getRetentionPolicy().equals("SOURCE")) {
+ rt.getWorld().getMessageHandler().handleMessage(
+ MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,annotationType,annotated),getSourceLocation()));
+ return FuzzyBoolean.NO;
+ }
+ }
+ return FuzzyBoolean.YES;
+ } else if (checkSupers) {
+ ResolvedType toMatchAgainst = ((ResolvedType) annotated).getSuperclass();
+ while (toMatchAgainst != null) {
+ if (toMatchAgainst.hasAnnotation(annotationType)) {
+ return FuzzyBoolean.YES;
+ }
+ toMatchAgainst = toMatchAgainst.getSuperclass();
+ }
+ }
+ } else {
+ // check parameter annotations
+ if (parameterAnnotations==null) return FuzzyBoolean.NO;
+ for (int i = 0; i < parameterAnnotations.length; i++) {
+ if (annotationType.equals(parameterAnnotations[i])) {
+ return FuzzyBoolean.YES;
+ }
}
- }
+ }
+
+
return FuzzyBoolean.NO;
}
binding.copyLocationFrom(this);
bindings.register(binding, scope);
binding.resolveBinding(scope.getWorld());
+ if (isForParameterAnnotationMatch()) binding.setForParameterAnnotationMatch();
return binding;
}
ret.formalName = formalName;
ret.bindingPattern = bindingPattern;
ret.copyLocationFrom(this);
+ if (isForParameterAnnotationMatch()) ret.setForParameterAnnotationMatch();
return ret;
}
annotationType.write(s);
}
writeLocation(s);
+ s.writeBoolean(isForParameterAnnotationMatch());
}
public static AnnotationTypePattern read(VersionedDataInputStream s,ISourceContext context) throws IOException {
ret = new ExactAnnotationTypePattern(UnresolvedType.read(s));
}
ret.readLocation(context,s);
+ if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MINOR_AJ160) {
+ if (s.readBoolean()) ret.setForParameterAnnotationMatch();
+ }
return ret;
}
public boolean equals(Object obj) {
if (!(obj instanceof ExactAnnotationTypePattern)) return false;
ExactAnnotationTypePattern other = (ExactAnnotationTypePattern) obj;
- return (other.annotationType.equals(annotationType));
+ return (other.annotationType.equals(annotationType)) && isForParameterAnnotationMatch()==other.isForParameterAnnotationMatch();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
- return annotationType.hashCode();
+ return annotationType.hashCode()*37+(isForParameterAnnotationMatch()?0:1);
}
public String toString() {
/** extension handlers used in weaver tools API only */
private Set pointcutDesignatorHandlers = Collections.EMPTY_SET;
private ReflectionWorld world;
+
+ private AnnotationTypePattern[] parameterAnnotationTypePatterns;
/**
* Constructor for PatternParser.
*/
eat(":");
allowHasTypePatterns = true;
- TypePattern p = parseTypePattern(false);
+ TypePattern p = parseTypePattern(false,false);
allowHasTypePatterns = false;
IToken t = tokenSource.next();
if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
AnnotationTypePattern.ANY));
} else if (kind.equals("handler")) {
eat("(");
- TypePattern typePat = parseTypePattern(false);
+ TypePattern typePat = parseTypePattern(false,false);
eat(")");
p = new HandlerPointcut(typePat);
} else if (kind.equals("lock") || kind.equals("unlock")) {
p = new KindedPointcut(Shadow.Initialization, sig);
} else if (kind.equals("staticinitialization")) {
eat("(");
- TypePattern typePat = parseTypePattern(false);
+ TypePattern typePat = parseTypePattern(false,false);
eat(")");
p = new KindedPointcut(Shadow.StaticInitialization,
new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY,
*/
private Pointcut parseArgsPointcut() {
//parseIdentifier();
- TypePatternList arguments = parseArgumentsPattern();
+ TypePatternList arguments = parseArgumentsPattern(false);
return new ArgsPointcut(arguments);
}
throw new ParserException("(",tokenSource.peek(-1));
}
- TypePatternList arguments = parseArgumentsPattern();
+ TypePatternList arguments = parseArgumentsPattern(false);
return new ReferencePointcut(onType, simpleName, arguments);
}
}
public TypePattern parseTypePattern() {
- return parseTypePattern(false);
+ return parseTypePattern(false,false);
}
- public TypePattern parseTypePattern(boolean insideTypeParameters) {
- TypePattern p = parseAtomicTypePattern(insideTypeParameters);
+ public TypePattern parseTypePattern(boolean insideTypeParameters,boolean parameterAnnotationsPossible) {
+ TypePattern p = parseAtomicTypePattern(insideTypeParameters,parameterAnnotationsPossible);
if (maybeEat("&&")) {
- p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters));
+ p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters,parameterAnnotationsPossible));
}
if (maybeEat("||")) {
- p = new OrTypePattern(p, parseTypePattern(insideTypeParameters));
+ p = new OrTypePattern(p, parseTypePattern(insideTypeParameters,parameterAnnotationsPossible));
}
return p;
}
- private TypePattern parseNotOrTypePattern(boolean insideTypeParameters) {
- TypePattern p = parseAtomicTypePattern(insideTypeParameters);
+ private TypePattern parseNotOrTypePattern(boolean insideTypeParameters,boolean parameterAnnotationsPossible) {
+ TypePattern p = parseAtomicTypePattern(insideTypeParameters,parameterAnnotationsPossible);
if (maybeEat("&&")) {
- p = new AndTypePattern(p, parseTypePattern(insideTypeParameters));
+ p = new AndTypePattern(p, parseTypePattern(insideTypeParameters,parameterAnnotationsPossible));
}
return p;
}
- private TypePattern parseAtomicTypePattern(boolean insideTypeParameters) {
- AnnotationTypePattern ap = maybeParseAnnotationPattern();
+
+ // Need to differentiate in here between two kinds of annotation pattern - depending on where the ( is
+
+ private TypePattern parseAtomicTypePattern(boolean insideTypeParameters,boolean parameterAnnotationsPossible) {
+ AnnotationTypePattern ap = maybeParseAnnotationPattern(); // might be parameter annotation pattern or type annotation pattern
if (maybeEat("!")) {
//int startPos = tokenSource.peek(-1).getStart();
//??? we lose source location for true start of !type
- TypePattern p = new NotTypePattern(parseAtomicTypePattern(insideTypeParameters));
- p = setAnnotationPatternForTypePattern(p,ap);
+ TypePattern p = new NotTypePattern(parseAtomicTypePattern(insideTypeParameters,parameterAnnotationsPossible));
+ p = setAnnotationPatternForTypePattern(p,ap,false);
return p;
}
if (maybeEat("(")) {
- TypePattern p = parseTypePattern(insideTypeParameters);
- p = setAnnotationPatternForTypePattern(p,ap);
+ TypePattern p = parseTypePattern(insideTypeParameters,false);
+ p = setAnnotationPatternForTypePattern(p,ap,parameterAnnotationsPossible);
eat(")");
boolean isVarArgs = maybeEat("...");
if (isVarArgs) p.setIsVarArgs(isVarArgs);
int startPos = tokenSource.peek().getStart();
TypePattern p = parseSingleTypePattern(insideTypeParameters);
int endPos = tokenSource.peek(-1).getEnd();
- p = setAnnotationPatternForTypePattern(p,ap);
+ p = setAnnotationPatternForTypePattern(p,ap,false);
p.setLocation(sourceContext, startPos, endPos);
return p;
}
- private TypePattern setAnnotationPatternForTypePattern(TypePattern t, AnnotationTypePattern ap) {
+
+ private TypePattern setAnnotationPatternForTypePattern(TypePattern t, AnnotationTypePattern ap,boolean parameterAnnotationsPattern) {
TypePattern ret = t;
+ if (parameterAnnotationsPattern) ap.setForParameterAnnotationMatch();
if (ap != AnnotationTypePattern.ANY) {
if (t == TypePattern.ANY) {
ret = new WildTypePattern(new NamePattern[] {NamePattern.ANY},false,0,false,null);
TypePattern[] additionalInterfaceBounds = new TypePattern[0];
TypePattern lowerBound = null;
if (maybeEatIdentifier("extends")) {
- upperBound = parseTypePattern(false);
+ upperBound = parseTypePattern(false,false);
additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
}
if (maybeEatIdentifier("super")) {
- lowerBound = parseTypePattern(false);
+ lowerBound = parseTypePattern(false,false);
}
int endPos = tokenSource.peek(-1).getEnd();
return new WildTypePattern(names,false,0,endPos,false,null,upperBound,additionalInterfaceBounds,lowerBound);
}
}
- public TypePatternList parseArgumentsPattern() {
+ public TypePatternList parseArgumentsPattern(boolean parameterAnnotationsPossible) {
List patterns = new ArrayList();
eat("(");
+
+ // ()
if (maybeEat(")")) {
return new TypePatternList();
}
do {
- if (maybeEat(".")) {
+ if (maybeEat(".")) { // ..
eat(".");
patterns.add(TypePattern.ELLIPSIS);
- } else {
- patterns.add(parseTypePattern());
+ } else {
+ patterns.add(parseTypePattern(false,parameterAnnotationsPossible));
}
} while (maybeEat(","));
eat(")");
int startPos = tokenSource.peek().getStart();
AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
ModifiersPattern modifiers = parseModifiersPattern();
- TypePattern returnType = parseTypePattern(false);
+ TypePattern returnType = parseTypePattern(false,false);
TypePattern declaringType;
NamePattern name = null;
} else {
kind = Member.METHOD;
IToken nameToken = tokenSource.peek();
- declaringType = parseTypePattern(false);
+ declaringType = parseTypePattern(false,false);
if (maybeEat(".")) {
nameToken = tokenSource.peek();
name = parseNamePattern();
}
}
- TypePatternList parameterTypes = parseArgumentsPattern();
-
+ TypePatternList parameterTypes = parseArgumentsPattern(true);
+
ThrowsPattern throwsPattern = parseOptionalThrowsPattern();
SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes, throwsPattern, annotationPattern);
int endPos = tokenSource.peek(-1).getEnd();
if (!maybeEat("<")) return null;
List typePats = new ArrayList();
do {
- TypePattern tp = parseTypePattern(true);
+ TypePattern tp = parseTypePattern(true,false);
typePats.add(tp);
} while(maybeEat(","));
eat(">");
protected boolean matchesExactly(ResolvedType type) {
annotationPattern.resolve(type.getWorld());
- return annotationPattern.matches(type).alwaysTrue();
+ boolean b = false;
+ if (type.temporaryAnnotationTypes!=null) {
+ b = annotationPattern.matches(type,type.temporaryAnnotationTypes).alwaysTrue();
+ } else {
+ b = annotationPattern.matches(type).alwaysTrue();
+ }
+ return b;
}
+
protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
annotationPattern.resolve(type.getWorld());
return annotationPattern.matches(annotatedType).alwaysTrue();
return (size() -ellipsisCount) <= numParams;
}
}
+ public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind) {
+ return matches(types,kind,null);
+ }
//XXX shares much code with WildTypePattern and with NamePattern
/**
*
* This method will never return FuzzyBoolean.NEVER
*/
- public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind) {
+ public FuzzyBoolean matches(ResolvedType[] types, TypePattern.MatchKind kind, ResolvedType[][] parameterAnnotations) {
int nameLength = types.length;
int patternLength = typePatterns.length;
if (nameLength != patternLength) return FuzzyBoolean.NO;
FuzzyBoolean finalReturn = FuzzyBoolean.YES;
while (patternIndex < patternLength) {
- FuzzyBoolean ret = typePatterns[patternIndex++].matches(types[nameIndex++], kind);
+ ResolvedType t = types[nameIndex];
+ FuzzyBoolean ret = null;
+ try {
+ if (parameterAnnotations!=null) t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
+ ret = typePatterns[patternIndex].matches(t,kind);
+ } finally {
+ t.temporaryAnnotationTypes=null;
+ }
+ patternIndex++;
+ nameIndex++;
if (ret == FuzzyBoolean.NO) return ret;
if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
}
if (p == TypePattern.ELLIPSIS) {
nameIndex = nameLength - (patternLength-patternIndex);
} else {
- FuzzyBoolean ret = p.matches(types[nameIndex++], kind);
+ ResolvedType t = types[nameIndex];
+ FuzzyBoolean ret = null;
+ try {
+ if (parameterAnnotations!=null) t.temporaryAnnotationTypes = parameterAnnotations[nameIndex];
+ ret = p.matches(t, kind);
+ } finally {
+ t.temporaryAnnotationTypes=null;
+ }
+ nameIndex++;
if (ret == FuzzyBoolean.NO) return ret;
if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
}
return matchesExactlyByName(targetTypeName,type.isAnonymous(),type.isNested()) &&
matchesParameters(type,STATIC) &&
- matchesBounds(type,STATIC) &&
- annotationPattern.matches(annotatedType).alwaysTrue();
+ matchesBounds(type,STATIC) &&
+ annotationPattern.matches(annotatedType,type.temporaryAnnotationTypes).alwaysTrue();
}
if (dim == 0 && !isVarArgs && upperBound == null && lowerBound == null && (additionalInterfaceBounds == null || additionalInterfaceBounds.length==0)) { // pr72531
return TypePattern.ANY; //??? loses source location
}
- } else {
+ } else if (!isVarArgs){
annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annotationPattern);
ret.setLocation(sourceContext,start,end);
public void testParseAnythingTypeVariable() {
PatternParser parser = new PatternParser("?");
- WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true);
+ WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true,false);
assertEquals("Expected type variable ?","?",tp.maybeGetSimpleName());
}
public void testParseAnythingExtendsTypeVariable() {
PatternParser parser = new PatternParser("? extends Number");
- WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true);
+ WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true,false);
assertEquals("Expected type variable ?","?",tp.maybeGetSimpleName());
assertEquals("upper Bound of Number",new PatternParser("Number").parseTypePattern(),tp.getUpperBound());
}
public void testParseAnythingSuperTypeVariable() {
PatternParser parser = new PatternParser("? super Number+");
- WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true);
+ WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true,false);
assertEquals("Expected type variable ?","?",tp.maybeGetSimpleName());
assertEquals("lower Bound of Number+",new PatternParser("Number+").parseTypePattern(),tp.getLowerBound());
}
public void testParameterizedTypePatternsAny() {
try {
PatternParser parser = new PatternParser("*<T,S extends Number>");
- WildTypePattern wtp = (WildTypePattern) parser.parseTypePattern(false);
+ WildTypePattern wtp = (WildTypePattern) parser.parseTypePattern(false,false);
// TypePatternList tvs = wtp.getTypeParameters();
// assertEquals("2 type parameters",2,tvs.getTypePatterns().length);
// assertEquals("T",new PatternParser("T").parseTypePattern(),tvs.getTypePatterns()[0]);
public void testTypeParamList() {
PatternParser parser = new PatternParser("Bar<T,S extends T, R extends S>");
try {
- TypePattern tp = parser.parseTypePattern(false);
+ TypePattern tp = parser.parseTypePattern(false,false);
// TypePattern[] tps = tp.getTypeParameters().getTypePatterns();
// assertEquals("3 type patterns",3,tps.length);
// assertEquals("T",tps[0].toString());
}
private TypePatternList makeArgumentsPattern(String pattern) {
- return new PatternParser(pattern).parseArgumentsPattern();
+ return new PatternParser(pattern).parseArgumentsPattern(false);
}
private void checkStaticMatch(String pattern, String[] names,