Browse Source

partial fix for bug 61568.

These changes are both (a) a performance optimization, and (b) an
improvement on the binding across || rules that we implemented in
1.2.1.
Instead of saying the the first binding in a left-to-right traversal of the
pointcuts DNF is the one that you get (too much to ask users to do DNF
rewriting in their heads), this version implements the rule that every
|| branch in the DNF must bind all formals, and if two || branches can have
any join points in common (can match join points of the same kind), then
both must bind all formals identically.

So it allows things like execution(* *(..)) && args(x) || call(* *(..)) && this(x)
which previously we used to forbid.

But primarily it turned out to be a performance optimization.
tags/Root_AspectJ5_Development
acolyer 19 years ago
parent
commit
1b6e9edfac
50 changed files with 1794 additions and 156 deletions
  1. 1
    1
      tests/bugs/DisjunctVarBinding.java
  2. 1
    1
      tests/bugs/DisjunctVarBinding_3.java
  3. 1
    2
      tests/src/org/aspectj/systemtest/ajc120/ajc120-tests.xml
  4. 7
    12
      tests/src/org/aspectj/systemtest/ajc121/ajc121-tests.xml
  5. 3
    1
      tests/src/org/aspectj/systemtest/ajc150/VarargsTests.java
  6. 13
    0
      weaver/src/org/aspectj/weaver/Advice.java
  7. 13
    0
      weaver/src/org/aspectj/weaver/Shadow.java
  8. 5
    0
      weaver/src/org/aspectj/weaver/ShadowMunger.java
  9. 5
    0
      weaver/src/org/aspectj/weaver/WeaverMessages.java
  10. 254
    0
      weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
  11. 17
    4
      weaver/src/org/aspectj/weaver/patterns/AndPointcut.java
  12. 17
    1
      weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java
  13. 4
    0
      weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java
  14. 37
    11
      weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java
  15. 37
    5
      weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java
  16. 43
    12
      weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java
  17. 2
    0
      weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java
  18. 14
    5
      weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java
  19. 17
    2
      weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java
  20. 2
    0
      weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java
  21. 16
    3
      weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java
  22. 43
    9
      weaver/src/org/aspectj/weaver/patterns/IfPointcut.java
  23. 14
    2
      weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java
  24. 4
    1
      weaver/src/org/aspectj/weaver/patterns/NameBindingPointcut.java
  25. 10
    3
      weaver/src/org/aspectj/weaver/patterns/NotPointcut.java
  26. 15
    0
      weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java
  27. 13
    3
      weaver/src/org/aspectj/weaver/patterns/OrPointcut.java
  28. 19
    0
      weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java
  29. 7
    2
      weaver/src/org/aspectj/weaver/patterns/PerCflow.java
  30. 8
    3
      weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java
  31. 18
    2
      weaver/src/org/aspectj/weaver/patterns/PerObject.java
  32. 8
    3
      weaver/src/org/aspectj/weaver/patterns/PerSingleton.java
  33. 84
    9
      weaver/src/org/aspectj/weaver/patterns/Pointcut.java
  34. 114
    0
      weaver/src/org/aspectj/weaver/patterns/PointcutEvaluationExpenseComparator.java
  35. 277
    0
      weaver/src/org/aspectj/weaver/patterns/PointcutRewriter.java
  36. 7
    2
      weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java
  37. 2
    0
      weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
  38. 49
    11
      weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java
  39. 55
    14
      weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java
  40. 2
    1
      weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java
  41. 36
    0
      weaver/src/org/aspectj/weaver/patterns/TypePattern.java
  42. 3
    0
      weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java
  43. 37
    11
      weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java
  44. 47
    11
      weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java
  45. 10
    3
      weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java
  46. 23
    4
      weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java
  47. 6
    0
      weaver/src/org/aspectj/weaver/weaver-messages.properties
  48. 1
    0
      weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java
  49. 366
    0
      weaver/testsrc/org/aspectj/weaver/patterns/PointcutRewriterTest.java
  50. 7
    2
      weaver/testsrc/org/aspectj/weaver/patterns/PointcutTestCase.java

+ 1
- 1
tests/bugs/DisjunctVarBinding.java View File

