import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import java.util.StringTokenizer;
import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Attribute;
private final static List EMPTY_LIST = new ArrayList();
private final static String[] EMPTY_STRINGS = new String[0];
private final static String VALUE = "value";
+ private final static String ARGNAMES = "argNames";
private final static String POINTCUT = "pointcut";
private final static String THROWING = "throwing";
private final static String RETURNING = "returning";
*/
private static class AjAttributeMethodStruct extends AjAttributeStruct {
- /**
- * Argument names as they appear in the SOURCE code, ordered, and lazyly populated
- * Used to do formal binding
- */
+ // argument names used for formal binding
private String[] m_argumentNamesLazy = null;
+ public String unparsedArgumentNames = null; // Set only if discovered as argNames attribute of annotation
final Method method;
final BcelMethod bMethod;
public String[] getArgumentNames() {
if (m_argumentNamesLazy == null) {
- m_argumentNamesLazy = getMethodArgumentNamesAsInSource(method);
+ m_argumentNamesLazy = getMethodArgumentNames(method,unparsedArgumentNames,this);
}
return m_argumentNamesLazy;
}
ElementNameValuePair beforeAdvice = getAnnotationElement(before, VALUE);
if (beforeAdvice != null) {
// this/target/args binding
+ String argumentNames = getArgNamesValue(before);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
try {
bindings = extractBindings(struct);
if (afterAdvice != null) {
// this/target/args binding
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
+ String argumentNames = getArgNamesValue(after);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
try {
bindings = extractBindings(struct);
} catch (UnreadableDebugInfoException unreadableDebugInfoException) {
}
}
}
-
+ String argumentNames = getArgNamesValue(after);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
// this/target/args binding
// exclude the return binding from the pointcut binding since it is an extraArg binding
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
}
}
}
-
+ String argumentNames = getArgNamesValue(after);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
// this/target/args binding
// exclude the throwned binding from the pointcut binding since it is an extraArg binding
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
if (around != null) {
ElementNameValuePair aroundAdvice = getAnnotationElement(around, VALUE);
if (aroundAdvice != null) {
- // this/target/args binding
+ // this/target/args binding
+ String argumentNames = getArgNamesValue(around);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
try {
bindings = extractBindings(struct);
if (pointcut != null) {
ElementNameValuePair pointcutExpr = getAnnotationElement(pointcut, VALUE);
+
// semantic check: the method must return void, or be "public static boolean" for if() support
if (!(Type.VOID.equals(struct.method.getReturnType())
|| (Type.BOOLEAN.equals(struct.method.getReturnType()) && struct.method.isStatic() && struct.method.isPublic()))) {
;// no need to stop
}
+ String argumentNames = getArgNamesValue(pointcut);
+ if (argumentNames!=null) {
+ struct.unparsedArgumentNames = argumentNames;
+ }
// this/target/args binding
final IScope binding;
try {
}
return null;
}
+
+ /**
+ * Return the argNames set for an annotation or null if it is not specified.
+ */
+ private static String getArgNamesValue(Annotation anno) {
+ for (Iterator iterator1 = anno.getValues().iterator(); iterator1.hasNext();) {
+ ElementNameValuePair element = (ElementNameValuePair) iterator1.next();
+ if (ARGNAMES.equals(element.getNameString())) {
+ return element.getValue().stringifyValue();
+ }
+ }
+ return null;
+ }
+
+ private static String lastbit(String fqname) {
+ int i = fqname.lastIndexOf(".");
+ if (i==-1) return fqname; else return fqname.substring(i+1);
+ }
/**
- * Extract the method argument names as in source from debug info
- * returns an empty array upon inconsistency
+ * Extract the method argument names. First we try the debug info attached
+ * to the method (the LocalVariableTable) - if we cannot find that we look
+ * to use the argNames value that may have been supplied on the associated
+ * annotation. If that fails we just don't know and return an empty string.
*
* @param method
- * @return method arg names as in source
+ * @param argNamesFromAnnotation
+ * @param methodStruct
+ * @return method argument names
*/
- private static String[] getMethodArgumentNamesAsInSource(Method method) {
+ private static String[] getMethodArgumentNames(Method method, String argNamesFromAnnotation, AjAttributeMethodStruct methodStruct) {
if (method.getArgumentTypes().length == 0) {
return EMPTY_STRINGS;
}
}
}
}
+ } else {
+ // No debug info, do we have an annotation value we can rely on?
+ if (argNamesFromAnnotation!=null) {
+ StringTokenizer st = new StringTokenizer(argNamesFromAnnotation," ,");
+ List args = new ArrayList();
+ while (st.hasMoreTokens()) { args.add(st.nextToken());}
+ if (args.size()!=method.getArgumentTypes().length) {
+ StringBuffer shortString = new StringBuffer().append(lastbit(method.getReturnType().toString())).append(" ").append(method.getName());
+ if (method.getArgumentTypes().length>0) {
+ shortString.append("(");
+ for (int i =0; i<method.getArgumentTypes().length;i++) {
+ shortString.append(lastbit(method.getArgumentTypes()[i].toString()));
+ if ((i+1)<method.getArgumentTypes().length) shortString.append(",");
+
+ }
+ shortString.append(")");
+ }
+ reportError("argNames annotation value does not specify the right number of argument names for the method '"+shortString.toString()+"'",methodStruct);
+ return EMPTY_STRINGS;
+ }
+ return (String[])args.toArray(new String[]{});
+ }
}
if (arguments.size() != method.getArgumentTypes().length) {
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.StringTokenizer;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ExceptionTable;
import org.aspectj.apache.bcel.classfile.Signature;
import org.aspectj.apache.bcel.classfile.Signature.TypeVariableSignature;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
+import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.weaver.AjAttribute;
LocalVariableTable varTable = method.getLocalVariableTable();
int len = getArity();
if (varTable == null) {
+ // do we have an annotation with the argNames value specified...
+ if (hasAnnotations()) {
+ AnnotationX[] axs = getAnnotations();
+ for (int i = 0; i < axs.length; i++) {
+ AnnotationX annotationX = axs[i];
+ String typename = annotationX.getTypeName();
+ if (typename.equals("org.aspectj.lang.annotation.Pointcut") ||
+ typename.equals("org.aspectj.lang.annotation.Before") ||
+ typename.equals("org.aspectj.lang.annotation.Around") ||
+ typename.startsWith("org.aspectj.lang.annotation.After")) {
+ Annotation a = annotationX.getBcelAnnotation();
+ if (a!=null) {
+ List values = a.getValues();
+ for (Iterator iterator = values.iterator(); iterator
+ .hasNext();) {
+ ElementNameValuePair nvPair = (ElementNameValuePair) iterator.next();
+ if (nvPair.getNameString().equals("argNames")) {
+ String argNames = nvPair.getValue().stringifyValue();
+ StringTokenizer argNameTokenizer = new StringTokenizer(argNames," ,");
+ List argsList = new ArrayList();
+ while (argNameTokenizer.hasMoreTokens()) {
+ argsList.add(argNameTokenizer.nextToken());
+ }
+ int requiredCount = getParameterTypes().length;
+ while (argsList.size()<requiredCount) {
+ argsList.add("arg"+argsList.size());
+ }
+ setParameterNames((String[])argsList.toArray(new String[]{}));
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
setParameterNames(Utility.makeArgNames(len));
} else {
UnresolvedType[] paramTypes = getParameterTypes();