summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Clement2016-12-02 13:32:17 -0500
committerAndy Clement2016-12-02 13:32:17 -0500
commitd10618d25a9e995ffeb8080b3b9468ad241a163c (patch)
treee6d7392533635926c055048deb040e778fe92e20
parentb6f2b6337fbaf95b78c20862cd90f0e027509531 (diff)
downloadorg.aspectj-paramAnnotationBinding.tar.gz
org.aspectj-paramAnnotationBinding.tar.xz
org.aspectj-paramAnnotationBinding.zip
259416: preliminary workparamAnnotationBinding
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/Member.java2
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java5
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java2
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java66
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java30
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java15
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java2
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java12
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java18
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java39
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java19
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/reflect/StandardShadow.java8
-rw-r--r--tests/bugs1810/259416/Caveats0
-rw-r--r--tests/bugs1810/259416/ColouredAnnotation.classbin0 -> 315 bytes
-rw-r--r--tests/bugs1810/259416/ColouredAnnotation.java6
-rw-r--r--tests/bugs1810/259416/Creating0
-rw-r--r--tests/bugs1810/259416/Downloading0
-rw-r--r--tests/bugs1810/259416/Filler.java5
-rw-r--r--tests/bugs1810/259416/RGB.classbin0 -> 898 bytes
-rw-r--r--tests/bugs1810/259416/RGB.java3
-rw-r--r--tests/bugs1810/259416/Tapping0
-rw-r--r--tests/bugs1810/259416/Test1.java13
-rw-r--r--tests/bugs1810/259416/Test2.java13
-rw-r--r--tests/bugs1810/259416/Test3.java13
-rw-r--r--tests/bugs1810/259416/Test4.java13
-rw-r--r--tests/src/org/aspectj/systemtest/ajc1810/Ajc1810Tests.java36
-rw-r--r--tests/src/org/aspectj/systemtest/ajc1810/ajc1810.xml45
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelShadow.java64
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/ParamAnnotationAccessVar.java206
-rw-r--r--weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java71
-rw-r--r--weaver5/java5-src/org/aspectj/weaver/reflect/ReflectiveAnnotationAJ.java103
-rw-r--r--weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java54
32 files changed, 809 insertions, 54 deletions
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Member.java b/org.aspectj.matcher/src/org/aspectj/weaver/Member.java
index 8134e8df2..f3a11ff9b 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/Member.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/Member.java
@@ -78,6 +78,8 @@ public interface Member extends Comparable<Member> {
*/
public boolean canBeParameterized();
+ public AnnotationAJ[][] getParameterAnnotations();
+
public AnnotationAJ[] getAnnotations();
public Collection<ResolvedType> getDeclaringTypes(World world);
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java
index fbf497ed2..89e0e39e1 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java
@@ -506,6 +506,11 @@ public class MemberImpl implements Member {
}
return resolved.getParameterNames();
}
+
+ public AnnotationAJ[][] getParameterAnnotations() {
+ throw new UnsupportedOperationException("You should resolve this member '" + this
+ + "' and call getParameterAnnotations() on the result...");
+ }
/**
* All the signatures that a join point with this member as its signature has.
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java b/org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java
index 587d19c15..07c62aaa6 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java
@@ -236,6 +236,8 @@ public abstract class Shadow {
public abstract Var getArgAnnotationVar(int i, UnresolvedType forAnnotationType);
+ public abstract Var getArgParamAnnotationVar(int i, UnresolvedType forAnnotationType);
+
public abstract Member getEnclosingCodeSignature();
/**
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java
index 0b93b48d1..af8827202 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java
@@ -14,10 +14,12 @@ import java.util.List;
import java.util.Map;
import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AnnotationAJ;
import org.aspectj.weaver.CompressingDataOutputStream;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
@@ -72,10 +74,11 @@ public class AnnotationPatternList extends PatternNode {
typePatterns[i].resolve(inWorld);
}
}
-
- public FuzzyBoolean matches(ResolvedType[] someArgs) {
+
+ public FuzzyBoolean matches(ResolvedType[] parameterTypes, Shadow shadow) {
+ ResolvedType[][] paramAnnotationTypes = null;
// do some quick length tests first
- int numArgsMatchedByEllipsis = (someArgs.length + ellipsisCount) - typePatterns.length;
+ int numArgsMatchedByEllipsis = (parameterTypes.length + ellipsisCount) - typePatterns.length;
if (numArgsMatchedByEllipsis < 0) {
return FuzzyBoolean.NO;
}
@@ -91,14 +94,26 @@ public class AnnotationPatternList extends PatternNode {
argsIndex += numArgsMatchedByEllipsis;
} else if (typePatterns[i] == AnnotationTypePattern.ANY) {
argsIndex++;
+ } else if (typePatterns[i].isForParameterAnnotationMatch()) {
+ if (paramAnnotationTypes == null) {
+ paramAnnotationTypes = shadow.getResolvedSignature().getParameterAnnotationTypes();
+ }
+ ExactAnnotationTypePattern ap = (ExactAnnotationTypePattern) typePatterns[i];
+ FuzzyBoolean matches = ap.matches(null, paramAnnotationTypes.length==0?ResolvedType.NONE:paramAnnotationTypes[argsIndex]);
+ if (matches == FuzzyBoolean.NO) {
+ return FuzzyBoolean.NO;
+ } else {
+ argsIndex++;
+ ret = ret.and(matches);
+ }
} else {
// match the argument type at argsIndex with the ExactAnnotationTypePattern
// we know it is exact because nothing else is allowed in args
- if (someArgs[argsIndex].isPrimitiveType()) {
+ if (parameterTypes[argsIndex].isPrimitiveType()) {
return FuzzyBoolean.NO; // can never match
}
ExactAnnotationTypePattern ap = (ExactAnnotationTypePattern) typePatterns[i];
- FuzzyBoolean matches = ap.matchesRuntimeType(someArgs[argsIndex]);
+ FuzzyBoolean matches = ap.matchesRuntimeType(parameterTypes[argsIndex]);
if (matches == FuzzyBoolean.NO) {
return FuzzyBoolean.MAYBE; // could still match at runtime
} else {
@@ -110,6 +125,47 @@ public class AnnotationPatternList extends PatternNode {
return ret;
}
+ public FuzzyBoolean matches(ResolvedType[] someArgs) {
+ // do some quick length tests first
+ int numArgsMatchedByEllipsis = (someArgs.length + ellipsisCount) - typePatterns.length;
+ if (numArgsMatchedByEllipsis < 0) {
+ return FuzzyBoolean.NO;
+ }
+ if ((numArgsMatchedByEllipsis > 0) && (ellipsisCount == 0)) {
+ return FuzzyBoolean.NO;
+ }
+ // now work through the args and the patterns, skipping at ellipsis
+ FuzzyBoolean ret = FuzzyBoolean.YES;
+ int argsIndex = 0;
+ for (int i = 0; i < typePatterns.length; i++) {
+ if (typePatterns[i] == AnnotationTypePattern.ELLIPSIS) {
+ // match ellipsisMatchCount args
+ argsIndex += numArgsMatchedByEllipsis;
+ } else if (typePatterns[i] == AnnotationTypePattern.ANY) {
+ argsIndex++;
+ } else {
+ // match the argument type at argsIndex with the ExactAnnotationTypePattern
+ // we know it is exact because nothing else is allowed in args
+ if (someArgs[argsIndex].isPrimitiveType()) {
+ return FuzzyBoolean.NO; // can never match
+ }
+ ExactAnnotationTypePattern ap = (ExactAnnotationTypePattern) typePatterns[i];
+// if (ap.isForParameterAnnotationMatch()) {
+// ap.matches(null,)
+// } else {
+ FuzzyBoolean matches = ap.matchesRuntimeType(someArgs[argsIndex]);
+ if (matches == FuzzyBoolean.NO) {
+ return FuzzyBoolean.MAYBE; // could still match at runtime
+ } else {
+ argsIndex++;
+ ret = ret.and(matches);
+ }
+// }
+ }
+ }
+ return ret;
+ }
+
public int size() {
return typePatterns.length;
}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java
index db612b8cd..9eeaf5b2c 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java
@@ -76,15 +76,11 @@ public class ArgsAnnotationPointcut extends NameBindingPointcut {
return FuzzyBoolean.MAYBE;
}
- /*
- * (non-Javadoc)
- *
- * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
- */
protected FuzzyBoolean matchInternal(Shadow shadow) {
arguments.resolve(shadow.getIWorld());
- FuzzyBoolean ret = arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()));
- return ret;
+ FuzzyBoolean ret1 = arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()),shadow);
+// FuzzyBoolean ret2 = arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()));
+ return ret1;
}
/*
@@ -166,12 +162,22 @@ public class ArgsAnnotationPointcut extends NameBindingPointcut {
ResolvedType rAnnType = ap.getAnnotationType().resolve(shadow.getIWorld());
if (ap instanceof BindingAnnotationTypePattern) {
BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern) ap;
- Var annvar = shadow.getArgAnnotationVar(argsIndex, rAnnType);
- state.set(btp.getFormalIndex(), annvar);
+ Var v = btp.isForParameterAnnotationMatch() ?
+ shadow.getArgParamAnnotationVar(argsIndex, rAnnType) :
+ shadow.getArgAnnotationVar(argsIndex, rAnnType);
+ state.set(btp.getFormalIndex(), v);
}
- if (!ap.matches(rArgType).alwaysTrue()) {
- // we need a test...
- ret = Test.makeAnd(ret, Test.makeHasAnnotation(shadow.getArgVar(argsIndex), rAnnType));
+ if (ap.isForParameterAnnotationMatch()) {
+ if (!ap.matches(null,new ResolvedType[] {rAnnType}).alwaysTrue()) {
+ if (true) throw new IllegalStateException();
+ // need something intelligent here...
+ ret = Test.makeAnd(ret, Test.makeHasAnnotation(shadow.getArgVar(argsIndex), rAnnType));
+ }
+ } else {
+ if (!ap.matches(rAnnType).alwaysTrue()) {
+ // we need a test...
+ ret = Test.makeAnd(ret, Test.makeHasAnnotation(shadow.getArgVar(argsIndex), rAnnType));
+ }
}
argsIndex++;
}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
index 142f6155e..f8e27ad2e 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
@@ -29,9 +29,6 @@ public class BindingAnnotationTypePattern extends ExactAnnotationTypePattern imp
protected int formalIndex;
- /**
- * @param annotationType
- */
public BindingAnnotationTypePattern(UnresolvedType annotationType, int index) {
super(annotationType, null);
this.formalIndex = index;
@@ -107,12 +104,17 @@ public class BindingAnnotationTypePattern extends ExactAnnotationTypePattern imp
}
public AnnotationTypePattern remapAdviceFormals(IntMap bindings) {
+ AnnotationTypePattern atp;
if (!bindings.hasKey(formalIndex)) {
- return new ExactAnnotationTypePattern(annotationType, null);
+ atp = new ExactAnnotationTypePattern(annotationType, null);
} else {
int newFormalIndex = bindings.get(formalIndex);
- return new BindingAnnotationTypePattern(annotationType, newFormalIndex);
+ atp = new BindingAnnotationTypePattern(annotationType, newFormalIndex);
+ if (this.isForParameterAnnotationMatch()) {
+ atp.setForParameterAnnotationMatch();
+ }
}
+ return atp;
}
private static final byte VERSION = 1; // rev if serialised form changed
@@ -124,6 +126,7 @@ public class BindingAnnotationTypePattern extends ExactAnnotationTypePattern imp
annotationType.write(s);
s.writeShort((short) formalIndex);
writeLocation(s);
+ s.writeBoolean(isForParameterAnnotationMatch());
}
public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
@@ -133,6 +136,8 @@ public class BindingAnnotationTypePattern extends ExactAnnotationTypePattern imp
}
AnnotationTypePattern ret = new BindingAnnotationTypePattern(UnresolvedType.read(s), s.readShort());
ret.readLocation(context, s);
+ if (s.readBoolean())
+ ret.setForParameterAnnotationMatch();
return ret;
}
}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
index 772e8f6ca..0ee8a3369 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
@@ -43,6 +43,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
protected boolean resolved = false;
protected boolean bindingPattern = false;
private Map<String, String> annotationValues;
+ private int annotationNumber;
// OPTIMIZE is annotationtype really unresolved???? surely it is resolved by
// now...
@@ -232,6 +233,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
.error("Compiler limitation: annotation value matching for parameter annotations not yet supported"));
return FuzzyBoolean.NO;
}
+ this.annotationNumber= i;
return FuzzyBoolean.YES;
}
}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java
index 106376aad..8f3068ac1 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java
@@ -1174,9 +1174,15 @@ public class PatternParser {
p.setLocation(sourceContext, startPos, endPos);
// For optimized syntax that allows binding directly to annotation values (pr234943)
if (maybeEat("(")) {
- String formalName = parseIdentifier();
- p = new ExactAnnotationFieldTypePattern(p, formalName);
- eat(")");
+ if (maybeEat("*")) {
+ // Attempt to bind parameter annotation: @args(@SomeParamAnnotation (*),..)
+ p.setForParameterAnnotationMatch();
+ eat(")");
+ } else {
+ String formalName = parseIdentifier();
+ p = new ExactAnnotationFieldTypePattern(p, formalName);
+ eat(")");
+ }
}
return p;
}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java
index 7efeac9ae..5e1957f20 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java
@@ -1,5 +1,5 @@
/* *******************************************************************
- * Copyright (c) 2005 Contributors.
+ * Copyright (c) 2005-2016 Contributors.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
@@ -20,7 +20,10 @@ import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
/**
- * @author colyer Used in 1.4 code to access annotations safely
+ * Used in 1.4 code to access annotations safely.
+ *
+ * @author Adrian Colyer
+ * @author Andy Clement
*/
public interface AnnotationFinder {
@@ -32,14 +35,15 @@ public interface AnnotationFinder {
Object getAnnotationFromMember(ResolvedType annotationType, Member aMember);
- public AnnotationAJ getAnnotationOfType(UnresolvedType ofType,
- Member onMember);
+ AnnotationAJ getAnnotationOfType(UnresolvedType ofType, Member onMember);
- public String getAnnotationDefaultValue(Member onMember);
+ String getAnnotationDefaultValue(Member onMember);
- Object getAnnotationFromClass(ResolvedType annotationType, Class aClass);
+ Object getAnnotationFromClass(ResolvedType annotationType, Class<?> aClass);
- Set/* ResolvedType */getAnnotations(Member onMember);
+ Set<ResolvedType> getAnnotations(Member onMember);
ResolvedType[][] getParameterAnnotationTypes(Member onMember);
+
+ Object getParamAnnotation(Member subject, int argsIndex, int paramAnnoIndex);
}
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java
index 0c6277e59..4e6e0cef8 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java
@@ -28,8 +28,8 @@ import org.aspectj.weaver.ast.Var;
import org.aspectj.weaver.tools.MatchingContext;
/**
- * @author colyer
- *
+ * @author Adrian Colyer
+ * @author Andy Clement
*/
public class ReflectionShadow extends Shadow {
@@ -42,10 +42,11 @@ public class ReflectionShadow extends Shadow {
private Var[] argsVars = null;
private Var atThisVar = null;
private Var atTargetVar = null;
- private Map atArgsVars = new HashMap();
- private Map withinAnnotationVar = new HashMap();
- private Map withinCodeAnnotationVar = new HashMap();
- private Map annotationVar = new HashMap();
+ private Map<ResolvedType,Var[]> atArgsVars = new HashMap<>();
+ private Map<ResolvedType,Var[]> atArgParamVars = new HashMap<>();
+ private Map<ResolvedType,Var> withinAnnotationVar = new HashMap<>();
+ private Map<ResolvedType,Var> withinCodeAnnotationVar = new HashMap<>();
+ private Map<ResolvedType,Var> annotationVar = new HashMap<>();
private AnnotationFinder annotationFinder;
public static Shadow makeExecutionShadow(World inWorld, java.lang.reflect.Member forMethod, MatchingContext withContext) {
@@ -311,11 +312,6 @@ public class ReflectionShadow extends Shadow {
return atTargetVar;
}
- /*
- * (non-Javadoc)
- *
- * @see org.aspectj.weaver.Shadow#getArgAnnotationVar(int, org.aspectj.weaver.UnresolvedType)
- */
public Var getArgAnnotationVar(int i, UnresolvedType forAnnotationType) {
ResolvedType annType = forAnnotationType.resolve(world);
if (atArgsVars.get(annType) == null) {
@@ -330,6 +326,27 @@ public class ReflectionShadow extends Shadow {
}
return vars[i];
}
+
+ public Var getArgParamAnnotationVar(int i, UnresolvedType forAnnotationType) {
+ ResolvedType resolvedAnnotationType = forAnnotationType.resolve(world);
+ if (atArgParamVars.get(resolvedAnnotationType) == null) {
+ Var[] vars = new Var[getArgCount()];
+ atArgParamVars.put(resolvedAnnotationType, vars);
+ }
+ Var[] vars = (Var[]) atArgParamVars.get(resolvedAnnotationType);
+ if (i > (vars.length - 1))
+ return null;
+ if (vars[i] == null) {
+ ResolvedMember rm = getSignature().resolve(world);
+ ResolvedType[] paramAnnos = rm.getParameterAnnotationTypes()[i];
+ for (int j=0;j<paramAnnos.length;j++) {
+ if (paramAnnos[j].equals(resolvedAnnotationType)) {
+ vars[i] = ReflectionVar.createArgsParamAnnotationVar(resolvedAnnotationType, i, j, this.annotationFinder);
+ }
+ }
+ }
+ return vars[i];
+ }
/*
* (non-Javadoc)
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java
index 59876a737..542d36cad 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java
@@ -30,6 +30,7 @@ public final class ReflectionVar extends Var {
static final int AT_WITHIN_VAR = 6;
static final int AT_WITHINCODE_VAR = 7;
static final int AT_ANNOTATION_VAR = 8;
+ static final int AT_ARGS_PARAM_ANNO_VAR = 9;
private AnnotationFinder annotationFinder = null;
@@ -48,6 +49,7 @@ public final class ReflectionVar extends Var {
// }
private int argsIndex = 0;
+ private int paramAnnoIndex;
private int varType;
public static ReflectionVar createThisVar(ResolvedType type,AnnotationFinder finder) {
@@ -87,6 +89,14 @@ public final class ReflectionVar extends Var {
ret.argsIndex = index;
return ret;
}
+
+ public static ReflectionVar createArgsParamAnnotationVar(ResolvedType type, int index, int paramAnnoIndex, AnnotationFinder finder) {
+ ReflectionVar ret = new ReflectionVar(type,finder);
+ ret.varType = AT_ARGS_PARAM_ANNO_VAR;
+ ret.argsIndex = index;
+ ret.paramAnnoIndex = paramAnnoIndex;
+ return ret;
+ }
public static ReflectionVar createWithinAnnotationVar(ResolvedType annType, AnnotationFinder finder) {
ReflectionVar ret = new ReflectionVar(annType,finder);
@@ -106,7 +116,7 @@ public final class ReflectionVar extends Var {
return ret;
}
- private ReflectionVar(ResolvedType type,AnnotationFinder finder) {
+ private ReflectionVar(ResolvedType type, AnnotationFinder finder) {
super(type);
this.annotationFinder = finder;
}
@@ -115,9 +125,11 @@ public final class ReflectionVar extends Var {
public Object getBindingAtJoinPoint(Object thisObject, Object targetObject, Object[] args) {
return getBindingAtJoinPoint(thisObject,targetObject,args,null,null,null);
}
+
/**
* At a join point with the given this, target, and args, return the object to which this
* var is bound.
+ *
* @param thisObject
* @param targetObject
* @param args
@@ -149,6 +161,11 @@ public final class ReflectionVar extends Var {
if (annotationFinder != null) {
return annotationFinder.getAnnotation(getType(), args[argsIndex]);
} else return null;
+ case AT_ARGS_PARAM_ANNO_VAR:
+ if (this.argsIndex > (args.length - 1)) return null;
+ if (annotationFinder != null) {
+ return annotationFinder.getParamAnnotation(subject, argsIndex, paramAnnoIndex);
+ } else return null;
case AT_WITHIN_VAR:
if (annotationFinder != null) {
return annotationFinder.getAnnotationFromClass(getType(), withinType);
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/StandardShadow.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/StandardShadow.java
index c151b228e..0594a8ff6 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/StandardShadow.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/StandardShadow.java
@@ -44,10 +44,10 @@ public class StandardShadow extends Shadow {
private Var[] argsVars = null;
private Var atThisVar = null;
private Var atTargetVar = null;
- private Map atArgsVars = new HashMap();
- private Map withinAnnotationVar = new HashMap();
- private Map withinCodeAnnotationVar = new HashMap();
- private Map annotationVar = new HashMap();
+ private Map<ResolvedType,Var[]> atArgsVars = new HashMap<>();
+ private Map<ResolvedType,Var> withinAnnotationVar = new HashMap<>();
+ private Map<ResolvedType,Var> withinCodeAnnotationVar = new HashMap<>();
+ private Map<ResolvedType,Var> annotationVar = new HashMap<>();
private AnnotationFinder annotationFinder;
public static Shadow makeExecutionShadow(World inWorld, java.lang.reflect.Member forMethod, MatchingContext withContext) {
diff --git a/tests/bugs1810/259416/Caveats b/tests/bugs1810/259416/Caveats
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/bugs1810/259416/Caveats
diff --git a/tests/bugs1810/259416/ColouredAnnotation.class b/tests/bugs1810/259416/ColouredAnnotation.class
new file mode 100644
index 000000000..ff8b19572
--- /dev/null
+++ b/tests/bugs1810/259416/ColouredAnnotation.class
Binary files differ
diff --git a/tests/bugs1810/259416/ColouredAnnotation.java b/tests/bugs1810/259416/ColouredAnnotation.java
new file mode 100644
index 000000000..1886a2f03
--- /dev/null
+++ b/tests/bugs1810/259416/ColouredAnnotation.java
@@ -0,0 +1,6 @@
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ColouredAnnotation {
+ RGB value();
+}
diff --git a/tests/bugs1810/259416/Creating b/tests/bugs1810/259416/Creating
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/bugs1810/259416/Creating
diff --git a/tests/bugs1810/259416/Downloading b/tests/bugs1810/259416/Downloading
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/bugs1810/259416/Downloading
diff --git a/tests/bugs1810/259416/Filler.java b/tests/bugs1810/259416/Filler.java
new file mode 100644
index 000000000..dc5592b41
--- /dev/null
+++ b/tests/bugs1810/259416/Filler.java
@@ -0,0 +1,5 @@
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Filler {
+}
diff --git a/tests/bugs1810/259416/RGB.class b/tests/bugs1810/259416/RGB.class
new file mode 100644
index 000000000..737e3b6bb
--- /dev/null
+++ b/tests/bugs1810/259416/RGB.class
Binary files differ
diff --git a/tests/bugs1810/259416/RGB.java b/tests/bugs1810/259416/RGB.java
new file mode 100644
index 000000000..04d4e9474
--- /dev/null
+++ b/tests/bugs1810/259416/RGB.java
@@ -0,0 +1,3 @@
+public enum RGB {
+ RED, GREEN, BLUE;
+}
diff --git a/tests/bugs1810/259416/Tapping b/tests/bugs1810/259416/Tapping
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/bugs1810/259416/Tapping
diff --git a/tests/bugs1810/259416/Test1.java b/tests/bugs1810/259416/Test1.java
new file mode 100644
index 000000000..e4961f039
--- /dev/null
+++ b/tests/bugs1810/259416/Test1.java
@@ -0,0 +1,13 @@
+public class Test1 {
+ public static void main(String[] argv) {
+ coloured("abc");
+ }
+ public static void coloured(@ColouredAnnotation(RGB.RED) String param1) {}
+}
+
+aspect X {
+ // execution(@ColouredAnnotation * colouredMethod(..)) && @annotation(ColouredAnnotation(colour));
+ before(ColouredAnnotation ca): execution(* *(@ColouredAnnotation (*))) && @args(ca (*)) {
+ System.out.println("Annotation from parameter on method "+thisJoinPoint+" is "+ca);
+ }
+}
diff --git a/tests/bugs1810/259416/Test2.java b/tests/bugs1810/259416/Test2.java
new file mode 100644
index 000000000..a2a026dbc
--- /dev/null
+++ b/tests/bugs1810/259416/Test2.java
@@ -0,0 +1,13 @@
+public class Test2 {
+ public static void main(String[] argv) {
+ coloured("abc");
+ }
+ public static void coloured(@ColouredAnnotation(RGB.GREEN) String param1) {}
+}
+
+aspect X {
+ // execution(@ColouredAnnotation * colouredMethod(..)) && @annotation(ColouredAnnotation(colour));
+ before(ColouredAnnotation ca): execution(* *(..)) && @args(ca (*)) {
+ System.out.println("Annotation from parameter on method "+thisJoinPoint+" is "+ca);
+ }
+}
diff --git a/tests/bugs1810/259416/Test3.java b/tests/bugs1810/259416/Test3.java
new file mode 100644
index 000000000..49744de78
--- /dev/null
+++ b/tests/bugs1810/259416/Test3.java
@@ -0,0 +1,13 @@
+public class Test3 {
+ public static void main(String[] argv) {
+ coloured(1,"abc");
+ }
+ public static void coloured(int param1, @ColouredAnnotation(RGB.RED) String param2) {}
+}
+
+aspect X {
+ // execution(@ColouredAnnotation * colouredMethod(..)) && @annotation(ColouredAnnotation(colour));
+ before(ColouredAnnotation ca): execution(* *(..)) && @args(*, ca (*)) {
+ System.out.println("Annotation from parameter on method "+thisJoinPoint+" is "+ca);
+ }
+}
diff --git a/tests/bugs1810/259416/Test4.java b/tests/bugs1810/259416/Test4.java
new file mode 100644
index 000000000..92324f883
--- /dev/null
+++ b/tests/bugs1810/259416/Test4.java
@@ -0,0 +1,13 @@
+public class Test4 {
+ public static void main(String[] argv) {
+ coloured(1,"abc");
+ }
+ public static void coloured(int param1, @Filler @ColouredAnnotation(RGB.GREEN) String param2) {}
+}
+
+aspect X {
+ // execution(@ColouredAnnotation * colouredMethod(..)) && @annotation(ColouredAnnotation(colour));
+ before(ColouredAnnotation ca): execution(* *(..)) && @args(*, ca (*)) {
+ System.out.println("Annotation from parameter on method "+thisJoinPoint+" is "+ca);
+ }
+}
diff --git a/tests/src/org/aspectj/systemtest/ajc1810/Ajc1810Tests.java b/tests/src/org/aspectj/systemtest/ajc1810/Ajc1810Tests.java
index 3cae1378c..36232a91d 100644
--- a/tests/src/org/aspectj/systemtest/ajc1810/Ajc1810Tests.java
+++ b/tests/src/org/aspectj/systemtest/ajc1810/Ajc1810Tests.java
@@ -24,6 +24,42 @@ import junit.framework.Test;
*/
public class Ajc1810Tests extends org.aspectj.testing.XMLBasedAjcTestCase {
+ // Basic with execution(* *(@Foo (*))) && @args(ca (*))
+ public void testParamAnnoBinding_259416_1() {
+ runTest("param anno binding");
+ }
+
+ // Basic with execution(* *(..)) && args(ca (*))
+ public void testParamAnnoBinding_259416_2() {
+ runTest("param anno binding 2");
+ }
+
+ // Basic with execution(* *(..)) && args(*,ca (*))
+ public void testParamAnnoBinding_259416_3() {
+ runTest("param anno binding 3");
+ }
+
+ // Basic with execution(* *(..)) && args(*,ca (*)) where target has two parameter annotations and we match the 2nd one
+ public void testParamAnnoBinding_259416_4() {
+ runTest("param anno binding 4");
+ }
+
+ // execution(* *(..)) && args(f *,ca (*))
+
+ // args(ca1 (*),ca2 (*))
+
+ // args(ca(*))
+
+ // args(ca1 (f))
+
+ // args(ca1 ba1 (*))
+
+ // args(ca1 ba1 (f1 f2))
+
+ // args(ca1 (*), .., ca2 (*))
+
+
+
public void testBinding_500035() {
runTest("ataspectj binding");
}
diff --git a/tests/src/org/aspectj/systemtest/ajc1810/ajc1810.xml b/tests/src/org/aspectj/systemtest/ajc1810/ajc1810.xml
index 7485c1c20..75edcbc5e 100644
--- a/tests/src/org/aspectj/systemtest/ajc1810/ajc1810.xml
+++ b/tests/src/org/aspectj/systemtest/ajc1810/ajc1810.xml
@@ -2,6 +2,51 @@
<suite>
+ <ajc-test dir="bugs1810/259416" title="param anno binding">
+ <compile options="-1.8 -showWeaveInfo" files="RGB.java ColouredAnnotation.java Test1.java">
+ <message kind="weave" text="Join point 'method-execution(void Test1.coloured(java.lang.String))' in Type 'Test1' (Test1.java:5) advised by before advice from 'X' (Test1.java:10)"/>
+ </compile>
+ <run class="Test1">
+ <stdout>
+ <line text="Annotation from parameter on method execution(void Test1.coloured(String)) is @ColouredAnnotation(value=RED)"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs1810/259416" title="param anno binding 2">
+ <compile options="-1.8 -showWeaveInfo" files="RGB.java ColouredAnnotation.java Test2.java">
+ <message kind="weave" text="Join point 'method-execution(void Test2.coloured(java.lang.String))' in Type 'Test2' (Test2.java:5) advised by before advice from 'X' (Test2.java:10)"/>
+ </compile>
+ <run class="Test2">
+ <stdout>
+ <line text="Annotation from parameter on method execution(void Test2.coloured(String)) is @ColouredAnnotation(value=GREEN)"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs1810/259416" title="param anno binding 3">
+ <compile options="-1.8 -showWeaveInfo" files="RGB.java ColouredAnnotation.java Test3.java">
+ <message kind="weave" text="Join point 'method-execution(void Test3.coloured(int, java.lang.String))' in Type 'Test3' (Test3.java:5) advised by before advice from 'X' (Test3.java:10)"/>
+ </compile>
+ <run class="Test3">
+ <stdout>
+ <line text="Annotation from parameter on method execution(void Test3.coloured(int, String)) is @ColouredAnnotation(value=RED)"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs1810/259416" title="param anno binding 4">
+ <compile options="-1.8 -showWeaveInfo" files="RGB.java ColouredAnnotation.java Test4.java Filler.java">
+ <message kind="weave" text="Join point 'method-execution(void Test4.coloured(int, java.lang.String))' in Type 'Test4' (Test4.java:5) advised by before advice from 'X' (Test4.java:10)"/>
+ </compile>
+ <run class="Test4">
+ <stdout>
+ <line text="Annotation from parameter on method execution(void Test4.coloured(int, String)) is @ColouredAnnotation(value=GREEN)"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+
<ajc-test dir="bugs1810/500035" title="ataspectj binding">
<compile options="-1.8" files="Code.java"/>
<run class="Code">
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
index 10fdbd05c..914e99697 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
@@ -875,6 +875,7 @@ public class BcelShadow extends Shadow {
private BcelVar targetVar = null;
private BcelVar[] argVars = null;
private Map<ResolvedType, AnnotationAccessVar> kindedAnnotationVars = null;
+ private Map<ResolvedType,AnnotationAccessVar>[] paramAnnoVars = null;
private Map<ResolvedType, TypeAnnotationAccessVar> thisAnnotationVars = null;
private Map<ResolvedType, TypeAnnotationAccessVar> targetAnnotationVars = null;
// private Map/* <UnresolvedType,BcelVar> */[] argAnnotationVars = null;
@@ -953,6 +954,12 @@ public class BcelShadow extends Shadow {
}
@Override
+ public Var getArgParamAnnotationVar(int parameterIndex, UnresolvedType forAnnotationType) {
+ initializeKindedAnnotationVars();
+ return paramAnnoVars[parameterIndex].get(forAnnotationType);
+ }
+
+ @Override
public Var getWithinAnnotationVar(UnresolvedType forAnnotationType) {
initializeWithinAnnotationVars();
return withinAnnotationVars.get(forAnnotationType);
@@ -1538,6 +1545,41 @@ public class BcelShadow extends Shadow {
}
return foundMember.getAnnotationTypes();
}
+
+ protected ResolvedType[][] getParameterAnnotations(ResolvedMember foundMember, Member relevantMember, ResolvedType relevantType) {
+ if (foundMember == null) {
+ // check the ITD'd dooberries
+ List<ConcreteTypeMunger> mungers = relevantType.resolve(world).getInterTypeMungers();
+ for (Iterator<ConcreteTypeMunger> iter = mungers.iterator(); iter.hasNext();) {
+ Object munger = iter.next();
+ ConcreteTypeMunger typeMunger = (ConcreteTypeMunger) munger;
+ if (typeMunger.getMunger() instanceof NewMethodTypeMunger
+ || typeMunger.getMunger() instanceof NewConstructorTypeMunger) {
+ ResolvedMember fakerm = typeMunger.getSignature();
+ // if (fakerm.hasAnnotations())
+
+ ResolvedMember ajcMethod = (getSignature().getKind() == ResolvedMember.CONSTRUCTOR ? AjcMemberMaker
+ .postIntroducedConstructor(typeMunger.getAspectType(), fakerm.getDeclaringType(),
+ fakerm.getParameterTypes()) : AjcMemberMaker.interMethodDispatcher(fakerm,
+ typeMunger.getAspectType()));
+ // AjcMemberMaker.interMethodBody(fakerm,typeMunger.getAspectType()));
+ ResolvedMember rmm = findMethod(typeMunger.getAspectType(), ajcMethod);
+ if (fakerm.getName().equals(getSignature().getName())
+ && fakerm.getParameterSignature().equals(getSignature().getParameterSignature())) {
+ relevantType = typeMunger.getAspectType();
+ foundMember = rmm;
+ return foundMember.getParameterAnnotationTypes();
+ }
+ }
+ }
+ // didn't find in ITDs, look in supers
+ foundMember = relevantType.lookupMemberWithSupersAndITDs(relevantMember);
+ if (foundMember == null) {
+ throw new IllegalStateException("Couldn't find member " + relevantMember + " for type " + relevantType);
+ }
+ }
+ return foundMember.getParameterAnnotationTypes();
+ }
/**
* By determining what "kind" of shadow we are, we can find out the annotations on the appropriate element (method, field,
@@ -1550,6 +1592,7 @@ public class BcelShadow extends Shadow {
kindedAnnotationVars = new HashMap<ResolvedType, AnnotationAccessVar>();
ResolvedType[] annotations = null;
+ ResolvedType[][] paramAnnotations = null;
Member shadowSignature = getSignature();
Member annotationHolder = getSignature();
ResolvedType relevantType = shadowSignature.getDeclaringType().resolve(world);
@@ -1564,6 +1607,7 @@ public class BcelShadow extends Shadow {
} else if (getKind() == Shadow.MethodCall || getKind() == Shadow.ConstructorCall) {
ResolvedMember foundMember = findMethod2(relevantType.resolve(world).getDeclaredMethods(), getSignature());
annotations = getAnnotations(foundMember, shadowSignature, relevantType);
+ paramAnnotations = getParameterAnnotations(foundMember, shadowSignature, relevantType);
annotationHolder = getRelevantMember(foundMember, shadowSignature, relevantType);
relevantType = annotationHolder.getDeclaringType().resolve(world);
} else if (getKind() == Shadow.FieldSet || getKind() == Shadow.FieldGet) {
@@ -1589,17 +1633,15 @@ public class BcelShadow extends Shadow {
} else if (getKind() == Shadow.MethodExecution || getKind() == Shadow.ConstructorExecution
|| getKind() == Shadow.AdviceExecution) {
-
ResolvedMember foundMember = findMethod2(relevantType.getDeclaredMethods(), getSignature());
annotations = getAnnotations(foundMember, shadowSignature, relevantType);
+ paramAnnotations = getParameterAnnotations(foundMember, shadowSignature, relevantType);
annotationHolder = getRelevantMember(foundMember, annotationHolder, relevantType);
UnresolvedType ut = annotationHolder.getDeclaringType();
relevantType = ut.resolve(world);
-
} else if (getKind() == Shadow.ExceptionHandler) {
relevantType = getSignature().getParameterTypes()[0].resolve(world);
annotations = relevantType.getAnnotationTypes();
-
} else if (getKind() == Shadow.PreInitialization || getKind() == Shadow.Initialization) {
ResolvedMember found = findMethod2(relevantType.getDeclaredMethods(), getSignature());
annotations = found.getAnnotationTypes();
@@ -1615,6 +1657,22 @@ public class BcelShadow extends Shadow {
annotationHolder, false);
kindedAnnotationVars.put(annotationType, accessVar);
}
+
+ if (paramAnnotations != null) {
+ int max = paramAnnotations.length;
+ paramAnnoVars = new HashMap[max];
+ for (int p=0;p<max;p++) {
+ ResolvedType[] annotationsOnParticularParam = paramAnnotations[p];
+ paramAnnoVars[p] = new HashMap<ResolvedType,AnnotationAccessVar>();
+ for (int i=0;i<annotationsOnParticularParam.length;i++) {
+// for (ResolvedType annotationOnParticularParam: annotationsOnParticularParam) {
+ ResolvedType annotationOnParticularParam = annotationsOnParticularParam[i];
+ ParamAnnotationAccessVar paramAccessVar = new ParamAnnotationAccessVar(this, getKind(), annotationOnParticularParam, relevantType,
+ annotationHolder, false, p, i);
+ paramAnnoVars[p].put(annotationOnParticularParam, paramAccessVar);
+ }
+ }
+ }
}
private ResolvedMember findMethod2(ResolvedMember members[], Member sig) {
diff --git a/weaver/src/org/aspectj/weaver/bcel/ParamAnnotationAccessVar.java b/weaver/src/org/aspectj/weaver/bcel/ParamAnnotationAccessVar.java
new file mode 100644
index 000000000..e3cebc37f
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/ParamAnnotationAccessVar.java
@@ -0,0 +1,206 @@
+/* *******************************************************************
+ * Copyright (c) 2016 Contributors
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.bcel;
+
+import org.aspectj.apache.bcel.Constants;
+import org.aspectj.apache.bcel.classfile.Field;
+import org.aspectj.apache.bcel.generic.Instruction;
+import org.aspectj.apache.bcel.generic.InstructionBranch;
+import org.aspectj.apache.bcel.generic.InstructionConstants;
+import org.aspectj.apache.bcel.generic.InstructionFactory;
+import org.aspectj.apache.bcel.generic.InstructionHandle;
+import org.aspectj.apache.bcel.generic.InstructionList;
+import org.aspectj.apache.bcel.generic.ObjectType;
+import org.aspectj.apache.bcel.generic.Type;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.Shadow.Kind;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.ast.Var;
+
+/**
+ * Represents access to an parameter annotation on a member element.
+ */
+public class ParamAnnotationAccessVar extends AnnotationAccessVar {
+
+ private BcelShadow shadow;
+ private Kind kind; // What kind of shadow are we at?
+ private UnresolvedType containingType; // The type upon which we want to ask for 'member'
+ private Member member; // Holds the member that has the annotations (for method/field join points)
+ private boolean isWithin; // implies @within() or @withincode(). If false, that implies @annotation()
+ private int parameterNumber;
+ private int annotationOnParameterNumber;
+
+ public ParamAnnotationAccessVar(BcelShadow shadow, Kind kind, ResolvedType annotationType,
+ UnresolvedType theTargetIsStoredHere, Member sig, boolean isWithin, int parameterNumber, int annotationOnParameterNumber) {
+ super(shadow, kind, annotationType, theTargetIsStoredHere, sig, isWithin);
+ this.shadow = shadow;
+ this.kind = kind;
+ this.containingType = theTargetIsStoredHere;
+ this.member = sig;
+ this.isWithin = isWithin;
+ this.parameterNumber = parameterNumber;
+ this.annotationOnParameterNumber = annotationOnParameterNumber;
+ }
+
+ @Override
+ public String toString() {
+ return "ParamAnnotationAccessVar(" + getType() + ")";
+ }
+
+ private InstructionList createLoadInstructions(ResolvedType toType, InstructionFactory fact) {
+ InstructionList il = new InstructionList();
+ Type jlClass = BcelWorld.makeBcelType(UnresolvedType.JL_CLASS);
+ Type jlString = BcelWorld.makeBcelType(UnresolvedType.JL_STRING);
+ Type jlClassArray = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_CLASS_ARRAY);
+ Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_ANNOTATION);
+ Type jlaAnnotationArrayArray = BcelWorld.makeBcelType(UnresolvedType.makeArray(UnresolvedType.JAVA_LANG_ANNOTATION, 2));
+ Instruction pushConstant = fact.createConstant(new ObjectType(toType.getName()));
+ if (kind == Shadow.MethodCall || kind == Shadow.MethodExecution || kind == Shadow.PreInitialization
+ || kind == Shadow.Initialization || kind == Shadow.ConstructorCall || kind == Shadow.ConstructorExecution
+ || kind == Shadow.AdviceExecution ||
+ // annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD
+ ((kind == Shadow.FieldGet || kind == Shadow.FieldSet) && member.getKind() == Member.METHOD)) {
+
+ Type jlrMethod = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava/lang/reflect/Method;"));
+ Type jlAnnotation = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava/lang/annotation/Annotation;"));
+ Type[] paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes());
+
+ if (kind == Shadow.MethodCall
+ || kind == Shadow.MethodExecution
+ || kind == Shadow.AdviceExecution
+ ||
+ // annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD
+ ((kind == Shadow.FieldGet || kind == Shadow.FieldSet) && member.getKind() == Member.METHOD)
+ || ((kind == Shadow.ConstructorCall || kind == Shadow.ConstructorExecution) && member.getKind() == Member.METHOD)) {
+
+ // Need to look at the cached annotation before going to fetch it again
+ Field annotationCachingField = shadow.getEnclosingClass().getAnnotationCachingField(shadow, toType, isWithin);
+
+ // Basic idea here is to check if the cached field is null, if it is then initialize it, otherwise use it
+ il.append(fact.createGetStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
+ il.append(InstructionConstants.DUP);
+ InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
+ il.append(ifNonNull);
+ il.append(InstructionConstants.POP);
+ il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
+
+ il.append(fact.createConstant(member.getName()));
+ buildArray(il, fact, jlClass, paramTypes, 1);
+ // OPTIMIZE cache result of getDeclaredMethod?
+ il.append(fact.createInvoke("java/lang/Class", "getDeclaredMethod", jlrMethod,
+ new Type[] { jlString, jlClassArray }, Constants.INVOKEVIRTUAL));
+// il.append(pushConstant);// fact.createConstant(new ObjectType(toType.getName())));
+ il.append(fact.createInvoke("java/lang/reflect/Method", "getParameterAnnotations", jlaAnnotationArrayArray, null, Constants.INVOKEVIRTUAL));
+ il.append(fact.createConstant(parameterNumber));
+ il.append(InstructionConstants.AALOAD);
+ il.append(fact.createConstant(annotationOnParameterNumber));
+ il.append(InstructionConstants.AALOAD);
+ il.append(InstructionConstants.DUP);
+ // Could loop over the set of annotations or we could 'guess' the right one?
+
+ il.append(fact.createPutStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
+ InstructionHandle ifNullElse = il.append(InstructionConstants.NOP);
+ ifNonNull.setTarget(ifNullElse);
+
+ } else { // init/preinit/ctor-call/ctor-exec
+ il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
+ buildArray(il, fact, jlClass, paramTypes, 1);
+ Type jlrCtor = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_REFLECT_CONSTRUCTOR);
+ // OPTIMIZE cache result of getDeclaredConstructor and getAnnotation? Might be able to use it again if someone else
+ // needs the same annotations?
+ il.append(fact.createInvoke("java/lang/Class", "getDeclaredConstructor", jlrCtor, new Type[] { jlClassArray },
+ Constants.INVOKEVIRTUAL));
+ il.append(pushConstant);
+ il.append(fact.createInvoke("java/lang/reflect/Constructor", "getAnnotation", jlaAnnotation,
+ new Type[] { jlClass }, Constants.INVOKEVIRTUAL));
+ }
+ } else {
+ throw new RuntimeException("Don't understand this kind " + kind);
+ }
+ il.append(Utility.createConversion(fact, jlaAnnotation, BcelWorld.makeBcelType(toType)));
+ return il;
+ }
+
+ private void buildArray(InstructionList il, InstructionFactory fact, Type arrayElementType, Type[] arrayEntries, int dim) {
+ il.append(fact.createConstant(Integer.valueOf(arrayEntries == null ? 0 : arrayEntries.length)));
+ il.append(fact.createNewArray(arrayElementType, (short) dim));
+ if (arrayEntries == null) {
+ return;
+ }
+ for (int i = 0; i < arrayEntries.length; i++) {
+ il.append(InstructionFactory.createDup(1));
+ il.append(fact.createConstant(Integer.valueOf(i)));
+ switch (arrayEntries[i].getType()) {
+ case Constants.T_ARRAY:
+ il.append(fact.createConstant(new ObjectType(arrayEntries[i].getSignature()))); // FIXME should be getName() and not
+ // getSignature()?
+ break;
+ case Constants.T_BOOLEAN:
+ il.append(fact.createGetStatic("java/lang/Boolean", "TYPE", arrayElementType));
+ break;
+ case Constants.T_BYTE:
+ il.append(fact.createGetStatic("java/lang/Byte", "TYPE", arrayElementType));
+ break;
+ case Constants.T_CHAR:
+ il.append(fact.createGetStatic("java/lang/Character", "TYPE", arrayElementType));
+ break;
+ case Constants.T_INT:
+ il.append(fact.createGetStatic("java/lang/Integer", "TYPE", arrayElementType));
+ break;
+ case Constants.T_LONG:
+ il.append(fact.createGetStatic("java/lang/Long", "TYPE", arrayElementType));
+ break;
+ case Constants.T_DOUBLE:
+ il.append(fact.createGetStatic("java/lang/Double", "TYPE", arrayElementType));
+ break;
+ case Constants.T_FLOAT:
+ il.append(fact.createGetStatic("java/lang/Float", "TYPE", arrayElementType));
+ break;
+ case Constants.T_SHORT:
+ il.append(fact.createGetStatic("java/lang/Short", "TYPE", arrayElementType));
+ break;
+ default:
+ il.append(fact.createConstant(arrayEntries[i]));
+ }
+ il.append(InstructionConstants.AASTORE);
+ }
+ }
+
+ @Override
+ public void appendLoad(InstructionList il, InstructionFactory fact) {
+ il.append(createLoadInstructions(getType(), fact));
+ }
+
+ @Override
+ public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
+ il.append(createLoadInstructions(toType, fact));
+ }
+
+ @Override
+ public void insertLoad(InstructionList il, InstructionFactory fact) {
+ il.insert(createLoadInstructions(getType(), fact));
+ }
+
+ /**
+ * Return an object that can access a particular field of this annotation.
+ *
+ * @param valueType The type from the annotation that is of interest
+ * @param the formal name expressed in the pointcut, can be used to disambiguate
+ * @return a variable that represents access to that annotation field
+ */
+ @Override
+ public Var getAccessorForValue(ResolvedType valueType, String formalName) {
+ throw new IllegalStateException("Not supported for parameter annotations");
+ }
+}
diff --git a/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java b/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java
index a978d9605..5de589f15 100644
--- a/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java
+++ b/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java
@@ -26,6 +26,7 @@ import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.LocalVariable;
import org.aspectj.apache.bcel.classfile.LocalVariableTable;
+import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
import org.aspectj.apache.bcel.util.NonCachingClassLoaderRepository;
import org.aspectj.apache.bcel.util.Repository;
import org.aspectj.weaver.AnnotationAJ;
@@ -321,8 +322,7 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder {
// here we really want both the runtime visible AND the class visible
// annotations
// so we bail out to Bcel and then chuck away the JavaClass so that we
- // don't hog
- // memory.
+ // don't hog memory.
try {
JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass());
org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[][] anns = null;
@@ -386,5 +386,72 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder {
}
return result;
}
+
+ public Object getParamAnnotation(Member onMember, int argsIndex, int paramAnnoIndex) {
+ if (!(onMember instanceof AccessibleObject))
+ return null;
+ // here we really want both the runtime visible AND the class visible
+ // annotations so we bail out to Bcel and then chuck away the JavaClass so that we
+ // don't hog memory.
+// try {
+// JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass());
+// org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[][] anns = null;
+// if (onMember instanceof Method) {
+// org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method) onMember);
+// if (bcelMethod == null) {
+// // pr220430
+// // System.err.println(
+// // "Unexpected problem in Java15AnnotationFinder: cannot retrieve annotations on method '"
+// // + onMember.getName()+"' in class '"+jc.getClassName()+"'");
+// } else {
+// anns = bcelMethod.getParameterAnnotations();
+// }
+// } else if (onMember instanceof Constructor) {
+// org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor) onMember);
+// anns = bcelCons.getParameterAnnotations();
+// } else if (onMember instanceof Field) {
+// // anns = null;
+// }
+// // the answer is cached and we don't want to hold on to memory
+// bcelRepository.clear();
+// if (anns == null)
+// return null;
+//
+// if (argsIndex>=anns.length) {
+// return null;
+// }
+// AnnotationGen[] parameterAnnotationsOnParticularArg = anns[argsIndex];
+// if (parameterAnnotationsOnParticularArg==null || paramAnnoIndex>=parameterAnnotationsOnParticularArg.length) {
+// return null;
+// }
+// AnnotationGen parameterAnnotation = parameterAnnotationsOnParticularArg[paramAnnoIndex];
+//// if (parameterAnnotation.getTypeSignature().equals(ofType.getSignature())) {
+// return new BcelAnnotation(parameterAnnotation, world);
+//// } else {
+//// return null;
+//// }
+// } catch (ClassNotFoundException cnfEx) {
+// // just use reflection then
+// }
+
+ // reflection...
+ AccessibleObject ao = (AccessibleObject) onMember;
+ Annotation[][] anns = null;
+ if (onMember instanceof Method) {
+ anns = ((Method) ao).getParameterAnnotations();
+ } else if (onMember instanceof Constructor) {
+ anns = ((Constructor) ao).getParameterAnnotations();
+ } else if (onMember instanceof Field) {
+ // anns = null;
+ }
+ if (anns == null || argsIndex>=anns.length) {
+ return null;
+ }
+ Annotation[] parameterAnnotationsOnParticularArg = anns[argsIndex];
+ if (parameterAnnotationsOnParticularArg==null || paramAnnoIndex>=parameterAnnotationsOnParticularArg.length) {
+ return null;
+ }
+ return parameterAnnotationsOnParticularArg[paramAnnoIndex];
+ }
}
diff --git a/weaver5/java5-src/org/aspectj/weaver/reflect/ReflectiveAnnotationAJ.java b/weaver5/java5-src/org/aspectj/weaver/reflect/ReflectiveAnnotationAJ.java
new file mode 100644
index 000000000..0b486b7ed
--- /dev/null
+++ b/weaver5/java5-src/org/aspectj/weaver/reflect/ReflectiveAnnotationAJ.java
@@ -0,0 +1,103 @@
+/* *******************************************************************
+ * Copyright (c) 2016 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement Initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.reflect;
+
+import java.lang.annotation.Annotation;
+import java.util.Set;
+
+import org.aspectj.weaver.AnnotationAJ;
+import org.aspectj.weaver.ResolvedType;
+
+/**
+ * An AnnotationAJ that wraps a java.lang.reflect Annotation.
+ *
+ * @author Andy Clement
+ */
+public class ReflectiveAnnotationAJ implements AnnotationAJ {
+
+ private Annotation anno;
+
+ public ReflectiveAnnotationAJ(Annotation anno) {
+ this.anno = anno;
+ }
+
+ public String getTypeSignature() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getTypeName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public ResolvedType getType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean allowedOnAnnotationType() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean allowedOnField() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean allowedOnRegularType() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public Set<String> getTargets() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean hasNamedValue(String name) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean hasNameValuePair(String name, String value) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public String getValidTargets() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String stringify() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean specifiesTarget() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isRuntimeVisible() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public String getStringFormOfValue(String name) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java b/weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java
index 9b155df3e..e3a4981c1 100644
--- a/weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java
+++ b/weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java
@@ -11,6 +11,7 @@
* ******************************************************************/
package org.aspectj.weaver.tools;
+import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
@@ -63,6 +64,9 @@ public class Java15PointcutExpressionTest extends TestCase {
private Method b;
private Method c;
private Method d;
+ private Method e;
+ private Method f;
+
/**
* Parse some expressions and ensure we capture the parameter annotations and parameter type annotations correctly.
@@ -508,6 +512,43 @@ public class Java15PointcutExpressionTest extends TestCase {
assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[1].getBinding());
}
+ public void testAtArgsWithParamBinding() throws Exception {
+ // B class contains: public void e(@MyAnnotation A anA, B aB) {}
+ PointcutParameter pp = parser.createPointcutParameter("a", MyAnnotation.class);
+ PointcutExpression atArgs = parser.parsePointcutExpression("@args(a (*),..)",A.class,new PointcutParameter[] {pp});
+ ShadowMatch shadowMatch = atArgs.matchesMethodExecution(e);
+ assertTrue(shadowMatch.alwaysMatches());
+ JoinPointMatch jpm = shadowMatch.matchesJoinPoint(new B(), new B(), new Object[] {new A(), new B()});
+ assertEquals(1,jpm.getParameterBindings().length);
+ MyAnnotation expectedAnnotation = (MyAnnotation)B.class.getDeclaredMethod("e", A.class,B.class).getParameterAnnotations()[0][0];
+ Object boundAnnotation = jpm.getParameterBindings()[0].getBinding();
+ assertEquals(expectedAnnotation,boundAnnotation);
+
+ pp = parser.createPointcutParameter("a", MyAnnotationWithValue.class);
+ PointcutParameter pp2 = parser.createPointcutParameter("b", MyAnnotationWithValue.class);
+ atArgs = parser.parsePointcutExpression("@args(a,b)",A.class,new PointcutParameter[] {pp,pp2});
+ shadowMatch = atArgs.matchesMethodExecution(f);
+ assertTrue(shadowMatch.alwaysMatches());
+ jpm = shadowMatch.matchesJoinPoint(new B(), new B(), new Object[] {new A(), new B()});
+ assertEquals(2,jpm.getParameterBindings().length);
+ MyAnnotationWithValue expectedAnnotation1 = (MyAnnotationWithValue)B.class.getDeclaredMethod("e", A.class,B.class).getParameterAnnotations()[0][0];
+ MyAnnotationWithValue expectedAnnotation2 = (MyAnnotationWithValue)B.class.getDeclaredMethod("e", A.class,B.class).getParameterAnnotations()[1][0];
+ Object boundAnnotation1 = jpm.getParameterBindings()[0].getBinding();
+ assertEquals(expectedAnnotation1,boundAnnotation1);
+ Object boundAnnotation2 = jpm.getParameterBindings()[1].getBinding();
+ assertEquals(expectedAnnotation2,boundAnnotation1);
+
+//
+// atArgs = parser.parsePointcutExpression("@args(a,b)",A.class,new PointcutParameter[] {p1,p2});
+// sMatch2 = atArgs.matchesMethodExecution(c);
+// assertTrue("maybe matches C",sMatch2.maybeMatches());
+// jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[] {new B(),new B()});
+// assertTrue("matches",jp2.matches());
+// assertEquals(2,jp2.getParameterBindings().length);
+// assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[0].getBinding());
+// assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[1].getBinding());
+ }
+
public void testAtWithin() {
PointcutExpression atWithin = parser.parsePointcutExpression("@within(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
ShadowMatch sMatch1 = atWithin.matchesMethodExecution(a);
@@ -670,11 +711,18 @@ public class Java15PointcutExpressionTest extends TestCase {
b = B.class.getMethod("b");
c = B.class.getMethod("c",new Class[] {A.class,B.class});
d = B.class.getMethod("d",new Class[] {A.class,A.class});
+ e = B.class.getMethod("e", new Class[] {A.class, B.class});
+ f = B.class.getMethod("f", A.class, B.class);
}
@Retention(RetentionPolicy.RUNTIME)
private @interface MyAnnotation {}
-
+
+ @Retention(RetentionPolicy.RUNTIME)
+ private @interface MyAnnotationWithValue {
+ String value();
+ }
+
private @interface MyClassFileRetentionAnnotation {}
private static class A {
@@ -687,6 +735,10 @@ public class Java15PointcutExpressionTest extends TestCase {
public void c(A anA, B aB) {}
public void d(A anA, A anotherA) {}
+
+ public void e(@MyAnnotation A anA, B aB) {}
+
+ public void f(@MyAnnotationWithValue("abc") A anA, @MyAnnotationWithValue("def") B aB) {}
}
private static class C {