aspect IfPointcut { aspect IfPointcut {


after(A a, B b) returning: after(A a, B b) returning:
call(* foo(*,*)) &&
execution(* foo(*,*)) &&
(args(b,a) || args(a,b)) { (args(b,a) || args(a,b)) {
System.out.println("Woven"); System.out.println("Woven");
} }

+ 1
- 1
tests/bugs/DisjunctVarBinding_3.java View File

aspect IfPointcut { aspect IfPointcut {


after(A a, B b) returning: after(A a, B b) returning:
call(* foo(*,*)) &&
execution(* foo(*,*)) &&
(args(b,a) || args(a,b)) { (args(b,a) || args(a,b)) {
System.out.println("Woven"); System.out.println("Woven");
} }

+ 1
- 2
tests/src/org/aspectj/systemtest/ajc120/ajc120-tests.xml View File

<ajc-test dir="bugs" <ajc-test dir="bugs"
pr="61568" title="wrong variable binding in || pointcuts"> pr="61568" title="wrong variable binding in || pointcuts">
<compile files="DisjunctVarBinding.java"> <compile files="DisjunctVarBinding.java">
<message kind="error" line="34" text="Ambiguous binding of type B"/>
<message kind="error" line="34" text="Ambiguous binding of type A"/>
<message kind="error" line="17" text="ambiguous binding of parameter(s) a, b across '||' in pointcut"/>
</compile> </compile>
</ajc-test> </ajc-test>

+ 7
- 12
tests/src/org/aspectj/systemtest/ajc121/ajc121-tests.xml View File

<ajc-test dir="bugs" <ajc-test dir="bugs"
pr="62073" title="false ambiguous binding error (introduced in 1.2rc2)"> pr="62073" title="false ambiguous binding error (introduced in 1.2rc2)">
<compile files="DisjunctVarBinding_2.java,DisjunctVarBinding_3.java"> <compile files="DisjunctVarBinding_2.java,DisjunctVarBinding_3.java">
<message kind="error" line="25" file="DisjunctVarBinding_2.java" text="Ambiguous binding of type B"/>
<message kind="error" line="25" file="DisjunctVarBinding_2.java" text="Ambiguous binding of type A"/>
<message kind="error" line="4" file="DisjunctVarBinding_3.java" text="ambiguous binding of parameter(s) a, b across '||' in pointcut"/>
</compile> </compile>
<compile files="DisjunctVarBinding_3.java,DisjunctVarBinding_2.java"> <compile files="DisjunctVarBinding_3.java,DisjunctVarBinding_2.java">
<message kind="error" line="25" file="DisjunctVarBinding_2.java" text="Ambiguous binding of type B"/>
<message kind="error" line="25" file="DisjunctVarBinding_2.java" text="Ambiguous binding of type A"/>
<message kind="error" line="4" file="DisjunctVarBinding_3.java" text="ambiguous binding of parameter(s) a, b across '||' in pointcut"/>
</compile> </compile>
</ajc-test> </ajc-test>
<ajc-test dir="bugs/oxford" pr="65319" <ajc-test dir="bugs/oxford" pr="65319"
title="ajc crashes when compiling the following program (binding this() and target())"> title="ajc crashes when compiling the following program (binding this() and target())">
<compile files="PR65319.java"> <compile files="PR65319.java">
<message kind="error" line="7" text="Cannot use target() to match at this"/>
<message kind="error" line="7" text="Cannot use this() to match at this"/>
<message kind="error" line="11" text="Cannot use target() to match at this"/>
<message kind="error" line="11" text="Cannot use this() to match at this"/>
<message kind="error" line="11" text="Ambiguous binding of type Test"/>
<message kind="error" line="15" text="Cannot use target() to match at this"/>
<message kind="error" line="15" text="Cannot use this() to match at this"/>
<message kind="error" line="15" text="Ambiguous binding of type Test"/>
<!-- target comes before this comes before args, and we only report one error -->
<message kind="error" line="23" text="ambiguous binding of parameter(s) x across '||' in pointcut"/>
<message kind="error" line="25" text="ambiguous binding of parameter(s) x across '||' in pointcut"/>
<message kind="error" line="27" text="ambiguous binding of parameter(s) x across '||' in pointcut"/>
<message kind="error" line="29" text="ambiguous binding of parameter(s) x across '||' in pointcut"/>
</compile> </compile>
</ajc-test> </ajc-test>

+ 3
- 1
tests/src/org/aspectj/systemtest/ajc150/VarargsTests.java View File

// In this test, it can be tricky to understand the results!! The reason being that the shadow // In this test, it can be tricky to understand the results!! The reason being that the shadow
// isn't included in the error message (it really should be, but thats a bit hard to do cleanly) // isn't included in the error message (it really should be, but thats a bit hard to do cleanly)
public void test003_cantMatchVarargsWithObjectArray_withincodePCD() { public void test003_cantMatchVarargsWithObjectArray_withincodePCD() {
CompilationResult cR = binaryWeave("testcode.jar","VarargsAspect04.aj",0,7,true);
CompilationResult cR = binaryWeave("testcode.jar","VarargsAspect04.aj",0,6,true);
// There are 7. Each piece of the pointcut is matched against all the shadows, so both // There are 7. Each piece of the pointcut is matched against all the shadows, so both
// the 'withincode' PCD and the 'call' PCD are matched against every join point. // the 'withincode' PCD and the 'call' PCD are matched against every join point.
// AMC - there are now SIX. We detect early that a call(* *(..)) pcd cannot match
// constructor call shadows and never do the match.
assertTrue("Did not get expected message about a varargs mismatch, instead got: "+cR.getWarningMessages(), assertTrue("Did not get expected message about a varargs mismatch, instead got: "+cR.getWarningMessages(),
((IMessage)cR.getWarningMessages().get(0)).toString().indexOf("varargs declared method")!=-1); ((IMessage)cR.getWarningMessages().get(0)).toString().indexOf("varargs declared method")!=-1);

+ 13
- 0
weaver/src/org/aspectj/weaver/Advice.java View File

return getSignature().getParameterTypes().length - getExtraParameterCount(); return getSignature().getParameterTypes().length - getExtraParameterCount();
} }


public String[] getBaseParameterNames(World world) {
String[] allNames = getSignature().getParameterNames(world);
int extras = getExtraParameterCount();
if (extras == 0) return allNames;
String[] result = new String[getBaseParameterCount()];
for (int i = 0; i < result.length; i++) {
result[i] = allNames[i];
}
return result;
}
public TypeX getExtraParameterType() { public TypeX getExtraParameterType() {
if (!hasExtraParameter()) return ResolvedTypeX.MISSING; if (!hasExtraParameter()) return ResolvedTypeX.MISSING;
return signature.getParameterTypes()[getBaseParameterCount()]; return signature.getParameterTypes()[getBaseParameterCount()];
// assert !fromType.isAbstract(); // assert !fromType.isAbstract();
Pointcut p = pointcut.concretize(fromType, signature.getArity(), this); Pointcut p = pointcut.concretize(fromType, signature.getArity(), this);
if (clause != null) { if (clause != null) {
Pointcut oldP = p;
p = new AndPointcut(clause, p); p = new AndPointcut(clause, p);
p.copyLocationFrom(oldP);
p.state = Pointcut.CONCRETE; p.state = Pointcut.CONCRETE;
} }

+ 13
- 0
weaver/src/org/aspectj/weaver/Shadow.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set;


import org.aspectj.asm.IRelationship; import org.aspectj.asm.IRelationship;
import org.aspectj.bridge.*; import org.aspectj.bridge.*;
*/ */


public abstract class Shadow { public abstract class Shadow {

// every Shadow has a unique id, doesn't matter if it wraps...
private static int nextShadowID = 100; // easier to spot than zero.
private final Kind kind; private final Kind kind;
private final Member signature; private final Member signature;
protected final Shadow enclosingShadow; protected final Shadow enclosingShadow;
protected List mungers = new ArrayList(1); protected List mungers = new ArrayList(1);


public int shadowId = nextShadowID++; // every time we build a shadow, it gets a new id


// ---- // ----
protected Shadow(Kind kind, Member signature, Shadow enclosingShadow) { protected Shadow(Kind kind, Member signature, Shadow enclosingShadow) {
AdviceExecution, Initialization, ExceptionHandler, AdviceExecution, Initialization, ExceptionHandler,
}; };


public static final Set ALL_SHADOW_KINDS = new HashSet();
static {
for (int i = 0; i < SHADOW_KINDS.length; i++) {
ALL_SHADOW_KINDS.add(SHADOW_KINDS[i]);
}
}


/** A type-safe enum representing the kind of shadows /** A type-safe enum representing the kind of shadows
*/ */

+ 5
- 0
weaver/src/org/aspectj/weaver/ShadowMunger.java View File

public Pointcut getPointcut() { public Pointcut getPointcut() {
return pointcut; return pointcut;
} }
// pointcut may be updated during rewriting...
public void setPointcut(Pointcut pointcut) {
this.pointcut = pointcut;
}




/** /**

+ 5
- 0
weaver/src/org/aspectj/weaver/WeaverMessages.java View File

public static final String XLINT_KEY_ERROR = "invalidXLintKey"; public static final String XLINT_KEY_ERROR = "invalidXLintKey";
public static final String XLINT_VALUE_ERROR = "invalidXLintMessageKind"; public static final String XLINT_VALUE_ERROR = "invalidXLintMessageKind";
public static final String UNBOUND_FORMAL = "unboundFormalInPC";
public static final String AMBIGUOUS_BINDING = "ambiguousBindingInPC";
public static final String AMBIGUOUS_BINDING_IN_OR = "ambiguousBindingInOrPC";
public static final String NEGATION_DOESNT_ALLOW_BINDING = "negationDoesntAllowBinding";
// Java5 messages // Java5 messages
public static final String ITDC_ON_ENUM_NOT_ALLOWED = "itdcOnEnumNotAllowed"; public static final String ITDC_ON_ENUM_NOT_ALLOWED = "itdcOnEnumNotAllowed";
public static final String ITDM_ON_ENUM_NOT_ALLOWED = "itdmOnEnumNotAllowed"; public static final String ITDM_ON_ENUM_NOT_ALLOWED = "itdmOnEnumNotAllowed";

+ 254
- 0
weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java View File

import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.jar.Attributes; import java.util.jar.Attributes;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import org.aspectj.bridge.SourceLocation; import org.aspectj.bridge.SourceLocation;
import org.aspectj.util.FileUtil; import org.aspectj.util.FileUtil;
import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.Advice;
import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.CrosscuttingMembersSet; import org.aspectj.weaver.CrosscuttingMembersSet;
import org.aspectj.weaver.IClassFileProvider; import org.aspectj.weaver.IClassFileProvider;
import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.WeaverMetrics; import org.aspectj.weaver.WeaverMetrics;
import org.aspectj.weaver.WeaverStateInfo; import org.aspectj.weaver.WeaverStateInfo;
import org.aspectj.weaver.patterns.AndPointcut;
import org.aspectj.weaver.patterns.BindingAnnotationTypePattern;
import org.aspectj.weaver.patterns.BindingTypePattern;
import org.aspectj.weaver.patterns.CflowPointcut; import org.aspectj.weaver.patterns.CflowPointcut;
import org.aspectj.weaver.patterns.ConcreteCflowPointcut;
import org.aspectj.weaver.patterns.DeclareParents; import org.aspectj.weaver.patterns.DeclareParents;
import org.aspectj.weaver.patterns.FastMatchInfo; import org.aspectj.weaver.patterns.FastMatchInfo;
import org.aspectj.weaver.patterns.IfPointcut;
import org.aspectj.weaver.patterns.NameBindingPointcut;
import org.aspectj.weaver.patterns.NotPointcut;
import org.aspectj.weaver.patterns.OrPointcut;
import org.aspectj.weaver.patterns.Pointcut;
import org.aspectj.weaver.patterns.PointcutRewriter;




public class BcelWeaver implements IWeaver { public class BcelWeaver implements IWeaver {
} }


shadowMungerList = xcutSet.getShadowMungers(); shadowMungerList = xcutSet.getShadowMungers();
rewritePointcuts(shadowMungerList);
typeMungerList = xcutSet.getTypeMungers(); typeMungerList = xcutSet.getTypeMungers();
declareParentsList = xcutSet.getDeclareParents(); declareParentsList = xcutSet.getDeclareParents();
}); });
} }
/*
* Rewrite all of the pointcuts in the world into their most efficient
* form for subsequent matching. Also ensure that if pc1.equals(pc2)
* then pc1 == pc2 (for non-binding pcds) by making references all
* point to the same instance.
* Since pointcuts remember their match decision on the last shadow,
* this makes matching faster when many pointcuts share common elements,
* or even when one single pointcut has one common element (which can
* be a side-effect of DNF rewriting).
*/
private void rewritePointcuts(List/*ShadowMunger*/ shadowMungers) {
PointcutRewriter rewriter = new PointcutRewriter();
for (Iterator iter = shadowMungers.iterator(); iter.hasNext();) {
ShadowMunger munger = (ShadowMunger) iter.next();
Pointcut p = munger.getPointcut();
Pointcut newP = rewriter.rewrite(p);
// validateBindings now whilst we still have around the pointcut
// that resembles what the user actually wrote in their program
// text.
if (munger instanceof Advice) {
Advice advice = (Advice) munger;
if (advice.getSignature() != null) {
int numFormals = advice.getBaseParameterCount();
if (numFormals > 0) {
String[] names = advice.getBaseParameterNames(world);
validateBindings(newP,p,numFormals,names);
}
}
}
munger.setPointcut(newP);
}
// now that we have optimized individual pointcuts, optimize
// across the set of pointcuts....
// Use a map from key based on pc equality, to value based on
// pc identity.
Map/*<Pointcut,Pointcut>*/ pcMap = new HashMap();
for (Iterator iter = shadowMungers.iterator(); iter.hasNext();) {
ShadowMunger munger = (ShadowMunger) iter.next();
Pointcut p = munger.getPointcut();
munger.setPointcut(shareEntriesFromMap(p,pcMap));
}
}
private Pointcut shareEntriesFromMap(Pointcut p,Map pcMap) {
// some things cant be shared...
if (p instanceof NameBindingPointcut) return p;
if (p instanceof IfPointcut) return p;
if (p instanceof ConcreteCflowPointcut) return p;
if (p instanceof AndPointcut) {
AndPointcut apc = (AndPointcut) p;
Pointcut left = shareEntriesFromMap(apc.getLeft(),pcMap);
Pointcut right = shareEntriesFromMap(apc.getRight(),pcMap);
return new AndPointcut(left,right);
} else if (p instanceof OrPointcut) {
OrPointcut opc = (OrPointcut) p;
Pointcut left = shareEntriesFromMap(opc.getLeft(),pcMap);
Pointcut right = shareEntriesFromMap(opc.getRight(),pcMap);
return new OrPointcut(left,right);
} else if (p instanceof NotPointcut) {
NotPointcut npc = (NotPointcut) p;
Pointcut not = shareEntriesFromMap(npc.getNegatedPointcut(),pcMap);
return new NotPointcut(not);
} else {
// primitive pcd
if (pcMap.containsKey(p)) { // based on equality
return (Pointcut) pcMap.get(p); // same instance (identity)
} else {
pcMap.put(p,p);
return p;
}
}
}
// userPointcut is the pointcut that the user wrote in the program text.
// dnfPointcut is the same pointcut rewritten in DNF
// numFormals is the number of formal parameters in the pointcut
// if numFormals > 0 then every branch of a disjunction must bind each formal once and only once.
// in addition, the left and right branches of a disjunction must hold on join point kinds in
// common.
private void validateBindings(Pointcut dnfPointcut, Pointcut userPointcut, int numFormals, String[] names) {
if (numFormals == 0) return; // nothing to check
if (dnfPointcut.couldMatchKinds().isEmpty()) return; // cant have problems if you dont match!
if (dnfPointcut instanceof OrPointcut) {
OrPointcut orBasedDNFPointcut = (OrPointcut) dnfPointcut;
Pointcut[] leftBindings = new Pointcut[numFormals];
Pointcut[] rightBindings = new Pointcut[numFormals];
validateOrBranch(orBasedDNFPointcut,userPointcut,numFormals,names,leftBindings,rightBindings);
} else {
Pointcut[] bindings = new Pointcut[numFormals];
validateSingleBranch(dnfPointcut, userPointcut, numFormals, names,bindings);
}
}
private void validateOrBranch(OrPointcut pc, Pointcut userPointcut, int numFormals,
String[] names, Pointcut[] leftBindings, Pointcut[] rightBindings) {
Pointcut left = pc.getLeft();
Pointcut right = pc.getRight();
if (left instanceof OrPointcut) {
Pointcut[] newRightBindings = new Pointcut[numFormals];
validateOrBranch((OrPointcut)left,userPointcut,numFormals,names,leftBindings,newRightBindings);
} else {
if (left.couldMatchKinds().size() > 0)
validateSingleBranch(left, userPointcut, numFormals, names, leftBindings);
}
if (right instanceof OrPointcut) {
Pointcut[] newLeftBindings = new Pointcut[numFormals];
validateOrBranch((OrPointcut)right,userPointcut,numFormals,names,newLeftBindings,rightBindings);
} else {
if (right.couldMatchKinds().size() > 0)
validateSingleBranch(right, userPointcut, numFormals, names, rightBindings);
}
Set kindsInCommon = left.couldMatchKinds();
kindsInCommon.retainAll(right.couldMatchKinds());
if (!kindsInCommon.isEmpty()) {
// we know that every branch binds every formal, so there is no ambiguity
// if each branch binds it in exactly the same way...
List ambiguousNames = new ArrayList();
for (int i = 0; i < numFormals; i++) {
if (!leftBindings[i].equals(rightBindings[i])) {
ambiguousNames.add(names[i]);
}
}
if (!ambiguousNames.isEmpty())
raiseAmbiguityInDisjunctionError(userPointcut,ambiguousNames);
}
}
// pc is a pointcut that does not contain any disjunctions
// check that every formal is bound (negation doesn't count).
// we know that numFormals > 0 or else we would not be called
private void validateSingleBranch(Pointcut pc, Pointcut userPointcut, int numFormals, String[] names, Pointcut[] bindings) {
boolean[] foundFormals = new boolean[numFormals];
for (int i = 0; i < foundFormals.length; i++) {
foundFormals[i] = false;
}
validateSingleBranchRecursion(pc, userPointcut, foundFormals, names, bindings);
for (int i = 0; i < foundFormals.length; i++) {
if (!foundFormals[i]) {
raiseUnboundFormalError(names[i],userPointcut);
}
}
}
// each formal must appear exactly once
private void validateSingleBranchRecursion(Pointcut pc, Pointcut userPointcut, boolean[] foundFormals, String[] names, Pointcut[] bindings) {
if (pc instanceof NotPointcut) {
// nots can only appear at leaves in DNF
NotPointcut not = (NotPointcut) pc;
if (not.getNegatedPointcut() instanceof NameBindingPointcut) {
NameBindingPointcut nnbp = (NameBindingPointcut) not.getNegatedPointcut();
if (!nnbp.getBindingAnnotationTypePatterns().isEmpty() && !nnbp.getBindingTypePatterns().isEmpty())
raiseNegationBindingError(userPointcut);
}
} else if (pc instanceof AndPointcut) {
AndPointcut and = (AndPointcut) pc;
validateSingleBranchRecursion(and.getLeft(), userPointcut,foundFormals,names,bindings);
validateSingleBranchRecursion(and.getRight(),userPointcut,foundFormals,names,bindings);
} else if (pc instanceof NameBindingPointcut) {
List/*BindingTypePattern*/ btps = ((NameBindingPointcut)pc).getBindingTypePatterns();
for (Iterator iter = btps.iterator(); iter.hasNext();) {
BindingTypePattern btp = (BindingTypePattern) iter.next();
int index = btp.getFormalIndex();
bindings[index] = pc;
if (foundFormals[index]) {
raiseAmbiguousBindingError(names[index],userPointcut);
} else {
foundFormals[index] = true;
}
}
List/*BindingAnnotationTypePattern*/ baps = ((NameBindingPointcut)pc).getBindingAnnotationTypePatterns();
for (Iterator iter = baps.iterator(); iter.hasNext();) {
BindingAnnotationTypePattern bap = (BindingAnnotationTypePattern) iter.next();
int index = bap.getFormalIndex();
bindings[index] = pc;
if (foundFormals[index]) {
raiseAmbiguousBindingError(names[index],userPointcut);
} else {
foundFormals[index] = true;
}
}
} else if (pc instanceof ConcreteCflowPointcut) {
ConcreteCflowPointcut cfp = (ConcreteCflowPointcut) pc;
int[] slots = cfp.getUsedFormalSlots();
for (int i = 0; i < slots.length; i++) {
bindings[slots[i]] = cfp;
if (foundFormals[slots[i]]) {
raiseAmbiguousBindingError(names[slots[i]],userPointcut);
} else {
foundFormals[slots[i]] = true;
}
}
}
}
/**
* @param userPointcut
*/
private void raiseNegationBindingError(Pointcut userPointcut) {
world.showMessage(IMessage.ERROR,
WeaverMessages.format(WeaverMessages.NEGATION_DOESNT_ALLOW_BINDING),
userPointcut.getSourceContext().makeSourceLocation(userPointcut),null);
}

/**
* @param string
* @param userPointcut
*/
private void raiseAmbiguousBindingError(String name, Pointcut userPointcut) {
world.showMessage(IMessage.ERROR,
WeaverMessages.format(WeaverMessages.AMBIGUOUS_BINDING,
name),
userPointcut.getSourceContext().makeSourceLocation(userPointcut),null);
}

/**
* @param userPointcut
*/
private void raiseAmbiguityInDisjunctionError(Pointcut userPointcut, List names) {
StringBuffer formalNames = new StringBuffer(names.get(0).toString());
for (int i = 1; i < names.size(); i++) {
formalNames.append(", ");
formalNames.append(names.get(i));
}
world.showMessage(IMessage.ERROR,
WeaverMessages.format(WeaverMessages.AMBIGUOUS_BINDING_IN_OR,formalNames),
userPointcut.getSourceContext().makeSourceLocation(userPointcut),null);
}

/**
* @param string
* @param userPointcut
*/
private void raiseUnboundFormalError(String name, Pointcut userPointcut) {
world.showMessage(IMessage.ERROR,
WeaverMessages.format(WeaverMessages.UNBOUND_FORMAL,
name),
userPointcut.getSourceContext().makeSourceLocation(userPointcut),null);
}


// public void dumpUnwoven(File file) throws IOException { // public void dumpUnwoven(File file) throws IOException {
// BufferedOutputStream os = FileUtil.makeOutputStream(file); // BufferedOutputStream os = FileUtil.makeOutputStream(file);
// this.zipOutputStream = new ZipOutputStream(os); // this.zipOutputStream = new ZipOutputStream(os);

+ 17
- 4
weaver/src/org/aspectj/weaver/patterns/AndPointcut.java View File

import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.HashSet;
import java.util.Set;


import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
public class AndPointcut extends Pointcut { public class AndPointcut extends Pointcut {
Pointcut left, right; // exposed for testing Pointcut left, right; // exposed for testing


private Set couldMatchKinds;
public AndPointcut(Pointcut left, Pointcut right) { public AndPointcut(Pointcut left, Pointcut right) {
super(); super();
this.left = left; this.left = left;
this.right = right; this.right = right;
this.pointcutKind = AND; this.pointcutKind = AND;
setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
couldMatchKinds = new HashSet();
couldMatchKinds.addAll(left.couldMatchKinds());
couldMatchKinds.retainAll(right.couldMatchKinds());
}
public Set couldMatchKinds() {
return couldMatchKinds;
} }


public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return left.fastMatch(type).and(right.fastMatch(type)); return left.fastMatch(type).and(right.fastMatch(type));
} }


public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return left.match(shadow).and(right.match(shadow)); return left.match(shadow).and(right.match(shadow));
} }
} }




public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return Test.makeAnd(left.findResidue(shadow, state), right.findResidue(shadow, state)); return Test.makeAnd(left.findResidue(shadow, state), right.findResidue(shadow, state));
} }


public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
return new AndPointcut(left.concretize(inAspect, bindings),
right.concretize(inAspect, bindings));
AndPointcut ret = new AndPointcut(left.concretize(inAspect, bindings),
right.concretize(inAspect, bindings));
ret.copyLocationFrom(this);
return ret;
} }


public Pointcut getLeft() { public Pointcut getLeft() {

+ 17
- 1
weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java View File

private TypePattern left, right; private TypePattern left, right;
public AndTypePattern(TypePattern left, TypePattern right) { public AndTypePattern(TypePattern left, TypePattern right) {
super(false,false); //??? we override all methods that care about includeSubtypes
super(false,false); //?? we override all methods that care about includeSubtypes
this.left = left; this.left = left;
this.right = right; this.right = right;
setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
return buff.toString(); return buff.toString();
} }


public boolean equals(Object obj) {
if (! (obj instanceof AndTypePattern)) return false;
AndTypePattern atp = (AndTypePattern) obj;
return left.equals(atp.left) && right.equals(atp.right);
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
int ret = 17;
ret = ret + 37 * left.hashCode();
ret = ret + 37 * right.hashCode();
return ret;
}
} }

+ 4
- 0
weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java View File

this((AnnotationTypePattern[]) l.toArray(new AnnotationTypePattern[l.size()])); this((AnnotationTypePattern[]) l.toArray(new AnnotationTypePattern[l.size()]));
} }


protected AnnotationTypePattern[] getAnnotationPatterns() {
return typePatterns;
}
public void resolve(World inWorld) { public void resolve(World inWorld) {
for (int i = 0; i < typePatterns.length; i++) { for (int i = 0; i < typePatterns.length; i++) {
typePatterns[i].resolve(inWorld); typePatterns[i].resolve(inWorld);

+ 37
- 11
weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;


import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message; import org.aspectj.bridge.Message;
this.munger = munger; this.munger = munger;
} }


public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/ */
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
*/ */
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
AnnotatedElement toMatchAgainst = null; AnnotatedElement toMatchAgainst = null;
Member member = shadow.getSignature(); Member member = shadow.getSignature();
ResolvedMember rMember = member.resolve(shadow.getIWorld()); ResolvedMember rMember = member.resolve(shadow.getIWorld());
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
*/ */
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
if (annotationTypePattern instanceof BindingAnnotationTypePattern) { if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern; BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
Var var = shadow.getKindedAnnotationVar(annotationType); Var var = shadow.getKindedAnnotationVar(annotationType);
if (var == null) return Literal.FALSE; if (var == null) return Literal.FALSE;
// Check if we have already bound something to this formal // Check if we have already bound something to this formal
if (state.get(btp.getFormalIndex())!=null) {
ISourceLocation pcdSloc = getSourceLocation();
ISourceLocation shadowSloc = shadow.getSourceLocation();
Message errorMessage = new Message(
"Cannot use @pointcut to match at this location and bind a formal to type '"+var.getType()+
"' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
". The secondary source location points to the problematic binding.",
shadowSloc,true,new ISourceLocation[]{pcdSloc});
shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
if ((state.get(btp.getFormalIndex())!=null) &&(lastMatchedShadowId == shadow.shadowId)) {
// ISourceLocation pcdSloc = getSourceLocation();
// ISourceLocation shadowSloc = shadow.getSourceLocation();
// Message errorMessage = new Message(
// "Cannot use @pointcut to match at this location and bind a formal to type '"+var.getType()+
// "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
// ". The secondary source location points to the problematic binding.",
// shadowSloc,true,new ISourceLocation[]{pcdSloc});
// shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
state.setErroneousVar(btp.getFormalIndex()); state.setErroneousVar(btp.getFormalIndex());
} }
state.set(btp.getFormalIndex(),var); state.set(btp.getFormalIndex(),var);
return Literal.TRUE; return Literal.TRUE;
} }


/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
*/
public List getBindingAnnotationTypePatterns() {
if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
List l = new ArrayList();
l.add(annotationTypePattern);
return l;
} else return Collections.EMPTY_LIST;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
*/
public List getBindingTypePatterns() {
return Collections.EMPTY_LIST;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/ */

+ 37
- 5
weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;


import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.ISourceLocation;
public class ArgsAnnotationPointcut extends NameBindingPointcut { public class ArgsAnnotationPointcut extends NameBindingPointcut {


private AnnotationPatternList arguments; private AnnotationPatternList arguments;
/** /**
* *
*/ */
super(); super();
this.arguments = arguments; this.arguments = arguments;
} }
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS; // empty args() matches jps with no args
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/ */
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
*/ */
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
arguments.resolve(shadow.getIWorld()); arguments.resolve(shadow.getIWorld());
FuzzyBoolean ret = FuzzyBoolean ret =
arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes())); arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()));
return Pointcut.makeMatchesNothing(Pointcut.CONCRETE); return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
} }
AnnotationPatternList list = arguments.resolveReferences(bindings); AnnotationPatternList list = arguments.resolveReferences(bindings);
return new ArgsAnnotationPointcut(list);
Pointcut ret = new ArgsAnnotationPointcut(list);
ret.copyLocationFrom(this);
return ret;
} }


/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
*/ */
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
int len = shadow.getArgCount(); int len = shadow.getArgCount();
// do some quick length tests first // do some quick length tests first
return ret; return ret;
} }


/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
*/
public List getBindingAnnotationTypePatterns() {
List l = new ArrayList();
AnnotationTypePattern[] pats = arguments.getAnnotationPatterns();
for (int i = 0; i < pats.length; i++) {
if (pats[i] instanceof BindingAnnotationTypePattern) {
l.add(pats[i]);
}
}
return l;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
*/
public List getBindingTypePatterns() {
return Collections.EMPTY_LIST;
}

/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/ */

+ 43
- 12
weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java View File

import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Set;


import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.ISourceLocation;
this.arguments = arguments; this.arguments = arguments;
this.pointcutKind = ARGS; this.pointcutKind = ARGS;
} }

public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS; // empty args() matches jps with no args
}

public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }


public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
FuzzyBoolean ret = FuzzyBoolean ret =
arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()), TypePattern.DYNAMIC); arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()), TypePattern.DYNAMIC);
return ret; return ret;
return ret; return ret;
} }


/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
*/
public List getBindingAnnotationTypePatterns() {
return Collections.EMPTY_LIST;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
*/
public List getBindingTypePatterns() {
List l = new ArrayList();
TypePattern[] pats = arguments.getTypePatterns();
for (int i = 0; i < pats.length; i++) {
if (pats[i] instanceof BindingTypePattern) {
l.add(pats[i]);
}
}
return l;
}
public void write(DataOutputStream s) throws IOException { public void write(DataOutputStream s) throws IOException {
s.writeByte(Pointcut.ARGS); s.writeByte(Pointcut.ARGS);
arguments.write(s); arguments.write(s);
if (inAspect.crosscuttingMembers != null) { if (inAspect.crosscuttingMembers != null) {
inAspect.crosscuttingMembers.exposeTypes(args.getExactTypes()); inAspect.crosscuttingMembers.exposeTypes(args.getExactTypes());
} }
return new ArgsPointcut(args);
Pointcut ret = new ArgsPointcut(args);
ret.copyLocationFrom(this);
return ret;
} }


private Test findResidueNoEllipsis(Shadow shadow, ExposedState state, TypePattern[] patterns) { private Test findResidueNoEllipsis(Shadow shadow, ExposedState state, TypePattern[] patterns) {
} else { } else {
BindingTypePattern btp = (BindingTypePattern)type; BindingTypePattern btp = (BindingTypePattern)type;
// Check if we have already bound something to this formal // Check if we have already bound something to this formal
if (state.get(btp.getFormalIndex())!=null) {
ISourceLocation isl = getSourceLocation();
Message errorMessage = new Message(
"Ambiguous binding of type "+type.getExactType().toString()+
" using args(..) at this line - formal is already bound"+
". See secondary source location for location of args(..)",
shadow.getSourceLocation(),true,new ISourceLocation[]{getSourceLocation()});
shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
if ((state.get(btp.getFormalIndex())!=null) &&(lastMatchedShadowId != shadow.shadowId)) {
// ISourceLocation isl = getSourceLocation();
// Message errorMessage = new Message(
// "Ambiguous binding of type "+type.getExactType().toString()+
// " using args(..) at this line - formal is already bound"+
// ". See secondary source location for location of args(..)",
// shadow.getSourceLocation(),true,new ISourceLocation[]{getSourceLocation()});
// shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
state.setErroneousVar(btp.getFormalIndex()); state.setErroneousVar(btp.getFormalIndex());
} }
} }
return ret; return ret;
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
if (arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()), TypePattern.DYNAMIC).alwaysFalse()) { if (arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()), TypePattern.DYNAMIC).alwaysFalse()) {
return Literal.FALSE; return Literal.FALSE;
} }

+ 2
- 0
weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java View File

public boolean equals(Object other) { public boolean equals(Object other) {
if (!(other instanceof BindingTypePattern)) return false; if (!(other instanceof BindingTypePattern)) return false;
BindingTypePattern o = (BindingTypePattern)other; BindingTypePattern o = (BindingTypePattern)other;
if (includeSubtypes != o.includeSubtypes) return false;
if (isVarArgs != o.isVarArgs) return false;
return o.type.equals(this.type) && o.formalIndex == this.formalIndex; return o.type.equals(this.type) && o.formalIndex == this.formalIndex;
} }
public int hashCode() { public int hashCode() {

+ 14
- 5
weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java View File

import java.util.Collection; import java.util.Collection;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
import java.util.Set;


import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessage;
import org.aspectj.util.FileUtil; import org.aspectj.util.FileUtil;
this.freeVars = freeVars; this.freeVars = freeVars;
this.pointcutKind = CFLOW; this.pointcutKind = CFLOW;
} }

public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
//??? this is not maximally efficient //??? this is not maximally efficient
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
return "cflow" + (isBelow ? "below" : "") + "(" + entry + ")"; return "cflow" + (isBelow ? "below" : "") + "(" + entry + ")";
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
throw new RuntimeException("unimplemented"); throw new RuntimeException("unimplemented");
} }
putCflowfield(concreteEntry,localCflowField); // Remember it putCflowfield(concreteEntry,localCflowField); // Remember it
} }
return new ConcreteCflowPointcut(localCflowField, null,true);
Pointcut ret = new ConcreteCflowPointcut(localCflowField, null,true);
ret.copyLocationFrom(this);
return ret;
} else { } else {


List slots = new ArrayList(); List slots = new ArrayList();
world.makeCflowStackFieldAdder(localCflowField)); world.makeCflowStackFieldAdder(localCflowField));
putCflowfield(concreteEntry,localCflowField); putCflowfield(concreteEntry,localCflowField);
} }
return new ConcreteCflowPointcut(localCflowField, slots,false);
Pointcut ret = new ConcreteCflowPointcut(localCflowField, slots,false);
ret.copyLocationFrom(this);
return ret;
} }
} }

+ 17
- 2
weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java View File

import java.io.IOException; import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set;


import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.IntMap; import org.aspectj.weaver.IntMap;
this.pointcutKind = CFLOW; this.pointcutKind = CFLOW;
} }
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
//??? this is not maximally efficient //??? this is not maximally efficient
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
throw new UnsupportedOperationException("cflow pointcut matching not supported by this operation"); throw new UnsupportedOperationException("cflow pointcut matching not supported by this operation");
} }


// used by weaver when validating bindings
public int[] getUsedFormalSlots() {
if (slots == null) return new int[0];
int[] indices = new int[slots.size()];
for (int i = 0; i < indices.length; i++) {
indices[i] = ((Slot)slots.get(i)).formalIndex;
}
return indices;
}
public void write(DataOutputStream s) throws IOException { public void write(DataOutputStream s) throws IOException {
throw new RuntimeException("unimplemented"); throw new RuntimeException("unimplemented");
} }
return "concretecflow(" + cflowField + ")"; return "concretecflow(" + cflowField + ")";
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
//System.out.println("find residue: " + this); //System.out.println("find residue: " + this);
if (usesCounter) { if (usesCounter) {
return Test.makeFieldGetCall(cflowField, cflowCounterIsValidMethod, Expr.NONE); return Test.makeFieldGetCall(cflowField, cflowCounterIsValidMethod, Expr.NONE);

+ 2
- 0
weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java View File

public boolean equals(Object other) { public boolean equals(Object other) {
if (!(other instanceof ExactTypePattern)) return false; if (!(other instanceof ExactTypePattern)) return false;
ExactTypePattern o = (ExactTypePattern)other; ExactTypePattern o = (ExactTypePattern)other;
if (includeSubtypes != o.includeSubtypes) return false;
if (isVarArgs != o.isVarArgs) return false;
return (o.type.equals(this.type) && o.annotationPattern.equals(this.annotationPattern)); return (o.type.equals(this.type) && o.annotationPattern.equals(this.annotationPattern));
} }

+ 16
- 3
weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java View File

import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.HashSet;
import java.util.Set;


import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
public class HandlerPointcut extends Pointcut { public class HandlerPointcut extends Pointcut {
TypePattern exceptionType; TypePattern exceptionType;


private static final Set MATCH_KINDS = new HashSet();
static {
MATCH_KINDS.add(Shadow.ExceptionHandler);
}
public HandlerPointcut(TypePattern exceptionType) { public HandlerPointcut(TypePattern exceptionType) {
this.exceptionType = exceptionType; this.exceptionType = exceptionType;
this.pointcutKind = HANDLER; this.pointcutKind = HANDLER;
} }


public Set couldMatchKinds() {
return MATCH_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
//??? should be able to do better by finding all referenced types in type //??? should be able to do better by finding all referenced types in type
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
if (shadow.getKind() != Shadow.ExceptionHandler) return FuzzyBoolean.NO; if (shadow.getKind() != Shadow.ExceptionHandler) return FuzzyBoolean.NO;
// we know we have exactly one parameter since we're checking an exception handler // we know we have exactly one parameter since we're checking an exception handler
exceptionType = exceptionType.resolveBindingsFromRTTI(false,false); exceptionType = exceptionType.resolveBindingsFromRTTI(false,false);
} }
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE; return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
} }
public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
return new HandlerPointcut(exceptionType);
Pointcut ret = new HandlerPointcut(exceptionType);
ret.copyLocationFrom(this);
return ret;
} }
} }

+ 43
- 9
weaver/src/org/aspectj/weaver/patterns/IfPointcut.java View File

import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;


import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessage;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
this.pointcutKind = IF; this.pointcutKind = IF;
} }
public FuzzyBoolean fastMatch(FastMatchInfo type) {
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}

public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
//??? this is not maximally efficient //??? this is not maximally efficient
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }


public boolean alwaysFalse() {
return false;
}
public boolean alwaysTrue() {
return false;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[])
*/ */
//??? The implementation of name binding and type checking in if PCDs is very convoluted //??? The implementation of name binding and type checking in if PCDs is very convoluted
// There has to be a better way... // There has to be a better way...
private boolean findingResidue = false; private boolean findingResidue = false;
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
if (findingResidue) return Literal.TRUE; if (findingResidue) return Literal.TRUE;
findingResidue = true; findingResidue = true;
try { try {
} }
} }

// amc - the only reason this override seems to be here is to stop the copy, but
// that can be prevented by overriding shouldCopyLocationForConcretization,
// allowing me to make the method final in Pointcut.
// public Pointcut concretize(ResolvedTypeX inAspect, IntMap bindings) {
// return this.concretize1(inAspect, bindings);
// }
public Pointcut concretize(ResolvedTypeX inAspect, IntMap bindings) {
return this.concretize1(inAspect, bindings);
protected boolean shouldCopyLocationForConcretize() {
return false;
} }
private IfPointcut partiallyConcretized = null; private IfPointcut partiallyConcretized = null;
return partiallyConcretized; return partiallyConcretized;
} }
IfPointcut ret = new IfPointcut(testMethod, extraParameterFlags); IfPointcut ret = new IfPointcut(testMethod, extraParameterFlags);
ret.copyLocationFrom(this);
partiallyConcretized = ret; partiallyConcretized = ret;
// It is possible to directly code your pointcut expression in a per clause // It is possible to directly code your pointcut expression in a per clause
super(null,0); super(null,0);
} }
public Test findResidue(Shadow shadow, ExposedState state) {
public Set couldMatchKinds() {
return Collections.EMPTY_SET;
}
public boolean alwaysFalse() {
return true;
}
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return Literal.FALSE; // can only get here if an earlier error occurred return Literal.FALSE; // can only get here if an earlier error occurred
} }


return FuzzyBoolean.NO; return FuzzyBoolean.NO;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.NO; return FuzzyBoolean.NO;
} }
public IfTruePointcut() { public IfTruePointcut() {
super(null,0); super(null,0);
} }

public boolean alwaysTrue() {
return true;
}
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return Literal.TRUE; // can only get here if an earlier error occurred return Literal.TRUE; // can only get here if an earlier error occurred
} }


return FuzzyBoolean.YES; return FuzzyBoolean.YES;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.YES; return FuzzyBoolean.YES;
} }

+ 14
- 2
weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet;
import java.util.Set;


import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.ISourceLocation;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
public class KindedPointcut extends Pointcut { public class KindedPointcut extends Pointcut {
Shadow.Kind kind; Shadow.Kind kind;
SignaturePattern signature; SignaturePattern signature;
private Set matchKinds;
private ShadowMunger munger = null; // only set after concretization private ShadowMunger munger = null; // only set after concretization


this.kind = kind; this.kind = kind;
this.signature = signature; this.signature = signature;
this.pointcutKind = KINDED; this.pointcutKind = KINDED;
this.matchKinds = new HashSet();
matchKinds.add(kind);
} }
public KindedPointcut( public KindedPointcut(
Shadow.Kind kind, Shadow.Kind kind,
this(kind, signature); this(kind, signature);
this.munger = munger; this.munger = munger;
} }
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#couldMatchKinds()
*/
public Set couldMatchKinds() {
return matchKinds;
}
public FuzzyBoolean fastMatch(FastMatchInfo info) { public FuzzyBoolean fastMatch(FastMatchInfo info) {
if (info.getKind() != null) { if (info.getKind() != null) {
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
if (shadow.getKind() != kind) return FuzzyBoolean.NO; if (shadow.getKind() != kind) return FuzzyBoolean.NO;


if (!signature.matches(shadow.getSignature(), shadow.getIWorld())){ if (!signature.matches(shadow.getSignature(), shadow.getIWorld())){
signature = signature.resolveBindingsFromRTTI(); signature = signature.resolveBindingsFromRTTI();
} }
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE; return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
} }

+ 4
- 1
weaver/src/org/aspectj/weaver/patterns/NameBindingPointcut.java View File



package org.aspectj.weaver.patterns; package org.aspectj.weaver.patterns;


import java.util.List;

import org.aspectj.weaver.TypeX; import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.World; import org.aspectj.weaver.World;
import org.aspectj.weaver.ast.Test; import org.aspectj.weaver.ast.Test;
return Test.makeInstanceof(var, myType.resolve(world)); return Test.makeInstanceof(var, myType.resolve(world));
} }
public abstract List/*<BindingTypePattern>*/ getBindingTypePatterns();
public abstract List/*<BindingAnnotationTypePattern>*/ getBindingAnnotationTypePatterns();




} }

+ 10
- 3
weaver/src/org/aspectj/weaver/patterns/NotPointcut.java View File

import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.Set;


import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
setLocation(pointcut.getSourceContext(), startPos, pointcut.getEnd()); setLocation(pointcut.getSourceContext(), startPos, pointcut.getEnd());
} }


public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
public Pointcut getNegatedPointcut() { return body; } public Pointcut getNegatedPointcut() { return body; }


public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return body.fastMatch(type).not(); return body.fastMatch(type).not();
} }


public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return body.match(shadow).not(); return body.match(shadow).not();
} }


return ret; return ret;
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return Test.makeNot(body.findResidue(shadow, state)); return Test.makeNot(body.findResidue(shadow, state));
} }
public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
return new NotPointcut(body.concretize(inAspect, bindings));
Pointcut ret = new NotPointcut(body.concretize(inAspect, bindings));
ret.copyLocationFrom(this);
return ret;
} }


} }

+ 15
- 0
weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java View File

} }
return buff.toString(); return buff.toString();
} }
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (! (obj instanceof NotTypePattern)) return false;
return (pattern.equals(((NotTypePattern)obj).pattern));
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return 17 + 37 * pattern.hashCode();
}
} }

+ 13
- 3
weaver/src/org/aspectj/weaver/patterns/OrPointcut.java View File

import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.HashSet;
import java.util.Set;


import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;


public class OrPointcut extends Pointcut { public class OrPointcut extends Pointcut {
private Pointcut left, right; private Pointcut left, right;
private Set couldMatchKinds;


public OrPointcut(Pointcut left, Pointcut right) { public OrPointcut(Pointcut left, Pointcut right) {
super(); super();
this.right = right; this.right = right;
setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
this.pointcutKind = OR; this.pointcutKind = OR;
this.couldMatchKinds = new HashSet(left.couldMatchKinds());
this.couldMatchKinds.addAll(right.couldMatchKinds());
} }


public Set couldMatchKinds() {
return couldMatchKinds;
}


public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return left.fastMatch(type).or(right.fastMatch(type)); return left.fastMatch(type).or(right.fastMatch(type));
} }


public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return left.match(shadow).or(right.match(shadow)); return left.match(shadow).or(right.match(shadow));
} }
return ret; return ret;
} }
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return Test.makeOr(left.findResidue(shadow, state), right.findResidue(shadow, state)); return Test.makeOr(left.findResidue(shadow, state), right.findResidue(shadow, state));
} }
public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
return new OrPointcut(left.concretize(inAspect, bindings),
Pointcut ret = new OrPointcut(left.concretize(inAspect, bindings),
right.concretize(inAspect, bindings)); right.concretize(inAspect, bindings));
ret.copyLocationFrom(this);
return ret;
} }
public Pointcut getLeft() { public Pointcut getLeft() {

+ 19
- 0
weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java View File

} }
return buff.toString(); return buff.toString();
} }
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (! (obj instanceof OrTypePattern)) return false;
OrTypePattern other = (OrTypePattern) obj;
return left.equals(other.left) && right.equals(other.right);
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
int ret = 17;
ret = ret + 37 * left.hashCode();
ret = ret + 37 * right.hashCode();
return ret;
}
} }

+ 7
- 2
weaver/src/org/aspectj/weaver/patterns/PerCflow.java View File

import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set;


import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.Advice; import org.aspectj.weaver.Advice;
// ----- // -----
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.YES; return FuzzyBoolean.YES;
} }


entry.resolve(scope); entry.resolve(scope);
} }
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
Expr myInstance = Expr myInstance =
Expr.makeCallExpr(AjcMemberMaker.perCflowAspectOfMethod(inAspect), Expr.makeCallExpr(AjcMemberMaker.perCflowAspectOfMethod(inAspect),
Expr.NONE, inAspect); Expr.NONE, inAspect);

+ 8
- 3
weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Set;


import org.aspectj.bridge.MessageUtil; import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
public PerFromSuper(PerClause.Kind kind) { public PerFromSuper(PerClause.Kind kind) {
this.kind = kind; this.kind = kind;
} }

public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}

public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
throw new RuntimeException("unimplemented"); throw new RuntimeException("unimplemented");
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
throw new RuntimeException("unimplemented"); throw new RuntimeException("unimplemented");
} }


// this method intentionally left blank // this method intentionally left blank
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
throw new RuntimeException("unimplemented"); throw new RuntimeException("unimplemented");
} }



+ 18
- 2
weaver/src/org/aspectj/weaver/patterns/PerObject.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;


import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.Advice; import org.aspectj.weaver.Advice;
public class PerObject extends PerClause { public class PerObject extends PerClause {
private boolean isThis; private boolean isThis;
private Pointcut entry; private Pointcut entry;
private static final Set thisKindSet = new HashSet(Shadow.ALL_SHADOW_KINDS);
private static final Set targetKindSet = new HashSet(Shadow.ALL_SHADOW_KINDS);
static {
for (Iterator iter = Shadow.ALL_SHADOW_KINDS.iterator(); iter.hasNext();) {
Shadow.Kind kind = (Shadow.Kind) iter.next();
if (kind.neverHasThis()) thisKindSet.remove(kind);
if (kind.neverHasTarget()) targetKindSet.remove(kind);
}
}
public PerObject(Pointcut entry, boolean isThis) { public PerObject(Pointcut entry, boolean isThis) {
this.entry = entry; this.entry = entry;
this.isThis = isThis; this.isThis = isThis;
} }

public Set couldMatchKinds() {
return isThis ? thisKindSet : targetKindSet;
}
// ----- // -----
public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
//System.err.println("matches " + this + " ? " + shadow + ", " + shadow.hasTarget()); //System.err.println("matches " + this + " ? " + shadow + ", " + shadow.hasTarget());
//??? could probably optimize this better by testing could match //??? could probably optimize this better by testing could match
if (isThis) return FuzzyBoolean.fromBoolean(shadow.hasThis()); if (isThis) return FuzzyBoolean.fromBoolean(shadow.hasThis());
return isThis ? shadow.getThisVar() : shadow.getTargetVar(); return isThis ? shadow.getThisVar() : shadow.getTargetVar();
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
Expr myInstance = Expr myInstance =
Expr.makeCallExpr(AjcMemberMaker.perObjectAspectOfMethod(inAspect), Expr.makeCallExpr(AjcMemberMaker.perObjectAspectOfMethod(inAspect),
new Expr[] {getVar(shadow)}, inAspect); new Expr[] {getVar(shadow)}, inAspect);

+ 8
- 3
weaver/src/org/aspectj/weaver/patterns/PerSingleton.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Set;


import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AjcMemberMaker; import org.aspectj.weaver.AjcMemberMaker;
public class PerSingleton extends PerClause { public class PerSingleton extends PerClause {
public PerSingleton() { public PerSingleton() {
} }

public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}

public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.YES; return FuzzyBoolean.YES;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.YES; return FuzzyBoolean.YES;
} }


// this method intentionally left blank // this method intentionally left blank
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
Expr myInstance = Expr myInstance =
Expr.makeCallExpr(AjcMemberMaker.perSingletonAspectOfMethod(inAspect), Expr.makeCallExpr(AjcMemberMaker.perSingletonAspectOfMethod(inAspect),
Expr.NONE, inAspect); Expr.NONE, inAspect);

+ 84
- 9
weaver/src/org/aspectj/weaver/patterns/Pointcut.java View File

import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.Collections;
import java.util.Set;


import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.FuzzyBoolean;
* *
* @author Erik Hilsdale * @author Erik Hilsdale
* @author Jim Hugunin * @author Jim Hugunin
*
* A day in the life of a pointcut.... - AMC.
* ==========================================
*
* Pointcuts are created by the PatternParser, which is called by ajdt to
* parse a pointcut from the PseudoTokens AST node (which in turn are part
* of a PointcutDesignator AST node).
*
* Pointcuts are resolved by ajdt when an AdviceDeclaration or a
* PointcutDeclaration has its statements resolved. This happens as
* part of completeTypeBindings in the AjLookupEnvironment which is
* called after the diet parse phase of the compiler. Named pointcuts,
* and references to named pointcuts are instances of ReferencePointcut.
*
* At the end of the compilation process, the pointcuts are serialized
* (write method) into attributes in the class file.
*
* When the weaver loads the class files, it unpacks the attributes
* and deserializes the pointcuts (read). All aspects are added to the
* world, by calling addOrReplaceAspect on
* the crosscutting members set of the world. When aspects are added or
* replaced, the crosscutting members in the aspect are extracted as
* ShadowMungers (each holding a pointcut). The ShadowMungers are
* concretized, which concretizes the pointcuts. At this stage
* ReferencePointcuts are replaced by their declared content.
*
* During weaving, the weaver processes type by type. It first culls
* potentially matching ShadowMungers by calling the fastMatch method
* on their pointcuts. Only those that might match make it through to
* the next phase. At the next phase, all of the shadows within the
* type are created and passed to the pointcut for matching (match).
*
* When the actual munging happens, matched pointcuts are asked for
* their residue (findResidue) - the runtime test if any. Because of
* negation, findResidue may be called on pointcuts that could never
* match the shadow.
*
*/ */
public abstract class Pointcut extends PatternNode implements PointcutExpressionMatching { public abstract class Pointcut extends PatternNode implements PointcutExpressionMatching {
public static final class State extends TypeSafeEnum { public static final class State extends TypeSafeEnum {
public static final State CONCRETE = new State("concrete", 2); public static final State CONCRETE = new State("concrete", 2);


protected byte pointcutKind; protected byte pointcutKind;
public State state; public State state;


protected int lastMatchedShadowId;
private FuzzyBoolean lastMatchedShadowResult;
private Test lastMatchedShadowResidue;
/** /**
* Constructor for Pattern. * Constructor for Pattern.
*/ */
* Could I match any shadows in the code defined within this type? * Could I match any shadows in the code defined within this type?
*/ */
public abstract FuzzyBoolean fastMatch(FastMatchInfo info); public abstract FuzzyBoolean fastMatch(FastMatchInfo info);

/**
* The set of ShadowKinds that this Pointcut could possibly match
*/
public abstract /*Enum*/Set/*<Shadow.Kind>*/ couldMatchKinds();
/** /**
* Do I really match this shadow? * Do I really match this shadow?
* XXX implementors need to handle state * XXX implementors need to handle state
*/ */
public abstract FuzzyBoolean match(Shadow shadow);
public final FuzzyBoolean match(Shadow shadow) {
if (shadow.shadowId == lastMatchedShadowId) return lastMatchedShadowResult;
FuzzyBoolean ret;
// this next test will prevent a lot of un-needed matching going on....
if (couldMatchKinds().contains(shadow.getKind())) {
ret = matchInternal(shadow);
} else {
ret = FuzzyBoolean.NO;
}
lastMatchedShadowId = shadow.shadowId;
lastMatchedShadowResult = ret;
return ret;
}
protected abstract FuzzyBoolean matchInternal(Shadow shadow);
/* /*
* for runtime / dynamic pointcuts. * for runtime / dynamic pointcuts.
/** /**
* Returns this pointcut mutated * Returns this pointcut mutated
*/ */
public Pointcut resolve(IScope scope) {
public final Pointcut resolve(IScope scope) {
assertState(SYMBOLIC); assertState(SYMBOLIC);
Bindings bindingTable = new Bindings(scope.getFormalCount()); Bindings bindingTable = new Bindings(scope.getFormalCount());
this.resolveBindings(scope, bindingTable); this.resolveBindings(scope, bindingTable);
/** /**
* Returns a new pointcut * Returns a new pointcut
* Only used by test cases
*/ */
public Pointcut concretize(ResolvedTypeX inAspect, int arity) {
public final Pointcut concretize(ResolvedTypeX inAspect, int arity) {
return concretize(inAspect, IntMap.idMap(arity)); return concretize(inAspect, IntMap.idMap(arity));
} }
//XXX this is the signature we're moving to //XXX this is the signature we're moving to
public Pointcut concretize(ResolvedTypeX inAspect, int arity, ShadowMunger advice) {
public final Pointcut concretize(ResolvedTypeX inAspect, int arity, ShadowMunger advice) {
//if (state == CONCRETE) return this; //??? //if (state == CONCRETE) return this; //???
IntMap map = IntMap.idMap(arity); IntMap map = IntMap.idMap(arity);
map.setEnclosingAdvice(advice); map.setEnclosingAdvice(advice);
} }
public Pointcut concretize(ResolvedTypeX inAspect, IntMap bindings) {
public final Pointcut concretize(ResolvedTypeX inAspect, IntMap bindings) {
//!!! add this test -- assertState(RESOLVED); //!!! add this test -- assertState(RESOLVED);
Pointcut ret = this.concretize1(inAspect, bindings); Pointcut ret = this.concretize1(inAspect, bindings);
if (shouldCopyLocationForConcretize()) ret.copyLocationFrom(this); if (shouldCopyLocationForConcretize()) ret.copyLocationFrom(this);
* This can be called from NotPointcut even for Pointcuts that * This can be called from NotPointcut even for Pointcuts that
* don't match the shadow * don't match the shadow
*/ */
public abstract Test findResidue(Shadow shadow, ExposedState state);
public final Test findResidue(Shadow shadow, ExposedState state) {
// if (shadow.shadowId == lastMatchedShadowId) return lastMatchedShadowResidue;
Test ret = findResidueInternal(shadow,state);
// lastMatchedShadowResidue = ret;
lastMatchedShadowId = shadow.shadowId;
return ret;
}
protected abstract Test findResidueInternal(Shadow shadow,ExposedState state);


//XXX we're not sure whether or not this is needed //XXX we're not sure whether or not this is needed
//XXX currently it's unused we're keeping it around as a stub //XXX currently it's unused we're keeping it around as a stub
} }
private static class MatchesNothingPointcut extends Pointcut { private static class MatchesNothingPointcut extends Pointcut {
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return Literal.FALSE; // can only get here if an earlier error occurred return Literal.FALSE; // can only get here if an earlier error occurred
} }


public Set couldMatchKinds() {
return Collections.EMPTY_SET;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.NO; return FuzzyBoolean.NO;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.NO; return FuzzyBoolean.NO;
} }

+ 114
- 0
weaver/src/org/aspectj/weaver/patterns/PointcutEvaluationExpenseComparator.java View File

/* *******************************************************************
* Copyright (c) 2004 IBM Corporation.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* ******************************************************************/
package org.aspectj.weaver.patterns;

import java.util.Comparator;

import org.aspectj.weaver.Shadow;

public class PointcutEvaluationExpenseComparator implements Comparator {

private static final int MATCHES_NOTHING = -1;
private static final int WITHIN = 1;
private static final int ATWITHIN = 2;
private static final int STATICINIT = 3;
private static final int ADVICEEXECUTION = 4;
private static final int HANDLER = 5;
private static final int GET_OR_SET = 6;
private static final int WITHINCODE = 7;
private static final int ATWITHINCODE = 8;
private static final int EXE_INIT_PREINIT = 9;
private static final int CALL = 10;
private static final int ANNOTATION = 11;
private static final int THIS_OR_TARGET = 12;
private static final int AT_THIS_OR_TARGET = 13;
private static final int ARGS = 14;
private static final int AT_ARGS = 15;
private static final int CFLOW = 16;
private static final int IF = 17;
private static final int OTHER = 20;
/**
* Compare 2 pointcuts based on an estimate of how expensive they may be
* to evaluate.
*
* within
* @within
* staticinitialization [make sure this has a fast match method]
* adviceexecution
* handler
* get, set
* withincode
* @withincode
* execution, initialization, preinitialization
* call
* @annotation
* this, target
* @this, @target
* args
* @args
* cflow, cflowbelow
* if
*/
public int compare(Object o1, Object o2) {
Pointcut p1 = (Pointcut) o1;
Pointcut p2 = (Pointcut) o2;
// important property for a well-defined comparator
if (p1.equals(p2)) return 0;
int result = getScore(p1) - getScore(p2);
if (result == 0) {
// they have the same evaluation expense, but are not 'equal'
// sort by hashCode
result = p1.hashCode() - p2.hashCode();
if (result == 0) /*not allowed if ne*/ return -1;
}
return result;
}

// a higher score means a more expensive evaluation
private int getScore(Pointcut p) {
if (p.couldMatchKinds().isEmpty()) return MATCHES_NOTHING;
if (p instanceof WithinPointcut) return WITHIN;
if (p instanceof WithinAnnotationPointcut) return ATWITHIN;
if (p instanceof KindedPointcut) {
KindedPointcut kp = (KindedPointcut) p;
Shadow.Kind kind = kp.getKind();
if (kind == Shadow.AdviceExecution) {
return ADVICEEXECUTION;
} else if ((kind == Shadow.ConstructorCall) || (kind == Shadow.MethodCall)) {
return CALL;
} else if ((kind == Shadow.ConstructorExecution) || (kind == Shadow.MethodExecution) ||
(kind == Shadow.Initialization) || (kind == Shadow.PreInitialization)) {
return EXE_INIT_PREINIT;
} else if (kind == Shadow.ExceptionHandler) {
return HANDLER;
} else if ((kind == Shadow.FieldGet) || (kind == Shadow.FieldSet)) {
return GET_OR_SET;
} else if (kind == Shadow.StaticInitialization) {
return STATICINIT;
} else return OTHER;
}
if (p instanceof AnnotationPointcut) return ANNOTATION;
if (p instanceof ArgsPointcut) return ARGS;
if (p instanceof ArgsAnnotationPointcut) return AT_ARGS;
if (p instanceof CflowPointcut) return CFLOW;
if (p instanceof HandlerPointcut) return HANDLER;
if (p instanceof IfPointcut) return IF;
if (p instanceof ThisOrTargetPointcut) return THIS_OR_TARGET;
if (p instanceof ThisOrTargetAnnotationPointcut) return AT_THIS_OR_TARGET;
if (p instanceof WithincodePointcut) return WITHINCODE;
if (p instanceof WithinCodeAnnotationPointcut) return ATWITHINCODE;
if (p instanceof NotPointcut) return getScore(((NotPointcut)p).getNegatedPointcut());
if (p instanceof AndPointcut) return getScore(((AndPointcut)p).getLeft());
if (p instanceof OrPointcut) return getScore(((OrPointcut)p).getLeft());
return OTHER;
}
}

+ 277
- 0
weaver/src/org/aspectj/weaver/patterns/PointcutRewriter.java View File

/* *******************************************************************
* Copyright (c) 2004 IBM Corporation.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* ******************************************************************/
package org.aspectj.weaver.patterns;

import java.util.Iterator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.aspectj.weaver.Shadow;

/**
* @author colyer
*
* Performs term rewriting for pointcut expressions.
*
*/
public class PointcutRewriter {

private static final boolean WATCH_PROGRESS = false;
public Pointcut rewrite(Pointcut pc) {
if (WATCH_PROGRESS) System.out.println(pc);
Pointcut result = distributeNot(pc);
if (WATCH_PROGRESS) System.out.println("==> " + result);
result = pullUpDisjunctions(result);
if (WATCH_PROGRESS) System.out.println("==> " + result);
result = simplifyAnds(result);
if (WATCH_PROGRESS) System.out.println("==> " + result);
result = sortOrs(result);
if (WATCH_PROGRESS) System.out.println("==> " + result);
return result;
}
// !!X => X
// !(X && Y) => !X || !Y
// !(X || Y) => !X && !Y
private Pointcut distributeNot(Pointcut pc) {
if (isNot(pc)) {
NotPointcut npc = (NotPointcut) pc;
Pointcut notBody = distributeNot(npc.getNegatedPointcut());
if (isNot(notBody)) {
// !!X => X
return ((NotPointcut)notBody).getNegatedPointcut();
} else if (isAnd(notBody)) {
// !(X && Y) => !X || !Y
AndPointcut apc = (AndPointcut) notBody;
Pointcut newLeft = distributeNot(new NotPointcut(apc.getLeft()));
Pointcut newRight = distributeNot(new NotPointcut(apc.getRight()));
return new OrPointcut(newLeft,newRight);
} else if (isOr(notBody)) {
// !(X || Y) => !X && !Y
OrPointcut opc = (OrPointcut) notBody;
Pointcut newLeft = distributeNot(new NotPointcut(opc.getLeft()));
Pointcut newRight = distributeNot(new NotPointcut(opc.getRight()));
return new AndPointcut(newLeft,newRight);
} else {
return new NotPointcut(notBody);
}
} else if (isAnd(pc)) {
AndPointcut apc = (AndPointcut) pc;
Pointcut left = distributeNot(apc.getLeft());
Pointcut right = distributeNot(apc.getRight());
return new AndPointcut(left,right);
} else if (isOr(pc)) {
OrPointcut opc = (OrPointcut) pc;
Pointcut left = distributeNot(opc.getLeft());
Pointcut right = distributeNot(opc.getRight());
return new OrPointcut(left,right);
} else {
return pc;
}
}
// A && (B || C) => (A && B) || (A && C)
// (A || B) && C => (A && C) || (B && C)
private Pointcut pullUpDisjunctions(Pointcut pc) {
if (isNot(pc)) {
NotPointcut npc = (NotPointcut)pc;
return new NotPointcut(pullUpDisjunctions(npc.getNegatedPointcut()));
} else if (isAnd(pc)) {
AndPointcut apc = (AndPointcut) pc;
// dive into left and right here...
Pointcut left = pullUpDisjunctions(apc.getLeft());
Pointcut right = pullUpDisjunctions(apc.getRight());
if (isOr(left) && !isOr(right)) {
// (A || B) && C => (A && C) || (B && C)
Pointcut leftLeft = ((OrPointcut)left).getLeft();
Pointcut leftRight = ((OrPointcut)left).getRight();
return new OrPointcut(
new AndPointcut(leftLeft,right),
new AndPointcut(leftRight,right));
} else if (isOr(right) && !isOr(left)) {
// A && (B || C) => (A && B) || (A && C)
Pointcut rightLeft = ((OrPointcut)right).getLeft();
Pointcut rightRight = ((OrPointcut)right).getRight();
return new OrPointcut(
new AndPointcut(left,rightLeft),
new AndPointcut(left,rightRight));
} else {
return new AndPointcut(left,right);
}
} else if (isOr(pc)){
OrPointcut opc = (OrPointcut) pc;
return new OrPointcut(pullUpDisjunctions(opc.getLeft()),
pullUpDisjunctions(opc.getRight()));
} else {
return pc;
}
}
// NOT: execution(* TP.*(..)) => within(TP) && execution(* *(..))
// since this breaks when the pattern matches an interface
// NOT: withincode(* TP.*(..)) => within(TP) && withincode(* *(..))
// since this is not correct when an aspect makes an ITD
// private Pointcut splitOutWithins(Pointcut pc) {
// if (isExecution(pc)) {
// KindedPointcut kpc = (KindedPointcut) pc;
// SignaturePattern sp = kpc.signature;
// TypePattern within = sp.getDeclaringType();
// if (isAnyType(within)) return pc;
// SignaturePattern simplified = removeDeclaringTypePattern(sp);
// return new AndPointcut(new WithinPointcut(within),
// new KindedPointcut(kpc.kind,simplified));
// } else if (isNot(pc)) {
// return new NotPointcut(splitOutWithins(((NotPointcut)pc).getNegatedPointcut()));
// } else if (isAnd(pc)) {
// AndPointcut apc = (AndPointcut) pc;
// return new AndPointcut(splitOutWithins(apc.getLeft()),
// splitOutWithins(apc.getRight()));
// } else if (isOr(pc)) {
// OrPointcut opc = (OrPointcut) pc;
// return new OrPointcut(splitOutWithins(opc.getLeft()),
// splitOutWithins(opc.getRight()));
// } else {
// return pc;
// }
// }
private SignaturePattern removeDeclaringTypePattern(SignaturePattern sp) {
return new SignaturePattern(
sp.getKind(),
sp.getModifiers(),
sp.getReturnType(),
TypePattern.ANY,
sp.getName(),
sp.getParameterTypes(),
sp.getThrowsPattern(),
sp.getAnnotationPattern()
);
}

// this finds the root of each && tree and then aggregates all of the branches
// into a sorted set:
// - duplicates are removed
// - A && !A is replaced by a matchesNothingPointcut
// - the kind(s) matched by the set are evaluated
// - elements are sorted by evaluation complexity
// - the result is written out with the least expensive branch leftmost
private Pointcut simplifyAnds(Pointcut pc) {
if (isNot(pc)) {
NotPointcut npc = (NotPointcut) pc;
return new NotPointcut(simplifyAnds(npc.getNegatedPointcut()));
} else if (isOr(pc)) {
OrPointcut opc = (OrPointcut) pc;
return new OrPointcut(simplifyAnds(opc.getLeft()),simplifyAnds(opc.getRight()));
} else if (isAnd(pc)) {
return simplifyAnd((AndPointcut)pc);
} else {
return pc;
}
}
private Pointcut simplifyAnd(AndPointcut apc) {
SortedSet nodes = new TreeSet(new PointcutEvaluationExpenseComparator());
collectAndNodes(apc,nodes);
// look for A and !A, or IfFalse
for (Iterator iter = nodes.iterator(); iter.hasNext();) {
Pointcut element = (Pointcut) iter.next();
if (element instanceof NotPointcut) {
Pointcut body = ((NotPointcut)element).getNegatedPointcut();
if (nodes.contains(body)) return Pointcut.makeMatchesNothing(body.state);
}
if (element instanceof IfPointcut) {
if (((IfPointcut)element).alwaysFalse()) return Pointcut.makeMatchesNothing(element.state);
}
if (element.toString().equals("")) return element; // matches nothing...
}
if (apc.couldMatchKinds().isEmpty()) return Pointcut.makeMatchesNothing(apc.state);
// write out with cheapest on left
Iterator iter = nodes.iterator();
Pointcut result = (Pointcut) iter.next();
while(iter.hasNext()) {
Pointcut right = (Pointcut) iter.next();
result = new AndPointcut(result,right);
}
return result;
}
private Pointcut sortOrs(Pointcut pc) {
SortedSet nodes = new TreeSet(new PointcutEvaluationExpenseComparator());
collectOrNodes(pc,nodes);
// write out with cheapest on left
Iterator iter = nodes.iterator();
Pointcut result = (Pointcut) iter.next();
while(iter.hasNext()) {
Pointcut right = (Pointcut) iter.next();
result = new OrPointcut(result,right);
}
return result;
}
private void collectAndNodes(AndPointcut apc,Set nodesSoFar) {
Pointcut left = apc.getLeft();
Pointcut right = apc.getRight();
if (isAnd(left)) {
collectAndNodes((AndPointcut)left,nodesSoFar);
} else {
nodesSoFar.add(left);
}
if (isAnd(right)) {
collectAndNodes((AndPointcut)right,nodesSoFar);
} else {
nodesSoFar.add(right);
}
}
private void collectOrNodes(Pointcut pc, Set nodesSoFar) {
if (isOr(pc)) {
OrPointcut opc = (OrPointcut) pc;
collectOrNodes(opc.getLeft(),nodesSoFar);
collectOrNodes(opc.getRight(),nodesSoFar);
} else {
nodesSoFar.add(pc);
}
}
private boolean isNot(Pointcut pc) {
return (pc instanceof NotPointcut);
}
private boolean isAnd(Pointcut pc) {
return (pc instanceof AndPointcut);
}
private boolean isOr(Pointcut pc) {
return (pc instanceof OrPointcut);
}
private boolean isExecution(Pointcut pc) {
if (pc instanceof KindedPointcut) {
KindedPointcut kp = (KindedPointcut) pc;
if (kp.kind == Shadow.MethodExecution) return true;
if (kp.kind == Shadow.ConstructorExecution) return true;
}
return false;
}
private boolean isWithinCode(Pointcut pc) {
return (pc instanceof WithincodePointcut);
}
private boolean isAnyType(TypePattern tp) {
if (tp == TypePattern.ANY) return true;
if (tp.toString().equals("*")) return true;
return false;
}
}

+ 7
- 2
weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java View File

import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Set;


import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageUtil; import org.aspectj.bridge.MessageUtil;
this.pointcutKind = REFERENCE; this.pointcutKind = REFERENCE;
} }
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}



//??? do either of these match methods make any sense??? //??? do either of these match methods make any sense???
public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
/** /**
* Do I really match this shadow? * Do I really match this shadow?
*/ */
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.NO; return FuzzyBoolean.NO;
} }
arguments.postRead(enclosingType); arguments.postRead(enclosingType);
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
throw new RuntimeException("shouldn't happen"); throw new RuntimeException("shouldn't happen");
} }



