/*******************************************************************************
 * Copyright (c) 2005 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:
 * initial implementation              Alexandre Vasseur
 *******************************************************************************/
package org.aspectj.weaver.bcel;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
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;
import org.aspectj.apache.bcel.classfile.Constant;
import org.aspectj.apache.bcel.classfile.ConstantUtf8;
import org.aspectj.apache.bcel.classfile.Field;
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.Method;
import org.aspectj.apache.bcel.classfile.Unknown;
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue;
import org.aspectj.apache.bcel.classfile.annotation.ClassElementValue;
import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos;
import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.asm.AsmManager;
import org.aspectj.asm.IHierarchy;
import org.aspectj.asm.IProgramElement;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.weaver.Advice;
import org.aspectj.weaver.AdviceKind;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.BindingScope;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.MethodDelegateTypeMunger;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ReferenceTypeDelegate;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedPointcutDefinition;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
import org.aspectj.weaver.patterns.DeclareParents;
import org.aspectj.weaver.patterns.DeclareParentsMixin;
import org.aspectj.weaver.patterns.DeclarePrecedence;
import org.aspectj.weaver.patterns.FormalBinding;
import org.aspectj.weaver.patterns.IScope;
import org.aspectj.weaver.patterns.ParserException;
import org.aspectj.weaver.patterns.PatternParser;
import org.aspectj.weaver.patterns.PerCflow;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.PerFromSuper;
import org.aspectj.weaver.patterns.PerObject;
import org.aspectj.weaver.patterns.PerSingleton;
import org.aspectj.weaver.patterns.PerTypeWithin;
import org.aspectj.weaver.patterns.Pointcut;
import org.aspectj.weaver.patterns.TypePattern;

/**
 * Annotation defined aspect reader. Reads the Java 5 annotations and turns them into AjAttributes
 * 
 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
 */
public class AtAjAttributes {

	private final static List<AjAttribute> NO_ATTRIBUTES = Collections.emptyList();
	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 final static String STRING_DESC = "Ljava/lang/String;";

	/**
	 * A struct that allows to add extra arguments without always breaking the API
	 */
	private static class AjAttributeStruct {

		/**
		 * The list of AjAttribute.XXX that we are populating from the @AJ read
		 */
		List<AjAttribute> ajAttributes = new ArrayList<AjAttribute>();

		/**
		 * The resolved type (class) for which we are reading @AJ for (be it class, method, field annotations)
		 */
		final ResolvedType enclosingType;

		final ISourceContext context;
		final IMessageHandler handler;

		public AjAttributeStruct(ResolvedType type, ISourceContext sourceContext, IMessageHandler messageHandler) {
			enclosingType = type;
			context = sourceContext;
			handler = messageHandler;
		}
	}

	/**
	 * A struct when we read @AJ on method
	 * 
	 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
	 */
	private static class AjAttributeMethodStruct extends AjAttributeStruct {

		// 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 AjAttributeMethodStruct(Method method, BcelMethod bMethod, ResolvedType type, ISourceContext sourceContext,
				IMessageHandler messageHandler) {
			super(type, sourceContext, messageHandler);
			this.method = method;
			this.bMethod = bMethod;
		}

