Browse Source

259416: preliminary work

paramAnnotationBinding
Andy Clement 7 years ago
parent
commit
d10618d25a
32 changed files with 809 additions and 54 deletions
  1. 2
    0
      org.aspectj.matcher/src/org/aspectj/weaver/Member.java
  2. 5
    0
      org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java
  3. 2
    0
      org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java
  4. 61
    5
      org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java
  5. 18
    12
      org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java
  6. 10
    5
      org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
  7. 2
    0
      org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
  8. 9
    3
      org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java
  9. 11
    7
      org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java
  10. 28
    11
      org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java
  11. 18
    1
      org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java
  12. 4
    4
      org.aspectj.matcher/src/org/aspectj/weaver/reflect/StandardShadow.java
  13. 0
    0
      tests/bugs1810/259416/Caveats
  14. BIN
      tests/bugs1810/259416/ColouredAnnotation.class
  15. 6
    0
      tests/bugs1810/259416/ColouredAnnotation.java
  16. 0
    0
      tests/bugs1810/259416/Creating
  17. 0
    0
      tests/bugs1810/259416/Downloading
  18. 5
    0
      tests/bugs1810/259416/Filler.java
  19. BIN
      tests/bugs1810/259416/RGB.class
  20. 3
    0
      tests/bugs1810/259416/RGB.java
  21. 0
    0
      tests/bugs1810/259416/Tapping
  22. 13
    0
      tests/bugs1810/259416/Test1.java
  23. 13
    0
      tests/bugs1810/259416/Test2.java
  24. 13
    0
      tests/bugs1810/259416/Test3.java
  25. 13
    0
      tests/bugs1810/259416/Test4.java
  26. 36
    0
      tests/src/org/aspectj/systemtest/ajc1810/Ajc1810Tests.java
  27. 45
    0
      tests/src/org/aspectj/systemtest/ajc1810/ajc1810.xml
  28. 61
    3
      weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
  29. 206
    0
      weaver/src/org/aspectj/weaver/bcel/ParamAnnotationAccessVar.java
  30. 69
    2
      weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java
  31. 103
    0
      weaver5/java5-src/org/aspectj/weaver/reflect/ReflectiveAnnotationAJ.java
  32. 53
    1
      weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java

+ 2
- 0
org.aspectj.matcher/src/org/aspectj/weaver/Member.java View File

@@ -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);

+ 5
- 0
org.aspectj.matcher/src/org/aspectj/weaver/MemberImpl.java View File

@@ -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.

+ 2
- 0
org.aspectj.matcher/src/org/aspectj/weaver/Shadow.java View File

@@ -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();

/**

+ 61
- 5
org.aspectj.matcher/src/org/aspectj/weaver/patterns/AnnotationPatternList.java View File

@@ -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;
}

+ 18
- 12
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java View File

@@ -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++;
}

+ 10
- 5
org.aspectj.matcher/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java View File

@@ -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;
}
}

+ 2
- 0
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java View File

@@ -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;
}
}

+ 9
- 3
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java View File

@@ -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;
}

+ 11
- 7
org.aspectj.matcher/src/org/aspectj/weaver/reflect/AnnotationFinder.java View File

@@ -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);
}

+ 28
- 11
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionShadow.java View File

@@ -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)

+ 18
- 1
org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionVar.java View File

@@ -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);

+ 4
- 4
org.aspectj.matcher/src/org/aspectj/weaver/reflect/StandardShadow.java View File

@@ -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) {

+ 0
- 0
tests/bugs1810/259416/Caveats View File


BIN
tests/bugs1810/259416/ColouredAnnotation.class View File


+ 6
- 0
tests/bugs1810/259416/ColouredAnnotation.java View File

@@ -0,0 +1,6 @@
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface ColouredAnnotation {
RGB value();
}

+ 0
- 0
tests/bugs1810/259416/Creating View File


+ 0
- 0
tests/bugs1810/259416/Downloading View File


+ 5
- 0
tests/bugs1810/259416/Filler.java View File

@@ -0,0 +1,5 @@
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface Filler {
}

BIN
tests/bugs1810/259416/RGB.class View File


+ 3
- 0
tests/bugs1810/259416/RGB.java View File

@@ -0,0 +1,3 @@
public enum RGB {
RED, GREEN, BLUE;
}

+ 0
- 0
tests/bugs1810/259416/Tapping View File


+ 13
- 0
tests/bugs1810/259416/Test1.java View File

@@ -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);
}
}

+ 13
- 0
tests/bugs1810/259416/Test2.java View File

@@ -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);
}
}

+ 13
- 0
tests/bugs1810/259416/Test3.java View File

@@ -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);
}
}

+ 13
- 0
tests/bugs1810/259416/Test4.java View File

@@ -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);
}
}

+ 36
- 0
tests/src/org/aspectj/systemtest/ajc1810/Ajc1810Tests.java View File

@@ -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");
}

+ 45
- 0
tests/src/org/aspectj/systemtest/ajc1810/ajc1810.xml View File

@@ -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">

+ 61
- 3
weaver/src/org/aspectj/weaver/bcel/BcelShadow.java View File

@@ -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;
@@ -952,6 +953,12 @@ public class BcelShadow extends Shadow {
return kindedAnnotationVars.get(forAnnotationType);
}

@Override
public Var getArgParamAnnotationVar(int parameterIndex, UnresolvedType forAnnotationType) {
initializeKindedAnnotationVars();
return paramAnnoVars[parameterIndex].get(forAnnotationType);
}

@Override
public Var getWithinAnnotationVar(UnresolvedType forAnnotationType) {
initializeWithinAnnotationVars();
@@ -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) {

+ 206
- 0
weaver/src/org/aspectj/weaver/bcel/ParamAnnotationAccessVar.java View File

@@ -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");
}
}

+ 69
- 2
weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java View File

@@ -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];
}

}

+ 103
- 0
weaver5/java5-src/org/aspectj/weaver/reflect/ReflectiveAnnotationAJ.java View File

@@ -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;
}

}

+ 53
- 1
weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java View File

@@ -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 {

Loading…
Cancel
Save