+ 2
- 0
weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java View File

&& o.declaringType.equals(this.declaringType) && o.declaringType.equals(this.declaringType)
&& o.name.equals(this.name) && o.name.equals(this.name)
&& o.parameterTypes.equals(this.parameterTypes) && o.parameterTypes.equals(this.parameterTypes)
&& o.throwsPattern.equals(this.throwsPattern)
&& o.annotationPattern.equals(this.annotationPattern); && o.annotationPattern.equals(this.annotationPattern);
} }
public int hashCode() { public int hashCode() {
result = 37*result + declaringType.hashCode(); result = 37*result + declaringType.hashCode();
result = 37*result + name.hashCode(); result = 37*result + name.hashCode();
result = 37*result + parameterTypes.hashCode(); result = 37*result + parameterTypes.hashCode();
result = 37*result + throwsPattern.hashCode();
result = 37*result + annotationPattern.hashCode(); result = 37*result + annotationPattern.hashCode();
return result; return result;
} }

+ 49
- 11
weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;


import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.ISourceLocation;
private boolean alreadyWarnedAboutDEoW = false; private boolean alreadyWarnedAboutDEoW = false;
private ExactAnnotationTypePattern annotationTypePattern; private ExactAnnotationTypePattern annotationTypePattern;
private ShadowMunger munger; private ShadowMunger munger;
private static final Set thisKindSet = new HashSet(Shadow.ALL_SHADOW_KINDS);
private static final Set targetKindSet = new HashSet(Shadow.ALL_SHADOW_KINDS);
static {
for (Iterator iter = Shadow.ALL_SHADOW_KINDS.iterator(); iter.hasNext();) {
Shadow.Kind kind = (Shadow.Kind) iter.next();
if (kind.neverHasThis()) thisKindSet.remove(kind);
if (kind.neverHasTarget()) targetKindSet.remove(kind);
}
}
/** /**
* *
this.munger = munger; this.munger = munger;
} }
public Set couldMatchKinds() {
return isThis ? thisKindSet : targetKindSet;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/ */
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
*/ */
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
if (!couldMatch(shadow)) return FuzzyBoolean.NO; if (!couldMatch(shadow)) return FuzzyBoolean.NO;
ResolvedTypeX toMatchAgainst = ResolvedTypeX toMatchAgainst =
(isThis ? shadow.getThisType() : shadow.getTargetType() ).resolve(shadow.getIWorld()); (isThis ? shadow.getThisType() : shadow.getTargetType() ).resolve(shadow.getIWorld());
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
*/ */
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
if (!couldMatch(shadow)) return Literal.FALSE; if (!couldMatch(shadow)) return Literal.FALSE;
boolean alwaysMatches = match(shadow).alwaysTrue(); boolean alwaysMatches = match(shadow).alwaysTrue();
Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar(); Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar();
shadow.getTargetAnnotationVar(annotationType); shadow.getTargetAnnotationVar(annotationType);
if (annVar == null) return Literal.TRUE; // should be exception when we implement properly if (annVar == null) return Literal.TRUE; // should be exception when we implement properly
// Check if we have already bound something to this formal // Check if we have already bound something to this formal
if (state.get(btp.getFormalIndex())!=null) {
ISourceLocation pcdSloc = getSourceLocation();
ISourceLocation shadowSloc = shadow.getSourceLocation();
Message errorMessage = new Message(
"Cannot use @pointcut to match at this location and bind a formal to type '"+annVar.getType()+
"' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
". The secondary source location points to the problematic binding.",
shadowSloc,true,new ISourceLocation[]{pcdSloc});
shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
if ((state.get(btp.getFormalIndex())!=null) &&(lastMatchedShadowId == shadow.shadowId)) {
// ISourceLocation pcdSloc = getSourceLocation();
// ISourceLocation shadowSloc = shadow.getSourceLocation();
// Message errorMessage = new Message(
// "Cannot use @pointcut to match at this location and bind a formal to type '"+annVar.getType()+
// "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
// ". The secondary source location points to the problematic binding.",
// shadowSloc,true,new ISourceLocation[]{pcdSloc});
// shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
state.setErroneousVar(btp.getFormalIndex()); state.setErroneousVar(btp.getFormalIndex());
} }
state.set(btp.getFormalIndex(),annVar); state.set(btp.getFormalIndex(),annVar);
return isThis ? shadow.hasThis() : shadow.hasTarget(); return isThis ? shadow.hasThis() : shadow.hasTarget();
} }
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
*/
public List getBindingAnnotationTypePatterns() {
if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
List l = new ArrayList();
l.add(annotationTypePattern);
return l;
} else return Collections.EMPTY_LIST;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
*/
public List getBindingTypePatterns() {
return Collections.EMPTY_LIST;
}

/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/ */

+ 55
- 14
weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java View File

import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;


import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.ISourceLocation;
public class ThisOrTargetPointcut extends NameBindingPointcut { public class ThisOrTargetPointcut extends NameBindingPointcut {
private boolean isThis; private boolean isThis;
private TypePattern type; private TypePattern type;

private static final Set thisKindSet = new HashSet(Shadow.ALL_SHADOW_KINDS);
private static final Set targetKindSet = new HashSet(Shadow.ALL_SHADOW_KINDS);
static {
for (Iterator iter = Shadow.ALL_SHADOW_KINDS.iterator(); iter.hasNext();) {
Shadow.Kind kind = (Shadow.Kind) iter.next();
if (kind.neverHasThis()) thisKindSet.remove(kind);
if (kind.neverHasTarget()) targetKindSet.remove(kind);
}
}

public ThisOrTargetPointcut(boolean isThis, TypePattern type) { public ThisOrTargetPointcut(boolean isThis, TypePattern type) {
this.isThis = isThis; this.isThis = isThis;
this.type = type; this.type = type;
} }
public boolean isThis() { return isThis; } public boolean isThis() { return isThis; }

public Set couldMatchKinds() {
return isThis ? thisKindSet : targetKindSet;
}

public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
return isThis ? shadow.hasThis() : shadow.hasTarget(); return isThis ? shadow.hasThis() : shadow.hasTarget();
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
if (!couldMatch(shadow)) return FuzzyBoolean.NO; if (!couldMatch(shadow)) return FuzzyBoolean.NO;
TypeX typeToMatch = isThis ? shadow.getThisType() : shadow.getTargetType(); TypeX typeToMatch = isThis ? shadow.getThisType() : shadow.getTargetType();
//if (typeToMatch == ResolvedTypeX.MISSING) return FuzzyBoolean.NO; //if (typeToMatch == ResolvedTypeX.MISSING) return FuzzyBoolean.NO;
type.postRead(enclosingType); type.postRead(enclosingType);
} }
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
*/
public List getBindingAnnotationTypePatterns() {
return Collections.EMPTY_LIST;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
*/
public List getBindingTypePatterns() {
if (type instanceof BindingTypePattern) {
List l = new ArrayList();
l.add(type);
return l;
} else return Collections.EMPTY_LIST;
}

public boolean equals(Object other) { public boolean equals(Object other) {
if (!(other instanceof ThisOrTargetPointcut)) return false; if (!(other instanceof ThisOrTargetPointcut)) return false;
ThisOrTargetPointcut o = (ThisOrTargetPointcut)other; ThisOrTargetPointcut o = (ThisOrTargetPointcut)other;
return (isThis ? "this(" : "target(") + type + ")"; return (isThis ? "this(" : "target(") + type + ")";
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
if (!couldMatch(shadow)) return Literal.FALSE; if (!couldMatch(shadow)) return Literal.FALSE;
if (type == TypePattern.ANY) return Literal.TRUE; if (type == TypePattern.ANY) return Literal.TRUE;
if (type instanceof BindingTypePattern) { if (type instanceof BindingTypePattern) {
BindingTypePattern btp = (BindingTypePattern)type; BindingTypePattern btp = (BindingTypePattern)type;
// Check if we have already bound something to this formal // Check if we have already bound something to this formal
if (state.get(btp.getFormalIndex())!=null) {
ISourceLocation pcdSloc = getSourceLocation();
ISourceLocation shadowSloc = shadow.getSourceLocation();
Message errorMessage = new Message(
"Cannot use "+(isThis?"this()":"target()")+" to match at this location and bind a formal to type '"+var.getType()+
"' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
". The secondary source location points to the problematic "+(isThis?"this()":"target()")+".",
shadowSloc,true,new ISourceLocation[]{pcdSloc});
shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
if ((state.get(btp.getFormalIndex())!=null) && (lastMatchedShadowId != shadow.shadowId)){
// ISourceLocation pcdSloc = getSourceLocation();
// ISourceLocation shadowSloc = shadow.getSourceLocation();
// Message errorMessage = new Message(
// "Cannot use "+(isThis?"this()":"target()")+" to match at this location and bind a formal to type '"+var.getType()+
// "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
// ". The secondary source location points to the problematic "+(isThis?"this()":"target()")+".",
// shadowSloc,true,new ISourceLocation[]{pcdSloc});
// shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
state.setErroneousVar(btp.getFormalIndex()); state.setErroneousVar(btp.getFormalIndex());
//return null; //return null;
} }
inAspect.crosscuttingMembers.exposeType(newType.getExactType()); inAspect.crosscuttingMembers.exposeType(newType.getExactType());
} }
return new ThisOrTargetPointcut(isThis, newType);
Pointcut ret = new ThisOrTargetPointcut(isThis, newType);
ret.copyLocationFrom(this);
return ret;
} }


} }

