From: aclement Date: Mon, 20 Oct 2008 04:39:52 +0000 (+0000) Subject: 251277: making asmmanager non-singleton X-Git-Tag: V1_6_3rc1~187 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=2d2a71a12696ca8a9fa9edd15f1f0c3cc0016671;p=aspectj.git 251277: making asmmanager non-singleton --- diff --git a/weaver/src/org/aspectj/weaver/Advice.java b/weaver/src/org/aspectj/weaver/Advice.java index a2a19a339..2935f0d08 100644 --- a/weaver/src/org/aspectj/weaver/Advice.java +++ b/weaver/src/org/aspectj/weaver/Advice.java @@ -15,7 +15,6 @@ package org.aspectj.weaver; import java.util.Collections; import java.util.List; -import org.aspectj.asm.AsmManager; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; import org.aspectj.weaver.patterns.AndPointcut; @@ -26,7 +25,7 @@ import org.aspectj.weaver.patterns.TypePattern; public abstract class Advice extends ShadowMunger { protected AjAttribute.AdviceAttribute attribute; // the pointcut field is - // ignored + // ignored protected AdviceKind kind; // alias of attribute.getKind() protected Member signature; @@ -36,8 +35,8 @@ public abstract class Advice extends ShadowMunger { protected ResolvedType concreteAspect; // null until after concretize protected List innerCflowEntries = Collections.EMPTY_LIST; // just for - // cflow*Entry - // kinds + // cflow*Entry + // kinds protected int nFreeVars; // just for cflow*Entry kinds protected TypePattern exceptionType; // just for Softener kind @@ -47,8 +46,8 @@ public abstract class Advice extends ShadowMunger { protected UnresolvedType[] bindingParameterTypes; protected List/* Lint.Kind */suppressedLintKinds = null; // based on - // annotations on - // this advice + // annotations on + // this advice ISourceLocation lastReportedMonitorExitJoinpointLocation = null; @@ -185,11 +184,11 @@ public abstract class Advice extends ShadowMunger { ResolvedType adviceReturnType = getSignature().getGenericReturnType().resolve(world); if (shadowReturnType.isParameterizedType() && adviceReturnType.isRawType()) { // Set - // < - // Integer - // > - // and - // Set + // < + // Integer + // > + // and + // Set ResolvedType shadowReturnGenericType = shadowReturnType.getGenericType(); // Set ResolvedType adviceReturnGenericType = adviceReturnType.getGenericType(); // Set if (shadowReturnGenericType.isAssignableFrom(adviceReturnGenericType) @@ -216,11 +215,10 @@ public abstract class Advice extends ShadowMunger { } /** - * In after returning advice if we are binding the extra parameter to a - * parameterized type we may not be able to do a type-safe conversion. + * In after returning advice if we are binding the extra parameter to a parameterized type we may not be able to do a type-safe + * conversion. * - * @param resolvedExtraParameterType the type in the after returning - * declaration + * @param resolvedExtraParameterType the type in the after returning declaration * @param shadowReturnType the type at the shadow * @param world */ @@ -390,14 +388,14 @@ public abstract class Advice extends ShadowMunger { if (!(other instanceof Advice)) return false; Advice o = (Advice) other; - return o.kind.equals(kind) - && ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut)) - && ((o.signature == null) ? (signature == null) : o.signature.equals(signature)) - && (AsmManager.getDefault().getHandleProvider().dependsOnLocation() ? ((o.getSourceLocation() == null) ? (getSourceLocation() == null) - : o.getSourceLocation().equals(getSourceLocation())) - : true) // pr134471 - remove when handles are improved - // to be independent of location - ; + return o.kind.equals(kind) && ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut)) + && ((o.signature == null) ? (signature == null) : o.signature.equals(signature)); + // && (AsmManager.getDefault().getHandleProvider().dependsOnLocation() ? ((o.getSourceLocation() == null) ? + // (getSourceLocation() == null) + // : o.getSourceLocation().equals(getSourceLocation())) + // : true) // pr134471 - remove when handles are improved + // // to be independent of location + // ; } diff --git a/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java b/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java index d8efcaf08..52336bfb8 100644 --- a/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java +++ b/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java @@ -41,94 +41,74 @@ public class AsmRelationshipProvider { public static final String ANNOTATES = "annotates"; public static final String ANNOTATED_BY = "annotated by"; - public void checkerMunger(IHierarchy model, Shadow shadow, Checker checker) { - if (!AsmManager.isCreatingModel()) + public void checkerMunger(AsmManager asm, Shadow shadow, Checker checker) { + if (asm == null) // !AsmManager.isCreatingModel()) return; - if (shadow.getSourceLocation() == null - || checker.getSourceLocation() == null) + if (shadow.getSourceLocation() == null || checker.getSourceLocation() == null) return; if (World.createInjarHierarchy) { - checker.createHierarchy(); + checker.createHierarchy(asm); } // Ensure a node for the target exists - IProgramElement targetNode = getNode(AsmManager.getDefault() - .getHierarchy(), shadow); + IProgramElement targetNode = getNode(asm, shadow); if (targetNode == null) return; - String targetHandle = AsmManager.getDefault().getHandleProvider() - .createHandleIdentifier(targetNode); + String targetHandle = asm.getHandleProvider().createHandleIdentifier(targetNode); if (targetHandle == null) return; - IProgramElement sourceNode = AsmManager.getDefault().getHierarchy() - .findElementForSourceLine(checker.getSourceLocation()); - String sourceHandle = AsmManager.getDefault().getHandleProvider() - .createHandleIdentifier(sourceNode); + IProgramElement sourceNode = asm.getHierarchy().findElementForSourceLine(checker.getSourceLocation()); + String sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); if (sourceHandle == null) return; - IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, - IRelationship.Kind.DECLARE, MATCHED_BY, false, true); + IRelationshipMap mapper = asm.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE, MATCHED_BY, false, true); foreward.addTarget(targetHandle); - IRelationship back = mapper.get(targetHandle, - IRelationship.Kind.DECLARE, MATCHES_DECLARE, false, true); + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, MATCHES_DECLARE, false, true); if (back != null && back.getTargets() != null) { back.addTarget(sourceHandle); } - if (sourceNode.getSourceLocation()!=null) { - AsmManager.getDefault().addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); + if (sourceNode.getSourceLocation() != null) { + asm.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); } } // For ITDs - public void addRelationship(ResolvedType onType, ResolvedTypeMunger munger, - ResolvedType originatingAspect) { + public void addRelationship(AsmManager asm, ResolvedType onType, ResolvedTypeMunger munger, ResolvedType originatingAspect) { - if (!AsmManager.isCreatingModel()) + if (asm == null)// !AsmManager.isCreatingModel()) return; if (originatingAspect.getSourceLocation() != null) { String sourceHandle = ""; IProgramElement sourceNode = null; - if (munger.getSourceLocation() != null - && munger.getSourceLocation().getOffset() != -1) { - sourceNode = AsmManager.getDefault() - .getHierarchy().findElementForSourceLine( - munger.getSourceLocation()); - sourceHandle = AsmManager.getDefault().getHandleProvider() - .createHandleIdentifier(sourceNode); + if (munger.getSourceLocation() != null && munger.getSourceLocation().getOffset() != -1) { + sourceNode = asm.getHierarchy().findElementForSourceLine(munger.getSourceLocation()); + sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); } else { - sourceNode = AsmManager.getDefault() - .getHierarchy().findElementForSourceLine( - originatingAspect.getSourceLocation()); - sourceHandle = AsmManager.getDefault().getHandleProvider() - .createHandleIdentifier(sourceNode); + sourceNode = asm.getHierarchy().findElementForSourceLine(originatingAspect.getSourceLocation()); + sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); } if (sourceHandle == null) return; - IProgramElement targetNode = AsmManager.getDefault().getHierarchy() - .findElementForSourceLine(onType.getSourceLocation()); - String targetHandle = AsmManager.getDefault().getHandleProvider() - .createHandleIdentifier(targetNode); + IProgramElement targetNode = asm.getHierarchy().findElementForSourceLine(onType.getSourceLocation()); + String targetHandle = asm.getHandleProvider().createHandleIdentifier(targetNode); if (targetHandle == null) return; - IRelationshipMap mapper = AsmManager.getDefault() - .getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, - IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES, - false, true); + IRelationshipMap mapper = asm.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES, false, + true); foreward.addTarget(targetHandle); - IRelationship back = mapper.get(targetHandle, - IRelationship.Kind.DECLARE_INTER_TYPE, - INTER_TYPE_DECLARED_BY, false, true); + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY, false, + true); back.addTarget(sourceHandle); - AsmManager.getDefault().addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); + asm.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); } } @@ -165,47 +145,37 @@ public class AsmRelationshipProvider { // } /** - * Adds a declare annotation relationship, sometimes entities don't have - * source locs (methods/fields) so use other variants of this method if that - * is the case as they will look the entities up in the structure model. + * Adds a declare annotation relationship, sometimes entities don't have source locs (methods/fields) so use other variants of + * this method if that is the case as they will look the entities up in the structure model. */ - public void addDeclareAnnotationRelationship( - ISourceLocation declareAnnotationLocation, + public void addDeclareAnnotationRelationship(AsmManager asm, ISourceLocation declareAnnotationLocation, ISourceLocation annotatedLocation) { - if (!AsmManager.isCreatingModel()) + if (asm == null) // !AsmManager.isCreatingModel()) return; - IProgramElement sourceNode = AsmManager.getDefault().getHierarchy() - .findElementForSourceLine(declareAnnotationLocation); - String sourceHandle = AsmManager.getDefault().getHandleProvider() - .createHandleIdentifier(sourceNode); + IProgramElement sourceNode = asm.getHierarchy().findElementForSourceLine(declareAnnotationLocation); + String sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); if (sourceHandle == null) return; - IProgramElement targetNode = AsmManager.getDefault().getHierarchy() - .findElementForSourceLine(annotatedLocation); - String targetHandle = AsmManager.getDefault().getHandleProvider() - .createHandleIdentifier(targetNode); + IProgramElement targetNode = asm.getHierarchy().findElementForSourceLine(annotatedLocation); + String targetHandle = asm.getHandleProvider().createHandleIdentifier(targetNode); if (targetHandle == null) return; - IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, - IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); + IRelationshipMap mapper = asm.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); foreward.addTarget(targetHandle); - IRelationship back = mapper.get(targetHandle, - IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, - true); + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true); back.addTarget(sourceHandle); - if (sourceNode.getSourceLocation()!=null) { - AsmManager.getDefault().addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); + if (sourceNode.getSourceLocation() != null) { + asm.addAspectInEffectThisBuild(sourceNode.getSourceLocation().getSourceFile()); } } - public void adviceMunger(IHierarchy model, Shadow shadow, - ShadowMunger munger) { - if (!AsmManager.isCreatingModel()) + public void adviceMunger(AsmManager asm, Shadow shadow, ShadowMunger munger) { + if (asm == null) // !AsmManager.isCreatingModel()) return; if (munger instanceof Advice) { Advice advice = (Advice) munger; @@ -216,13 +186,11 @@ public class AsmRelationshipProvider { } if (World.createInjarHierarchy) { - munger.createHierarchy(); + munger.createHierarchy(asm); } - IRelationshipMap mapper = AsmManager.getDefault() - .getRelationshipMap(); - IProgramElement targetNode = getNode(AsmManager.getDefault() - .getHierarchy(), shadow); + IRelationshipMap mapper = asm.getRelationshipMap(); + IProgramElement targetNode = getNode(asm, shadow); if (targetNode == null) return; boolean runtimeTest = advice.hasDynamicTests(); @@ -230,7 +198,7 @@ public class AsmRelationshipProvider { // Work out extra info to inform interested UIs ! IProgramElement.ExtraInformation ai = new IProgramElement.ExtraInformation(); - String adviceHandle = advice.getHandle(); + String adviceHandle = advice.getHandle(asm); if (adviceHandle == null) return; @@ -239,50 +207,42 @@ public class AsmRelationshipProvider { // get it into CVS !!! AdviceKind ak = ((Advice) munger).getKind(); ai.setExtraAdviceInformation(ak.getName()); - IProgramElement adviceElement = AsmManager.getDefault() - .getHierarchy().findElementForHandle(adviceHandle); + IProgramElement adviceElement = asm.getHierarchy().findElementForHandle(adviceHandle); if (adviceElement != null) { adviceElement.setExtraInfo(ai); } String targetHandle = targetNode.getHandleIdentifier(); if (advice.getKind().equals(AdviceKind.Softener)) { - IRelationship foreward = mapper.get(adviceHandle, - IRelationship.Kind.DECLARE_SOFT, SOFTENS, runtimeTest, - true); + IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.DECLARE_SOFT, SOFTENS, runtimeTest, true); if (foreward != null) - foreward.addTarget(targetHandle);//foreward.getTargets().add - // (targetHandle); + foreward.addTarget(targetHandle);// foreward.getTargets().add + // (targetHandle); - IRelationship back = mapper.get(targetHandle, - IRelationship.Kind.DECLARE, SOFTENED_BY, runtimeTest, - true); + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, SOFTENED_BY, runtimeTest, true); if (back != null) back.addTarget(adviceHandle);// back.getTargets().add( - // adviceHandle); + // adviceHandle); } else { - IRelationship foreward = mapper.get(adviceHandle, - IRelationship.Kind.ADVICE, ADVISES, runtimeTest, true); + IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.ADVICE, ADVISES, runtimeTest, true); if (foreward != null) - foreward.addTarget(targetHandle);//foreward.getTargets().add - // (targetHandle); + foreward.addTarget(targetHandle);// foreward.getTargets().add + // (targetHandle); - IRelationship back = mapper.get(targetHandle, - IRelationship.Kind.ADVICE, ADVISED_BY, runtimeTest, - true); + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.ADVICE, ADVISED_BY, runtimeTest, true); if (back != null) back.addTarget(adviceHandle);// back.getTargets().add( - // adviceHandle); + // adviceHandle); } - if (adviceElement.getSourceLocation()!=null) { - AsmManager.getDefault().addAspectInEffectThisBuild(adviceElement.getSourceLocation().getSourceFile()); + if (adviceElement.getSourceLocation() != null) { + asm.addAspectInEffectThisBuild(adviceElement.getSourceLocation().getSourceFile()); } } } - protected IProgramElement getNode(IHierarchy model, Shadow shadow) { + protected IProgramElement getNode(AsmManager model, Shadow shadow) { Member enclosingMember = shadow.getEnclosingCodeSignature(); - IProgramElement enclosingNode = lookupMember(model, enclosingMember); + IProgramElement enclosingNode = lookupMember(model.getHierarchy(), enclosingMember); if (enclosingNode == null) { Lint.Kind err = shadow.getIWorld().getLint().shadowNotInStructure; if (err.isEnabled()) { @@ -293,10 +253,8 @@ public class AsmRelationshipProvider { Member shadowSig = shadow.getSignature(); // pr235204 - if (shadow.getKind() == Shadow.MethodCall - || !shadowSig.equals(enclosingMember)) { - IProgramElement bodyNode = findOrCreateCodeNode(enclosingNode, - shadowSig, shadow); + if (shadow.getKind() == Shadow.MethodCall || !shadowSig.equals(enclosingMember)) { + IProgramElement bodyNode = findOrCreateCodeNode(model, enclosingNode, shadowSig, shadow); return bodyNode; } else { return enclosingNode; @@ -312,32 +270,23 @@ public class AsmRelationshipProvider { /** * Finds or creates a code IProgramElement for the given shadow. * - * The byteCodeName of the created node is set to 'shadowSig.getName() + "!" - * + counter', eg "println!3". The counter is the occurence count of - * children within the enclosingNode which have the same name. So, for - * example, if a method contains two System.out.println statements, the - * first one will have byteCodeName 'println!1' and the second will have - * byteCodeName 'println!2'. This is to ensure the two nodes have unique - * handles when the handles do not depend on sourcelocations. + * The byteCodeName of the created node is set to 'shadowSig.getName() + "!" + counter', eg "println!3". The counter is the + * occurence count of children within the enclosingNode which have the same name. So, for example, if a method contains two + * System.out.println statements, the first one will have byteCodeName 'println!1' and the second will have byteCodeName + * 'println!2'. This is to ensure the two nodes have unique handles when the handles do not depend on sourcelocations. * - * Currently the shadows are examined in the sequence they appear in the - * source file. This means that the counters are consistent over incremental - * builds. All aspects are compiled up front and any new aspect created will - * force a full build. Moreover, if the body of the enclosingShadow is - * changed, then the model for this is rebuilt from scratch. + * Currently the shadows are examined in the sequence they appear in the source file. This means that the counters are + * consistent over incremental builds. All aspects are compiled up front and any new aspect created will force a full build. + * Moreover, if the body of the enclosingShadow is changed, then the model for this is rebuilt from scratch. */ - private IProgramElement findOrCreateCodeNode(IProgramElement enclosingNode, - Member shadowSig, Shadow shadow) { + private IProgramElement findOrCreateCodeNode(AsmManager asm, IProgramElement enclosingNode, Member shadowSig, Shadow shadow) { for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext();) { IProgramElement node = (IProgramElement) it.next(); int excl = node.getBytecodeName().lastIndexOf('!'); - if (((excl != -1 && shadowSig.getName().equals( - node.getBytecodeName().substring(0, excl))) || shadowSig - .getName().equals(node.getBytecodeName())) - && shadowSig.getSignature().equals( - node.getBytecodeSignature()) - && sourceLinesMatch(node.getSourceLocation(), shadow - .getSourceLocation())) { + if (((excl != -1 && shadowSig.getName().equals(node.getBytecodeName().substring(0, excl))) || shadowSig.getName() + .equals(node.getBytecodeName())) + && shadowSig.getSignature().equals(node.getBytecodeSignature()) + && sourceLinesMatch(node.getSourceLocation(), shadow.getSourceLocation())) { return node; } } @@ -346,11 +295,9 @@ public class AsmRelationshipProvider { // XXX why not use shadow file? new SourceLocation(sl.getSourceFile(), // sl.getLine()), - SourceLocation peLoc = new SourceLocation(enclosingNode - .getSourceLocation().getSourceFile(), sl.getLine()); + SourceLocation peLoc = new SourceLocation(enclosingNode.getSourceLocation().getSourceFile(), sl.getLine()); peLoc.setOffset(sl.getOffset()); - IProgramElement peNode = new ProgramElement(shadow.toString(), - IProgramElement.Kind.CODE, peLoc, 0, null, null); + IProgramElement peNode = new ProgramElement(asm, shadow.toString(), IProgramElement.Kind.CODE, peLoc, 0, null, null); // check to see if the enclosing shadow already has children with the // same name. If so we want to add a counter to the byteCodeName @@ -363,8 +310,7 @@ public class AsmRelationshipProvider { numberOfChildrenWithThisName++; } } - peNode.setBytecodeName(shadowSig.getName() + "!" - + String.valueOf(numberOfChildrenWithThisName + 1)); + peNode.setBytecodeName(shadowSig.getName() + "!" + String.valueOf(numberOfChildrenWithThisName + 1)); peNode.setBytecodeSignature(shadowSig.getSignature()); enclosingNode.addChild(peNode); return peNode; @@ -372,20 +318,16 @@ public class AsmRelationshipProvider { protected IProgramElement lookupMember(IHierarchy model, Member member) { UnresolvedType declaringType = member.getDeclaringType(); - IProgramElement classNode = model.findElementForType(declaringType - .getPackageName(), declaringType.getClassName()); + IProgramElement classNode = model.findElementForType(declaringType.getPackageName(), declaringType.getClassName()); return findMemberInClass(classNode, member); } - protected IProgramElement findMemberInClass(IProgramElement classNode, - Member member) { + protected IProgramElement findMemberInClass(IProgramElement classNode, Member member) { if (classNode == null) return null; // XXX remove this check for (Iterator it = classNode.getChildren().iterator(); it.hasNext();) { IProgramElement node = (IProgramElement) it.next(); - if (member.getName().equals(node.getBytecodeName()) - && member.getSignature() - .equals(node.getBytecodeSignature())) { + if (member.getName().equals(node.getBytecodeName()) && member.getSignature().equals(node.getBytecodeSignature())) { return node; } } @@ -425,16 +367,15 @@ public class AsmRelationshipProvider { } /** - * Add a relationship to the known set for a declare @method/@constructor - * construct. Locating the method is a messy (for messy read 'fragile') bit - * of code that could break at any moment but it's working for my simple - * testcase. Currently just fails silently if any of the lookup code doesn't - * find anything... + * Add a relationship to the known set for a declare @method/@constructor construct. Locating the method is a messy (for messy + * read 'fragile') bit of code that could break at any moment but it's working for my simple testcase. Currently just fails + * silently if any of the lookup code doesn't find anything... + * + * @param hierarchy */ - public void addDeclareAnnotationMethodRelationship( - ISourceLocation sourceLocation, String typename, - ResolvedMember method) { - if (!AsmManager.isCreatingModel()) + public void addDeclareAnnotationMethodRelationship(ISourceLocation sourceLocation, String typename, ResolvedMember method, + AsmManager structureModel) { + if (structureModel == null) // !AsmManager.isCreatingModel()) return; String pkg = null; @@ -445,8 +386,9 @@ public class AsmRelationshipProvider { type = typename.substring(packageSeparator + 1); } - IProgramElement typeElem = AsmManager.getDefault().getHierarchy() - .findElementForType(pkg, type); + IHierarchy hierarchy = structureModel.getHierarchy(); + + IProgramElement typeElem = hierarchy.findElementForType(pkg, type); if (typeElem == null) return; @@ -455,7 +397,7 @@ public class AsmRelationshipProvider { // Type[] args = method.getArgumentTypes(); for (int i = 0; i < args.length; i++) { String s = args[i].getName();// Utility.signatureToString(args[i]. - // getName()getSignature(), false); + // getName()getSignature(), false); parmString.append(s); if ((i + 1) < args.length) parmString.append(","); @@ -465,19 +407,12 @@ public class AsmRelationshipProvider { if (method.getName().startsWith("")) { // its a ctor - methodElem = AsmManager - .getDefault() - .getHierarchy() - .findElementForSignature(typeElem, - IProgramElement.Kind.CONSTRUCTOR, type + parmString); + methodElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.CONSTRUCTOR, type + parmString); if (methodElem == null && args.length == 0) methodElem = typeElem; // assume default ctor } else { // its a method - methodElem = AsmManager.getDefault().getHierarchy() - .findElementForSignature(typeElem, - IProgramElement.Kind.METHOD, - method.getName() + parmString); + methodElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.METHOD, method.getName() + parmString); } if (methodElem == null) @@ -488,42 +423,32 @@ public class AsmRelationshipProvider { if (targetHandle == null) return; - IProgramElement sourceNode = AsmManager.getDefault().getHierarchy() - .findElementForSourceLine(sourceLocation); - String sourceHandle = AsmManager.getDefault().getHandleProvider() - .createHandleIdentifier(sourceNode); + IProgramElement sourceNode = hierarchy.findElementForSourceLine(sourceLocation); + String sourceHandle = structureModel.getHandleProvider().createHandleIdentifier(sourceNode); if (sourceHandle == null) return; - IRelationshipMap mapper = AsmManager.getDefault() - .getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, - IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, - true); + IRelationshipMap mapper = structureModel.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); foreward.addTarget(targetHandle); - IRelationship back = mapper.get(targetHandle, - IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, - true); + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true); back.addTarget(sourceHandle); } catch (Throwable t) { // I'm worried about that code above, this will - // make sure we don't explode if it plays up + // make sure we don't explode if it plays up t.printStackTrace(); // I know I know .. but I don't want to lose - // it! + // it! } } /** - * Add a relationship to the known set for a declare @field construct. - * Locating the field is trickier than it might seem since we have no line - * number info for it, we have to dig through the structure model under the - * fields' type in order to locate it. Currently just fails silently if any - * of the lookup code doesn't find anything... + * Add a relationship to the known set for a declare @field construct. Locating the field is trickier than it might seem since + * we have no line number info for it, we have to dig through the structure model under the fields' type in order to locate it. + * Currently just fails silently if any of the lookup code doesn't find anything... */ - public void addDeclareAnnotationFieldRelationship( - ISourceLocation sourceLocation, String typename, + public void addDeclareAnnotationFieldRelationship(AsmManager asm, ISourceLocation sourceLocation, String typename, ResolvedMember field) { - if (!AsmManager.isCreatingModel()) + if (asm == null) // !AsmManager.isCreatingModel()) return; String pkg = null; @@ -533,15 +458,12 @@ public class AsmRelationshipProvider { pkg = typename.substring(0, packageSeparator); type = typename.substring(packageSeparator + 1); } - - IProgramElement typeElem = AsmManager.getDefault().getHierarchy() - .findElementForType(pkg, type); + IHierarchy hierarchy = asm.getHierarchy(); + IProgramElement typeElem = hierarchy.findElementForType(pkg, type); if (typeElem == null) return; - IProgramElement fieldElem = AsmManager.getDefault().getHierarchy() - .findElementForSignature(typeElem, IProgramElement.Kind.FIELD, - field.getName()); + IProgramElement fieldElem = hierarchy.findElementForSignature(typeElem, IProgramElement.Kind.FIELD, field.getName()); if (fieldElem == null) return; @@ -549,21 +471,16 @@ public class AsmRelationshipProvider { if (targetHandle == null) return; - IProgramElement sourceNode = AsmManager.getDefault().getHierarchy() - .findElementForSourceLine(sourceLocation); - String sourceHandle = AsmManager.getDefault().getHandleProvider() - .createHandleIdentifier(sourceNode); + IProgramElement sourceNode = hierarchy.findElementForSourceLine(sourceLocation); + String sourceHandle = asm.getHandleProvider().createHandleIdentifier(sourceNode); if (sourceHandle == null) return; - IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap(); - IRelationship foreward = mapper.get(sourceHandle, - IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); + IRelationshipMap mapper = asm.getRelationshipMap(); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATES, false, true); foreward.addTarget(targetHandle); - IRelationship back = mapper.get(targetHandle, - IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, - true); + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, ANNOTATED_BY, false, true); back.addTarget(sourceHandle); } diff --git a/weaver/src/org/aspectj/weaver/Checker.java b/weaver/src/org/aspectj/weaver/Checker.java index 9ff4dce5f..6f521b233 100644 --- a/weaver/src/org/aspectj/weaver/Checker.java +++ b/weaver/src/org/aspectj/weaver/Checker.java @@ -10,14 +10,12 @@ * PARC initial implementation * ******************************************************************/ - package org.aspectj.weaver; import java.util.Collection; import java.util.Collections; import java.util.Map; -import org.aspectj.asm.AsmManager; import org.aspectj.asm.IRelationship; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; @@ -26,7 +24,6 @@ import org.aspectj.weaver.patterns.DeclareErrorOrWarning; import org.aspectj.weaver.patterns.PerClause; import org.aspectj.weaver.patterns.Pointcut; - public class Checker extends ShadowMunger { private String msg; @@ -36,16 +33,16 @@ public class Checker extends ShadowMunger { super(deow.getPointcut(), deow.getStart(), deow.getEnd(), deow.getSourceContext()); this.msg = deow.getMessage(); this.isError = deow.isError(); - } - + } + private Checker(Pointcut pc, int start, int end, ISourceContext context) { - super(pc,start,end,context); + super(pc, start, end, context); } - public ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause) { - pointcut = pointcut.concretize(fromType, getDeclaringType(), 0, this); - return this; - } + public ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause) { + pointcut = pointcut.concretize(fromType, getDeclaringType(), 0, this); + return this; + } public void specializeOn(Shadow shadow) { throw new RuntimeException("illegal state"); @@ -54,13 +51,10 @@ public class Checker extends ShadowMunger { public void implementOn(Shadow shadow) { throw new RuntimeException("illegal state"); } - - public ShadowMunger parameterizeWith(ResolvedType declaringType,Map typeVariableMap) { - Checker ret = new Checker( - getPointcut().parameterizeWith(typeVariableMap,declaringType.getWorld()), - getStart(), - getEnd(), - this.sourceContext); + + public ShadowMunger parameterizeWith(ResolvedType declaringType, Map typeVariableMap) { + Checker ret = new Checker(getPointcut().parameterizeWith(typeVariableMap, declaringType.getWorld()), getStart(), getEnd(), + this.sourceContext); ret.msg = this.msg; ret.isError = this.isError; return ret; @@ -68,25 +62,18 @@ public class Checker extends ShadowMunger { public boolean match(Shadow shadow, World world) { if (super.match(shadow, world)) { - IMessage message = new Message( - msg, - shadow.toString(), - isError ? IMessage.ERROR : IMessage.WARNING, - shadow.getSourceLocation(), - null, - new ISourceLocation[]{this.getSourceLocation()},true, - 0, // id - -1,-1); // source start/end - - world.getMessageHandler().handleMessage(message); - + IMessage message = new Message(msg, shadow.toString(), isError ? IMessage.ERROR : IMessage.WARNING, shadow + .getSourceLocation(), null, new ISourceLocation[] { this.getSourceLocation() }, true, 0, // id + -1, -1); // source start/end + + world.getMessageHandler().handleMessage(message); + if (world.getCrossReferenceHandler() != null) { - world.getCrossReferenceHandler().addCrossReference(this.getSourceLocation(), - shadow.getSourceLocation(), - (this.isError?IRelationship.Kind.DECLARE_ERROR:IRelationship.Kind.DECLARE_WARNING),false); - + world.getCrossReferenceHandler().addCrossReference(this.getSourceLocation(), shadow.getSourceLocation(), + (this.isError ? IRelationship.Kind.DECLARE_ERROR : IRelationship.Kind.DECLARE_WARNING), false); + } - + if (world.getModel() != null) { AsmRelationshipProvider.getDefault().checkerMunger(world.getModel(), shadow, this); } @@ -97,39 +84,44 @@ public class Checker extends ShadowMunger { public int compareTo(Object other) { return 0; } - - public Collection getThrownExceptions() { return Collections.EMPTY_LIST; } - /** - * Default to true - * FIXME Alex: ATAJ is that ok in all cases ? - * @return - */ - public boolean mustCheckExceptions() { return true; } + public Collection getThrownExceptions() { + return Collections.EMPTY_LIST; + } + /** + * Default to true FIXME Alex: ATAJ is that ok in all cases ? + * + * @return + */ + public boolean mustCheckExceptions() { + return true; + } // XXX this perhaps ought to take account of the other fields in advice ... - public boolean equals(Object other) { - if (! (other instanceof Checker)) return false; - Checker o = (Checker) other; - return - o.isError == isError && - ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut)) && - (AsmManager.getDefault().getHandleProvider().dependsOnLocation() - ?((o.getSourceLocation()==null) ? (getSourceLocation()==null): o.getSourceLocation().equals(getSourceLocation())):true) // pr134471 - remove when handles are improved to be independent of location - ; - } + public boolean equals(Object other) { + if (!(other instanceof Checker)) + return false; + Checker o = (Checker) other; + return o.isError == isError && ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut)) + // && + // (AsmManager.getDefault().getHandleProvider().dependsOnLocation() + // ?((o.getSourceLocation()==null) ? (getSourceLocation()==null): o.getSourceLocation().equals(getSourceLocation())):true) + // // pr134471 - remove when handles are improved to be independent of location + ; + } private volatile int hashCode = -1; - public int hashCode() { - if (hashCode == -1) { - int result = 17; - result = 37*result + (isError?1:0); - result = 37*result + ((pointcut == null) ? 0 : pointcut.hashCode()); - hashCode = result; + + public int hashCode() { + if (hashCode == -1) { + int result = 17; + result = 37 * result + (isError ? 1 : 0); + result = 37 * result + ((pointcut == null) ? 0 : pointcut.hashCode()); + hashCode = result; } - return hashCode; - } + return hashCode; + } public boolean isError() { return isError; diff --git a/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java b/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java index e560ae8b2..186d7ef6f 100644 --- a/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java +++ b/weaver/src/org/aspectj/weaver/CrosscuttingMembersSet.java @@ -10,7 +10,6 @@ * PARC initial implementation * ******************************************************************/ - package org.aspectj.weaver; import java.util.ArrayList; @@ -21,68 +20,66 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.aspectj.asm.AsmManager; import org.aspectj.weaver.patterns.DeclareParents; import org.aspectj.weaver.patterns.IVerificationRequired; import org.aspectj.weaver.tools.Trace; import org.aspectj.weaver.tools.TraceFactory; /** - * This holds on to all CrosscuttingMembers for a world. It handles - * management of change. + * This holds on to all CrosscuttingMembers for a world. It handles management of change. * * @author Jim Hugunin */ public class CrosscuttingMembersSet { - //FIXME AV - ? we may need a sequencedHashMap there to ensure source based precedence for @AJ advice - private Map /* ResolvedType (the aspect) > CrosscuttingMembers */members = new HashMap(); - - private List shadowMungers = null; - private List typeMungers = null; - private List lateTypeMungers = null; - private List declareSofts = null; - private List declareParents = null; - private List declareAnnotationOnTypes = null; - private List declareAnnotationOnFields = null; - private List declareAnnotationOnMethods= null; // includes ctors - private List declareDominates = null; + // FIXME AV - ? we may need a sequencedHashMap there to ensure source based precedence for @AJ advice + private final Map /* ResolvedType (the aspect) > CrosscuttingMembers */members = new HashMap(); + + private List shadowMungers = null; + private List typeMungers = null; + private List lateTypeMungers = null; + private List declareSofts = null; + private List declareParents = null; + private List declareAnnotationOnTypes = null; + private List declareAnnotationOnFields = null; + private List declareAnnotationOnMethods = null; // includes ctors + private List declareDominates = null; private boolean changedSinceLastReset = false; - private List /*IVerificationRequired*/ verificationList = null; // List of things to be verified once the type system is 'complete' - + private List /* IVerificationRequired */verificationList = null; // List of things to be verified once the type system is + // 'complete' + private static Trace trace = TraceFactory.getTraceFactory().getTrace(CrosscuttingMembersSet.class); - + public CrosscuttingMembersSet(World world) { - trace.enter("",this,world); + trace.enter("", this, world); trace.exit(""); } public boolean addOrReplaceAspect(ResolvedType aspectType) { - return addOrReplaceAspect(aspectType,true); + return addOrReplaceAspect(aspectType, true); } /** - * @return whether or not that was a change to the global signature - * XXX for efficiency we will need a richer representation than this + * @return whether or not that was a change to the global signature XXX for efficiency we will need a richer representation than + * this */ public boolean addOrReplaceAspect(ResolvedType aspectType, boolean inWeavingPhase) { - trace.enter("addOrReplaceAspect",this,new Object[] {aspectType,new Boolean(inWeavingPhase)}); - + trace.enter("addOrReplaceAspect", this, new Object[] { aspectType, new Boolean(inWeavingPhase) }); + boolean change = false; - CrosscuttingMembers xcut = (CrosscuttingMembers)members.get(aspectType); + CrosscuttingMembers xcut = (CrosscuttingMembers) members.get(aspectType); if (xcut == null) { members.put(aspectType, aspectType.collectCrosscuttingMembers(inWeavingPhase)); clearCaches(); change = true; } else { - if (xcut.replaceWith(aspectType.collectCrosscuttingMembers(inWeavingPhase),inWeavingPhase)) { + if (xcut.replaceWith(aspectType.collectCrosscuttingMembers(inWeavingPhase), inWeavingPhase)) { clearCaches(); change = true; } else { - if (!AsmManager.getDefault().getHandleProvider().dependsOnLocation() - && inWeavingPhase) { - // bug 134541 - even though we haven't changed we may have updated the + if (inWeavingPhase) { + // bug 134541 - even though we haven't changed we may have updated the // sourcelocation for the shadowMunger which we need to pick up shadowMungers = null; } @@ -91,221 +88,218 @@ public class CrosscuttingMembersSet { } if (aspectType.isAbstract()) { // we might have sub-aspects that need to re-collect their crosscutting members from us - boolean ancestorChange = addOrReplaceDescendantsOf(aspectType,inWeavingPhase); + boolean ancestorChange = addOrReplaceDescendantsOf(aspectType, inWeavingPhase); change = change || ancestorChange; } changedSinceLastReset = changedSinceLastReset || change; - trace.exit("addOrReplaceAspect",change); + trace.exit("addOrReplaceAspect", change); return change; } - + private boolean addOrReplaceDescendantsOf(ResolvedType aspectType, boolean inWeavePhase) { - //System.err.println("Looking at descendants of "+aspectType.getName()); + // System.err.println("Looking at descendants of "+aspectType.getName()); Set knownAspects = members.keySet(); Set toBeReplaced = new HashSet(); - for(Iterator it = knownAspects.iterator(); it.hasNext(); ) { - ResolvedType candidateDescendant = (ResolvedType)it.next(); + for (Iterator it = knownAspects.iterator(); it.hasNext();) { + ResolvedType candidateDescendant = (ResolvedType) it.next(); if ((candidateDescendant != aspectType) && (aspectType.isAssignableFrom(candidateDescendant))) { toBeReplaced.add(candidateDescendant); } } boolean change = false; - for (Iterator it = toBeReplaced.iterator(); it.hasNext(); ) { - ResolvedType next = (ResolvedType)it.next(); - boolean thisChange = addOrReplaceAspect(next,inWeavePhase); + for (Iterator it = toBeReplaced.iterator(); it.hasNext();) { + ResolvedType next = (ResolvedType) it.next(); + boolean thisChange = addOrReplaceAspect(next, inWeavePhase); change = change || thisChange; } return change; } - - public void addAdviceLikeDeclares(ResolvedType aspectType) { - CrosscuttingMembers xcut = (CrosscuttingMembers)members.get(aspectType); - xcut.addDeclares(aspectType.collectDeclares(true)); - } - + + public void addAdviceLikeDeclares(ResolvedType aspectType) { + CrosscuttingMembers xcut = (CrosscuttingMembers) members.get(aspectType); + xcut.addDeclares(aspectType.collectDeclares(true)); + } + public boolean deleteAspect(UnresolvedType aspectType) { boolean isAspect = members.remove(aspectType) != null; clearCaches(); return isAspect; } - + public boolean containsAspect(UnresolvedType aspectType) { return members.containsKey(aspectType); } - - //XXX only for testing + + // XXX only for testing public void addFixedCrosscuttingMembers(ResolvedType aspectType) { members.put(aspectType, aspectType.crosscuttingMembers); clearCaches(); } - - + private void clearCaches() { shadowMungers = null; typeMungers = null; - lateTypeMungers = null; + lateTypeMungers = null; declareSofts = null; declareParents = null; - declareAnnotationOnFields=null; - declareAnnotationOnMethods=null; - declareAnnotationOnTypes=null; + declareAnnotationOnFields = null; + declareAnnotationOnMethods = null; + declareAnnotationOnTypes = null; declareDominates = null; } - - + public List getShadowMungers() { if (shadowMungers == null) { ArrayList ret = new ArrayList(); - for (Iterator i = members.values().iterator(); i.hasNext(); ) { - ret.addAll(((CrosscuttingMembers)i.next()).getShadowMungers()); + for (Iterator i = members.values().iterator(); i.hasNext();) { + ret.addAll(((CrosscuttingMembers) i.next()).getShadowMungers()); } shadowMungers = ret; } return shadowMungers; } - + public List getTypeMungers() { if (typeMungers == null) { ArrayList ret = new ArrayList(); - for (Iterator i = members.values().iterator(); i.hasNext(); ) { - ret.addAll(((CrosscuttingMembers)i.next()).getTypeMungers()); + for (Iterator i = members.values().iterator(); i.hasNext();) { + ret.addAll(((CrosscuttingMembers) i.next()).getTypeMungers()); } typeMungers = ret; } return typeMungers; } - public List getLateTypeMungers() { - if (lateTypeMungers == null) { - ArrayList ret = new ArrayList(); - for (Iterator i = members.values().iterator(); i.hasNext(); ) { - ret.addAll(((CrosscuttingMembers)i.next()).getLateTypeMungers()); - } - lateTypeMungers = ret; - } - return lateTypeMungers; - } + public List getLateTypeMungers() { + if (lateTypeMungers == null) { + ArrayList ret = new ArrayList(); + for (Iterator i = members.values().iterator(); i.hasNext();) { + ret.addAll(((CrosscuttingMembers) i.next()).getLateTypeMungers()); + } + lateTypeMungers = ret; + } + return lateTypeMungers; + } public List getDeclareSofts() { if (declareSofts == null) { Set ret = new HashSet(); - for (Iterator i = members.values().iterator(); i.hasNext(); ) { - ret.addAll(((CrosscuttingMembers)i.next()).getDeclareSofts()); + for (Iterator i = members.values().iterator(); i.hasNext();) { + ret.addAll(((CrosscuttingMembers) i.next()).getDeclareSofts()); } declareSofts = new ArrayList(); declareSofts.addAll(ret); } return declareSofts; } - + public List getDeclareParents() { if (declareParents == null) { Set ret = new HashSet(); - for (Iterator i = members.values().iterator(); i.hasNext(); ) { - ret.addAll(((CrosscuttingMembers)i.next()).getDeclareParents()); + for (Iterator i = members.values().iterator(); i.hasNext();) { + ret.addAll(((CrosscuttingMembers) i.next()).getDeclareParents()); } declareParents = new ArrayList(); declareParents.addAll(ret); } return declareParents; } - + // DECAT Merge multiple together public List getDeclareAnnotationOnTypes() { if (declareAnnotationOnTypes == null) { Set ret = new HashSet(); - for (Iterator i = members.values().iterator(); i.hasNext(); ) { - ret.addAll(((CrosscuttingMembers)i.next()).getDeclareAnnotationOnTypes()); + for (Iterator i = members.values().iterator(); i.hasNext();) { + ret.addAll(((CrosscuttingMembers) i.next()).getDeclareAnnotationOnTypes()); } declareAnnotationOnTypes = new ArrayList(); declareAnnotationOnTypes.addAll(ret); } return declareAnnotationOnTypes; } - + public List getDeclareAnnotationOnFields() { if (declareAnnotationOnFields == null) { Set ret = new HashSet(); - for (Iterator i = members.values().iterator(); i.hasNext(); ) { - ret.addAll(((CrosscuttingMembers)i.next()).getDeclareAnnotationOnFields()); + for (Iterator i = members.values().iterator(); i.hasNext();) { + ret.addAll(((CrosscuttingMembers) i.next()).getDeclareAnnotationOnFields()); } declareAnnotationOnFields = new ArrayList(); declareAnnotationOnFields.addAll(ret); } return declareAnnotationOnFields; } - + /** * Return an amalgamation of the declare @method/@constructor statements. */ public List getDeclareAnnotationOnMethods() { if (declareAnnotationOnMethods == null) { Set ret = new HashSet(); - for (Iterator i = members.values().iterator(); i.hasNext(); ) { - ret.addAll(((CrosscuttingMembers)i.next()).getDeclareAnnotationOnMethods()); + for (Iterator i = members.values().iterator(); i.hasNext();) { + ret.addAll(((CrosscuttingMembers) i.next()).getDeclareAnnotationOnMethods()); } declareAnnotationOnMethods = new ArrayList(); declareAnnotationOnMethods.addAll(ret); } return declareAnnotationOnMethods; } - + public List getDeclareDominates() { if (declareDominates == null) { ArrayList ret = new ArrayList(); - for (Iterator i = members.values().iterator(); i.hasNext(); ) { - ret.addAll(((CrosscuttingMembers)i.next()).getDeclareDominates()); + for (Iterator i = members.values().iterator(); i.hasNext();) { + ret.addAll(((CrosscuttingMembers) i.next()).getDeclareDominates()); } declareDominates = ret; } return declareDominates; } - public ResolvedType findAspectDeclaringParents(DeclareParents p) { Set keys = this.members.keySet(); for (Iterator iter = keys.iterator(); iter.hasNext();) { ResolvedType element = (ResolvedType) iter.next(); - for (Iterator i = ((CrosscuttingMembers)members.get(element)).getDeclareParents().iterator(); i.hasNext(); ) { - DeclareParents dp = (DeclareParents)i.next(); - if (dp.equals(p)) return element; + for (Iterator i = ((CrosscuttingMembers) members.get(element)).getDeclareParents().iterator(); i.hasNext();) { + DeclareParents dp = (DeclareParents) i.next(); + if (dp.equals(p)) + return element; } } return null; } public void reset() { - verificationList=null; + verificationList = null; changedSinceLastReset = false; } - + public boolean hasChangedSinceLastReset() { return changedSinceLastReset; } /** - * Record something that needs verifying when we believe the type system is complete. - * Used for things that can't be verified as we go along - for example some - * recursive type variable references (pr133307) + * Record something that needs verifying when we believe the type system is complete. Used for things that can't be verified as + * we go along - for example some recursive type variable references (pr133307) */ public void recordNecessaryCheck(IVerificationRequired verification) { - if (verificationList==null) verificationList = new ArrayList(); + if (verificationList == null) + verificationList = new ArrayList(); verificationList.add(verification); } - - + /** - * Called when type bindings are complete - calls all registered verification - * objects in turn. + * Called when type bindings are complete - calls all registered verification objects in turn. */ public void verify() { - if (verificationList==null) return; + if (verificationList == null) + return; for (Iterator iter = verificationList.iterator(); iter.hasNext();) { IVerificationRequired element = (IVerificationRequired) iter.next(); element.verify(); } verificationList = null; } - + } diff --git a/weaver/src/org/aspectj/weaver/ShadowMunger.java b/weaver/src/org/aspectj/weaver/ShadowMunger.java index 2f5dcbc73..c99525459 100644 --- a/weaver/src/org/aspectj/weaver/ShadowMunger.java +++ b/weaver/src/org/aspectj/weaver/ShadowMunger.java @@ -99,12 +99,12 @@ public abstract class ShadowMunger implements PartialOrder.PartialComparable, IH return sourceLocation; } - public String getHandle() { + public String getHandle(AsmManager asm) { if (null == handle) { ISourceLocation sl = getSourceLocation(); if (sl != null) { - IProgramElement ipe = AsmManager.getDefault().getHierarchy().findElementForSourceLine(sl); - handle = AsmManager.getDefault().getHandleProvider().createHandleIdentifier(ipe); + IProgramElement ipe = asm.getHierarchy().findElementForSourceLine(sl); + handle = asm.getHandleProvider().createHandleIdentifier(ipe); } } return handle; @@ -152,11 +152,11 @@ public abstract class ShadowMunger implements PartialOrder.PartialComparable, IH /** * Creates the hierarchy for binary aspects */ - public void createHierarchy() { + public void createHierarchy(AsmManager asm) { if (!isBinary()) return; - IProgramElement sourceFileNode = AsmManager.getDefault().getHierarchy().findElementForSourceLine(getSourceLocation()); + IProgramElement sourceFileNode = asm.getHierarchy().findElementForSourceLine(getSourceLocation()); // the call to findElementForSourceLine(ISourceLocation) returns a file // node // if it can't find a node in the hierarchy for the given @@ -170,25 +170,23 @@ public abstract class ShadowMunger implements PartialOrder.PartialComparable, IH ResolvedType aspect = getDeclaringType(); // create the class file node - IProgramElement classFileNode = new ProgramElement(sourceFileNode.getName(), IProgramElement.Kind.FILE, + IProgramElement classFileNode = new ProgramElement(asm, sourceFileNode.getName(), IProgramElement.Kind.FILE, getBinarySourceLocation(aspect.getSourceLocation()), 0, null, null); // create package ipe if one exists.... - IProgramElement root = AsmManager.getDefault().getHierarchy().getRoot(); - IProgramElement binaries = AsmManager.getDefault().getHierarchy().findElementForLabel(root, - IProgramElement.Kind.SOURCE_FOLDER, "binaries"); + IProgramElement root = asm.getHierarchy().getRoot(); + IProgramElement binaries = asm.getHierarchy().findElementForLabel(root, IProgramElement.Kind.SOURCE_FOLDER, "binaries"); if (binaries == null) { - binaries = new ProgramElement("binaries", IProgramElement.Kind.SOURCE_FOLDER, new ArrayList()); + binaries = new ProgramElement(asm, "binaries", IProgramElement.Kind.SOURCE_FOLDER, new ArrayList()); root.addChild(binaries); } // if (aspect.getPackageName() != null) { String packagename = aspect.getPackageName() == null ? "" : aspect.getPackageName(); // check that there doesn't already exist a node with this name - IProgramElement pkgNode = AsmManager.getDefault().getHierarchy().findElementForLabel(binaries, - IProgramElement.Kind.PACKAGE, packagename); + IProgramElement pkgNode = asm.getHierarchy().findElementForLabel(binaries, IProgramElement.Kind.PACKAGE, packagename); // note packages themselves have no source location if (pkgNode == null) { - pkgNode = new ProgramElement(packagename, IProgramElement.Kind.PACKAGE, new ArrayList()); + pkgNode = new ProgramElement(asm, packagename, IProgramElement.Kind.PACKAGE, new ArrayList()); binaries.addChild(pkgNode); pkgNode.addChild(classFileNode); } else { @@ -223,21 +221,21 @@ public abstract class ShadowMunger implements PartialOrder.PartialComparable, IH // } // add and create empty import declaration ipe - classFileNode - .addChild(new ProgramElement("import declarations", IProgramElement.Kind.IMPORT_REFERENCE, null, 0, null, null)); + classFileNode.addChild(new ProgramElement(asm, "import declarations", IProgramElement.Kind.IMPORT_REFERENCE, null, 0, null, + null)); // add and create aspect ipe - IProgramElement aspectNode = new ProgramElement(aspect.getSimpleName(), IProgramElement.Kind.ASPECT, + IProgramElement aspectNode = new ProgramElement(asm, aspect.getSimpleName(), IProgramElement.Kind.ASPECT, getBinarySourceLocation(aspect.getSourceLocation()), aspect.getModifiers(), null, null); classFileNode.addChild(aspectNode); - addChildNodes(aspectNode, aspect.getDeclaredPointcuts()); + addChildNodes(asm, aspectNode, aspect.getDeclaredPointcuts()); - addChildNodes(aspectNode, aspect.getDeclaredAdvice()); - addChildNodes(aspectNode, aspect.getDeclares()); + addChildNodes(asm, aspectNode, aspect.getDeclaredAdvice()); + addChildNodes(asm, aspectNode, aspect.getDeclares()); } - private void addChildNodes(IProgramElement parent, ResolvedMember[] children) { + private void addChildNodes(AsmManager asm, IProgramElement parent, ResolvedMember[] children) { for (int i = 0; i < children.length; i++) { ResolvedMember pcd = children[i]; if (pcd instanceof ResolvedPointcutDefinition) { @@ -246,13 +244,13 @@ public abstract class ShadowMunger implements PartialOrder.PartialComparable, IH if (sLoc == null) { sLoc = rpcd.getSourceLocation(); } - parent.addChild(new ProgramElement(pcd.getName(), IProgramElement.Kind.POINTCUT, getBinarySourceLocation(sLoc), pcd - .getModifiers(), null, Collections.EMPTY_LIST)); + parent.addChild(new ProgramElement(asm, pcd.getName(), IProgramElement.Kind.POINTCUT, + getBinarySourceLocation(sLoc), pcd.getModifiers(), null, Collections.EMPTY_LIST)); } } } - private void addChildNodes(IProgramElement parent, Collection children) { + private void addChildNodes(AsmManager asm, IProgramElement parent, Collection children) { int deCtr = 1; int dwCtr = 1; for (Iterator iter = children.iterator(); iter.hasNext();) { @@ -265,16 +263,16 @@ public abstract class ShadowMunger implements PartialOrder.PartialComparable, IH } else { counter = dwCtr++; } - parent.addChild(createDeclareErrorOrWarningChild(decl, counter)); + parent.addChild(createDeclareErrorOrWarningChild(asm, decl, counter)); } else if (element instanceof Advice) { Advice advice = (Advice) element; - parent.addChild(createAdviceChild(advice)); + parent.addChild(createAdviceChild(asm, advice)); } } } - private IProgramElement createDeclareErrorOrWarningChild(DeclareErrorOrWarning decl, int count) { - IProgramElement deowNode = new ProgramElement(decl.getName(), decl.isError() ? IProgramElement.Kind.DECLARE_ERROR + private IProgramElement createDeclareErrorOrWarningChild(AsmManager asm, DeclareErrorOrWarning decl, int count) { + IProgramElement deowNode = new ProgramElement(asm, decl.getName(), decl.isError() ? IProgramElement.Kind.DECLARE_ERROR : IProgramElement.Kind.DECLARE_WARNING, getBinarySourceLocation(decl.getSourceLocation()), decl.getDeclaringType() .getModifiers(), null, null); deowNode.setDetails("\"" + AsmRelationshipUtils.genDeclareMessage(decl.getMessage()) + "\""); @@ -284,8 +282,8 @@ public abstract class ShadowMunger implements PartialOrder.PartialComparable, IH return deowNode; } - private IProgramElement createAdviceChild(Advice advice) { - IProgramElement adviceNode = new ProgramElement(advice.kind.getName(), IProgramElement.Kind.ADVICE, + private IProgramElement createAdviceChild(AsmManager asm, Advice advice) { + IProgramElement adviceNode = new ProgramElement(asm, advice.kind.getName(), IProgramElement.Kind.ADVICE, getBinarySourceLocation(advice.getSourceLocation()), advice.signature.getModifiers(), null, Collections.EMPTY_LIST); adviceNode.setDetails(AsmRelationshipUtils.genPointcutDetails(advice.getPointcut())); adviceNode.setBytecodeName(advice.getSignature().getName()); diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java index 725d762dd..4feedae1a 100644 --- a/weaver/src/org/aspectj/weaver/World.java +++ b/weaver/src/org/aspectj/weaver/World.java @@ -28,7 +28,7 @@ import java.util.Properties; import java.util.Set; import java.util.WeakHashMap; -import org.aspectj.asm.IHierarchy; +import org.aspectj.asm.AsmManager; import org.aspectj.bridge.IMessageHandler; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.Message; @@ -50,14 +50,12 @@ public abstract class World implements Dump.INode { private IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR; /** - * handler for cross-reference information produced during the weaving - * process + * handler for cross-reference information produced during the weaving process */ private ICrossReferenceHandler xrefHandler = null; /** - * Currently 'active' scope in which to lookup (resolve) typevariable - * references + * Currently 'active' scope in which to lookup (resolve) typevariable references */ private TypeVariableDeclaringElement typeVariableLookupScope; @@ -78,7 +76,7 @@ public abstract class World implements Dump.INode { private final CrosscuttingMembersSet crosscuttingMembersSet = new CrosscuttingMembersSet(this); /** Model holds ASM relationships */ - private IHierarchy model = null; + private AsmManager model = null; /** for processing Xlint messages */ private Lint lint = new Lint(this); @@ -93,8 +91,7 @@ public abstract class World implements Dump.INode { private boolean XhasMember = false; /** - * Xpinpoint controls whether we put out developer info showing the source - * of messages + * Xpinpoint controls whether we put out developer info showing the source of messages */ private boolean Xpinpoint = false; @@ -136,14 +133,12 @@ public abstract class World implements Dump.INode { private long warningThreshold; /** - * A list of RuntimeExceptions containing full stack information for every - * type we couldn't find. + * A list of RuntimeExceptions containing full stack information for every type we couldn't find. */ private List dumpState_cantFindTypeExceptions = null; /** - * Play God. On the first day, God created the primitive types and put them - * in the type map. + * Play God. On the first day, God created the primitive types and put them in the type map. */ protected World() { super(); @@ -183,10 +178,10 @@ public abstract class World implements Dump.INode { } } - //========================================================================== + // ========================================================================== // === // T Y P E R E S O L U T I O N - //========================================================================== + // ========================================================================== // === /** @@ -197,10 +192,8 @@ public abstract class World implements Dump.INode { } /** - * Attempt to resolve a type - the source location gives you some context in - * which resolution is taking place. In the case of an error where we can't - * find the type - we can then at least report why (source location) we were - * trying to resolve it. + * Attempt to resolve a type - the source location gives you some context in which resolution is taking place. In the case of an + * error where we can't find the type - we can then at least report why (source location) we were trying to resolve it. */ public ResolvedType resolve(UnresolvedType ty, ISourceLocation isl) { ResolvedType ret = resolve(ty, true); @@ -220,8 +213,8 @@ public abstract class World implements Dump.INode { } /** - * Convenience method for resolving an array of unresolved types in one hit. - * Useful for e.g. resolving type parameters in signatures. + * Convenience method for resolving an array of unresolved types in one hit. Useful for e.g. resolving type parameters in + * signatures. */ public ResolvedType[] resolve(UnresolvedType[] types) { if (types == null) @@ -235,8 +228,7 @@ public abstract class World implements Dump.INode { } /** - * Resolve a type. This the hub of type resolution. The resolved type is - * added to the type map by signature. + * Resolve a type. This the hub of type resolution. The resolved type is added to the type map by signature. */ public ResolvedType resolve(UnresolvedType ty, boolean allowMissing) { @@ -299,16 +291,14 @@ public abstract class World implements Dump.INode { } /** - * Called when a type is resolved - enables its type hierarchy to be - * finished off before we proceed + * Called when a type is resolved - enables its type hierarchy to be finished off before we proceed */ protected void completeBinaryType(ResolvedType ret) { } /** - * Return true if the classloader relating to this world is definetly the - * one that will define the specified class. Return false otherwise or we - * don't know for certain. + * Return true if the classloader relating to this world is definetly the one that will define the specified class. Return false + * otherwise or we don't know for certain. */ public boolean isLocallyDefined(String classname) { return false; @@ -333,10 +323,8 @@ public abstract class World implements Dump.INode { } /** - * Some TypeFactory operations create resolved types directly, but these - * won't be in the typeMap - this resolution process puts them there. - * Resolved types are also told their world which is needed for the special - * autoboxing resolved types. + * Some TypeFactory operations create resolved types directly, but these won't be in the typeMap - this resolution process puts + * them there. Resolved types are also told their world which is needed for the special autoboxing resolved types. */ public ResolvedType resolve(ResolvedType ty) { if (ty.isTypeVariableReference()) @@ -351,8 +339,7 @@ public abstract class World implements Dump.INode { } /** - * Convenience method for finding a type by name and resolving it in one - * step. + * Convenience method for finding a type by name and resolving it in one step. */ public ResolvedType resolve(String name) { // trace.enter("resolve", this, new Object[] {name}); @@ -366,8 +353,8 @@ public abstract class World implements Dump.INode { } /** - * Resolve to a ReferenceType - simple, raw, parameterized, or generic. Raw, - * parameterized, and generic versions of a type share a delegate. + * Resolve to a ReferenceType - simple, raw, parameterized, or generic. Raw, parameterized, and generic versions of a type share + * a delegate. */ private final ResolvedType resolveToReferenceType(UnresolvedType ty, boolean allowMissing) { if (ty.isParameterizedType()) { @@ -480,8 +467,7 @@ public abstract class World implements Dump.INode { } /** - * Go from an unresolved generic wildcard (represented by UnresolvedType) to - * a resolved version (BoundedReferenceType). + * Go from an unresolved generic wildcard (represented by UnresolvedType) to a resolved version (BoundedReferenceType). */ private ReferenceType resolveGenericWildcardFor(WildcardedUnresolvedType aType) { BoundedReferenceType ret = null; @@ -501,15 +487,13 @@ public abstract class World implements Dump.INode { } /** - * Find the ReferenceTypeDelegate behind this reference type so that it can - * fulfill its contract. + * Find the ReferenceTypeDelegate behind this reference type so that it can fulfill its contract. */ protected abstract ReferenceTypeDelegate resolveDelegate(ReferenceType ty); /** - * Special resolution for "core" types like OBJECT. These are resolved just - * like any other type, but if they are not found it is more serious and we - * issue an error message immediately. + * Special resolution for "core" types like OBJECT. These are resolved just like any other type, but if they are not found it is + * more serious and we issue an error message immediately. */ // OPTIMIZE streamline path for core types? They are just simple types, // could look straight in the typemap? @@ -522,8 +506,7 @@ public abstract class World implements Dump.INode { } /** - * Lookup a type by signature, if not found then build one and put it in the - * map. + * Lookup a type by signature, if not found then build one and put it in the map. */ public ReferenceType lookupOrCreateName(UnresolvedType ty) { String signature = ty.getSignature(); @@ -536,22 +519,20 @@ public abstract class World implements Dump.INode { } /** - * Lookup a reference type in the world by its signature. Returns null if - * not found. + * Lookup a reference type in the world by its signature. Returns null if not found. */ public ReferenceType lookupBySignature(String signature) { return (ReferenceType) typeMap.get(signature); } - //========================================================================== + // ========================================================================== // === // T Y P E R E S O L U T I O N -- E N D - //========================================================================== + // ========================================================================== // === /** - * Member resolution is achieved by resolving the declaring type and then - * looking up the member in the resolved declaring type. + * Member resolution is achieved by resolving the declaring type and then looking up the member in the resolved declaring type. */ public ResolvedMember resolve(Member member) { ResolvedType declaring = member.getDeclaringType().resolve(this); @@ -588,8 +569,7 @@ public abstract class World implements Dump.INode { } /** - * Same signature as - * org.aspectj.util.PartialOrder.PartialComparable.compareTo + * Same signature as org.aspectj.util.PartialOrder.PartialComparable.compareTo */ public int compareByPrecedence(ResolvedType aspect1, ResolvedType aspect2) { return precedenceCalculator.compareByPrecedence(aspect1, aspect2); @@ -600,8 +580,7 @@ public abstract class World implements Dump.INode { } /** - * compares by precedence with the additional rule that a super-aspect is - * sorted before its sub-aspects + * compares by precedence with the additional rule that a super-aspect is sorted before its sub-aspects */ public int compareByPrecedenceAndHierarchy(ResolvedType aspect1, ResolvedType aspect2) { return precedenceCalculator.compareByPrecedenceAndHierarchy(aspect1, aspect2); @@ -611,8 +590,7 @@ public abstract class World implements Dump.INode { // =========================================================== /** - * Nobody should hold onto a copy of this message handler, or - * setMessageHandler won't work right. + * Nobody should hold onto a copy of this message handler, or setMessageHandler won't work right. */ public IMessageHandler getMessageHandler() { return messageHandler; @@ -627,8 +605,8 @@ public abstract class World implements Dump.INode { } /** - * convenenience method for creating and issuing messages via the message - * handler - if you supply two locations you will get two messages. + * convenenience method for creating and issuing messages via the message handler - if you supply two locations you will get two + * messages. */ public void showMessage(Kind kind, String message, ISourceLocation loc1, ISourceLocation loc2) { if (loc1 != null) { @@ -684,11 +662,11 @@ public abstract class World implements Dump.INode { return crosscuttingMembersSet; } - public IHierarchy getModel() { + public AsmManager getModel() { return model; } - public void setModel(IHierarchy model) { + public void setModel(AsmManager model) { this.model = model; } @@ -737,8 +715,7 @@ public abstract class World implements Dump.INode { } /** - * Set the error and warning threashold which can be taken from - * CompilerOptions (see bug 129282) + * Set the error and warning threashold which can be taken from CompilerOptions (see bug 129282) * * @param errorThreshold * @param warningThreshold @@ -749,8 +726,7 @@ public abstract class World implements Dump.INode { } /** - * @return true if ignoring the UnusedDeclaredThrownException and false if - * this compiler option is set to error or warning + * @return true if ignoring the UnusedDeclaredThrownException and false if this compiler option is set to error or warning */ public boolean isIgnoringUnusedDeclaredThrownException() { // the 0x800000 is CompilerOptions.UnusedDeclaredThrownException @@ -860,15 +836,13 @@ public abstract class World implements Dump.INode { b = true; else b = getTargetAspectjRuntimeLevel().equals(org.aspectj.weaver.Constants.RUNTIME_LEVEL_12); - //System.err.println("Asked if targetting runtime 1.2 , returning: "+b); + // System.err.println("Asked if targetting runtime 1.2 , returning: "+b); return b; } /* - * Map of types in the world, can have 'references' to expendable ones which - * can be garbage collected to recover memory. An expendable type is a - * reference type that is not exposed to the weaver (ie just pulled in for - * type resolution purposes). + * Map of types in the world, can have 'references' to expendable ones which can be garbage collected to recover memory. An + * expendable type is a reference type that is not exposed to the weaver (ie just pulled in for type resolution purposes). */ protected static class TypeMap { @@ -903,25 +877,21 @@ public abstract class World implements Dump.INode { if (trace.isTraceEnabled()) trace.enter("", this, w); this.w = w; - memoryProfiling = false;//!w.getMessageHandler().isIgnoring(Message. + memoryProfiling = false;// !w.getMessageHandler().isIgnoring(Message. // INFO); if (trace.isTraceEnabled()) trace.exit(""); } /** - * Add a new type into the map, the key is the type signature. Some - * types do *not* go in the map, these are ones involving *member* type - * variables. The reason is that when all you have is the signature - * which gives you a type variable name, you cannot guarantee you are - * using the type variable in the same way as someone previously working - * with a similarly named type variable. So, these do not go into the - * map: - TypeVariableReferenceType. - ParameterizedType where a member - * type variable is involved. - BoundedReferenceType when one of the - * bounds is a type variable. + * Add a new type into the map, the key is the type signature. Some types do *not* go in the map, these are ones involving + * *member* type variables. The reason is that when all you have is the signature which gives you a type variable name, you + * cannot guarantee you are using the type variable in the same way as someone previously working with a similarly named + * type variable. So, these do not go into the map: - TypeVariableReferenceType. - ParameterizedType where a member type + * variable is involved. - BoundedReferenceType when one of the bounds is a type variable. * - * definition: "member type variables" - a tvar declared on a generic - * method/ctor as opposed to those you see declared on a generic type. + * definition: "member type variables" - a tvar declared on a generic method/ctor as opposed to those you see declared on a + * generic type. */ public ResolvedType put(String key, ResolvedType type) { if (type.isParameterizedType() && type.isParameterizedWithTypeVariable()) { @@ -1000,8 +970,7 @@ public abstract class World implements Dump.INode { } /** - * Lookup a type by its signature, always look in the real map before - * the expendable map + * Lookup a type by its signature, always look in the real map before the expendable map */ public ResolvedType get(String key) { checkq(); @@ -1067,16 +1036,14 @@ public abstract class World implements Dump.INode { } /** - * Reference types we don't intend to weave may be ejected from the cache if - * we need the space. + * Reference types we don't intend to weave may be ejected from the cache if we need the space. */ protected boolean isExpendable(ResolvedType type) { return (!type.equals(UnresolvedType.OBJECT) && (!type.isExposedToWeaver()) && (!type.isPrimitiveType())); } /** - * This class is used to compute and store precedence relationships between - * aspects. + * This class is used to compute and store precedence relationships between aspects. */ private static class AspectPrecedenceCalculator { @@ -1089,9 +1056,8 @@ public abstract class World implements Dump.INode { } /** - * Ask every declare precedence in the world to order the two aspects. - * If more than one declare precedence gives an ordering, and the - * orderings conflict, then that's an error. + * Ask every declare precedence in the world to order the two aspects. If more than one declare precedence gives an + * ordering, and the orderings conflict, then that's an error. */ public int compareByPrecedence(ResolvedType firstAspect, ResolvedType secondAspect) { PrecedenceCacheKey key = new PrecedenceCacheKey(firstAspect, secondAspect); @@ -1294,8 +1260,7 @@ public abstract class World implements Dump.INode { } /** - * Register a new pointcut designator handler with the world - this can be - * used by any pointcut parsers attached to the world. + * Register a new pointcut designator handler with the world - this can be used by any pointcut parsers attached to the world. * * @param designatorHandler handler for the new pointcut */ diff --git a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java index 1eb7d4442..acdd19209 100644 --- a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java +++ b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java @@ -76,1770 +76,1639 @@ import org.aspectj.weaver.patterns.TypePattern; /** * Annotation defined aspect reader. Reads the Java 5 annotations and turns them into AjAttributes - * + * * @author Alexandre Vasseur */ public class AtAjAttributes { - private final static List EMPTY_LIST = new ArrayList(); - private final static String[] EMPTY_STRINGS = new String[0]; - private final static String VALUE = "value"; - private final static String ARGNAMES = "argNames"; - private final static String POINTCUT = "pointcut"; - private final static String THROWING = "throwing"; - private final static String RETURNING = "returning"; - private 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 ajAttributes = new ArrayList(); - - /** - * 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 Alexandre Vasseur - */ - 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 RuntimeVisibleAnnotations); - } - - /** - * Extract class level annotations and turn them into AjAttributes. - * - * @param javaClass - * @param type - * @param context - * @param msgHandler - * @return list of AjAttributes - */ - public static List readAj5ClassAttributes(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 EMPTY_LIST; - boolean containsPointcut = false; + private final static List EMPTY_LIST = new ArrayList(); + private final static String[] EMPTY_STRINGS = new String[0]; + private final static String VALUE = "value"; + private final static String ARGNAMES = "argNames"; + private final static String POINTCUT = "pointcut"; + private final static String THROWING = "throwing"; + private final static String RETURNING = "returning"; + private 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 ajAttributes = new ArrayList(); + + /** + * 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 Alexandre Vasseur + */ + 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 RuntimeVisibleAnnotations); + } + + /** + * Extract class level annotations and turn them into AjAttributes. + * + * @param javaClass + * @param type + * @param context + * @param msgHandler + * @return list of AjAttributes + */ + public static List 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 EMPTY_LIST; + 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).getBytes(); - 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 EMPTY_LIST; - - - AjAttributeStruct struct = new AjAttributeStruct(type, context, msgHandler); - Attribute[] attributes = javaClass.getAttributes(); - boolean hasAtAspectAnnotation = false; - boolean hasAtPrecedenceAnnotation = false; - - for (int i = 0; i < attributes.length; i++) { - Attribute attribute = attributes[i]; - if (acceptAttribute(attribute)) { - RuntimeAnnotations rvs = (RuntimeAnnotations) 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; - } - } - - // 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 EMPTY_LIST; - } - - // the following block will not detect @Pointcut in non @Aspect types for optimization purpose - if (!(hasAtAspectAnnotation || isCodeStyleAspect) && !containsPointcut) { - return EMPTY_LIST; - } - - //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)) { - mstruct = new AjAttributeMethodStruct(method, null, type, context, msgHandler);//FIXME AVASM - processedPointcut = handlePointcutAnnotation((RuntimeAnnotations) mattribute, mstruct); - // there can only be one RuntimeVisible bytecode attribute - break; - } - } - if (processedPointcut) { - // FIXME asc should check we aren't adding multiple versions... will do once I get the tests passing again... - struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo()); - 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)) { - RuntimeAnnotations frvs = (RuntimeAnnotations) fattribute; - if (handleDeclareErrorOrWarningAnnotation(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 readAj5MethodAttributes(Method method, BcelMethod bMethod, ResolvedType type, ResolvedPointcutDefinition preResolvedPointcut, ISourceContext context, IMessageHandler msgHandler) { - if (method.getName().startsWith(NameMangler.PREFIX)) return Collections.EMPTY_LIST; // 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)) { - RuntimeAnnotations rvs = (RuntimeAnnotations) 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.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 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.EMPTY_LIST; - } - - - /** - * Read @Aspect - * - * @param runtimeAnnotations - * @param struct - * @return true if found - */ - private static boolean handleAspectAnnotation(RuntimeAnnotations 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(); - } - - ElementNameValuePairGen 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 - // FIXME asc see related comment way about about the version... - 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(RuntimeAnnotations runtimeAnnotations, AjAttributeStruct struct) { - AnnotationGen aspect = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPRECEDENCE_ANNOTATION); - if (aspect != null) { - ElementNameValuePairGen 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(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) {//, ResolvedPointcutDefinition preResolvedPointcut) { - AnnotationGen decp = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPARENTS_ANNOTATION); - if (decp != null) { - ElementNameValuePairGen 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.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 parents = new ArrayList(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 = typePattern.resolveBindings(binding, Bindings.NONE, false, false); - //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; - ElementNameValuePairGen defaultImplNVP = getAnnotationElement(decp, "defaultImpl"); - if (defaultImplNVP != null) { - ClassElementValueGen defaultImpl = (ClassElementValueGen) 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(); - boolean hasNoCtorOrANoArgOne = true; - for (int i = 0; i < mm.length; i++) { - ResolvedMember resolvedMember = mm[i]; - if (resolvedMember.getName().equals("")) { - hasNoCtorOrANoArgOne = false; - if (resolvedMember.getParameterTypes().length == 0 - && resolvedMember.isPublic()) { - hasNoCtorOrANoArgOne = true; - } - } - if (hasNoCtorOrANoArgOne) { - break; - } - } - if (!hasNoCtorOrANoArgOne) { - 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; - ResolvedMember[] methods = (ResolvedMember[])fieldType.getMethodsWithoutIterator(true, false).toArray(new ResolvedMember[0]); - for (int i = 0; i < methods.length; i++) { - ResolvedMember method = methods[i]; - 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; - MethodDelegateTypeMunger mdtm = - new MethodDelegateTypeMunger( - method, - struct.enclosingType, - defaultImplClassName, - typePattern - ); - mdtm.setSourceLocation(struct.enclosingType.getSourceLocation()); - struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm)); - } - } - // successfull so far, we thus need a bcel type munger to have - // a field hosting the mixin in the target type - if (hasAtLeastOneMethod && defaultImplClassName!=null) { - struct.ajAttributes.add( - new AjAttribute.TypeMunger( - new MethodDelegateTypeMunger.FieldHostTypeMunger( - AjcMemberMaker.itdAtDeclareParentsField( - null,//prototyped - fieldType, - struct.enclosingType - ), - 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; - } - - /** - * Read @Before - * - * @param runtimeAnnotations - * @param struct - * @return true if found - */ - private static boolean handleBeforeAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, ResolvedPointcutDefinition preResolvedPointcut) { - AnnotationGen before = getAnnotation(runtimeAnnotations, AjcMemberMaker.BEFORE_ANNOTATION); - if (before != null) { - ElementNameValuePairGen 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(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, ResolvedPointcutDefinition preResolvedPointcut) { - AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTER_ANNOTATION); - if (after != null) { - ElementNameValuePairGen 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( - RuntimeAnnotations runtimeAnnotations, - AjAttributeMethodStruct struct, - ResolvedPointcutDefinition preResolvedPointcut, - BcelMethod owningMethod) - throws ReturningFormalNotDeclaredInAdviceSignatureException - { - AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERRETURNING_ANNOTATION); - if (after != null) { - ElementNameValuePairGen annValue = getAnnotationElement(after, VALUE); - ElementNameValuePairGen annPointcut = getAnnotationElement(after, POINTCUT); - ElementNameValuePairGen 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( - RuntimeAnnotations runtimeAnnotations, - AjAttributeMethodStruct struct, - ResolvedPointcutDefinition preResolvedPointcut, - BcelMethod owningMethod) - throws ThrownFormalNotDeclaredInAdviceSignatureException - { - AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERTHROWING_ANNOTATION); - if (after != null) { - ElementNameValuePairGen annValue = getAnnotationElement(after, VALUE); - ElementNameValuePairGen annPointcut = getAnnotationElement(after, POINTCUT); - ElementNameValuePairGen 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,//FIXME AVASM - struct.context - ) - ); - return true; - } - return false; - } - - /** - * Read @Around - * - * @param runtimeAnnotations - * @param struct - * @return true if found - */ - private static boolean handleAroundAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, ResolvedPointcutDefinition preResolvedPointcut) { - AnnotationGen around = getAnnotation(runtimeAnnotations, AjcMemberMaker.AROUND_ANNOTATION); - if (around != null) { - ElementNameValuePairGen 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(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct) { - AnnotationGen pointcut = getAnnotation(runtimeAnnotations, AjcMemberMaker.POINTCUT_ANNOTATION); - if (pointcut==null) return false; - ElementNameValuePairGen 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(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) { - AnnotationGen error = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREERROR_ANNOTATION); - boolean hasError = false; - if (error != null) { - ElementNameValuePairGen 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(deow,struct); - struct.ajAttributes.add(new AjAttribute.DeclareAttribute(deow)); - hasError = true; - } - } - } - AnnotationGen warning = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREWARNING_ANNOTATION); - boolean hasWarning = false; - if (warning != null) { - ElementNameValuePairGen 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(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(DeclareErrorOrWarning deow, AjAttributeFieldStruct struct) { - IHierarchy top = AsmManager.getDefault().getHierarchy(); - if (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; - } + 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).getBytes(); + 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 EMPTY_LIST; + + AjAttributeStruct struct = new AjAttributeStruct(type, context, msgHandler); + Attribute[] attributes = javaClass.getAttributes(); + boolean hasAtAspectAnnotation = false; + boolean hasAtPrecedenceAnnotation = false; + + for (int i = 0; i < attributes.length; i++) { + Attribute attribute = attributes[i]; + if (acceptAttribute(attribute)) { + RuntimeAnnotations rvs = (RuntimeAnnotations) 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; + } + } + + // 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 EMPTY_LIST; + } + + // the following block will not detect @Pointcut in non @Aspect types for optimization purpose + if (!(hasAtAspectAnnotation || isCodeStyleAspect) && !containsPointcut) { + return EMPTY_LIST; + } + + // 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)) { + mstruct = new AjAttributeMethodStruct(method, null, type, context, msgHandler);// FIXME AVASM + processedPointcut = handlePointcutAnnotation((RuntimeAnnotations) mattribute, mstruct); + // there can only be one RuntimeVisible bytecode attribute + break; + } + } + if (processedPointcut) { + // FIXME asc should check we aren't adding multiple versions... will do once I get the tests passing again... + struct.ajAttributes.add(new AjAttribute.WeaverVersionInfo()); + 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)) { + RuntimeAnnotations frvs = (RuntimeAnnotations) 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 readAj5MethodAttributes(Method method, BcelMethod bMethod, ResolvedType type, + ResolvedPointcutDefinition preResolvedPointcut, ISourceContext context, IMessageHandler msgHandler) { + if (method.getName().startsWith(NameMangler.PREFIX)) + return Collections.EMPTY_LIST; // 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)) { + RuntimeAnnotations rvs = (RuntimeAnnotations) 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.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 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.EMPTY_LIST; + } + + /** + * Read @Aspect + * + * @param runtimeAnnotations + * @param struct + * @return true if found + */ + private static boolean handleAspectAnnotation(RuntimeAnnotations 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(); + } + + ElementNameValuePairGen 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 + // FIXME asc see related comment way about about the version... + 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(RuntimeAnnotations runtimeAnnotations, AjAttributeStruct struct) { + AnnotationGen aspect = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPRECEDENCE_ANNOTATION); + if (aspect != null) { + ElementNameValuePairGen 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(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) {// , + // ResolvedPointcutDefinition + // preResolvedPointcut) + // { + AnnotationGen decp = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPARENTS_ANNOTATION); + if (decp != null) { + ElementNameValuePairGen 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.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 parents = new ArrayList(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 = typePattern.resolveBindings(binding, Bindings.NONE, false, false); + // 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; + ElementNameValuePairGen defaultImplNVP = getAnnotationElement(decp, "defaultImpl"); + if (defaultImplNVP != null) { + ClassElementValueGen defaultImpl = (ClassElementValueGen) 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(); + boolean hasNoCtorOrANoArgOne = true; + for (int i = 0; i < mm.length; i++) { + ResolvedMember resolvedMember = mm[i]; + if (resolvedMember.getName().equals("")) { + hasNoCtorOrANoArgOne = false; + if (resolvedMember.getParameterTypes().length == 0 && resolvedMember.isPublic()) { + hasNoCtorOrANoArgOne = true; + } + } + if (hasNoCtorOrANoArgOne) { + break; + } + } + if (!hasNoCtorOrANoArgOne) { + 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; + ResolvedMember[] methods = (ResolvedMember[]) fieldType.getMethodsWithoutIterator(true, false).toArray( + new ResolvedMember[0]); + for (int i = 0; i < methods.length; i++) { + ResolvedMember method = methods[i]; + 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; + MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType, + defaultImplClassName, typePattern); + mdtm.setSourceLocation(struct.enclosingType.getSourceLocation()); + struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm)); + } + } + // successfull so far, we thus need a bcel type munger to have + // a field hosting the mixin in the target type + if (hasAtLeastOneMethod && defaultImplClassName != null) { + struct.ajAttributes.add(new AjAttribute.TypeMunger(new MethodDelegateTypeMunger.FieldHostTypeMunger( + AjcMemberMaker.itdAtDeclareParentsField(null,// prototyped + fieldType, struct.enclosingType), 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; + } + + /** + * Read @Before + * + * @param runtimeAnnotations + * @param struct + * @return true if found + */ + private static boolean handleBeforeAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, + ResolvedPointcutDefinition preResolvedPointcut) { + AnnotationGen before = getAnnotation(runtimeAnnotations, AjcMemberMaker.BEFORE_ANNOTATION); + if (before != null) { + ElementNameValuePairGen 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(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, + ResolvedPointcutDefinition preResolvedPointcut) { + AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTER_ANNOTATION); + if (after != null) { + ElementNameValuePairGen 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(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, + ResolvedPointcutDefinition preResolvedPointcut, BcelMethod owningMethod) + throws ReturningFormalNotDeclaredInAdviceSignatureException { + AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERRETURNING_ANNOTATION); + if (after != null) { + ElementNameValuePairGen annValue = getAnnotationElement(after, VALUE); + ElementNameValuePairGen annPointcut = getAnnotationElement(after, POINTCUT); + ElementNameValuePairGen 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; } - 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 '' in Ant)", struct); - throw new UnreadableDebugInfoException(); - } - - List bindings = new ArrayList(); - 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 (FormalBinding[]) 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(RuntimeAnnotations rvs, UnresolvedType annotationType) { - final String annotationTypeName = annotationType.getName(); - for (Iterator iterator = rvs.getAnnotations().iterator(); iterator.hasNext();) { - AnnotationGen rv = (AnnotationGen) iterator.next(); - 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 ElementNameValuePairGen getAnnotationElement(AnnotationGen annotation, String elementName) { - for (Iterator iterator1 = annotation.getValues().iterator(); iterator1.hasNext();) { - ElementNameValuePairGen element = (ElementNameValuePairGen) iterator1.next(); - 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) { - for (Iterator iterator1 = anno.getValues().iterator(); iterator1.hasNext();) { - ElementNameValuePairGen element = (ElementNameValuePairGen) iterator1.next(); - if (ARGNAMES.equals(element.getNameString())) { - return element.getValue().stringifyValue(); - } - } - return null; - } - - private static String lastbit(String fqname) { - int i = fqname.lastIndexOf("."); - if (i==-1) return fqname; else return fqname.substring(i+1); - } - - /** - * Extract the method argument names. 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 arguments = new ArrayList(); - LocalVariableTable lt = method.getLocalVariableTable(); - if (lt != null) { - for (int j = 0; j < lt.getLocalVariableTable().length; j++) { - LocalVariable localVariable = lt.getLocalVariableTable()[j]; - if (localVariable.getStartPC() == 0) { - 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 args = new ArrayList(); - while (st.hasMoreTokens()) { args.add(st.nextToken());} - if (args.size()!=method.getArgumentTypes().length) { - StringBuffer shortString = new StringBuffer().append(lastbit(method.getReturnType().toString())).append(" ").append(method.getName()); - if (method.getArgumentTypes().length>0) { - shortString.append("("); - for (int i =0; i mo1.indexOnStack) { - return 1; - } else { - return -1; - } - } - } - ); - String[] argumentNames = new String[arguments.size()]; - int i = 0; - for (Iterator iterator = arguments.iterator(); iterator.hasNext(); i++) { - MethodArgument methodArgument = (MethodArgument) iterator.next(); - argumentNames[i] = methodArgument.name; - } - return argumentNames; - } - - /** - * A method argument, used for sorting by indexOnStack (ie order in signature) - * - * @author Alexandre Vasseur - */ - private static class MethodArgument { - String name; - int indexOnStack; - - public MethodArgument(String name, int indexOnStack) { - this.name = name; - this.indexOnStack = indexOnStack; - } - } - - /** - * BindingScope that knows the enclosingType, which is needed for pointcut reference resolution - * - * @author Alexandre Vasseur - */ - public static class BindingScope extends SimpleScope { - private ResolvedType m_enclosingType; - private ISourceContext m_sourceContext; - - public BindingScope(ResolvedType type, ISourceContext sourceContext, FormalBinding[] bindings) { - super(type.getWorld(), bindings); - m_enclosingType = type; - m_sourceContext = sourceContext; - } - - public ResolvedType getEnclosingType() { - return m_enclosingType; - } - - public ISourceLocation makeSourceLocation(IHasPosition location) { - return m_sourceContext.makeSourceLocation(location); - } - - public UnresolvedType lookupType(String name, IHasPosition location) { - // bug 126560 - if (m_enclosingType != null) { - // add the package we're in to the list of imported - // prefixes so that we can find types in the same package - String pkgName = m_enclosingType.getPackageName(); - if (pkgName != null && !pkgName.equals("")) { - String[] currentImports = getImportedPrefixes(); - String[] newImports = new String[currentImports.length + 1]; - for (int i = 0; i < currentImports.length; i++) { - newImports[i] = currentImports[i]; + return false; + } + + /** + * Read @AfterThrowing + * + * @param runtimeAnnotations + * @param struct + * @return true if found + */ + private static boolean handleAfterThrowingAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, + ResolvedPointcutDefinition preResolvedPointcut, BcelMethod owningMethod) + throws ThrownFormalNotDeclaredInAdviceSignatureException { + AnnotationGen after = getAnnotation(runtimeAnnotations, AjcMemberMaker.AFTERTHROWING_ANNOTATION); + if (after != null) { + ElementNameValuePairGen annValue = getAnnotationElement(after, VALUE); + ElementNameValuePairGen annPointcut = getAnnotationElement(after, POINTCUT); + ElementNameValuePairGen 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); + } } - newImports[currentImports.length] = pkgName.concat("."); - setImportedPrefixes(newImports); } + 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,// FIXME AVASM + struct.context)); + return true; + } + return false; + } + + /** + * Read @Around + * + * @param runtimeAnnotations + * @param struct + * @return true if found + */ + private static boolean handleAroundAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct, + ResolvedPointcutDefinition preResolvedPointcut) { + AnnotationGen around = getAnnotation(runtimeAnnotations, AjcMemberMaker.AROUND_ANNOTATION); + if (around != null) { + ElementNameValuePairGen 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(RuntimeAnnotations runtimeAnnotations, AjAttributeMethodStruct struct) { + AnnotationGen pointcut = getAnnotation(runtimeAnnotations, AjcMemberMaker.POINTCUT_ANNOTATION); + if (pointcut == null) + return false; + ElementNameValuePairGen 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, RuntimeAnnotations runtimeAnnotations, + AjAttributeFieldStruct struct) { + AnnotationGen error = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREERROR_ANNOTATION); + boolean hasError = false; + if (error != null) { + ElementNameValuePairGen 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) { + ElementNameValuePairGen 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 '' in Ant)", + struct); + throw new UnreadableDebugInfoException(); + } + + List bindings = new ArrayList(); + 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 (FormalBinding[]) 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(RuntimeAnnotations rvs, UnresolvedType annotationType) { + final String annotationTypeName = annotationType.getName(); + for (Iterator iterator = rvs.getAnnotations().iterator(); iterator.hasNext();) { + AnnotationGen rv = (AnnotationGen) iterator.next(); + 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 ElementNameValuePairGen getAnnotationElement(AnnotationGen annotation, String elementName) { + for (Iterator iterator1 = annotation.getValues().iterator(); iterator1.hasNext();) { + ElementNameValuePairGen element = (ElementNameValuePairGen) iterator1.next(); + 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) { + for (Iterator iterator1 = anno.getValues().iterator(); iterator1.hasNext();) { + ElementNameValuePairGen element = (ElementNameValuePairGen) iterator1.next(); + if (ARGNAMES.equals(element.getNameString())) { + return element.getValue().stringifyValue(); + } + } + return null; + } + + private static String lastbit(String fqname) { + int i = fqname.lastIndexOf("."); + if (i == -1) + return fqname; + else + return fqname.substring(i + 1); + } + + /** + * Extract the method argument names. 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 arguments = new ArrayList(); + LocalVariableTable lt = method.getLocalVariableTable(); + if (lt != null) { + for (int j = 0; j < lt.getLocalVariableTable().length; j++) { + LocalVariable localVariable = lt.getLocalVariableTable()[j]; + if (localVariable.getStartPC() == 0) { + 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 args = new ArrayList(); + while (st.hasMoreTokens()) { + args.add(st.nextToken()); + } + if (args.size() != method.getArgumentTypes().length) { + StringBuffer shortString = new StringBuffer().append(lastbit(method.getReturnType().toString())).append(" ") + .append(method.getName()); + if (method.getArgumentTypes().length > 0) { + shortString.append("("); + for (int i = 0; i < method.getArgumentTypes().length; i++) { + shortString.append(lastbit(method.getArgumentTypes()[i].toString())); + if ((i + 1) < method.getArgumentTypes().length) + shortString.append(","); + + } + shortString.append(")"); + } + reportError("argNames annotation value does not specify the right number of argument names for the method '" + + shortString.toString() + "'", methodStruct); + return EMPTY_STRINGS; + } + return (String[]) args.toArray(new String[] {}); + } + } + + if (arguments.size() != method.getArgumentTypes().length) { + return EMPTY_STRINGS; + } + + // sort by index + Collections.sort(arguments, new Comparator() { + public int compare(Object o, Object o1) { + MethodArgument mo = (MethodArgument) o; + MethodArgument mo1 = (MethodArgument) o1; + 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 (Iterator iterator = arguments.iterator(); iterator.hasNext(); i++) { + MethodArgument methodArgument = (MethodArgument) iterator.next(); + argumentNames[i] = methodArgument.name; + } + return argumentNames; + } + + /** + * A method argument, used for sorting by indexOnStack (ie order in signature) + * + * @author Alexandre Vasseur + */ + private static class MethodArgument { + String name; + int indexOnStack; + + public MethodArgument(String name, int indexOnStack) { + this.name = name; + this.indexOnStack = indexOnStack; + } + } + + /** + * BindingScope that knows the enclosingType, which is needed for pointcut reference resolution + * + * @author Alexandre Vasseur + */ + public static class BindingScope extends SimpleScope { + private final ResolvedType m_enclosingType; + private final ISourceContext m_sourceContext; + + public BindingScope(ResolvedType type, ISourceContext sourceContext, FormalBinding[] bindings) { + super(type.getWorld(), bindings); + m_enclosingType = type; + m_sourceContext = sourceContext; + } + + public ResolvedType getEnclosingType() { + return m_enclosingType; + } + + public ISourceLocation makeSourceLocation(IHasPosition location) { + return m_sourceContext.makeSourceLocation(location); + } + + public UnresolvedType lookupType(String name, IHasPosition location) { + // bug 126560 + if (m_enclosingType != null) { + // add the package we're in to the list of imported + // prefixes so that we can find types in the same package + String pkgName = m_enclosingType.getPackageName(); + if (pkgName != null && !pkgName.equals("")) { + String[] currentImports = getImportedPrefixes(); + String[] newImports = new String[currentImports.length + 1]; + for (int i = 0; i < currentImports.length; i++) { + newImports[i] = currentImports[i]; + } + newImports[currentImports.length] = pkgName.concat("."); + setImportedPrefixes(newImports); + } + } + return super.lookupType(name, location); + } + + } + + /** + * LazyResolvedPointcutDefinition lazyly resolve the pointcut so that we have time to register all pointcut referenced before + * pointcut resolution happens + * + * @author Alexandre Vasseur + */ + public static class LazyResolvedPointcutDefinition extends ResolvedPointcutDefinition { + private final Pointcut m_pointcutUnresolved; + 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, null); + m_pointcutUnresolved = pointcut; + m_binding = binding; + } + + public Pointcut getPointcut() { + if (m_lazyPointcut == 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 ignores = new ArrayList(); + for (int i = 0; i < bindings.length; i++) { + FormalBinding formalBinding = bindings[i]; + if (formalBinding instanceof FormalBinding.ImplicitFormalBinding) { + ignores.add(formalBinding.getName()); + } + } + pointcut.m_ignoreUnboundBindingForNames = (String[]) 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)); + } + } + + /** + * 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; } - return super.lookupType(name,location); - } - - } - - /** - * LazyResolvedPointcutDefinition lazyly resolve the pointcut so that we have time to register all - * pointcut referenced before pointcut resolution happens - * - * @author Alexandre Vasseur - */ - public static class LazyResolvedPointcutDefinition extends ResolvedPointcutDefinition { - private Pointcut m_pointcutUnresolved; - private 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, null); - m_pointcutUnresolved = pointcut; - m_binding = binding; - } - - public Pointcut getPointcut() { - if (m_lazyPointcut == 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 ignores = new ArrayList(); - for (int i = 0; i < bindings.length; i++) { - FormalBinding formalBinding = bindings[i]; - if (formalBinding instanceof FormalBinding.ImplicitFormalBinding) { - ignores.add(formalBinding.getName()); - } - } - pointcut.m_ignoreUnboundBindingForNames = (String[]) 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 - ) - ); - } - } - - /** - * 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 String formalName; - - public ThrownFormalNotDeclaredInAdviceSignatureException(String formalName) { - this.formalName = formalName; - } - - public String getFormalName() { return formalName; } - } - - static class ReturningFormalNotDeclaredInAdviceSignatureException extends Exception { - - private String formalName; - - public ReturningFormalNotDeclaredInAdviceSignatureException(String formalName) { - this.formalName = formalName; - } - - public String getFormalName() { return formalName; } - } + } } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java index 0414feb86..1b0b82a8a 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java @@ -123,11 +123,11 @@ class BcelClassWeaver implements IClassWeaver { private List addedSuperInitializersAsList = null; // List private final Map addedSuperInitializers = new HashMap(); // Interface -> // IfaceInitList - private List addedThisInitializers = new ArrayList(); // List - private List addedClassInitializers = new ArrayList(); // List + private final List addedClassInitializers = new ArrayList(); // List - private Map mapToAnnotations = new HashMap(); + private final Map mapToAnnotations = new HashMap(); // private BcelShadow clinitShadow = null; @@ -880,7 +880,7 @@ class BcelClassWeaver implements IClassWeaver { mg.addAnnotation(decaM.getAnnotationX()); AsmRelationshipProvider.getDefault().addDeclareAnnotationMethodRelationship(decaM.getSourceLocation(), - clazz.getName(), mg.getMemberView());//getMethod()); + clazz.getName(), mg.getMemberView(), world.getModel());// getMethod()); reportMethodCtorWeavingMessage(clazz, mg.getMemberView(), decaM, mg.getDeclarationLineNumber()); isChanged = true; modificationOccured = true; @@ -923,8 +923,8 @@ class BcelClassWeaver implements IClassWeaver { annotationsToAdd.add(a); mg.addAnnotation(decaM.getAnnotationX()); - AsmRelationshipProvider.getDefault().addDeclareAnnotationMethodRelationship(decaM.getSourceLocation(), - clazz.getName(), mg.getMemberView());//getMethod()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationMethodRelationship( + decaM.getSourceLocation(), clazz.getName(), mg.getMemberView(), world.getModel());// getMethod()); isChanged = true; modificationOccured = true; forRemoval.add(decaM); @@ -1102,8 +1102,8 @@ class BcelClassWeaver implements IClassWeaver { if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) continue; // skip this one... annotationHolder.addAnnotation(decaF.getAnnotationX()); - AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(), - itdIsActually.getSourceLocation()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(world.getModel(), + decaF.getSourceLocation(), itdIsActually.getSourceLocation()); isChanged = true; modificationOccured = true; @@ -1125,8 +1125,8 @@ class BcelClassWeaver implements IClassWeaver { if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) continue; // skip this one... annotationHolder.addAnnotation(decaF.getAnnotationX()); - AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(), - itdIsActually.getSourceLocation()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(world.getModel(), + decaF.getSourceLocation(), itdIsActually.getSourceLocation()); isChanged = true; modificationOccured = true; forRemoval.add(decaF); @@ -1160,8 +1160,8 @@ class BcelClassWeaver implements IClassWeaver { } annotationHolder.addAnnotation(decaMC.getAnnotationX()); isChanged = true; - AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(), - unMangledInterMethod.getSourceLocation()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(world.getModel(), + decaMC.getSourceLocation(), unMangledInterMethod.getSourceLocation()); reportMethodCtorWeavingMessage(clazz, unMangledInterMethod, decaMC, -1); modificationOccured = true; } else { @@ -1183,8 +1183,8 @@ class BcelClassWeaver implements IClassWeaver { continue; // skip this one... annotationHolder.addAnnotation(decaMC.getAnnotationX()); unMangledInterMethod.addAnnotation(decaMC.getAnnotationX()); - AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(), - unMangledInterMethod.getSourceLocation()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(world.getModel(), + decaMC.getSourceLocation(), unMangledInterMethod.getSourceLocation()); isChanged = true; modificationOccured = true; forRemoval.add(decaMC); @@ -1302,8 +1302,8 @@ class BcelClassWeaver implements IClassWeaver { } } - AsmRelationshipProvider.getDefault().addDeclareAnnotationFieldRelationship(decaF.getSourceLocation(), - clazz.getName(), aBcelField);//.getFieldAsIs()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationFieldRelationship(world.getModel(), + decaF.getSourceLocation(), clazz.getName(), aBcelField);// .getFieldAsIs()); reportFieldAnnotationWeavingMessage(clazz, fields, fieldCounter, decaF); isChanged = true; modificationOccured = true; @@ -1337,8 +1337,8 @@ class BcelClassWeaver implements IClassWeaver { continue; // skip this one... } aBcelField.addAnnotation(decaF.getAnnotationX()); - AsmRelationshipProvider.getDefault().addDeclareAnnotationFieldRelationship(decaF.getSourceLocation(), - clazz.getName(), aBcelField);//.getFieldAsIs()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationFieldRelationship(world.getModel(), + decaF.getSourceLocation(), clazz.getName(), aBcelField);// .getFieldAsIs()); isChanged = true; modificationOccured = true; forRemoval.add(decaF); diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java index 7f2dd5787..8f531a97a 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java @@ -353,8 +353,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate { typeMungers = new ArrayList(); declares = new ArrayList(); processAttributes(l, pointcuts, false); - l = AtAjAttributes.readAj5ClassAttributes(javaClass, getResolvedTypeX(), getResolvedTypeX().getSourceContext(), msgHandler, - isCodeStyleAspect); + l = AtAjAttributes.readAj5ClassAttributes(getResolvedTypeX().getWorld().getModel(), javaClass, getResolvedTypeX(), + getResolvedTypeX().getSourceContext(), msgHandler, isCodeStyleAspect); AjAttribute.Aspect deferredAspectAttribute = processAttributes(l, pointcuts, true); if (pointcuts.size() == 0) { diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index 54085bfbf..f0dee6d01 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -31,7 +31,6 @@ import org.aspectj.apache.bcel.generic.InstructionHandle; import org.aspectj.apache.bcel.generic.InstructionList; import org.aspectj.apache.bcel.generic.InvokeInstruction; import org.aspectj.apache.bcel.generic.Type; -import org.aspectj.asm.AsmManager; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.Message; @@ -118,7 +117,8 @@ public class BcelTypeMunger extends ConcreteTypeMunger { } if (changed && worthReporting) { - AsmRelationshipProvider.getDefault().addRelationship(weaver.getLazyClassGen().getType(), munger, getAspectType()); + AsmRelationshipProvider.getDefault().addRelationship(getWorld().getModel(), weaver.getLazyClassGen().getType(), munger, + getAspectType()); } // TAG: WeavingMessage @@ -1792,10 +1792,11 @@ public class BcelTypeMunger extends ConcreteTypeMunger { return false; BcelTypeMunger o = (BcelTypeMunger) other; return ((o.getMunger() == null) ? (getMunger() == null) : o.getMunger().equals(getMunger())) - && ((o.getAspectType() == null) ? (getAspectType() == null) : o.getAspectType().equals(getAspectType())) - && (AsmManager.getDefault().getHandleProvider().dependsOnLocation() ? ((o.getSourceLocation() == null) ? (getSourceLocation() == null) - : o.getSourceLocation().equals(getSourceLocation())) - : true); // pr134471 - remove when handles are improved + && ((o.getAspectType() == null) ? (getAspectType() == null) : o.getAspectType().equals(getAspectType())); + // && (AsmManager.getDefault().getHandleProvider().dependsOnLocation() ? ((o.getSourceLocation() == null) ? + // (getSourceLocation() == null) + // : o.getSourceLocation().equals(getSourceLocation())) + // : true); // pr134471 - remove when handles are improved // to be independent of location } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java index 810af0447..d08d8d55e 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java @@ -43,7 +43,6 @@ import java.util.zip.ZipOutputStream; import org.aspectj.apache.bcel.classfile.ClassParser; import org.aspectj.apache.bcel.classfile.JavaClass; -import org.aspectj.asm.AsmManager; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.Message; @@ -1114,10 +1113,10 @@ public class BcelWeaver { for (Iterator i = input.getClassFileIterator(); i.hasNext();) { UnwovenClassFile classFile = (UnwovenClassFile) i.next(); - if (AsmManager.isCreatingModel() && !isBatchWeave) { + if (world.getModel() != null /* AsmManager.isCreatingModel() */&& !isBatchWeave) { // remove all relationships where this file being woven is the // target of the relationship - AsmManager.getDefault().removeRelationshipsTargettingThisType(classFile.getClassName()); + world.getModel().removeRelationshipsTargettingThisType(classFile.getClassName()); } } @@ -1602,7 +1601,7 @@ public class BcelWeaver { boolean problemReported = verifyTargetIsOK(decA, onType, annoX, reportProblems); if (!problemReported) { - AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decA.getSourceLocation(), + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(world.getModel(), decA.getSourceLocation(), onType.getSourceLocation()); // TAG: WeavingMessage if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {