diff options
author | aclement <aclement> | 2011-09-14 00:05:18 +0000 |
---|---|---|
committer | aclement <aclement> | 2011-09-14 00:05:18 +0000 |
commit | 363c363afffc7152e96da039ef767db111bb8245 (patch) | |
tree | 8c1079119ef631fbc48ece863e68004a8ca028ca /org.aspectj.matcher | |
parent | e72228e3682ad8cb6503d2c0b1c06ac059ae7e1a (diff) | |
download | aspectj-363c363afffc7152e96da039ef767db111bb8245.tar.gz aspectj-363c363afffc7152e96da039ef767db111bb8245.zip |
354470
Diffstat (limited to 'org.aspectj.matcher')
3 files changed, 81 insertions, 5 deletions
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java index 43a7582af..6aa55a45a 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePattern.java @@ -24,6 +24,7 @@ import org.aspectj.weaver.CompressingDataOutputStream; import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.ISourceContext; import org.aspectj.weaver.Member; +import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.VersionedDataInputStream; import org.aspectj.weaver.WeaverMessages; @@ -50,7 +51,7 @@ public class HasMemberTypePattern extends TypePattern { return hasMethod(type); } } - + public ISignaturePattern getSignaturePattern() { return signaturePattern; } @@ -77,10 +78,10 @@ public class HasMemberTypePattern extends TypePattern { return false; } - private boolean hasMethod(ResolvedType type) { + protected boolean hasMethod(ResolvedType type) { // TODO what about ITDs World world = type.getWorld(); - for (Iterator iter = type.getMethods(true, true); iter.hasNext();) { + for (Iterator<ResolvedMember> iter = type.getMethods(true, true); iter.hasNext();) { Member method = (Member) iter.next(); if (method.getName().startsWith(declareAtPrefix)) { continue; @@ -94,7 +95,7 @@ public class HasMemberTypePattern extends TypePattern { return true; } } - // try itds before we give up + // try itds before we give up (this doesnt find annotations - the signature returned may not include them) List<ConcreteTypeMunger> mungers = type.getInterTypeMungersIncludingSupers(); for (Iterator<ConcreteTypeMunger> iter = mungers.iterator(); iter.hasNext();) { ConcreteTypeMunger munger = iter.next(); diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePatternForPerThisMatching.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePatternForPerThisMatching.java new file mode 100644 index 000000000..128338f8e --- /dev/null +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/HasMemberTypePatternForPerThisMatching.java @@ -0,0 +1,65 @@ +/* ******************************************************************* + * Copyright (c) 2011 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement Initial implementation + * ******************************************************************/ +package org.aspectj.weaver.patterns; + +import java.io.IOException; +import java.util.List; + +import org.aspectj.weaver.CompressingDataOutputStream; +import org.aspectj.weaver.ConcreteTypeMunger; +import org.aspectj.weaver.ResolvedType; + +/** + * pr354470. This is a special subtype of HasMemberTypePattern. In order to optimize this situation: <br> + * <code><pre> + * aspect X perthis(transactional()) {<br> + * pointcut transactional: execution(@Foo * *(..));<br> + * </pre></code> + * <p> + * When this occurs we obviously only want an aspect instance when there is a method annotated with @Foo. For a regular execution + * pointcut we couldn't really do this due to the multiple joinpoint signatures for each joinpoint (and so lots of types get the + * ajcMightHaveAspect interface). However, for an execution pointcut involving an annotation we can do something clever. Annotations + * must match against the first primary joinpoint signature - so when computing the type pattern to use for matching when processing + * the perthis() clause above, we can use the HasMemberTypePattern - because that effectively does what we want. We want an aspect + * instance if the type hasmethod(...) with the appropriate annotation. This would be great... but breaks in the face of ITDs. If + * the method that hasmethod() would match is introduced via an ITD we come unstuck, the code in HasMemberTypePattern.hasMethod() + * does look at ITDs but it won't see annotations, they aren't visible (at least through EclipseResolvedMember objects). And so this + * subclass is created to say 'if the supertype thinks it is a match, great, but if it doesnt then if there are ITDs on the target, + * they might match so just say 'true''. Note that returning true is just confirming whether the 'mightHaveAspect' interface (and + * friends) are getting added. + * + * @author Andy Clement + */ +public class HasMemberTypePatternForPerThisMatching extends HasMemberTypePattern { + + public HasMemberTypePatternForPerThisMatching(SignaturePattern aSignaturePattern) { + super(aSignaturePattern); + } + + protected boolean hasMethod(ResolvedType type) { + boolean b = super.hasMethod(type); + if (b) { + return true; + } + // If there are ITDs, have to be safe and just assume one of them might match + List<ConcreteTypeMunger> mungers = type.getInterTypeMungersIncludingSupers(); + if (mungers.size() != 0) { + return true; + } + return false; + } + + @Override + public void write(CompressingDataOutputStream s) throws IOException { + throw new IllegalAccessError("Should never be called, these are transient and don't get serialized"); + } +} diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java index e1cc54341..0020cefdc 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PerThisOrTargetPointcutVisitor.java @@ -90,7 +90,17 @@ public class PerThisOrTargetPointcutVisitor extends AbstractPatternNodeVisitor { } else if (node.getKind().equals(Shadow.ConstructorExecution) || node.getKind().equals(Shadow.Initialization) || node.getKind().equals(Shadow.MethodExecution) || node.getKind().equals(Shadow.PreInitialization) || node.getKind().equals(Shadow.StaticInitialization)) { - return node.getSignature().getDeclaringType(); + SignaturePattern signaturePattern = node.getSignature(); + boolean isStarAnnotation = signaturePattern.isStarAnnotation(); + // For a method execution joinpoint, we check for an annotation pattern. If there is one we know it will be matched + // against the 'primary' joinpoint (the one in the type) - 'super'joinpoints can't match it. If this situation occurs + // we can re-use the HasMemberTypePattern to guard on whether the perthis/target should match. pr354470 + if (!m_isTarget && node.getKind().equals(Shadow.MethodExecution)) { + if (!isStarAnnotation) { + return new HasMemberTypePatternForPerThisMatching(signaturePattern); + } + } + return signaturePattern.getDeclaringType(); } else if (node.getKind().equals(Shadow.ConstructorCall) || node.getKind().equals(Shadow.FieldGet) || node.getKind().equals(Shadow.FieldSet) || node.getKind().equals(Shadow.MethodCall)) { if (m_isTarget) { |