+ 2
- 1
weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java View File

public boolean equals(Object other) { public boolean equals(Object other) {
if (!(other instanceof ThrowsPattern)) return false; if (!(other instanceof ThrowsPattern)) return false;
ThrowsPattern o = (ThrowsPattern)other; ThrowsPattern o = (ThrowsPattern)other;
return o.required.equals(this.required) &&
boolean ret = o.required.equals(this.required) &&
o.forbidden.equals(this.forbidden); o.forbidden.equals(this.forbidden);
return ret;
} }
public int hashCode() { public int hashCode() {
int result = 17; int result = 17;

+ 36
- 0
weaver/src/org/aspectj/weaver/patterns/TypePattern.java View File

} }
public String toString() { return ".."; } public String toString() { return ".."; }
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return (obj instanceof EllipsisTypePattern);
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return 17 * 37;
}
} }


class AnyTypePattern extends TypePattern { class AnyTypePattern extends TypePattern {
} }
public String toString() { return "*"; } public String toString() { return "*"; }
public boolean equals(Object obj) {
return (obj instanceof AnyTypePattern);
}
public int hashCode() {
return 37;
}
} }


class NoTypePattern extends TypePattern { class NoTypePattern extends TypePattern {
} }
public String toString() { return "<nothing>"; } public String toString() { return "<nothing>"; }
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return (obj instanceof NoTypePattern);
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return 17 * 37 * 37;
}
} }



+ 3
- 0
weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java View File

WildTypePattern o = (WildTypePattern)other; WildTypePattern o = (WildTypePattern)other;
int len = o.namePatterns.length; int len = o.namePatterns.length;
if (len != this.namePatterns.length) return false; if (len != this.namePatterns.length) return false;
if (this.includeSubtypes != o.includeSubtypes) return false;
if (this.dim != o.dim) return false;
if (this.isVarArgs != o.isVarArgs) return false;
for (int i=0; i < len; i++) { for (int i=0; i < len; i++) {
if (!o.namePatterns[i].equals(this.namePatterns[i])) return false; if (!o.namePatterns[i].equals(this.namePatterns[i])) return false;
} }

+ 37
- 11
weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;


import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.ISourceLocation;
this.munger = munger; this.munger = munger;
} }


public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/ */
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
*/ */
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
ResolvedTypeX enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true); ResolvedTypeX enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true);
if (enclosingType == ResolvedTypeX.MISSING) { if (enclosingType == ResolvedTypeX.MISSING) {
IMessage msg = new Message( IMessage msg = new Message(
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
*/ */
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
if (annotationTypePattern instanceof BindingAnnotationTypePattern) { if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern; BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
TypeX annotationType = btp.annotationType; TypeX annotationType = btp.annotationType;
Var var = shadow.getWithinAnnotationVar(annotationType); Var var = shadow.getWithinAnnotationVar(annotationType);
if (var == null) return Literal.FALSE; if (var == null) return Literal.FALSE;
// Check if we have already bound something to this formal // Check if we have already bound something to this formal
if (state.get(btp.getFormalIndex())!=null) {
ISourceLocation pcdSloc = getSourceLocation();
ISourceLocation shadowSloc = shadow.getSourceLocation();
Message errorMessage = new Message(
"Cannot use @pointcut to match at this location and bind a formal to type '"+var.getType()+
"' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
". The secondary source location points to the problematic binding.",
shadowSloc,true,new ISourceLocation[]{pcdSloc});
shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
if ((state.get(btp.getFormalIndex())!=null) &&(lastMatchedShadowId == shadow.shadowId)) {
// ISourceLocation pcdSloc = getSourceLocation();
// ISourceLocation shadowSloc = shadow.getSourceLocation();
// Message errorMessage = new Message(
// "Cannot use @pointcut to match at this location and bind a formal to type '"+var.getType()+
// "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
// ". The secondary source location points to the problematic binding.",
// shadowSloc,true,new ISourceLocation[]{pcdSloc});
// shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
state.setErroneousVar(btp.getFormalIndex()); state.setErroneousVar(btp.getFormalIndex());
} }
state.set(btp.getFormalIndex(),var); state.set(btp.getFormalIndex(),var);
return Literal.TRUE; return Literal.TRUE;
} }


/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
*/
public List getBindingAnnotationTypePatterns() {
if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
List l = new ArrayList();
l.add(annotationTypePattern);
return l;
} else return Collections.EMPTY_LIST;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
*/
public List getBindingTypePatterns() {
return Collections.EMPTY_LIST;
}

/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/ */

+ 47
- 11
weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java View File

import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message; import org.aspectj.bridge.Message;


private ExactAnnotationTypePattern annotationTypePattern; private ExactAnnotationTypePattern annotationTypePattern;
private ShadowMunger munger = null; // only set after concretization private ShadowMunger munger = null; // only set after concretization
private static final Set matchedShadowKinds = new HashSet();
static {
matchedShadowKinds.addAll(Shadow.ALL_SHADOW_KINDS);
for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
if (Shadow.SHADOW_KINDS[i].isEnclosingKind())
matchedShadowKinds.remove(Shadow.SHADOW_KINDS[i]);
}
}
public WithinCodeAnnotationPointcut(ExactAnnotationTypePattern type) { public WithinCodeAnnotationPointcut(ExactAnnotationTypePattern type) {
super(); super();
this.munger = munger; this.munger = munger;
} }


public Set couldMatchKinds() {
return matchedShadowKinds;
}

/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/ */
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
*/ */
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
AnnotatedElement toMatchAgainst = null; AnnotatedElement toMatchAgainst = null;
Member member = shadow.getEnclosingCodeSignature(); Member member = shadow.getEnclosingCodeSignature();
ResolvedMember rMember = member.resolve(shadow.getIWorld()); ResolvedMember rMember = member.resolve(shadow.getIWorld());
/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
*/ */
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
if (annotationTypePattern instanceof BindingAnnotationTypePattern) { if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern; BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
Var var = shadow.getWithinCodeAnnotationVar(annotationType); Var var = shadow.getWithinCodeAnnotationVar(annotationType);
if (var == null) return Literal.FALSE; if (var == null) return Literal.FALSE;
// Check if we have already bound something to this formal // Check if we have already bound something to this formal
if (state.get(btp.getFormalIndex())!=null) {
ISourceLocation pcdSloc = getSourceLocation();
ISourceLocation shadowSloc = shadow.getSourceLocation();
Message errorMessage = new Message(
"Cannot use @pointcut to match at this location and bind a formal to type '"+var.getType()+
"' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
". The secondary source location points to the problematic binding.",
shadowSloc,true,new ISourceLocation[]{pcdSloc});
shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
if ((state.get(btp.getFormalIndex())!=null) &&(lastMatchedShadowId == shadow.shadowId)) {
// ISourceLocation pcdSloc = getSourceLocation();
// ISourceLocation shadowSloc = shadow.getSourceLocation();
// Message errorMessage = new Message(
// "Cannot use @pointcut to match at this location and bind a formal to type '"+var.getType()+
// "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
// ". The secondary source location points to the problematic binding.",
// shadowSloc,true,new ISourceLocation[]{pcdSloc});
// shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
state.setErroneousVar(btp.getFormalIndex()); state.setErroneousVar(btp.getFormalIndex());
} }
state.set(btp.getFormalIndex(),var); state.set(btp.getFormalIndex(),var);
return Literal.TRUE; return Literal.TRUE;
} }


/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
*/
public List getBindingAnnotationTypePatterns() {
if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
List l = new ArrayList();
l.add(annotationTypePattern);
return l;
} else return Collections.EMPTY_LIST;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
*/
public List getBindingTypePatterns() {
return Collections.EMPTY_LIST;
}

/* (non-Javadoc) /* (non-Javadoc)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/ */

+ 10
- 3
weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java View File

import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.Set;


import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.ISourceLocation;
} }
return FuzzyBoolean.NO; return FuzzyBoolean.NO;
} }

public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo info) { public FuzzyBoolean fastMatch(FastMatchInfo info) {
return isWithinType(info.getType()); return isWithinType(info.getType());
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
ResolvedTypeX enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true); ResolvedTypeX enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true);
if (enclosingType == ResolvedTypeX.MISSING) { if (enclosingType == ResolvedTypeX.MISSING) {
IMessage msg = new Message( IMessage msg = new Message(
return "within(" + typePattern + ")"; return "within(" + typePattern + ")";
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE; return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
} }
public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
return new WithinPointcut(typePattern);
Pointcut ret = new WithinPointcut(typePattern);
ret.copyLocationFrom(this);
return ret;
} }
} }

+ 23
- 4
weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java View File

import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.HashSet;
import java.util.Set;


import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.runtime.reflect.Factory; import org.aspectj.runtime.reflect.Factory;


public class WithincodePointcut extends Pointcut { public class WithincodePointcut extends Pointcut {
SignaturePattern signature; SignaturePattern signature;
private static final Set matchedShadowKinds = new HashSet();
static {
matchedShadowKinds.addAll(Shadow.ALL_SHADOW_KINDS);
for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
if (Shadow.SHADOW_KINDS[i].isEnclosingKind())
matchedShadowKinds.remove(Shadow.SHADOW_KINDS[i]);
}
// these next two are needed for inlining of field initializers
matchedShadowKinds.add(Shadow.ConstructorExecution);
matchedShadowKinds.add(Shadow.Initialization);
}
public WithincodePointcut(SignaturePattern signature) { public WithincodePointcut(SignaturePattern signature) {
this.signature = signature; this.signature = signature;
this.pointcutKind = WITHINCODE; this.pointcutKind = WITHINCODE;
} }
public Set couldMatchKinds() {
return matchedShadowKinds;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) { public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE; return FuzzyBoolean.MAYBE;
} }
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
//This will not match code in local or anonymous classes as if //This will not match code in local or anonymous classes as if
//they were withincode of the outer signature //they were withincode of the outer signature
return FuzzyBoolean.fromBoolean( return FuzzyBoolean.fromBoolean(
return "withincode(" + signature + ")"; return "withincode(" + signature + ")";
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE; return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
} }
public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { public Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
return new WithincodePointcut(signature);
Pointcut ret = new WithincodePointcut(signature);
ret.copyLocationFrom(this);
return ret;
} }
} }

+ 6
- 0
weaver/src/org/aspectj/weaver/weaver-messages.properties View File

invalidXLintKey=invalid Xlint key: {0} invalidXLintKey=invalid Xlint key: {0}
invalidXLintMessageKind=invalid Xlint message kind (must be one of ignore, warning, error): {0} invalidXLintMessageKind=invalid Xlint message kind (must be one of ignore, warning, error): {0}


# Binding of formals
unboundFormalInPC=the parameter {0} is not bound in [all branches of] pointcut
ambiguousBindingInPC=the binding of parameter {0} is ambiguous in pointcut
ambiguousBindingInOrPC=ambiguous binding of parameter(s) {0} across ''||'' in pointcut
negationDoesntAllowBinding=cannot bind a parameter in a negated expression

# Java5 # Java5


# Enum # Enum

+ 1
- 0
weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java View File

suite.addTestSuite(WithinCodeTestCase.class); suite.addTestSuite(WithinCodeTestCase.class);
suite.addTestSuite(AnnotationPatternTestCase.class); suite.addTestSuite(AnnotationPatternTestCase.class);
suite.addTestSuite(AnnotationPatternMatchingTestCase.class); suite.addTestSuite(AnnotationPatternMatchingTestCase.class);
suite.addTestSuite(PointcutRewriterTest.class);
//$JUnit-END$ //$JUnit-END$
return suite; return suite;
} }

+ 366
- 0
weaver/testsrc/org/aspectj/weaver/patterns/PointcutRewriterTest.java View File

/* *******************************************************************
* Copyright (c) 2004 IBM Corporation.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* ******************************************************************/
package org.aspectj.weaver.patterns;

import java.util.Iterator;
import java.util.Set;

import org.aspectj.weaver.Shadow;

import junit.framework.TestCase;

