/* *******************************************************************
 * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
 * 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: 
 *     PARC     initial implementation 
 * ******************************************************************/

package org.aspectj.weaver.bcel;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.aspectj.apache.bcel.classfile.AnnotationDefault;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ExceptionTable;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.LineNumber;
import org.aspectj.apache.bcel.classfile.LineNumberTable;
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.annotation.AnnotationGen;
import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.util.GenericSignature;
import org.aspectj.util.GenericSignature.TypeVariableSignature;
import org.aspectj.util.GenericSignatureParser;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
import org.aspectj.weaver.AnnotationAJ;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.MemberKind;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.ResolvedPointcutDefinition;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.ShadowMunger;
import org.aspectj.weaver.TypeVariable;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;

//public final 
class BcelMethod extends ResolvedMemberImpl {

  private final static String ASPECTJ_ANNOTATION_PACKAGE = "org.aspectj.lang.annotation";
  private final static char PACKAGE_INITIAL_CHAR = ASPECTJ_ANNOTATION_PACKAGE.charAt(0);

	private Method method;

	// these fields are not set for many BcelMethods...
	private ShadowMunger associatedShadowMunger;
	private ResolvedPointcutDefinition preResolvedPointcut; // used when ajc has pre-resolved the pointcut of some @Advice
	private AjAttribute.EffectiveSignatureAttribute effectiveSignature;

	private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber;
	private final BcelObjectType bcelObjectType;

	private int bitflags;
	private static final int KNOW_IF_SYNTHETIC = 0x0001;
	private static final int PARAMETER_NAMES_INITIALIZED = 0x0002;
	private static final int CAN_BE_PARAMETERIZED = 0x0004;
	private static final int UNPACKED_GENERIC_SIGNATURE = 0x0008;
	private static final int IS_AJ_SYNTHETIC = 0x0040;
	private static final int IS_SYNTHETIC = 0x0080;
	private static final int IS_SYNTHETIC_INVERSE = 0x7f7f; // all bits but
	// IS_SYNTHETIC (and
	// topmost bit)
	private static final int HAS_ANNOTATIONS = 0x0400;
	private static final int HAVE_DETERMINED_ANNOTATIONS = 0x0800;

	// genericized version of return and parameter types
	private UnresolvedType genericReturnType = null;
	private UnresolvedType[] genericParameterTypes = null;

	BcelMethod(BcelObjectType declaringType, Method method) {
		super(method.getName().equals("<init>") ? CONSTRUCTOR : (method.getName().equals("<clinit>") ? STATIC_INITIALIZATION
				: METHOD), declaringType.getResolvedTypeX(), method.getModifiers(), method.getName(), method.getSignature());
		this.method = method;
		sourceContext = declaringType.getResolvedTypeX().getSourceContext();
		bcelObjectType = declaringType;
		unpackJavaAttributes();
		unpackAjAttributes(bcelObjectType.getWorld());
	}

	
This constructor expects to be passed the attributes, rather than deserializing them.
/** * This constructor expects to be passed the attributes, rather than deserializing them. */
BcelMethod(BcelObjectType declaringType, Method method, List<AjAttribute> attributes) { super(method.getName().equals("<init>") ? CONSTRUCTOR : (method.getName().equals("<clinit>") ? STATIC_INITIALIZATION : METHOD), declaringType.getResolvedTypeX(), method.getModifiers(), method.getName(), method.getSignature()); this.method = method; sourceContext = declaringType.getResolvedTypeX().getSourceContext(); bcelObjectType = declaringType; unpackJavaAttributes(); processAttributes(bcelObjectType.getWorld(), attributes); } // ---- private void unpackJavaAttributes() { ExceptionTable exnTable = method.getExceptionTable(); checkedExceptions = (exnTable == null) ? UnresolvedType.NONE : UnresolvedType.forNames(exnTable.getExceptionNames()); } @Override public String[] getParameterNames() { determineParameterNames(); return super.getParameterNames(); } public int getLineNumberOfFirstInstruction() { LineNumberTable lnt = method.getLineNumberTable(); if (lnt == null) { return -1; } LineNumber[] lns = lnt.getLineNumberTable(); if (lns == null || lns.length == 0) { return -1; } return lns[0].getLineNumber(); } public void determineParameterNames() { if ((bitflags & PARAMETER_NAMES_INITIALIZED) != 0) { return; } bitflags |= PARAMETER_NAMES_INITIALIZED; LocalVariableTable varTable = method.getLocalVariableTable(); int len = getArity(); if (varTable == null) { // do we have an annotation with the argNames value specified... AnnotationAJ[] annos = getAnnotations(); if (annos != null && annos.length != 0) { AnnotationAJ[] axs = getAnnotations(); for (int i = 0; i < axs.length; i++) { AnnotationAJ annotationX = axs[i]; String typename = annotationX.getTypeName(); if (typename.charAt(0) == PACKAGE_INITIAL_CHAR) { 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")) { AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation(); if (a != null) { List<NameValuePair> values = a.getValues(); for (NameValuePair nvPair : values) { if (nvPair.getNameString().equals("argNames")) { String argNames = nvPair.getValue().stringifyValue(); StringTokenizer argNameTokenizer = new StringTokenizer(argNames, " ,"); List<String> argsList = new ArrayList<String>(); while (argNameTokenizer.hasMoreTokens()) { argsList.add(argNameTokenizer.nextToken()); } int requiredCount = getParameterTypes().length; while (argsList.size() < requiredCount) { argsList.add("arg" + argsList.size()); } setParameterNames(argsList.toArray(new String[] {})); return; } } } } } } } setParameterNames(Utility.makeArgNames(len)); } else { UnresolvedType[] paramTypes = getParameterTypes(); String[] paramNames = new String[len]; int index = Modifier.isStatic(modifiers) ? 0 : 1; for (int i = 0; i < len; i++) { LocalVariable lv = varTable.getLocalVariable(index); if (lv == null) { paramNames[i] = "arg" + i; } else { paramNames[i] = lv.getName(); } index += paramTypes[i].getSize(); } setParameterNames(paramNames); } } private void unpackAjAttributes(World world) { associatedShadowMunger = null; ResolvedType resolvedDeclaringType = getDeclaringType().resolve(world); WeaverVersionInfo wvinfo = bcelObjectType.getWeaverVersionAttribute(); List<AjAttribute> as = Utility.readAjAttributes(resolvedDeclaringType.getClassName(), method.getAttributes(), resolvedDeclaringType.getSourceContext(), world, wvinfo, new BcelConstantPoolReader(method.getConstantPool())); processAttributes(world, as); as = AtAjAttributes.readAj5MethodAttributes(method, this, resolvedDeclaringType, preResolvedPointcut, resolvedDeclaringType.getSourceContext(), world.getMessageHandler()); processAttributes(world, as); } private void processAttributes(World world, List<AjAttribute> as) { for (AjAttribute attr : as) { if (attr instanceof AjAttribute.MethodDeclarationLineNumberAttribute) { declarationLineNumber = (AjAttribute.MethodDeclarationLineNumberAttribute) attr; } else if (attr instanceof AjAttribute.AdviceAttribute) { associatedShadowMunger = ((AjAttribute.AdviceAttribute) attr).reify(this, world, (ResolvedType) getDeclaringType()); } else if (attr instanceof AjAttribute.AjSynthetic) { bitflags |= IS_AJ_SYNTHETIC; } else if (attr instanceof AjAttribute.EffectiveSignatureAttribute) { effectiveSignature = (AjAttribute.EffectiveSignatureAttribute) attr; } else if (attr instanceof AjAttribute.PointcutDeclarationAttribute) { // this is an @AspectJ annotated advice method, with pointcut pre-resolved by ajc preResolvedPointcut = ((AjAttribute.PointcutDeclarationAttribute) attr).reify(); } else { throw new BCException("weird method attribute " + attr); } } } // // // for testing - if we have this attribute, return it - will return null // if // // it doesnt know anything // public AjAttribute[] getAttributes(String name) { // List results = new ArrayList(); // List l = Utility.readAjAttributes(getDeclaringType().getClassName(), // method.getAttributes(), // getSourceContext(bcelObjectType.getWorld()), bcelObjectType.getWorld(), // bcelObjectType.getWeaverVersionAttribute()); // for (Iterator iter = l.iterator(); iter.hasNext();) { // AjAttribute element = (AjAttribute) iter.next(); // if (element.getNameString().equals(name)) // results.add(element); // } // if (results.size() > 0) { // return (AjAttribute[]) results.toArray(new AjAttribute[] {}); // } // return null; // } @Override public String getAnnotationDefaultValue() { Attribute[] attrs = method.getAttributes(); for (int i = 0; i < attrs.length; i++) { Attribute attribute = attrs[i]; if (attribute.getName().equals("AnnotationDefault")) { AnnotationDefault def = (AnnotationDefault) attribute; return def.getElementValue().stringifyValue(); } } return null; } // for testing - use with the method above public String[] getAttributeNames(boolean onlyIncludeAjOnes) { Attribute[] as = method.getAttributes(); List<String> names = new ArrayList<String>(); // String[] strs = new String[as.length]; for (int j = 0; j < as.length; j++) { if (!onlyIncludeAjOnes || as[j].getName().startsWith(AjAttribute.AttributePrefix)) { names.add(as[j].getName()); } } return names.toArray(new String[] {}); } @Override public boolean isAjSynthetic() { return (bitflags & IS_AJ_SYNTHETIC) != 0; } @Override public ShadowMunger getAssociatedShadowMunger() { return associatedShadowMunger; } @Override public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() { return effectiveSignature; } public boolean hasDeclarationLineNumberInfo() { return declarationLineNumber != null; } public int getDeclarationLineNumber() { if (declarationLineNumber != null) { return declarationLineNumber.getLineNumber(); } else { return -1; } } public int getDeclarationOffset() { if (declarationLineNumber != null) { return declarationLineNumber.getOffset(); } else { return -1; } } @Override public ISourceLocation getSourceLocation() { ISourceLocation ret = super.getSourceLocation(); if ((ret == null || ret.getLine() == 0) && hasDeclarationLineNumberInfo()) { // lets see if we can do better ISourceContext isc = getSourceContext(); if (isc != null) { ret = isc.makeSourceLocation(getDeclarationLineNumber(), getDeclarationOffset()); } else { ret = new SourceLocation(null, getDeclarationLineNumber()); } } return ret; } @Override public MemberKind getKind() { if (associatedShadowMunger != null) { return ADVICE; } else { return super.getKind(); } } @Override public boolean hasAnnotation(UnresolvedType ofType) { ensureAnnotationsRetrieved(); for (ResolvedType aType : annotationTypes) { if (aType.equals(ofType)) { return true; } } return false; } @Override public AnnotationAJ[] getAnnotations() { ensureAnnotationsRetrieved(); if ((bitflags & HAS_ANNOTATIONS) != 0) { return annotations; } else { return AnnotationAJ.EMPTY_ARRAY; } } @Override public ResolvedType[] getAnnotationTypes() { ensureAnnotationsRetrieved(); return annotationTypes; } @Override public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { ensureAnnotationsRetrieved(); if ((bitflags & HAS_ANNOTATIONS) == 0) { return null; } for (int i = 0; i < annotations.length; i++) { if (annotations[i].getTypeName().equals(ofType.getName())) { return annotations[i]; } } return null; } @Override public void addAnnotation(AnnotationAJ annotation) { ensureAnnotationsRetrieved(); if ((bitflags & HAS_ANNOTATIONS) == 0) { annotations = new AnnotationAJ[1]; annotations[0] = annotation; annotationTypes = new ResolvedType[1]; annotationTypes[0] = annotation.getType(); } else { // Add it to the set of annotations int len = annotations.length; AnnotationAJ[] ret = new AnnotationAJ[len + 1]; System.arraycopy(annotations, 0, ret, 0, len); ret[len] = annotation; annotations = ret; ResolvedType[] newAnnotationTypes = new ResolvedType[len + 1]; System.arraycopy(annotationTypes, 0, newAnnotationTypes, 0, len); newAnnotationTypes[len] = annotation.getType(); annotationTypes = newAnnotationTypes; } bitflags |= HAS_ANNOTATIONS; } public void removeAnnotation(ResolvedType annotationType) { ensureAnnotationsRetrieved(); if ((bitflags & HAS_ANNOTATIONS) == 0) { // nothing to do, why did we get called? } else { int len = annotations.length; if (len == 1) { bitflags &= ~HAS_ANNOTATIONS; annotations = null; annotationTypes = null; return; } AnnotationAJ[] ret = new AnnotationAJ[len - 1]; int p = 0; for (AnnotationAJ annotation : annotations) { if (!annotation.getType().equals(annotationType)) { ret[p++] = annotation; } } annotations = ret; ResolvedType[] newAnnotationTypes = new ResolvedType[len - 1]; p = 0; for (AnnotationAJ annotation : annotations) { if (!annotation.getType().equals(annotationType)) { newAnnotationTypes[p++] = annotationType; } } annotationTypes = newAnnotationTypes; } bitflags |= HAS_ANNOTATIONS; } public static final AnnotationAJ[] NO_PARAMETER_ANNOTATIONS = new AnnotationAJ[] {}; public void addParameterAnnotation(int param, AnnotationAJ anno) { ensureParameterAnnotationsRetrieved(); if (parameterAnnotations == NO_PARAMETER_ANNOTATIONXS) { // First time we've added any, so lets set up the array parameterAnnotations = new AnnotationAJ[getArity()][]; for (int i = 0; i < getArity(); i++) { parameterAnnotations[i] = NO_PARAMETER_ANNOTATIONS; } } int existingCount = parameterAnnotations[param].length; if (existingCount == 0) { AnnotationAJ[] annoArray = new AnnotationAJ[1]; annoArray[0] = anno; parameterAnnotations[param] = annoArray; } else { AnnotationAJ[] newAnnoArray = new AnnotationAJ[existingCount + 1]; System.arraycopy(parameterAnnotations[param], 0, newAnnoArray, 0, existingCount); newAnnoArray[existingCount] = anno; parameterAnnotations[param] = newAnnoArray; } } private void ensureAnnotationsRetrieved() { if (method == null) { return; // must be ok, we have evicted it } if ((bitflags & HAVE_DETERMINED_ANNOTATIONS) != 0) { return; } bitflags |= HAVE_DETERMINED_ANNOTATIONS; AnnotationGen annos[] = method.getAnnotations(); if (annos.length == 0) { annotationTypes = ResolvedType.NONE; annotations = AnnotationAJ.EMPTY_ARRAY; } else { int annoCount = annos.length; annotationTypes = new ResolvedType[annoCount]; annotations = new AnnotationAJ[annoCount]; for (int i = 0; i < annoCount; i++) { AnnotationGen annotation = annos[i]; annotations[i] = new BcelAnnotation(annotation, bcelObjectType.getWorld()); annotationTypes[i] = annotations[i].getType(); } bitflags |= HAS_ANNOTATIONS; } } private void ensureParameterAnnotationsRetrieved() { if (method == null) { return; // must be ok, we have evicted it } AnnotationGen[][] pAnns = method.getParameterAnnotations(); if (parameterAnnotationTypes == null || pAnns.length != parameterAnnotationTypes.length) { if (pAnns == Method.NO_PARAMETER_ANNOTATIONS) { parameterAnnotationTypes = BcelMethod.NO_PARAMETER_ANNOTATION_TYPES; parameterAnnotations = BcelMethod.NO_PARAMETER_ANNOTATIONXS; } else { AnnotationGen annos[][] = method.getParameterAnnotations(); parameterAnnotations = new AnnotationAJ[annos.length][]; parameterAnnotationTypes = new ResolvedType[annos.length][]; for (int i = 0; i < annos.length; i++) { AnnotationGen[] annosOnThisParam = annos[i]; if (annos[i].length == 0) { parameterAnnotations[i] = AnnotationAJ.EMPTY_ARRAY; parameterAnnotationTypes[i] = ResolvedType.NONE; } else { parameterAnnotations[i] = new AnnotationAJ[annosOnThisParam.length]; parameterAnnotationTypes[i] = new ResolvedType[annosOnThisParam.length]; for (int j = 0; j < annosOnThisParam.length; j++) { parameterAnnotations[i][j] = new BcelAnnotation(annosOnThisParam[j], bcelObjectType.getWorld()); parameterAnnotationTypes[i][j] = bcelObjectType.getWorld().resolve( UnresolvedType.forSignature(annosOnThisParam[j].getTypeSignature())); } } } } } } @Override public AnnotationAJ[][] getParameterAnnotations() { ensureParameterAnnotationsRetrieved(); return parameterAnnotations; } @Override public ResolvedType[][] getParameterAnnotationTypes() { ensureParameterAnnotationsRetrieved(); return parameterAnnotationTypes; }
A method can be parameterized if it has one or more generic parameters. A generic parameter (type variable parameter) is identified by the prefix "T"
/** * A method can be parameterized if it has one or more generic parameters. A generic parameter (type variable parameter) is * identified by the prefix "T" */
@Override public boolean canBeParameterized() { unpackGenericSignature(); return (bitflags & CAN_BE_PARAMETERIZED) != 0; } @Override public UnresolvedType[] getGenericParameterTypes() { unpackGenericSignature(); return genericParameterTypes; }
Return the parameterized/generic return type or the normal return type if the method is not generic.
/** * Return the parameterized/generic return type or the normal return type if the method is not generic. */
@Override public UnresolvedType getGenericReturnType() { unpackGenericSignature(); return genericReturnType; }
For testing only
/** For testing only */
public Method getMethod() { return method; } private void unpackGenericSignature() { if ((bitflags & UNPACKED_GENERIC_SIGNATURE) != 0) { return; } bitflags |= UNPACKED_GENERIC_SIGNATURE; if (!bcelObjectType.getWorld().isInJava5Mode()) { genericReturnType = getReturnType(); genericParameterTypes = getParameterTypes(); return; } String gSig = method.getGenericSignature(); if (gSig != null) { GenericSignature.MethodTypeSignature mSig = new GenericSignatureParser().parseAsMethodSignature(gSig);// method // . // getGenericSignature // ()); if (mSig.formalTypeParameters.length > 0) { // generic method declaration bitflags |= CAN_BE_PARAMETERIZED; } typeVariables = new TypeVariable[mSig.formalTypeParameters.length]; for (int i = 0; i < typeVariables.length; i++) { GenericSignature.FormalTypeParameter methodFtp = mSig.formalTypeParameters[i]; try { typeVariables[i] = BcelGenericSignatureToTypeXConverter.formalTypeParameter2TypeVariable(methodFtp, mSig.formalTypeParameters, bcelObjectType.getWorld()); } catch (GenericSignatureFormatException e) { // this is a development bug, so fail fast with good info throw new IllegalStateException("While getting the type variables for method " + this.toString() + " with generic signature " + mSig + " the following error condition was detected: " + e.getMessage()); } } GenericSignature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals(); GenericSignature.FormalTypeParameter[] formals = new GenericSignature.FormalTypeParameter[parentFormals.length + mSig.formalTypeParameters.length]; // put method formal in front of type formals for overriding in // lookup System.arraycopy(mSig.formalTypeParameters, 0, formals, 0, mSig.formalTypeParameters.length); System.arraycopy(parentFormals, 0, formals, mSig.formalTypeParameters.length, parentFormals.length); GenericSignature.TypeSignature returnTypeSignature = mSig.returnType; try { genericReturnType = BcelGenericSignatureToTypeXConverter.typeSignature2TypeX(returnTypeSignature, formals, bcelObjectType.getWorld()); } catch (GenericSignatureFormatException e) { // development bug, fail fast with good info throw new IllegalStateException("While determing the generic return type of " + this.toString() + " with generic signature " + gSig + " the following error was detected: " + e.getMessage()); } GenericSignature.TypeSignature[] paramTypeSigs = mSig.parameters; if (paramTypeSigs.length == 0) { genericParameterTypes = UnresolvedType.NONE; } else { genericParameterTypes = new UnresolvedType[paramTypeSigs.length]; } for (int i = 0; i < paramTypeSigs.length; i++) { try { genericParameterTypes[i] = BcelGenericSignatureToTypeXConverter.typeSignature2TypeX(paramTypeSigs[i], formals, bcelObjectType.getWorld()); } catch (GenericSignatureFormatException e) { // development bug, fail fast with good info throw new IllegalStateException("While determining the generic parameter types of " + this.toString() + " with generic signature " + gSig + " the following error was detected: " + e.getMessage()); } if (paramTypeSigs[i] instanceof TypeVariableSignature) { bitflags |= CAN_BE_PARAMETERIZED; } } } else { genericReturnType = getReturnType(); genericParameterTypes = getParameterTypes(); } } @Override public void evictWeavingState() { if (method != null) { unpackGenericSignature(); unpackJavaAttributes(); ensureAnnotationsRetrieved(); ensureParameterAnnotationsRetrieved(); determineParameterNames(); // this.sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT; method = null; } } @Override public boolean isSynthetic() { if ((bitflags & KNOW_IF_SYNTHETIC) == 0) { workOutIfSynthetic(); } return (bitflags & IS_SYNTHETIC) != 0;// isSynthetic; } // Pre Java5 synthetic is an attribute 'Synthetic', post Java5 it is a // modifier (4096 or 0x1000) private void workOutIfSynthetic() { if ((bitflags & KNOW_IF_SYNTHETIC) != 0) { return; } bitflags |= KNOW_IF_SYNTHETIC; JavaClass jc = bcelObjectType.getJavaClass(); bitflags &= IS_SYNTHETIC_INVERSE; // unset the bit if (jc == null) { return; // what the hell has gone wrong? } if (jc.getMajor() < 49/* Java5 */) { // synthetic is an attribute String[] synthetics = getAttributeNames(false); if (synthetics != null) { for (int i = 0; i < synthetics.length; i++) { if (synthetics[i].equals("Synthetic")) { bitflags |= IS_SYNTHETIC; break; } } } } else { // synthetic is a modifier (4096) if ((modifiers & 4096) != 0) { bitflags |= IS_SYNTHETIC; } } }
Returns whether or not the given object is equivalent to the current one. Returns true if getMethod().getCode().getCodeString() are equal. Allows for different line number tables.
/** * Returns whether or not the given object is equivalent to the current one. Returns true if * getMethod().getCode().getCodeString() are equal. Allows for different line number tables. */
// bug 154054: is similar to equals(Object) however // doesn't require implementing equals in Method and Code // which proved expensive. Currently used within // CrosscuttingMembers.replaceWith() to decide if we need // to do a full build @Override public boolean isEquivalentTo(Object other) { if (!(other instanceof BcelMethod)) { return false; } BcelMethod o = (BcelMethod) other; return getMethod().getCode().getCodeString().equals(o.getMethod().getCode().getCodeString()); }
Return true if the method represents the default constructor. Hard to determine this from bytecode, but the existence of the MethodDeclarationLineNumber attribute should tell us.
Returns:true if this BcelMethod represents the default constructor
/** * Return true if the method represents the default constructor. Hard to determine this from bytecode, but the existence of the * MethodDeclarationLineNumber attribute should tell us. * * @return true if this BcelMethod represents the default constructor */
@Override public boolean isDefaultConstructor() { boolean mightBe = !hasDeclarationLineNumberInfo() && name.equals("<init>") && parameterTypes.length == 0; if (mightBe) { // TODO would be nice to do a check to see if the file was compiled with javac or ajc? // maybe by checking the constant pool for aspectj strings? return true; } else { return false; } } }