		public String[] getArgumentNames() {
			if (m_argumentNamesLazy == null) {
				m_argumentNamesLazy = getMethodArgumentNames(method, unparsedArgumentNames, this);
			}
			return m_argumentNamesLazy;
		}
	}

	/**
	 * A struct when we read @AJ on field
	 */
	private static class AjAttributeFieldStruct extends AjAttributeStruct {

		final Field field;

		// final BcelField bField;

		public AjAttributeFieldStruct(Field field, BcelField bField, ResolvedType type, ISourceContext sourceContext,
				IMessageHandler messageHandler) {
			super(type, sourceContext, messageHandler);
			this.field = field;
			// this.bField = bField;
		}
	}

	/**
	 * Annotations are RuntimeVisible only. This allow us to not visit RuntimeInvisible ones.
	 * 
	 * @param attribute
	 * @return true if runtime visible annotation
	 */
	public static boolean acceptAttribute(Attribute attribute) {
		return (attribute instanceof RuntimeVisAnnos);
	}

	/**
	 * Extract class level annotations and turn them into AjAttributes.
	 * 
	 * @param javaClass
	 * @param type
	 * @param context
	 * @param msgHandler
	 * @return list of AjAttributes
	 */
	public static List<AjAttribute> readAj5ClassAttributes(AsmManager model, JavaClass javaClass, ReferenceType type,
			ISourceContext context, IMessageHandler msgHandler, boolean isCodeStyleAspect) {
		boolean ignoreThisClass = javaClass.getClassName().charAt(0) == 'o'
				&& javaClass.getClassName().startsWith("org.aspectj.lang.annotation");
		if (ignoreThisClass) {
			return NO_ATTRIBUTES;
		}
		boolean containsPointcut = false;
		boolean containsAnnotationClassReference = false;
		Constant[] cpool = javaClass.getConstantPool().getConstantPool();
		for (int i = 0; i < cpool.length; i++) {
			Constant constant = cpool[i];
			if (constant != null && constant.getTag() == Constants.CONSTANT_Utf8) {
				String constantValue = ((ConstantUtf8) constant).getValue();
				if (constantValue.length() > 28 && constantValue.charAt(1) == 'o') {
					if (constantValue.startsWith("Lorg/aspectj/lang/annotation")) {
						containsAnnotationClassReference = true;
						if ("Lorg/aspectj/lang/annotation/DeclareAnnotation;".equals(constantValue)) {
							msgHandler.handleMessage(new Message(
									"Found @DeclareAnnotation while current release does not support it (see '" + type.getName()
											+ "')", IMessage.WARNING, null, type.getSourceLocation()));
						}
						if ("Lorg/aspectj/lang/annotation/Pointcut;".equals(constantValue)) {
							containsPointcut = true;
						}
					}

				}
			}
		}
		if (!containsAnnotationClassReference) {
			return NO_ATTRIBUTES;
		}

		AjAttributeStruct struct = new AjAttributeStruct(type, context, msgHandler);
		Attribute[] attributes = javaClass.getAttributes();
		boolean hasAtAspectAnnotation = false;
		boolean hasAtPrecedenceAnnotation = false;

		WeaverVersionInfo wvinfo = null;
		for (int i = 0; i < attributes.length; i++) {
			Attribute attribute = attributes[i];
			if (acceptAttribute(attribute)) {
				RuntimeAnnos rvs = (RuntimeAnnos) attribute;
				// we don't need to look for several attribute occurrences since
				// it cannot happen as per JSR175
				if (!isCodeStyleAspect && !javaClass.isInterface()) {
					hasAtAspectAnnotation = handleAspectAnnotation(rvs, struct);
					// TODO AV - if put outside the if isCodeStyleAspect then we
					// would enable mix style
					hasAtPrecedenceAnnotation = handlePrecedenceAnnotation(rvs, struct);
				}
				// there can only be one RuntimeVisible bytecode attribute
				break;
			}
		}
		for (int i = attributes.length - 1; i >= 0; i--) {
			Attribute attribute = attributes[i];
			if (attribute.getName().equals(WeaverVersionInfo.AttributeName)) {
				try {
					VersionedDataInputStream s = new VersionedDataInputStream(new ByteArrayInputStream(
							((Unknown) attribute).getBytes()), null);
					wvinfo = WeaverVersionInfo.read(s);
					struct.ajAttributes.add(0, wvinfo);
				} catch (IOException ioe) {
					ioe.printStackTrace();
				}
			}
		}
		if (wvinfo == null) {
			// If we are in here due to a resetState() call (presumably because of reweavable state processing), the
			// original type delegate will have been set with a version but that version will be missing from
			// the new set of attributes (looks like a bug where the version attribute was not included in the
			// data compressed into the attribute). So rather than 'defaulting' to current, we should use one
			// if it set on the delegate for the type.
			ReferenceTypeDelegate delegate = type.getDelegate();
			if (delegate instanceof BcelObjectType) {
				wvinfo = ((BcelObjectType) delegate).getWeaverVersionAttribute();
				if (wvinfo != null) {
					if (wvinfo.getMajorVersion() != WeaverVersionInfo.WEAVER_VERSION_MAJOR_UNKNOWN) {
						// use this one
						struct.ajAttributes.add(0, wvinfo);
					} else {
						wvinfo = null;
					}
				}
			}
			if (wvinfo == null) {
				struct.ajAttributes.add(0, wvinfo = new AjAttribute.WeaverVersionInfo());
			}
		}

		// basic semantic check
		if (hasAtPrecedenceAnnotation && !hasAtAspectAnnotation) {
			msgHandler.handleMessage(new Message("Found @DeclarePrecedence on a non @Aspect type '" + type.getName() + "'",
					IMessage.WARNING, null, type.getSourceLocation()));
			// bypass what we have read
			return NO_ATTRIBUTES;
		}

		// the following block will not detect @Pointcut in non @Aspect types
		// for optimization purpose
		if (!(hasAtAspectAnnotation || isCodeStyleAspect) && !containsPointcut) {
			return NO_ATTRIBUTES;
		}

		// FIXME AV - turn on when ajcMightHaveAspect
		// if (hasAtAspectAnnotation && type.isInterface()) {
		// msgHandler.handleMessage(
		// new Message(
		// "Found @Aspect on an interface type '" + type.getName() + "'",
		// IMessage.WARNING,
		// null,
		// type.getSourceLocation()
		// )
		// );
		// // bypass what we have read
		// return EMPTY_LIST;
		// }

		// semantic check: @Aspect must be public
		// FIXME AV - do we really want to enforce that?
		// if (hasAtAspectAnnotation && !javaClass.isPublic()) {
		// msgHandler.handleMessage(
		// new Message(
		// "Found @Aspect annotation on a non public class '" +
		// javaClass.getClassName() + "'",
		// IMessage.ERROR,
		// null,
		// type.getSourceLocation()
		// )
		// );
		// return EMPTY_LIST;
		// }

		// code style pointcuts are class attributes
		// we need to gather the @AJ pointcut right now and not at method level
		// annotation extraction time
		// in order to be able to resolve the pointcut references later on
		// we don't need to look in super class, the pointcut reference in the
		// grammar will do it

		for (int i = 0; i < javaClass.getMethods().length; i++) {
			Method method = javaClass.getMethods()[i];
			if (method.getName().startsWith(NameMangler.PREFIX)) {
				continue; // already dealt with by ajc...
			}
			// FIXME alex optimize, this method struct will gets recreated for
			// advice extraction
			AjAttributeMethodStruct mstruct = null;
			boolean processedPointcut = false;
			Attribute[] mattributes = method.getAttributes();
			for (int j = 0; j < mattributes.length; j++) {
				Attribute mattribute = mattributes[j];
				if (acceptAttribute(mattribute)) {
					// TODO speed all this nonsense up rather than looking
					// through all the annotations every time
					// same for fields
					mstruct = new AjAttributeMethodStruct(method, null, type, context, msgHandler);
					processedPointcut = handlePointcutAnnotation((RuntimeAnnos) mattribute, mstruct);
					if (!processedPointcut) {
						processedPointcut = handleDeclareMixinAnnotation((RuntimeAnnos) mattribute, mstruct);
					}
					// there can only be one RuntimeVisible bytecode attribute
					break;
				}
			}
			if (processedPointcut) {
				struct.ajAttributes.addAll(mstruct.ajAttributes);
			}
		}

		// code style declare error / warning / implements / parents are field
		// attributes
		Field[] fs = javaClass.getFields();
		for (int i = 0; i < fs.length; i++) {
			Field field = fs[i];
			if (field.getName().startsWith(NameMangler.PREFIX)) {
				continue; // already dealt with by ajc...
			}
			// FIXME alex optimize, this method struct will gets recreated for
			// advice extraction
			AjAttributeFieldStruct fstruct = new AjAttributeFieldStruct(field, null, type, context, msgHandler);
			Attribute[] fattributes = field.getAttributes();

			for (int j = 0; j < fattributes.length; j++) {
				Attribute fattribute = fattributes[j];
				if (acceptAttribute(fattribute)) {
					RuntimeAnnos frvs = (RuntimeAnnos) fattribute;
					if (handleDeclareErrorOrWarningAnnotation(model, frvs, fstruct)
							|| handleDeclareParentsAnnotation(frvs, fstruct)) {
						// semantic check - must be in an @Aspect [remove if
						// previous block bypassed in advance]
						if (!type.isAnnotationStyleAspect() && !isCodeStyleAspect) {
							msgHandler.handleMessage(new Message("Found @AspectJ annotations in a non @Aspect type '"
									+ type.getName() + "'", IMessage.WARNING, null, type.getSourceLocation()));
							// go ahead
						}
					}
					// there can only be one RuntimeVisible bytecode attribute
					break;
				}
			}
			struct.ajAttributes.addAll(fstruct.ajAttributes);
		}

		return struct.ajAttributes;
	}

	/**
	 * Extract method level annotations and turn them into AjAttributes.
	 * 
	 * @param method
	 * @param type
	 * @param context
	 * @param msgHandler
	 * @return list of AjAttributes
	 */
	public static List<AjAttribute> readAj5MethodAttributes(Method method, BcelMethod bMethod, ResolvedType type,
			ResolvedPointcutDefinition preResolvedPointcut, ISourceContext context, IMessageHandler msgHandler) {
		if (method.getName().startsWith(NameMangler.PREFIX)) {
			return Collections.emptyList(); // already dealt with by ajc...
		}

		AjAttributeMethodStruct struct = new AjAttributeMethodStruct(method, bMethod, type, context, msgHandler);
		Attribute[] attributes = method.getAttributes();

		// we remember if we found one @AJ annotation for minimal semantic error
		// reporting
		// the real reporting beeing done thru AJDT and the compiler mapping @AJ
		// to AjAtttribute
		// or thru APT
		//
		// Note: we could actually skip the whole thing if type is not itself an
		// @Aspect
		// but then we would not see any warning. We do bypass for pointcut but
		// not for advice since it would
		// be too silent.
		boolean hasAtAspectJAnnotation = false;
		boolean hasAtAspectJAnnotationMustReturnVoid = false;
		for (int i = 0; i < attributes.length; i++) {
			Attribute attribute = attributes[i];
			try {
				if (acceptAttribute(attribute)) {
					RuntimeAnnos rvs = (RuntimeAnnos) attribute;
					hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid
							|| handleBeforeAnnotation(rvs, struct, preResolvedPointcut);
					hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid
							|| handleAfterAnnotation(rvs, struct, preResolvedPointcut);
					hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid
							|| handleAfterReturningAnnotation(rvs, struct, preResolvedPointcut, bMethod);
					hasAtAspectJAnnotationMustReturnVoid = hasAtAspectJAnnotationMustReturnVoid
							|| handleAfterThrowingAnnotation(rvs, struct, preResolvedPointcut, bMethod);
					hasAtAspectJAnnotation = hasAtAspectJAnnotation || handleAroundAnnotation(rvs, struct, preResolvedPointcut);
					// there can only be one RuntimeVisible bytecode attribute
					break;
				}
			} catch (ReturningFormalNotDeclaredInAdviceSignatureException e) {
				msgHandler.handleMessage(new Message(WeaverMessages.format(WeaverMessages.RETURNING_FORMAL_NOT_DECLARED_IN_ADVICE,
						e.getFormalName()), IMessage.ERROR, null, bMethod.getSourceLocation()));
			} catch (ThrownFormalNotDeclaredInAdviceSignatureException e) {
				msgHandler.handleMessage(new Message(WeaverMessages.format(WeaverMessages.THROWN_FORMAL_NOT_DECLARED_IN_ADVICE,
						e.getFormalName()), IMessage.ERROR, null, bMethod.getSourceLocation()));
			}
		}
		hasAtAspectJAnnotation = hasAtAspectJAnnotation || hasAtAspectJAnnotationMustReturnVoid;

		// semantic check - must be in an @Aspect [remove if previous block
		// bypassed in advance]
		if (hasAtAspectJAnnotation && !type.isAspect()) { // isAnnotationStyleAspect())
			// {
			msgHandler.handleMessage(new Message("Found @AspectJ annotations in a non @Aspect type '" + type.getName() + "'",
					IMessage.WARNING, null, type.getSourceLocation()));
			// go ahead
		}
		// semantic check - advice must be public
		if (hasAtAspectJAnnotation && !struct.method.isPublic()) {
			msgHandler.handleMessage(new Message("Found @AspectJ annotation on a non public advice '"
					+ methodToString(struct.method) + "'", IMessage.ERROR, null, type.getSourceLocation()));
			// go ahead
		}

		// semantic check - advice must not be static
		if (hasAtAspectJAnnotation && struct.method.isStatic()) {
			msgHandler.handleMessage(MessageUtil.error("Advice cannot be declared static '" + methodToString(struct.method) + "'",
					type.getSourceLocation()));
			// new Message(
			// "Advice cannot be declared static '" +
			// methodToString(struct.method) + "'",
			// IMessage.ERROR,
			// null,
			// type.getSourceLocation()
			// )
			// );
			// go ahead
		}

		// semantic check for non around advice must return void
		if (hasAtAspectJAnnotationMustReturnVoid && !Type.VOID.equals(struct.method.getReturnType())) {
			msgHandler.handleMessage(new Message("Found @AspectJ annotation on a non around advice not returning void '"
					+ methodToString(struct.method) + "'", IMessage.ERROR, null, type.getSourceLocation()));
			// go ahead
		}

		return struct.ajAttributes;
	}

	/**
	 * Extract field level annotations and turn them into AjAttributes.
	 * 
	 * @param field
	 * @param type
	 * @param context
	 * @param msgHandler
	 * @return list of AjAttributes, always empty for now
	 */
	public static List<AjAttribute> readAj5FieldAttributes(Field field, BcelField bField, ResolvedType type,
			ISourceContext context, IMessageHandler msgHandler) {
		// Note: field annotation are for ITD and DEOW - processed at class
		// level directly
		return Collections.emptyList();
	}

	/**
	 * Read @Aspect
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handleAspectAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeStruct struct) {
		AnnotationGen aspect = getAnnotation(runtimeAnnotations, AjcMemberMaker.ASPECT_ANNOTATION);
		if (aspect != null) {
			// semantic check for inheritance (only one level up)
			boolean extendsAspect = false;
			if (!"java.lang.Object".equals(struct.enclosingType.getSuperclass().getName())) {
				if (!struct.enclosingType.getSuperclass().isAbstract() && struct.enclosingType.getSuperclass().isAspect()) {
					reportError("cannot extend a concrete aspect", struct);
					return false;
				}
				extendsAspect = struct.enclosingType.getSuperclass().isAspect();
			}

			NameValuePair aspectPerClause = getAnnotationElement(aspect, VALUE);
			final PerClause perClause;
			if (aspectPerClause == null) {
				// empty value means singleton unless inherited
				if (!extendsAspect) {
					perClause = new PerSingleton();
				} else {
					perClause = new PerFromSuper(struct.enclosingType.getSuperclass().getPerClause().getKind());
				}
			} else {
				String perX = aspectPerClause.getValue().stringifyValue();
				if (perX == null || perX.length() <= 0) {
					perClause = new PerSingleton();
				} else {
					perClause = parsePerClausePointcut(perX, struct);
				}
			}
			if (perClause == null) {
				// could not parse it, ignore the aspect
				return false;
			} else {
				perClause.setLocation(struct.context, -1, -1);// struct.context.getOffset(),
				// struct.context.getOffset()+1);//FIXME
				// AVASM
				// Not setting version here
				// struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo());
				AjAttribute.Aspect aspectAttribute = new AjAttribute.Aspect(perClause);
				struct.ajAttributes.add(aspectAttribute);
				FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
				final IScope binding;
				binding = new BindingScope(struct.enclosingType, struct.context, bindings);

				// // we can't resolve here since the perclause typically refers
				// to pointcuts
				// // defined in the aspect that we haven't told the
				// BcelObjectType about yet.
				//
				// perClause.resolve(binding);

				// so we prepare to do it later...
				aspectAttribute.setResolutionScope(binding);
				return true;
			}
		}
		return false;
	}

	/**
	 * Read a perClause, returns null on failure and issue messages
	 * 
	 * @param perClauseString like "pertarget(.....)"
	 * @param struct for which we are parsing the per clause
	 * @return a PerClause instance
	 */
	private static PerClause parsePerClausePointcut(String perClauseString, AjAttributeStruct struct) {
		final String pointcutString;
		Pointcut pointcut = null;
		TypePattern typePattern = null;
		final PerClause perClause;
		if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERCFLOW.getName())) {
			pointcutString = PerClause.KindAnnotationPrefix.PERCFLOW.extractPointcut(perClauseString);
			pointcut = parsePointcut(pointcutString, struct, false);
			perClause = new PerCflow(pointcut, false);
		} else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERCFLOWBELOW.getName())) {
			pointcutString = PerClause.KindAnnotationPrefix.PERCFLOWBELOW.extractPointcut(perClauseString);
			pointcut = parsePointcut(pointcutString, struct, false);
			perClause = new PerCflow(pointcut, true);
		} else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERTARGET.getName())) {
			pointcutString = PerClause.KindAnnotationPrefix.PERTARGET.extractPointcut(perClauseString);
			pointcut = parsePointcut(pointcutString, struct, false);
			perClause = new PerObject(pointcut, false);
		} else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERTHIS.getName())) {
			pointcutString = PerClause.KindAnnotationPrefix.PERTHIS.extractPointcut(perClauseString);
			pointcut = parsePointcut(pointcutString, struct, false);
			perClause = new PerObject(pointcut, true);
		} else if (perClauseString.startsWith(PerClause.KindAnnotationPrefix.PERTYPEWITHIN.getName())) {
			pointcutString = PerClause.KindAnnotationPrefix.PERTYPEWITHIN.extractPointcut(perClauseString);
			typePattern = parseTypePattern(pointcutString, struct);
			perClause = new PerTypeWithin(typePattern);
		} else if (perClauseString.equalsIgnoreCase(PerClause.SINGLETON.getName() + "()")) {
			perClause = new PerSingleton();
		} else {
			// could not parse the @AJ perclause - fallback to singleton and
			// issue an error
			reportError("@Aspect per clause cannot be read '" + perClauseString + "'", struct);
			return null;
		}

		if (!PerClause.SINGLETON.equals(perClause.getKind()) && !PerClause.PERTYPEWITHIN.equals(perClause.getKind())
				&& pointcut == null) {
			// we could not parse the pointcut
			return null;
		}
		if (PerClause.PERTYPEWITHIN.equals(perClause.getKind()) && typePattern == null) {
			// we could not parse the type pattern
			return null;
		}
		return perClause;
	}

	/**
	 * Read @DeclarePrecedence
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handlePrecedenceAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeStruct struct) {
		AnnotationGen aspect = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPRECEDENCE_ANNOTATION);
		if (aspect != null) {
			NameValuePair precedence = getAnnotationElement(aspect, VALUE);
			if (precedence != null) {
				String precedencePattern = precedence.getValue().stringifyValue();
				PatternParser parser = new PatternParser(precedencePattern);
				DeclarePrecedence ajPrecedence = parser.parseDominates();
				struct.ajAttributes.add(new AjAttribute.DeclareAttribute(ajPrecedence));
				return true;
			}
		}
		return false;
	}

	// /**
	// * Read @DeclareImplements
	// *
	// * @param runtimeAnnotations
	// * @param struct
	// * @return true if found
	// */
	// private static boolean
	// handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations,
	// AjAttributeFieldStruct
	// struct) {//, ResolvedPointcutDefinition preResolvedPointcut) {
	// Annotation deci = getAnnotation(runtimeAnnotations,
	// AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION);
	// if (deci != null) {
	// ElementNameValuePairGen deciPatternNVP = getAnnotationElement(deci,
	// VALUE);
	// String deciPattern = deciPatternNVP.getValue().stringifyValue();
	// if (deciPattern != null) {
	// TypePattern typePattern = parseTypePattern(deciPattern, struct);
	// ResolvedType fieldType =
	// UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld());
	// if (fieldType.isPrimitiveType()) {
	// return false;
	// } else if (fieldType.isInterface()) {
	// TypePattern parent = new
	// ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()),
	// false, false);
	// parent.resolve(struct.enclosingType.getWorld());
	// List parents = new ArrayList(1);
	// parents.add(parent);
	// //TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ??
	// struct.ajAttributes.add(
	// new AjAttribute.DeclareAttribute(
	// new DeclareParents(
	// typePattern,
	// parents,
	// false
	// )
	// )
	// );
	// return true;
	// } else {
	// reportError("@DeclareImplements: can only be used on field whose type is an interface",
	// struct);
	// return false;
	// }
	// }
	// }
	// return false;
	// }

	/**
	 * Read @DeclareParents
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handleDeclareParentsAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeFieldStruct struct) {// ,
		// ResolvedPointcutDefinition
		// preResolvedPointcut)
		// {
		AnnotationGen decp = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPARENTS_ANNOTATION);
		if (decp != null) {
			NameValuePair decpPatternNVP = getAnnotationElement(decp, VALUE);
			String decpPattern = decpPatternNVP.getValue().stringifyValue();
			if (decpPattern != null) {
				TypePattern typePattern = parseTypePattern(decpPattern, struct);
				ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(
						struct.enclosingType.getWorld());
				if (fieldType.isParameterizedOrRawType()) {
					fieldType = fieldType.getGenericType();
				}
				if (fieldType.isInterface()) {
					TypePattern parent = parseTypePattern(fieldType.getName(), struct);
					FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
					IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
					// first add the declare implements like
					List<TypePattern> parents = new ArrayList<TypePattern>(1);
					parents.add(parent);
					DeclareParents dp = new DeclareParents(typePattern, parents, false);
					dp.resolve(binding); // resolves the parent and child parts of the decp

					// resolve this so that we can use it for the
					// MethodDelegateMungers below.
					// eg. '@Coloured *' will change from a WildTypePattern to
					// an 'AnyWithAnnotationTypePattern' after this resolution
					typePattern = dp.getChild(); // this retrieves the resolved version
					// TODO kick ISourceLocation sl =
					// struct.bField.getSourceLocation(); ??
					// dp.setLocation(dp.getDeclaringType().getSourceContext(),
					// dp.getDeclaringType().getSourceLocation().getOffset(),
					// dp.getDeclaringType().getSourceLocation().getOffset());
					dp.setLocation(struct.context, -1, -1); // not ideal...
					struct.ajAttributes.add(new AjAttribute.DeclareAttribute(dp));

					// do we have a defaultImpl=xxx.class (ie implementation)
					String defaultImplClassName = null;
					NameValuePair defaultImplNVP = getAnnotationElement(decp, "defaultImpl");
					if (defaultImplNVP != null) {
						ClassElementValue defaultImpl = (ClassElementValue) defaultImplNVP.getValue();
						defaultImplClassName = UnresolvedType.forSignature(defaultImpl.getClassString()).getName();
						if (defaultImplClassName.equals("org.aspectj.lang.annotation.DeclareParents")) {
							defaultImplClassName = null;
						} else {
							// check public no arg ctor
							ResolvedType impl = struct.enclosingType.getWorld().resolve(defaultImplClassName, false);
							ResolvedMember[] mm = impl.getDeclaredMethods();
							int implModifiers = impl.getModifiers();
							boolean defaultVisibilityImpl = !(Modifier.isPrivate(implModifiers)
									|| Modifier.isProtected(implModifiers) || Modifier.isPublic(implModifiers));
							boolean hasNoCtorOrANoArgOne = true;
							ResolvedMember foundOneOfIncorrectVisibility = null;
							for (int i = 0; i < mm.length; i++) {
								ResolvedMember resolvedMember = mm[i];
								if (resolvedMember.getName().equals("<init>")) {
									hasNoCtorOrANoArgOne = false;

									if (resolvedMember.getParameterTypes().length == 0) {
										if (defaultVisibilityImpl) { // default visibility implementation
											if (resolvedMember.isPublic() || resolvedMember.isDefault()) {
												hasNoCtorOrANoArgOne = true;
											} else {
												foundOneOfIncorrectVisibility = resolvedMember;
											}
										} else if (Modifier.isPublic(implModifiers)) { // public
											// implementation
											if (resolvedMember.isPublic()) {
												hasNoCtorOrANoArgOne = true;
											} else {
												foundOneOfIncorrectVisibility = resolvedMember;
											}
										}
									}
								}
								if (hasNoCtorOrANoArgOne) {
									break;
								}
							}
							if (!hasNoCtorOrANoArgOne) {
								if (foundOneOfIncorrectVisibility != null) {
									reportError(
											"@DeclareParents: defaultImpl=\""
													+ defaultImplClassName
													+ "\" has a no argument constructor, but it is of incorrect visibility.  It must be at least as visible as the type.",
											struct);
								} else {
									reportError("@DeclareParents: defaultImpl=\"" + defaultImplClassName
											+ "\" has no public no-arg constructor", struct);
								}
							}
							if (!fieldType.isAssignableFrom(impl)) {
								reportError("@DeclareParents: defaultImpl=\"" + defaultImplClassName
										+ "\" does not implement the interface '" + fieldType.toString() + "'", struct);
							}
						}

					}

					// then iterate on field interface hierarchy (not object)
					boolean hasAtLeastOneMethod = false;
					Iterator<ResolvedMember> methodIterator = fieldType.getMethodsIncludingIntertypeDeclarations(false, true);
					while (methodIterator.hasNext()) {
						ResolvedMember method = methodIterator.next();
						if (method.isAbstract()) {
							// moved to be detected at weave time if the target
							// doesnt implement the methods
							// if (defaultImplClassName == null) {
							// // non marker interface with no default impl
							// provided
							// reportError("@DeclareParents: used with a non marker interface and no defaultImpl=\"...\" provided",
							// struct);
							// return false;
							// }
							hasAtLeastOneMethod = true;
							// What we are saying here:
							// We have this method 'method' and we want to put a
							// forwarding method into a type that matches
							// typePattern that should delegate to the version
							// of the method in 'defaultImplClassName'

							// Now the method may be from a supertype but the
							// declaring type of the method we pass into the
							// type
							// munger is what is used to determine the type of
							// the field that hosts the delegate instance.
							// So here we create a modified method with an
							// alternative declaring type so that we lookup
							// the right field. See pr164016.
							MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType, defaultImplClassName, typePattern);
							mdtm.setFieldType(fieldType);
							mdtm.setSourceLocation(struct.enclosingType.getSourceLocation());
							struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm));
						}
					}
					// successful so far, we thus need a bcel type munger to have
					// a field hosting the mixin in the target type
					if (hasAtLeastOneMethod && defaultImplClassName != null) {
						ResolvedMember fieldHost = AjcMemberMaker.itdAtDeclareParentsField(null, fieldType, struct.enclosingType);
						struct.ajAttributes.add(new AjAttribute.TypeMunger(new MethodDelegateTypeMunger.FieldHostTypeMunger(
								fieldHost, struct.enclosingType, typePattern)));
					}
					return true;
				} else {
					reportError("@DeclareParents: can only be used on a field whose type is an interface", struct);
					return false;
				}
			}
		}
		return false;
	}

	/**
	 * Return a nicely formatted method string, for example: int X.foo(java.lang.String)
	 */
	public static String getMethodForMessage(AjAttributeMethodStruct methodstructure) {
		StringBuffer sb = new StringBuffer();
		sb.append("Method '");
		sb.append(methodstructure.method.getReturnType().toString());
		sb.append(" ").append(methodstructure.enclosingType).append(".").append(methodstructure.method.getName());
		sb.append("(");
		Type[] args = methodstructure.method.getArgumentTypes();
		if (args != null) {
			for (int t = 0; t < args.length; t++) {
				if (t > 0) {
					sb.append(",");
				}
				sb.append(args[t].toString());
			}
		}
		sb.append(")'");
		return sb.toString();
	}

	/**
	 * Process any @DeclareMixin annotation.
	 * 
	 * Example Declaration <br>
	 * 
	 * @DeclareMixin("Foo+") public I createImpl(Object o) { return new Impl(o); }
	 * 
	 * <br>
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handleDeclareMixinAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct) {
		AnnotationGen declareMixinAnnotation = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREMIXIN_ANNOTATION);
		if (declareMixinAnnotation == null) {
			// No annotation found
			return false;
		}
		Method annotatedMethod = struct.method;
		World world = struct.enclosingType.getWorld();
		NameValuePair declareMixinPatternNameValuePair = getAnnotationElement(declareMixinAnnotation, VALUE);

		// declareMixinPattern could be of the form "Bar*" or "A || B" or "Foo+"
		String declareMixinPattern = declareMixinPatternNameValuePair.getValue().stringifyValue();
		TypePattern targetTypePattern = parseTypePattern(declareMixinPattern, struct);

		// Return value of the annotated method is the interface or class that the mixin delegate should have
		ResolvedType methodReturnType = UnresolvedType.forSignature(annotatedMethod.getReturnType().getSignature()).resolve(world);
		if (methodReturnType.isParameterizedOrRawType()) {
			methodReturnType = methodReturnType.getGenericType();
		}
		if (methodReturnType.isPrimitiveType()) {
			reportError(getMethodForMessage(struct) + ":  factory methods for a mixin cannot return void or a primitive type",
					struct);
			return false;
		}

		if (annotatedMethod.getArgumentTypes().length > 1) {
			reportError(getMethodForMessage(struct) + ": factory methods for a mixin can take a maximum of one parameter", struct);
			return false;
		}

		// The set of interfaces to be mixed in is either:
		// supplied as a list in the 'Class[] interfaces' value in the annotation value
		// supplied as just the interface return value of the annotated method
		// supplied as just the class return value of the annotated method
		NameValuePair interfaceListSpecified = getAnnotationElement(declareMixinAnnotation, "interfaces"); 

		List<TypePattern> newParents = new ArrayList<TypePattern>(1);
		List<ResolvedType> newInterfaceTypes = new ArrayList<ResolvedType>(1);
		if (interfaceListSpecified != null) {
			ArrayElementValue arrayOfInterfaceTypes = (ArrayElementValue) interfaceListSpecified.getValue();
			int numberOfTypes = arrayOfInterfaceTypes.getElementValuesArraySize();
			ElementValue[] theTypes = arrayOfInterfaceTypes.getElementValuesArray();
			for (int i = 0; i < numberOfTypes; i++) {
				ClassElementValue interfaceType = (ClassElementValue) theTypes[i];
				// Check: needs to be resolvable
				// TODO crappy replace required
				ResolvedType ajInterfaceType = UnresolvedType.forSignature(interfaceType.getClassString().replace("/", "."))
						.resolve(world);
				if (ajInterfaceType.isMissing() || !ajInterfaceType.isInterface()) {
					reportError(
							"Types listed in the 'interfaces' DeclareMixin annotation value must be valid interfaces. This is invalid: "
									+ ajInterfaceType.getName(), struct); // TODO better error location, use the method position
					return false;
				}
				if (!ajInterfaceType.isAssignableFrom(methodReturnType)) {
					reportError(getMethodForMessage(struct) + ": factory method does not return something that implements '"
							+ ajInterfaceType.getName() + "'", struct);
					return false;
				}
				newInterfaceTypes.add(ajInterfaceType);
				// Checking that it is a superinterface of the methods return value is done at weave time
				TypePattern newParent = parseTypePattern(ajInterfaceType.getName(), struct);
				newParents.add(newParent);
			}
		} else {
			if (methodReturnType.isClass()) {
				reportError(
						getMethodForMessage(struct)
								+ ": factory methods for a mixin must either return an interface type or specify interfaces in the annotation and return a class",
						struct);
				return false;
			}
			// Use the method return type: this might be a class or an interface
			TypePattern newParent = parseTypePattern(methodReturnType.getName(), struct);
			newInterfaceTypes.add(methodReturnType);
			newParents.add(newParent);
		}
		if (newParents.size() == 0) {
			// Warning: did they foolishly put @DeclareMixin(value="Bar+",interfaces={})
			// TODO output warning
			return false;
		}

		// Create the declare parents that will add the interfaces to matching targets
		FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0];
		IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);
		// how do we mark this as a decp due to decmixin?
		DeclareParents dp = new DeclareParentsMixin(targetTypePattern, newParents);
		dp.resolve(binding);
		targetTypePattern = dp.getChild();

		dp.setLocation(struct.context, -1, -1); // not ideal...
		struct.ajAttributes.add(new AjAttribute.DeclareAttribute(dp));

		// The factory method for building the implementation is the
		// one attached to the annotation:
		// Method implementationFactory = struct.method;

		boolean hasAtLeastOneMethod = false;

		for (Iterator<ResolvedType> iterator = newInterfaceTypes.iterator(); iterator.hasNext();) {
			ResolvedType typeForDelegation = iterator.next();
			// TODO check for overlapping interfaces. Eg. A implements I, I extends J - if they specify interfaces={I,J} we dont
			// want to do any methods twice
			ResolvedMember[] methods = typeForDelegation.getMethodsWithoutIterator(true, false, false).toArray(
					new ResolvedMember[0]);
			for (int i = 0; i < methods.length; i++) {
				ResolvedMember method = methods[i];
				if (method.isAbstract()) {
					hasAtLeastOneMethod = true;
					if (method.hasBackingGenericMember()) {
						method = method.getBackingGenericMember();
					}
					MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType, "",
							targetTypePattern, struct.method.getName(), struct.method.getSignature());
					mdtm.setFieldType(methodReturnType);
					mdtm.setSourceLocation(struct.enclosingType.getSourceLocation());
					struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm));
				}
			}
		}
		// if any method delegate was created then a field to hold the delegate instance must also be added
		if (hasAtLeastOneMethod) {
			ResolvedMember fieldHost = AjcMemberMaker.itdAtDeclareParentsField(null, methodReturnType, struct.enclosingType);
			struct.ajAttributes.add(new AjAttribute.TypeMunger(new MethodDelegateTypeMunger.FieldHostTypeMunger(fieldHost,
					struct.enclosingType, targetTypePattern)));
		}
		return true;
	}

	/**
	 * Read @Before
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handleBeforeAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
			ResolvedPointcutDefinition preResolvedPointcut) {
		AnnotationGen before = getAnnotation(runtimeAnnotations, AjcMemberMaker.BEFORE_ANNOTATION);
		if (before != null) {
			NameValuePair 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);
				} catch (UnreadableDebugInfoException unreadableDebugInfoException) {
					return false;
				}
				IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);

				// joinpoint, staticJoinpoint binding
				int extraArgument = extractExtraArgument(struct.method);

				Pointcut pc = null;
				if (preResolvedPointcut != null) {
					pc = preResolvedPointcut.getPointcut();
					// pc.resolve(binding);
				} else {
					pc = parsePointcut(beforeAdvice.getValue().stringifyValue(), struct, false);
					if (pc == null) {
						return false;// parse error
					}
					pc = pc.resolve(binding);
				}
				setIgnoreUnboundBindingNames(pc, bindings);

				ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
						struct.bMethod.getDeclarationOffset());
				struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.Before, pc, extraArgument, sl.getOffset(), sl
						.getOffset() + 1,// FIXME AVASM
						struct.context));
				return true;
			}
		}
		return false;
	}

	/**
	 * Read @After
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handleAfterAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
			ResolvedPointcutDefinition preResolvedPointcut) {
		AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTER_ANNOTATION);
		if (after != null) {
			NameValuePair afterAdvice = getAnnotationElement(after, VALUE);
			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) {
					return false;
				}
				IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);

				// joinpoint, staticJoinpoint binding
				int extraArgument = extractExtraArgument(struct.method);

				Pointcut pc = null;
				if (preResolvedPointcut != null) {
					pc = preResolvedPointcut.getPointcut();
				} else {
					pc = parsePointcut(afterAdvice.getValue().stringifyValue(), struct, false);
					if (pc == null) {
						return false;// parse error
					}
					pc.resolve(binding);
				}
				setIgnoreUnboundBindingNames(pc, bindings);

				ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
						struct.bMethod.getDeclarationOffset());
				struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.After, pc, extraArgument, sl.getOffset(), sl
						.getOffset() + 1,// FIXME AVASM
						struct.context));
				return true;
			}
		}
		return false;
	}

	/**
	 * Read @AfterReturning
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handleAfterReturningAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
			ResolvedPointcutDefinition preResolvedPointcut, BcelMethod owningMethod)
			throws ReturningFormalNotDeclaredInAdviceSignatureException {
		AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERRETURNING_ANNOTATION);
		if (after != null) {
			NameValuePair annValue = getAnnotationElement(after, VALUE);
			NameValuePair annPointcut = getAnnotationElement(after, POINTCUT);
			NameValuePair annReturned = getAnnotationElement(after, RETURNING);

			// extract the pointcut and returned type/binding - do some checks
			String pointcut = null;
			String returned = null;
			if ((annValue != null && annPointcut != null) || (annValue == null && annPointcut == null)) {
				reportError("@AfterReturning: either 'value' or 'poincut' must be provided, not both", struct);
				return false;
			}
			if (annValue != null) {
				pointcut = annValue.getValue().stringifyValue();
			} else {
				pointcut = annPointcut.getValue().stringifyValue();
			}
			if (isNullOrEmpty(pointcut)) {
				reportError("@AfterReturning: either 'value' or 'poincut' must be provided, not both", struct);
				return false;
			}
			if (annReturned != null) {
				returned = annReturned.getValue().stringifyValue();
				if (isNullOrEmpty(returned)) {
					returned = null;
				} else {
					// check that thrownFormal exists as the last parameter in
					// the advice
					String[] pNames = owningMethod.getParameterNames();
					if (pNames == null || pNames.length == 0 || !Arrays.asList(pNames).contains(returned)) {
						throw new ReturningFormalNotDeclaredInAdviceSignatureException(returned);
					}
				}
			}
			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];
			try {
				bindings = (returned == null ? extractBindings(struct) : extractBindings(struct, returned));
			} catch (UnreadableDebugInfoException unreadableDebugInfoException) {
				return false;
			}
			IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);

			// joinpoint, staticJoinpoint binding
			int extraArgument = extractExtraArgument(struct.method);

			// return binding
			if (returned != null) {
				extraArgument |= Advice.ExtraArgument;
			}

			Pointcut pc = null;
			if (preResolvedPointcut != null) {
				pc = preResolvedPointcut.getPointcut();
			} else {
				pc = parsePointcut(pointcut, struct, false);
				if (pc == null) {
					return false;// parse error
				}
				pc.resolve(binding);
			}
			setIgnoreUnboundBindingNames(pc, bindings);

			ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
					struct.bMethod.getDeclarationOffset());
			struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.AfterReturning, pc, extraArgument, sl.getOffset(),
					sl.getOffset() + 1,// FIXME AVASM
					struct.context));
			return true;
		}
		return false;
	}

	/**
	 * Read @AfterThrowing
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handleAfterThrowingAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
			ResolvedPointcutDefinition preResolvedPointcut, BcelMethod owningMethod)
			throws ThrownFormalNotDeclaredInAdviceSignatureException {
		AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERTHROWING_ANNOTATION);
		if (after != null) {
			NameValuePair annValue = getAnnotationElement(after, VALUE);
			NameValuePair annPointcut = getAnnotationElement(after, POINTCUT);
			NameValuePair annThrown = getAnnotationElement(after, THROWING);

			// extract the pointcut and throwned type/binding - do some checks
			String pointcut = null;
			String thrownFormal = null;
			if ((annValue != null && annPointcut != null) || (annValue == null && annPointcut == null)) {
				reportError("@AfterThrowing: either 'value' or 'poincut' must be provided, not both", struct);
				return false;
			}
			if (annValue != null) {
				pointcut = annValue.getValue().stringifyValue();
			} else {
				pointcut = annPointcut.getValue().stringifyValue();
			}
			if (isNullOrEmpty(pointcut)) {
				reportError("@AfterThrowing: either 'value' or 'poincut' must be provided, not both", struct);
				return false;
			}
			if (annThrown != null) {
				thrownFormal = annThrown.getValue().stringifyValue();
				if (isNullOrEmpty(thrownFormal)) {
					thrownFormal = null;
				} else {
					// check that thrownFormal exists as the last parameter in
					// the advice
					String[] pNames = owningMethod.getParameterNames();
					if (pNames == null || pNames.length == 0 || !Arrays.asList(pNames).contains(thrownFormal)) {
						throw new ThrownFormalNotDeclaredInAdviceSignatureException(thrownFormal);
					}
				}
			}
			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];
			try {
				bindings = (thrownFormal == null ? extractBindings(struct) : extractBindings(struct, thrownFormal));
			} catch (UnreadableDebugInfoException unreadableDebugInfoException) {
				return false;
			}
			IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);

			// joinpoint, staticJoinpoint binding
			int extraArgument = extractExtraArgument(struct.method);

			// return binding
			if (thrownFormal != null) {
				extraArgument |= Advice.ExtraArgument;
			}

			Pointcut pc = null;
			if (preResolvedPointcut != null) {
				pc = preResolvedPointcut.getPointcut();
			} else {
				pc = parsePointcut(pointcut, struct, false);
				if (pc == null) {
					return false;// parse error
				}
				pc.resolve(binding);
			}
			setIgnoreUnboundBindingNames(pc, bindings);

			ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
					struct.bMethod.getDeclarationOffset());
			struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.AfterThrowing, pc, extraArgument, sl.getOffset(), sl
					.getOffset() + 1, struct.context));
			return true;
		}
		return false;
	}

	/**
	 * Read @Around
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handleAroundAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct,
			ResolvedPointcutDefinition preResolvedPointcut) {
		AnnotationGen around = getAnnotation(runtimeAnnotations, AjcMemberMaker.AROUND_ANNOTATION);
		if (around != null) {
			NameValuePair aroundAdvice = getAnnotationElement(around, VALUE);
			if (aroundAdvice != null) {
				// 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);
				} catch (UnreadableDebugInfoException unreadableDebugInfoException) {
					return false;
				}
				IScope binding = new BindingScope(struct.enclosingType, struct.context, bindings);

				// joinpoint, staticJoinpoint binding
				int extraArgument = extractExtraArgument(struct.method);

				Pointcut pc = null;
				if (preResolvedPointcut != null) {
					pc = preResolvedPointcut.getPointcut();
				} else {
					pc = parsePointcut(aroundAdvice.getValue().stringifyValue(), struct, false);
					if (pc == null) {
						return false;// parse error
					}
					pc.resolve(binding);
				}
				setIgnoreUnboundBindingNames(pc, bindings);

				ISourceLocation sl = struct.context.makeSourceLocation(struct.bMethod.getDeclarationLineNumber(),
						struct.bMethod.getDeclarationOffset());
				struct.ajAttributes.add(new AjAttribute.AdviceAttribute(AdviceKind.Around, pc, extraArgument, sl.getOffset(), sl
						.getOffset() + 1,// FIXME AVASM
						struct.context));
				return true;
			}
		}
		return false;
	}

	/**
	 * Read @Pointcut and handle the resolving in a lazy way to deal with pointcut references
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if a pointcut was handled
	 */
	private static boolean handlePointcutAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeMethodStruct struct) {
		AnnotationGen pointcut = getAnnotation(runtimeAnnotations, AjcMemberMaker.POINTCUT_ANNOTATION);
		if (pointcut == null) {
			return false;
		}
		NameValuePair 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()))) {
			reportWarning("Found @Pointcut on a method not returning 'void' or not 'public static boolean'", struct);
			// no need to stop
		}

		// semantic check: the method must not throw anything
		if (struct.method.getExceptionTable() != null) {
			reportWarning("Found @Pointcut on a method throwing exception", struct);
			// no need to stop
		}

		String argumentNames = getArgNamesValue(pointcut);
		if (argumentNames != null) {
			struct.unparsedArgumentNames = argumentNames;
		}
		// this/target/args binding
		final IScope binding;
		try {
			if (struct.method.isAbstract()) {
				binding = null;
			} else {
				binding = new BindingScope(struct.enclosingType, struct.context, extractBindings(struct));
			}
		} catch (UnreadableDebugInfoException e) {
			return false;
		}

		UnresolvedType[] argumentTypes = new UnresolvedType[struct.method.getArgumentTypes().length];
		for (int i = 0; i < argumentTypes.length; i++) {
			argumentTypes[i] = UnresolvedType.forSignature(struct.method.getArgumentTypes()[i].getSignature());
		}

		Pointcut pc = null;
		if (struct.method.isAbstract()) {
			if ((pointcutExpr != null && isNullOrEmpty(pointcutExpr.getValue().stringifyValue())) || pointcutExpr == null) {
				// abstract pointcut
				// leave pc = null
			} else {
				reportError("Found defined @Pointcut on an abstract method", struct);
				return false;// stop
			}
		} else {
			if (pointcutExpr == null || isNullOrEmpty(pointcutExpr.getValue().stringifyValue())) {
				// the matches nothing pointcut (125475/125480) - perhaps not as
				// cleanly supported as it could be.
			} else {
				// if (pointcutExpr != null) {
				// use a LazyResolvedPointcutDefinition so that the pointcut is
				// resolved lazily
				// since for it to be resolved, we will need other pointcuts to
				// be registered as well
				pc = parsePointcut(pointcutExpr.getValue().stringifyValue(), struct, true);
				if (pc == null) {
					return false;// parse error
				}
				pc.setLocation(struct.context, -1, -1);// FIXME AVASM !! bMethod
				// is null here..
				// } else {
				// reportError("Found undefined @Pointcut on a non-abstract method",
				// struct);
				// return false;
				// }
			}
		}
		// do not resolve binding now but lazily
		struct.ajAttributes.add(new AjAttribute.PointcutDeclarationAttribute(new LazyResolvedPointcutDefinition(
				struct.enclosingType, struct.method.getModifiers(), struct.method.getName(), argumentTypes, UnresolvedType
						.forSignature(struct.method.getReturnType().getSignature()), pc,// can
				// be
				// null
				// for
				// abstract
				// pointcut
				binding // can be null for abstract pointcut
				)));
		return true;
	}

	/**
	 * Read @DeclareError, @DeclareWarning
	 * 
	 * @param runtimeAnnotations
	 * @param struct
	 * @return true if found
	 */
	private static boolean handleDeclareErrorOrWarningAnnotation(AsmManager model, RuntimeAnnos runtimeAnnotations,
			AjAttributeFieldStruct struct) {
		AnnotationGen error = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREERROR_ANNOTATION);
		boolean hasError = false;
		if (error != null) {
			NameValuePair declareError = getAnnotationElement(error, VALUE);
			if (declareError != null) {
				if (!STRING_DESC.equals(struct.field.getSignature()) || struct.field.getConstantValue() == null) {
					reportError("@DeclareError used on a non String constant field", struct);
					return false;
				}
				Pointcut pc = parsePointcut(declareError.getValue().stringifyValue(), struct, false);
				if (pc == null) {
					hasError = false;// cannot parse pointcut
				} else {
					DeclareErrorOrWarning deow = new DeclareErrorOrWarning(true, pc, struct.field.getConstantValue().toString());
					setDeclareErrorOrWarningLocation(model, deow, struct);
					struct.ajAttributes.add(new AjAttribute.DeclareAttribute(deow));
					hasError = true;
				}
			}
		}
		AnnotationGen warning = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREWARNING_ANNOTATION);
		boolean hasWarning = false;
		if (warning != null) {
			NameValuePair declareWarning = getAnnotationElement(warning, VALUE);
			if (declareWarning != null) {
				if (!STRING_DESC.equals(struct.field.getSignature()) || struct.field.getConstantValue() == null) {
					reportError("@DeclareWarning used on a non String constant field", struct);
					return false;
				}
				Pointcut pc = parsePointcut(declareWarning.getValue().stringifyValue(), struct, false);
				if (pc == null) {
					hasWarning = false;// cannot parse pointcut
				} else {
					DeclareErrorOrWarning deow = new DeclareErrorOrWarning(false, pc, struct.field.getConstantValue().toString());
					setDeclareErrorOrWarningLocation(model, deow, struct);
					struct.ajAttributes.add(new AjAttribute.DeclareAttribute(deow));
					return hasWarning = true;
				}
			}
		}
		return hasError || hasWarning;
	}

	/**
	 * Sets the location for the declare error / warning using the corresponding IProgramElement in the structure model. This will
	 * only fix bug 120356 if compiled with -emacssym, however, it does mean that the cross references view in AJDT will show the
	 * correct information.
	 * 
	 * Other possibilities for fix: 1. using the information in ajcDeclareSoft (if this is set correctly) which will fix the problem
	 * if compiled with ajc but not if compiled with javac. 2. creating an AjAttribute called FieldDeclarationLineNumberAttribute
	 * (much like MethodDeclarationLineNumberAttribute) which we can ask for the offset. This will again only fix bug 120356 when
	 * compiled with ajc.
	 * 
	 * @param deow
	 * @param struct
	 */
	private static void setDeclareErrorOrWarningLocation(AsmManager model, DeclareErrorOrWarning deow, AjAttributeFieldStruct struct) {
		IHierarchy top = (model == null ? null : model.getHierarchy());
		if (top != null && top.getRoot() != null) {
			IProgramElement ipe = top.findElementForLabel(top.getRoot(), IProgramElement.Kind.FIELD, struct.field.getName());
			if (ipe != null && ipe.getSourceLocation() != null) {
				ISourceLocation sourceLocation = ipe.getSourceLocation();
				int start = sourceLocation.getOffset();
				int end = start + struct.field.getName().length();
				deow.setLocation(struct.context, start, end);
				return;
			}
		}
		deow.setLocation(struct.context, -1, -1);
	}

	/**
	 * Returns a readable representation of a method. Method.toString() is not suitable.
	 * 
	 * @param method
	 * @return a readable representation of a method
	 */
	private static String methodToString(Method method) {
		StringBuffer sb = new StringBuffer();
		sb.append(method.getName());
		sb.append(method.getSignature());
		return sb.toString();
	}

	/**
	 * Build the bindings for a given method (pointcut / advice)
	 * 
	 * @param struct
	 * @return null if no debug info is available
	 */
	private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct) throws UnreadableDebugInfoException {
		Method method = struct.method;
		String[] argumentNames = struct.getArgumentNames();

		// assert debug info was here
		if (argumentNames.length != method.getArgumentTypes().length) {
			reportError(
					"Cannot read debug info for @Aspect to handle formal binding in pointcuts (please compile with 'javac -g' or '<javac debug='true'.../>' in Ant)",
					struct);
			throw new UnreadableDebugInfoException();
		}

		List<FormalBinding> bindings = new ArrayList<FormalBinding>();
		for (int i = 0; i < argumentNames.length; i++) {
			String argumentName = argumentNames[i];
			UnresolvedType argumentType = UnresolvedType.forSignature(method.getArgumentTypes()[i].getSignature());

			// do not bind JoinPoint / StaticJoinPoint /
			// EnclosingStaticJoinPoint
			// TODO solve me : this means that the JP/SJP/ESJP cannot appear as
			// binding
			// f.e. when applying advice on advice etc
			if ((AjcMemberMaker.TYPEX_JOINPOINT.equals(argumentType)
					|| AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.equals(argumentType)
					|| AjcMemberMaker.TYPEX_STATICJOINPOINT.equals(argumentType)
					|| AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.equals(argumentType) || AjcMemberMaker.AROUND_CLOSURE_TYPE
						.equals(argumentType))) {
				// continue;// skip
				bindings.add(new FormalBinding.ImplicitFormalBinding(argumentType, argumentName, i));
			} else {
				bindings.add(new FormalBinding(argumentType, argumentName, i));
			}
		}

		return bindings.toArray(new FormalBinding[] {});
	}

	// FIXME alex deal with exclude index
	private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct, String excludeFormal)
			throws UnreadableDebugInfoException {
		FormalBinding[] bindings = extractBindings(struct);
		// int excludeIndex = -1;
		for (int i = 0; i < bindings.length; i++) {
			FormalBinding binding = bindings[i];
			if (binding.getName().equals(excludeFormal)) {
				// excludeIndex = i;
				bindings[i] = new FormalBinding.ImplicitFormalBinding(binding.getType(), binding.getName(), binding.getIndex());
				break;
			}
		}
		return bindings;
		//
		// if (excludeIndex >= 0) {
		// FormalBinding[] bindingsFiltered = new
		// FormalBinding[bindings.length-1];
		// int k = 0;
		// for (int i = 0; i < bindings.length; i++) {
		// if (i == excludeIndex) {
		// ;
		// } else {
		// bindingsFiltered[k] = new FormalBinding(bindings[i].getType(),
		// bindings[i].getName(), k);
		// k++;
		// }
		// }
		// return bindingsFiltered;
		// } else {
		// return bindings;
		// }
	}

	/**
	 * Compute the flag for the xxxJoinPoint extra argument
	 * 
	 * @param method
	 * @return extra arg flag
	 */
	private static int extractExtraArgument(Method method) {
		Type[] methodArgs = method.getArgumentTypes();
		String[] sigs = new String[methodArgs.length];
		for (int i = 0; i < methodArgs.length; i++) {
			sigs[i] = methodArgs[i].getSignature();
		}
		return extractExtraArgument(sigs);
	}

	/**
	 * Compute the flag for the xxxJoinPoint extra argument
	 * 
	 * @param argumentSignatures
	 * @return extra arg flag
	 */
	public static int extractExtraArgument(String[] argumentSignatures) {
		int extraArgument = 0;
		for (int i = 0; i < argumentSignatures.length; i++) {
			if (AjcMemberMaker.TYPEX_JOINPOINT.getSignature().equals(argumentSignatures[i])) {
				extraArgument |= Advice.ThisJoinPoint;
			} else if (AjcMemberMaker.TYPEX_PROCEEDINGJOINPOINT.getSignature().equals(argumentSignatures[i])) {
				extraArgument |= Advice.ThisJoinPoint;
			} else if (AjcMemberMaker.TYPEX_STATICJOINPOINT.getSignature().equals(argumentSignatures[i])) {
				extraArgument |= Advice.ThisJoinPointStaticPart;
			} else if (AjcMemberMaker.TYPEX_ENCLOSINGSTATICJOINPOINT.getSignature().equals(argumentSignatures[i])) {
				extraArgument |= Advice.ThisEnclosingJoinPointStaticPart;
			}
		}
		return extraArgument;
	}

	/**
	 * Returns the runtime (RV/RIV) annotation of type annotationType or null if no such annotation
	 * 
	 * @param rvs
	 * @param annotationType
	 * @return annotation
	 */
	private static AnnotationGen getAnnotation(RuntimeAnnos rvs, UnresolvedType annotationType) {
		final String annotationTypeName = annotationType.getName();
		for (AnnotationGen rv : rvs.getAnnotations()) {
			if (annotationTypeName.equals(rv.getTypeName())) {
				return rv;
			}
		}
		return null;
	}

	/**
	 * Returns the value of a given element of an annotation or null if not found Caution: Does not handles default value.
	 * 
	 * @param annotation
	 * @param elementName
	 * @return annotation NVP
	 */
	private static NameValuePair getAnnotationElement(AnnotationGen annotation, String elementName) {
		for (NameValuePair element : annotation.getValues()) {
			if (elementName.equals(element.getNameString())) {
				return element;
			}
		}
		return null;
	}

	/**
	 * Return the argNames set for an annotation or null if it is not specified.
	 */
	private static String getArgNamesValue(AnnotationGen anno) {
		List<NameValuePair> elements = anno.getValues();
		for (NameValuePair element : elements) {
			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. 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
	 * @param argNamesFromAnnotation
	 * @param methodStruct
	 * @return method argument names
	 */
	private static String[] getMethodArgumentNames(Method method, String argNamesFromAnnotation,
			AjAttributeMethodStruct methodStruct) {
		if (method.getArgumentTypes().length == 0) {
			return EMPTY_STRINGS;
		}

		final int startAtStackIndex = method.isStatic() ? 0 : 1;
		final List<MethodArgument> arguments = new ArrayList<MethodArgument>();
		LocalVariableTable lt = method.getLocalVariableTable();
		if (lt != null) {
			LocalVariable[] lvt = lt.getLocalVariableTable();
			for (int j = 0; j < lvt.length; j++) {
				LocalVariable localVariable = lvt[j];
				if (localVariable != null) { // pr348488
					if (localVariable.getStartPC() == 0) {
						if (localVariable.getIndex() >= startAtStackIndex) {
							arguments.add(new MethodArgument(localVariable.getName(), localVariable.getIndex()));
						}
					}
				} else {
					String typename = (methodStruct.enclosingType != null ? methodStruct.enclosingType.getName() : "");
					System.err.println("AspectJ: 348488 debug: unusual local variable table for method " + typename + "."
							+ method.getName());
				}
			}
			if (arguments.size() == 0) {
				// could be cobertura code where some extra bytecode has been stuffed in at the start of the method
				// but the local variable table hasn't been repaired - for example:
				// LocalVariable(start_pc = 6, length = 40, index = 0:com.example.ExampleAspect this)
				// LocalVariable(start_pc = 6, length = 40, index = 1:org.aspectj.lang.ProceedingJoinPoint pjp)
				// LocalVariable(start_pc = 6, length = 40, index = 2:int __cobertura__line__number__)
				// LocalVariable(start_pc = 6, length = 40, index = 3:int __cobertura__branch__number__)
				LocalVariable localVariable = lvt[0];
				if (localVariable != null) { // pr348488
					if (localVariable.getStartPC() != 0) {
						// looks suspicious so let's use this information
						for (int j = 0; j < lvt.length && arguments.size() < method.getArgumentTypes().length; j++) {
							localVariable = lvt[j];
							if (localVariable.getIndex() >= startAtStackIndex) {
								arguments.add(new MethodArgument(localVariable.getName(), localVariable.getIndex()));
							}
						}
					}
				}
			}
		} else {
			// No debug info, do we have an annotation value we can rely on?
			if (argNamesFromAnnotation != null) {
				StringTokenizer st = new StringTokenizer(argNamesFromAnnotation, " ,");
				List<String> args = new ArrayList<String>();
				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 args.toArray(new String[] {});
			}
		}

		if (arguments.size() != method.getArgumentTypes().length) {
			return EMPTY_STRINGS;
		}

		// sort by index
		Collections.sort(arguments, new Comparator<MethodArgument>() {
			public int compare(MethodArgument mo, MethodArgument mo1) {
				if (mo.indexOnStack == mo1.indexOnStack) {
					return 0;
				} else if (mo.indexOnStack > mo1.indexOnStack) {
					return 1;
				} else {
					return -1;
				}
			}
		});
		String[] argumentNames = new String[arguments.size()];
		int i = 0;
		for (MethodArgument methodArgument : arguments) {
			argumentNames[i++] = methodArgument.name;
		}
		return argumentNames;
	}

	/**
	 * A method argument, used for sorting by indexOnStack (ie order in signature)
	 * 
	 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
	 */
	private static class MethodArgument {
		String name;
		int indexOnStack;

		public MethodArgument(String name, int indexOnStack) {
			this.name = name;
			this.indexOnStack = indexOnStack;
		}
	}

	/**
	 * LazyResolvedPointcutDefinition lazyly resolve the pointcut so that we have time to register all pointcut referenced before
	 * pointcut resolution happens
	 * 
	 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
	 */
	public static class LazyResolvedPointcutDefinition extends ResolvedPointcutDefinition {
		private final Pointcut m_pointcutUnresolved; // null for abstract
		// pointcut
		private final IScope m_binding;

		private Pointcut m_lazyPointcut = null;

		public LazyResolvedPointcutDefinition(UnresolvedType declaringType, int modifiers, String name,
				UnresolvedType[] parameterTypes, UnresolvedType returnType, Pointcut pointcut, IScope binding) {
			super(declaringType, modifiers, name, parameterTypes, returnType, Pointcut.makeMatchesNothing(Pointcut.RESOLVED));
			m_pointcutUnresolved = pointcut;
			m_binding = binding;
		}

		@Override
		public Pointcut getPointcut() {
			if (m_lazyPointcut == null && m_pointcutUnresolved == null) {
				m_lazyPointcut = Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
			}
			if (m_lazyPointcut == null && m_pointcutUnresolved != null) {
				m_lazyPointcut = m_pointcutUnresolved.resolve(m_binding);
				m_lazyPointcut.copyLocationFrom(m_pointcutUnresolved);
			}
			return m_lazyPointcut;
		}
	}

	/**
	 * Helper to test empty strings
	 * 
	 * @param s
	 * @return true if empty or null
	 */
	private static boolean isNullOrEmpty(String s) {
		return (s == null || s.length() <= 0);
	}

	/**
	 * Set the pointcut bindings for which to ignore unbound issues, so that we can implicitly bind xxxJoinPoint for @AJ advices
	 * 
	 * @param pointcut
	 * @param bindings
	 */
	private static void setIgnoreUnboundBindingNames(Pointcut pointcut, FormalBinding[] bindings) {
		// register ImplicitBindings as to be ignored since unbound
		// TODO is it likely to fail in a bad way if f.e. this(jp) etc ?
		List<String> ignores = new ArrayList<String>();
		for (int i = 0; i < bindings.length; i++) {
			FormalBinding formalBinding = bindings[i];
			if (formalBinding instanceof FormalBinding.ImplicitFormalBinding) {
				ignores.add(formalBinding.getName());
			}
		}
		pointcut.m_ignoreUnboundBindingForNames = ignores.toArray(new String[ignores.size()]);
	}

	/**
	 * A check exception when we cannot read debug info (needed for formal binding)
	 */
	private static class UnreadableDebugInfoException extends Exception {
	}

	/**
	 * Report an error
	 * 
	 * @param message
	 * @param location
	 */
	private static void reportError(String message, AjAttributeStruct location) {
		if (!location.handler.isIgnoring(IMessage.ERROR)) {
			location.handler.handleMessage(new Message(message, location.enclosingType.getSourceLocation(), true));
		}
	}

	// private static void reportError(String message, IMessageHandler handler, ISourceLocation sourceLocation) {
	// if (!handler.isIgnoring(IMessage.ERROR)) {
	// handler.handleMessage(new Message(message, sourceLocation, true));
	// }
	// }

	/**
	 * Report a warning
	 * 
	 * @param message
	 * @param location
	 */
	private static void reportWarning(String message, AjAttributeStruct location) {
		if (!location.handler.isIgnoring(IMessage.WARNING)) {
			location.handler.handleMessage(new Message(message, location.enclosingType.getSourceLocation(), false));
		}
	}

	/**
	 * Parse the given pointcut, return null on failure and issue an error
	 * 
	 * @param pointcutString
	 * @param struct
	 * @param allowIf
	 * @return pointcut, unresolved
	 */
	private static Pointcut parsePointcut(String pointcutString, AjAttributeStruct struct, boolean allowIf) {
		try {
			PatternParser parser = new PatternParser(pointcutString, struct.context);
			Pointcut pointcut = parser.parsePointcut();
			parser.checkEof();
			pointcut.check(null, struct.enclosingType.getWorld());
			if (!allowIf && pointcutString.indexOf("if()") >= 0 && hasIf(pointcut)) {
				reportError("if() pointcut is not allowed at this pointcut location '" + pointcutString + "'", struct);
				return null;
			}
			pointcut.setLocation(struct.context, -1, -1);// FIXME -1,-1 is not
			// good enough
			return pointcut;
		} catch (ParserException e) {
			reportError("Invalid pointcut '" + pointcutString + "': " + e.toString()
					+ (e.getLocation() == null ? "" : " at position " + e.getLocation().getStart()), struct);
			return null;
		}
	}

	private static boolean hasIf(Pointcut pointcut) {
		IfFinder visitor = new IfFinder();
		pointcut.accept(visitor, null);
		return visitor.hasIf;
	}

	/**
	 * Parse the given type pattern, return null on failure and issue an error
	 * 
	 * @param patternString
	 * @param location
	 * @return type pattern
	 */
	private static TypePattern parseTypePattern(String patternString, AjAttributeStruct location) {
		try {
			TypePattern typePattern = new PatternParser(patternString).parseTypePattern();
			typePattern.setLocation(location.context, -1, -1);// FIXME -1,-1 is
			// not good
			// enough
			return typePattern;
		} catch (ParserException e) {
			reportError("Invalid type pattern'" + patternString + "' : " + e.getLocation(), location);
			return null;
		}
	}

	static class ThrownFormalNotDeclaredInAdviceSignatureException extends Exception {

		private final String formalName;

		public ThrownFormalNotDeclaredInAdviceSignatureException(String formalName) {
			this.formalName = formalName;
		}

		public String getFormalName() {
			return formalName;
		}
	}

	static class ReturningFormalNotDeclaredInAdviceSignatureException extends Exception {

		private final String formalName;

		public ReturningFormalNotDeclaredInAdviceSignatureException(String formalName) {
			this.formalName = formalName;
		}

		public String getFormalName() {
			return formalName;
		}
	}
}