/**
* @author colyer
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class PointcutRewriterTest extends TestCase {

private PointcutRewriter prw;
public void testDistributeNot() {
Pointcut plain = getPointcut("this(Foo)");
assertEquals("Unchanged",plain,prw.rewrite(plain));
Pointcut not = getPointcut("!this(Foo)");
assertEquals("Unchanged",not,prw.rewrite(not));
Pointcut notNot = getPointcut("!!this(Foo)");
assertEquals("this(Foo)",prw.rewrite(notNot).toString());
Pointcut notNotNOT = getPointcut("!!!this(Foo)");
assertEquals("!this(Foo)",prw.rewrite(notNotNOT).toString());
Pointcut and = getPointcut("!(this(Foo) && this(Goo))");
assertEquals("(!this(Foo) || !this(Goo))",prw.rewrite(and).toString());
Pointcut or = getPointcut("!(this(Foo) || this(Goo))");
assertEquals("(!this(Foo) && !this(Goo))",prw.rewrite(or).toString());
Pointcut nestedNot = getPointcut("!(this(Foo) && !this(Goo))");
assertEquals("(!this(Foo) || this(Goo))",prw.rewrite(nestedNot).toString());
}
public void testPullUpDisjunctions() {
Pointcut aAndb = getPointcut("this(Foo) && this(Goo)");
assertEquals("Unchanged",aAndb,prw.rewrite(aAndb));
Pointcut aOrb = getPointcut("this(Foo) || this(Moo)");
assertEquals("Unchanged",aOrb,prw.rewrite(aOrb));
Pointcut leftOr = getPointcut("this(Foo) || (this(Goo) && this(Boo))");
System.out.println(prw.rewrite(leftOr));
assertEquals("(this(Foo) || (this(Boo) && this(Goo)))",prw.rewrite(leftOr).toString());
Pointcut rightOr = getPointcut("(this(Goo) && this(Boo)) || this(Foo)");
assertEquals("(this(Foo) || (this(Boo) && this(Goo)))",prw.rewrite(rightOr).toString());
Pointcut leftAnd = getPointcut("this(Foo) && (this(Goo) || this(Boo))");
assertEquals("((this(Boo) && this(Foo)) || (this(Foo) && this(Goo)))",prw.rewrite(leftAnd).toString());
Pointcut rightAnd = getPointcut("(this(Goo) || this(Boo)) && this(Foo)");
assertEquals("((this(Boo) && this(Foo)) || (this(Foo) && this(Goo)))",prw.rewrite(rightAnd).toString());
Pointcut nestedOrs = getPointcut("this(Foo) || this(Goo) || this(Boo)");
assertEquals("((this(Boo) || this(Foo)) || this(Goo))",prw.rewrite(nestedOrs).toString());
Pointcut nestedAnds = getPointcut("(this(Foo) && (this(Boo) && (this(Goo) || this(Moo))))");
// t(F) && (t(B) && (t(G) || t(M)))
// ==> t(F) && ((t(B) && t(G)) || (t(B) && t(M)))
// ==> (t(F) && (t(B) && t(G))) || (t(F) && (t(B) && t(M)))
assertEquals("(((this(Boo) && this(Foo)) && this(Goo)) || ((this(Boo) && this(Foo)) && this(Moo)))",
prw.rewrite(nestedAnds).toString());
}
// public void testSplitOutWithins() {
// Pointcut simpleExecution = getPointcut("execution(* *.*(..))");
// assertEquals("Unchanged",simpleExecution,prw.rewrite(simpleExecution));
// Pointcut simpleWithinCode = getPointcut("withincode(* *.*(..))");
// assertEquals("Unchanged",simpleWithinCode,prw.rewrite(simpleWithinCode));
// Pointcut execution = getPointcut("execution(@Foo Foo (@Goo org.xyz..*).m*(Foo,Boo))");
// assertEquals("(within((@(Goo) org.xyz..*)) && execution(@(Foo) Foo m*(Foo, Boo)))",
// prw.rewrite(execution).toString());
// Pointcut withincode = getPointcut("withincode(@Foo Foo (@Goo org.xyz..*).m*(Foo,Boo))");
// assertEquals("(within((@(Goo) org.xyz..*)) && withincode(@(Foo) Foo m*(Foo, Boo)))",
// prw.rewrite(withincode).toString());
// Pointcut notExecution = getPointcut("!execution(Foo BankAccount+.*(..))");
// assertEquals("(!within(BankAccount+) || !execution(Foo *(..)))",
// prw.rewrite(notExecution).toString());
// Pointcut andWithincode = getPointcut("withincode(Foo.new(..)) && this(Foo)");
// assertEquals("((within(Foo) && withincode(new(..))) && this(Foo))",
// prw.rewrite(andWithincode).toString());
// Pointcut orExecution = getPointcut("this(Foo) || execution(Goo Foo.moo(Baa))");
// assertEquals("((within(Foo) && execution(Goo moo(Baa))) || this(Foo))",
// prw.rewrite(orExecution).toString());
// }

public void testRemoveDuplicatesInAnd() {
Pointcut dupAnd = getPointcut("this(Foo) && this(Foo)");
assertEquals("this(Foo)",prw.rewrite(dupAnd).toString());
Pointcut splitdupAnd = getPointcut("(this(Foo) && target(Boo)) && this(Foo)");
assertEquals("(target(Boo) && this(Foo))",prw.rewrite(splitdupAnd).toString());
}
public void testNotRemoveNearlyDuplicatesInAnd() {
Pointcut toAndto = getPointcut("this(Object+) && this(Object)");
Pointcut rewritten = prw.rewrite(toAndto);
}
public void testAAndNotAinAnd() {
Pointcut aAndNota = getPointcut("this(Foo)&& !this(Foo)");
assertEquals("Matches nothing","",prw.rewrite(aAndNota).toString());
Pointcut aAndBAndNota = getPointcut("this(Foo) && execution(* *.*(..)) && !this(Foo)");
assertEquals("Matches nothing","",prw.rewrite(aAndBAndNota).toString());
}
public void testIfFalseInAnd() {
Pointcut ifFalse = IfPointcut.makeIfFalsePointcut(Pointcut.CONCRETE);
Pointcut p = getPointcut("this(A)");
assertEquals("Matches nothing","",prw.rewrite(new AndPointcut(ifFalse,p)).toString());
}

public void testMatchesNothinginAnd() {
Pointcut nothing = Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
Pointcut p = getPointcut("this(A)");
assertEquals("Matches nothing","",prw.rewrite(new AndPointcut(nothing,p)).toString());
}
public void testMixedKindsInAnd() {
Pointcut mixedKinds = getPointcut("call(* *(..)) && execution(* *(..))");
assertEquals("Matches nothing","",prw.rewrite(mixedKinds).toString());
Pointcut ok = getPointcut("call(* *(..)) && this(Foo)");
assertEquals(ok,prw.rewrite(ok));
}
public void testDetermineKindSetOfAnd() {
Pointcut oneKind = getPointcut("execution(* foo(..)) && this(Boo)");
AndPointcut rewritten = (AndPointcut) prw.rewrite(oneKind);
assertEquals("Only one kind",1,rewritten.couldMatchKinds().size());
assertTrue("It's Shadow.MethodExecution",rewritten.couldMatchKinds().contains(Shadow.MethodExecution));
}
public void testKindSetOfExecution() {
Pointcut p = getPointcut("execution(* foo(..))");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.MethodExecution",p.couldMatchKinds().contains(Shadow.MethodExecution));
p = getPointcut("execution(new(..))");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.ConstructorExecution",p.couldMatchKinds().contains(Shadow.ConstructorExecution));
}
public void testKindSetOfCall() {
Pointcut p = getPointcut("call(* foo(..))");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.MethodCall",p.couldMatchKinds().contains(Shadow.MethodCall));
p = getPointcut("call(new(..))");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.ConstructorCall",p.couldMatchKinds().contains(Shadow.ConstructorCall));
}
public void testKindSetOfAdviceExecution() {
Pointcut p = getPointcut("adviceexecution()");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.AdviceExecution",p.couldMatchKinds().contains(Shadow.AdviceExecution));
}
public void testKindSetOfGet() {
Pointcut p = getPointcut("get(* *)");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.FieldGet",p.couldMatchKinds().contains(Shadow.FieldGet));
}
public void testKindSetOfSet() {
Pointcut p = getPointcut("set(* *)");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.FieldSet",p.couldMatchKinds().contains(Shadow.FieldSet));
}
public void testKindSetOfHandler() {
Pointcut p = getPointcut("handler(*)");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.ExceptionHandler",p.couldMatchKinds().contains(Shadow.ExceptionHandler));
}
public void testKindSetOfInitialization() {
Pointcut p = getPointcut("initialization(new (..))");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.Initialization",p.couldMatchKinds().contains(Shadow.Initialization));
}
public void testKindSetOfPreInitialization() {
Pointcut p = getPointcut("preinitialization(new (..))");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.PreInitialization",p.couldMatchKinds().contains(Shadow.PreInitialization));
}
public void testKindSetOfStaticInitialization() {
Pointcut p = getPointcut("staticinitialization(*)");
assertEquals("Only one kind",1,p.couldMatchKinds().size());
assertTrue("It's Shadow.StaticInitialization",p.couldMatchKinds().contains(Shadow.StaticInitialization));
}
public void testKindSetOfThis() {
Pointcut p = getPointcut("this(Foo)");
Set matches = p.couldMatchKinds();
for (Iterator iter = matches.iterator(); iter.hasNext();) {
Shadow.Kind kind = (Shadow.Kind) iter.next();
assertFalse("No kinds that don't have a this",kind.neverHasThis());
}
for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
if (!Shadow.SHADOW_KINDS[i].neverHasThis()) {
assertTrue("All kinds that do have this",matches.contains(Shadow.SHADOW_KINDS[i]));
}
}
// + @
p = getPointcut("@this(@Foo)");
matches = p.couldMatchKinds();
for (Iterator iter = matches.iterator(); iter.hasNext();) {
Shadow.Kind kind = (Shadow.Kind) iter.next();
assertFalse("No kinds that don't have a this",kind.neverHasThis());
}
for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
if (!Shadow.SHADOW_KINDS[i].neverHasThis()) {
assertTrue("All kinds that do have this",matches.contains(Shadow.SHADOW_KINDS[i]));
}
}
}
public void testKindSetOfTarget() {
Pointcut p = getPointcut("target(Foo)");
Set matches = p.couldMatchKinds();
for (Iterator iter = matches.iterator(); iter.hasNext();) {
Shadow.Kind kind = (Shadow.Kind) iter.next();
assertFalse("No kinds that don't have a target",kind.neverHasTarget());
}
for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
if (!Shadow.SHADOW_KINDS[i].neverHasTarget()) {
assertTrue("All kinds that do have target",matches.contains(Shadow.SHADOW_KINDS[i]));
}
}
// + @
p = getPointcut("@target(@Foo)");
matches = p.couldMatchKinds();
for (Iterator iter = matches.iterator(); iter.hasNext();) {
Shadow.Kind kind = (Shadow.Kind) iter.next();
assertFalse("No kinds that don't have a target",kind.neverHasTarget());
}
for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
if (!Shadow.SHADOW_KINDS[i].neverHasTarget()) {
assertTrue("All kinds that do have target",matches.contains(Shadow.SHADOW_KINDS[i]));
}
}
}
public void testKindSetOfArgs() {
Pointcut p = getPointcut("args(..)");
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
// + @
p = getPointcut("@args(..)");
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
}
public void testKindSetOfAnnotation() {
Pointcut p = getPointcut("@annotation(@Foo)");
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
}
public void testKindSetOfWithin() {
Pointcut p = getPointcut("within(*)");
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
// + @
p = getPointcut("@within(@Foo)");
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
}
public void testKindSetOfWithinCode() {
Pointcut p = getPointcut("withincode(* foo(..))");
Set matches = p.couldMatchKinds();
for (Iterator iter = matches.iterator(); iter.hasNext();) {
Shadow.Kind kind = (Shadow.Kind) iter.next();
assertFalse("No kinds that are themselves enclosing",
(kind.isEnclosingKind() && kind != Shadow.ConstructorExecution && kind != Shadow.Initialization));
}
for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
if (!Shadow.SHADOW_KINDS[i].isEnclosingKind()) {
assertTrue("All kinds that are not enclosing",matches.contains(Shadow.SHADOW_KINDS[i]));
}
}
assertTrue("Need cons-exe for inlined field inits",matches.contains(Shadow.ConstructorExecution));
assertTrue("Need init for inlined field inits",matches.contains(Shadow.Initialization));
// + @
p = getPointcut("@withincode(@Foo)");
matches = p.couldMatchKinds();
for (Iterator iter = matches.iterator(); iter.hasNext();) {
Shadow.Kind kind = (Shadow.Kind) iter.next();
assertFalse("No kinds that are themselves enclosing",kind.isEnclosingKind());
}
for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
if (!Shadow.SHADOW_KINDS[i].isEnclosingKind()) {
assertTrue("All kinds that are not enclosing",matches.contains(Shadow.SHADOW_KINDS[i]));
}
}
}
public void testKindSetOfIf() {
Pointcut p = new IfPointcut(null,0);
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
p = IfPointcut.makeIfTruePointcut(Pointcut.CONCRETE);
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
p = IfPointcut.makeIfFalsePointcut(Pointcut.CONCRETE);
assertTrue("Nothing",p.couldMatchKinds().isEmpty());
}
public void testKindSetOfCflow() {
Pointcut p = getPointcut("cflow(this(Foo))");
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
// [below]
p = getPointcut("cflowbelow(this(Foo))");
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
}
public void testKindSetInNegation() {
Pointcut p = getPointcut("!execution(new(..))");
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS));
}
public void testKindSetOfOr() {
Pointcut p = getPointcut("execution(new(..)) || get(* *)");
Set matches = p.couldMatchKinds();
assertEquals("2 kinds",2,matches.size());
assertTrue("ConstructorExecution",matches.contains(Shadow.ConstructorExecution));
assertTrue("FieldGet",matches.contains(Shadow.FieldGet));
}
public void testOrderingInAnd() {
Pointcut bigLongPC = getPointcut("cflow(this(Foo)) && @args(@X) && args(X) && @this(@Foo) && @target(@Boo) && this(Moo) && target(Boo) && @annotation(@Moo) && @withincode(@Boo) && withincode(new(..)) && set(* *)&& @within(@Foo) && within(Foo)");
Pointcut rewritten = prw.rewrite(bigLongPC);
assertEquals("((((((((((((within(Foo) && @within(@Foo)) && set(* *)) && withincode(new(..))) && @withincode(@Boo)) && @annotation(@Moo)) && target(Boo)) && this(Moo)) && @target(@Boo)) && @this(@Foo)) && args(X)) && @args(@X)) && cflow(this(Foo)))",rewritten.toString());
}
public void testOrderingInSimpleOr() {
OrPointcut opc = (OrPointcut) getPointcut("execution(new(..)) || get(* *)");
assertEquals("reordered","(get(* *) || execution(new(..)))",prw.rewrite(opc).toString());
}
public void testOrderingInNestedOrs() {
OrPointcut opc = (OrPointcut) getPointcut("(execution(new(..)) || get(* *)) || within(abc)");
assertEquals("reordered","((within(abc) || get(* *)) || execution(new(..)))",
prw.rewrite(opc).toString());
}
public void testOrderingInOrsWithNestedAnds() {
OrPointcut opc = (OrPointcut) getPointcut("get(* *) || (execution(new(..)) && within(abc))");
assertEquals("reordered","((within(abc) && execution(new(..))) || get(* *))",
prw.rewrite(opc).toString());
}
private Pointcut getPointcut(String s) {
return new PatternParser(s).parsePointcut();
}
/*
* @see TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
prw = new PointcutRewriter();
}

}

+ 7
- 2
weaver/testsrc/org/aspectj/weaver/patterns/PointcutTestCase.java View File



import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Set;


import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature; import org.aspectj.lang.Signature;
public void testMatchJP() { public void testMatchJP() {
Pointcut p = new Pointcut() { Pointcut p = new Pointcut() {


public Set couldMatchKinds() {
return null;
}
public FuzzyBoolean fastMatch(FastMatchInfo info) { public FuzzyBoolean fastMatch(FastMatchInfo info) {
return null; return null;
} }


public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return null; return null;
} }


return null; return null;
} }


public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return null; return null;
} }



Loading…
Cancel
Save