瀏覽代碼

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 年之前
父節點
當前提交
1b6e9edfac
共有 50 個檔案被更改,包括 1794 行新增156 行删除
  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 查看文件

@@ -14,7 +14,7 @@ class B extends A {
aspect IfPointcut {

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

+ 1
- 1
tests/bugs/DisjunctVarBinding_3.java 查看文件

@@ -1,7 +1,7 @@
aspect IfPointcut {

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

+ 1
- 2
tests/src/org/aspectj/systemtest/ajc120/ajc120-tests.xml 查看文件

@@ -454,8 +454,7 @@
<ajc-test dir="bugs"
pr="61568" title="wrong variable binding in || pointcuts">
<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>
</ajc-test>

+ 7
- 12
tests/src/org/aspectj/systemtest/ajc121/ajc121-tests.xml 查看文件

@@ -4,12 +4,10 @@
<ajc-test dir="bugs"
pr="62073" title="false ambiguous binding error (introduced in 1.2rc2)">
<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 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>
</ajc-test>
@@ -213,14 +211,11 @@
<ajc-test dir="bugs/oxford" pr="65319"
title="ajc crashes when compiling the following program (binding this() and target())">
<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>
</ajc-test>

+ 3
- 1
tests/src/org/aspectj/systemtest/ajc150/VarargsTests.java 查看文件

@@ -59,10 +59,12 @@ public class VarargsTests extends TestUtils {
// 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)
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
// 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(),
((IMessage)cR.getWarningMessages().get(0)).toString().indexOf("varargs declared method")!=-1);

+ 13
- 0
weaver/src/org/aspectj/weaver/Advice.java 查看文件

@@ -185,6 +185,17 @@ public abstract class Advice extends ShadowMunger {
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() {
if (!hasExtraParameter()) return ResolvedTypeX.MISSING;
return signature.getParameterTypes()[getBaseParameterCount()];
@@ -215,7 +226,9 @@ public abstract class Advice extends ShadowMunger {
// assert !fromType.isAbstract();
Pointcut p = pointcut.concretize(fromType, signature.getArity(), this);
if (clause != null) {
Pointcut oldP = p;
p = new AndPointcut(clause, p);
p.copyLocationFrom(oldP);
p.state = Pointcut.CONCRETE;
}

+ 13
- 0
weaver/src/org/aspectj/weaver/Shadow.java 查看文件

@@ -16,8 +16,10 @@ package org.aspectj.weaver;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.aspectj.asm.IRelationship;
import org.aspectj.bridge.*;
@@ -35,11 +37,16 @@ import org.aspectj.weaver.bcel.BcelAdvice;
*/

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 Member signature;
protected final Shadow enclosingShadow;
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) {
@@ -202,6 +209,12 @@ public abstract class Shadow {
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
*/

+ 5
- 0
weaver/src/org/aspectj/weaver/ShadowMunger.java 查看文件

@@ -106,6 +106,11 @@ public abstract class ShadowMunger implements PartialOrder.PartialComparable, IH
public Pointcut getPointcut() {
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 查看文件

@@ -102,6 +102,11 @@ public class WeaverMessages {
public static final String XLINT_KEY_ERROR = "invalidXLintKey";
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
public static final String ITDC_ON_ENUM_NOT_ALLOWED = "itdcOnEnumNotAllowed";
public static final String ITDM_ON_ENUM_NOT_ALLOWED = "itdmOnEnumNotAllowed";

+ 254
- 0
weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java 查看文件

@@ -27,9 +27,11 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
@@ -48,6 +50,7 @@ import org.aspectj.bridge.Message;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.util.FileUtil;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.Advice;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.CrosscuttingMembersSet;
import org.aspectj.weaver.IClassFileProvider;
@@ -61,9 +64,19 @@ import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.WeaverMetrics;
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.ConcreteCflowPointcut;
import org.aspectj.weaver.patterns.DeclareParents;
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 {
@@ -340,6 +353,7 @@ public class BcelWeaver implements IWeaver {
}

shadowMungerList = xcutSet.getShadowMungers();
rewritePointcuts(shadowMungerList);
typeMungerList = xcutSet.getTypeMungers();
declareParentsList = xcutSet.getDeclareParents();
@@ -353,6 +367,246 @@ public class BcelWeaver implements IWeaver {
});
}
/*
* 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 {
// BufferedOutputStream os = FileUtil.makeOutputStream(file);
// this.zipOutputStream = new ZipOutputStream(os);

+ 17
- 4
weaver/src/org/aspectj/weaver/patterns/AndPointcut.java 查看文件

@@ -17,6 +17,8 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Member;
import java.util.HashSet;
import java.util.Set;

import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
@@ -29,19 +31,28 @@ import org.aspectj.weaver.ast.Test;
public class AndPointcut extends Pointcut {
Pointcut left, right; // exposed for testing

private Set couldMatchKinds;
public AndPointcut(Pointcut left, Pointcut right) {
super();
this.left = left;
this.right = right;
this.pointcutKind = AND;
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) {
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));
}
@@ -114,13 +125,15 @@ public class AndPointcut extends Pointcut {
}


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));
}

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() {

+ 17
- 1
weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java 查看文件

@@ -33,7 +33,7 @@ public class AndTypePattern extends TypePattern {
private TypePattern left, 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.right = right;
setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
@@ -114,4 +114,20 @@ public class AndTypePattern extends TypePattern {
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 查看文件

@@ -53,6 +53,10 @@ public class AnnotationPatternList extends PatternNode {
this((AnnotationTypePattern[]) l.toArray(new AnnotationTypePattern[l.size()]));
}

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

+ 37
- 11
weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java 查看文件

@@ -13,6 +13,10 @@ package org.aspectj.weaver.patterns;
import java.io.DataInputStream;
import java.io.DataOutputStream;
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.Message;
@@ -67,6 +71,10 @@ public class AnnotationPointcut extends NameBindingPointcut {
this.munger = munger;
}

public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/
@@ -81,7 +89,7 @@ public class AnnotationPointcut extends NameBindingPointcut {
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
*/
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
AnnotatedElement toMatchAgainst = null;
Member member = shadow.getSignature();
ResolvedMember rMember = member.resolve(shadow.getIWorld());
@@ -137,7 +145,7 @@ public class AnnotationPointcut extends NameBindingPointcut {
/* (non-Javadoc)
* @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) {
BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
@@ -145,15 +153,15 @@ public class AnnotationPointcut extends NameBindingPointcut {
Var var = shadow.getKindedAnnotationVar(annotationType);
if (var == null) return Literal.FALSE;
// 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.set(btp.getFormalIndex(),var);
@@ -161,6 +169,24 @@ public class AnnotationPointcut extends NameBindingPointcut {
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)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/

+ 37
- 5
weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java 查看文件

@@ -12,6 +12,10 @@ package org.aspectj.weaver.patterns;
import java.io.DataInputStream;
import java.io.DataOutputStream;
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.ISourceLocation;
@@ -35,7 +39,7 @@ import org.aspectj.weaver.ast.Test;
public class ArgsAnnotationPointcut extends NameBindingPointcut {

private AnnotationPatternList arguments;
/**
*
*/
@@ -43,7 +47,11 @@ public class ArgsAnnotationPointcut extends NameBindingPointcut {
super();
this.arguments = arguments;
}
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS; // empty args() matches jps with no args
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/
@@ -54,7 +62,7 @@ public class ArgsAnnotationPointcut extends NameBindingPointcut {
/* (non-Javadoc)
* @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());
FuzzyBoolean ret =
arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()));
@@ -91,13 +99,15 @@ public class ArgsAnnotationPointcut extends NameBindingPointcut {
return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
}
AnnotationPatternList list = arguments.resolveReferences(bindings);
return new ArgsAnnotationPointcut(list);
Pointcut ret = new ArgsAnnotationPointcut(list);
ret.copyLocationFrom(this);
return ret;
}

/* (non-Javadoc)
* @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();
// do some quick length tests first
@@ -141,6 +151,28 @@ public class ArgsAnnotationPointcut extends NameBindingPointcut {
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)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/

+ 43
- 12
weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java 查看文件

@@ -20,8 +20,12 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
@@ -53,12 +57,16 @@ public class ArgsPointcut extends NameBindingPointcut {
this.arguments = arguments;
this.pointcutKind = ARGS;
}

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

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

public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
FuzzyBoolean ret =
arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()), TypePattern.DYNAMIC);
return ret;
@@ -135,6 +143,27 @@ public class ArgsPointcut extends NameBindingPointcut {
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 {
s.writeByte(Pointcut.ARGS);
arguments.write(s);
@@ -190,7 +219,9 @@ public class ArgsPointcut extends NameBindingPointcut {
if (inAspect.crosscuttingMembers != null) {
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) {
@@ -218,14 +249,14 @@ public class ArgsPointcut extends NameBindingPointcut {
} else {
BindingTypePattern btp = (BindingTypePattern)type;
// 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());
}
}
@@ -236,7 +267,7 @@ public class ArgsPointcut extends NameBindingPointcut {
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()) {
return Literal.FALSE;
}

+ 2
- 0
weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java 查看文件

@@ -40,6 +40,8 @@ public class BindingTypePattern extends ExactTypePattern implements BindingPatte
public boolean equals(Object other) {
if (!(other instanceof BindingTypePattern)) return false;
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;
}
public int hashCode() {

+ 14
- 5
weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java 查看文件

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.util.FileUtil;
@@ -66,12 +67,16 @@ public class CflowPointcut extends Pointcut {
this.freeVars = freeVars;
this.pointcutKind = CFLOW;
}

public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE;
}
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
//??? this is not maximally efficient
return FuzzyBoolean.MAYBE;
}
@@ -147,7 +152,7 @@ public class CflowPointcut extends Pointcut {
return "cflow" + (isBelow ? "below" : "") + "(" + entry + ")";
}

public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
throw new RuntimeException("unimplemented");
}
@@ -227,7 +232,9 @@ public class CflowPointcut extends Pointcut {
putCflowfield(concreteEntry,localCflowField); // Remember it
}
return new ConcreteCflowPointcut(localCflowField, null,true);
Pointcut ret = new ConcreteCflowPointcut(localCflowField, null,true);
ret.copyLocationFrom(this);
return ret;
} else {

List slots = new ArrayList();
@@ -268,7 +275,9 @@ public class CflowPointcut extends Pointcut {
world.makeCflowStackFieldAdder(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 查看文件

@@ -17,6 +17,7 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.IntMap;
@@ -43,11 +44,15 @@ public class ConcreteCflowPointcut extends Pointcut {
this.pointcutKind = CFLOW;
}
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE;
}
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
//??? this is not maximally efficient
return FuzzyBoolean.MAYBE;
}
@@ -70,6 +75,16 @@ public class ConcreteCflowPointcut extends Pointcut {
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 {
throw new RuntimeException("unimplemented");
}
@@ -97,7 +112,7 @@ public class ConcreteCflowPointcut extends Pointcut {
return "concretecflow(" + cflowField + ")";
}

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

+ 2
- 0
weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java 查看文件

@@ -151,6 +151,8 @@ public class ExactTypePattern extends TypePattern {
public boolean equals(Object other) {
if (!(other instanceof ExactTypePattern)) return false;
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));
}

+ 16
- 3
weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java 查看文件

@@ -17,6 +17,8 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Member;
import java.util.HashSet;
import java.util.Set;

import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
@@ -37,17 +39,26 @@ import org.aspectj.weaver.internal.tools.PointcutExpressionImpl;
public class HandlerPointcut extends Pointcut {
TypePattern exceptionType;

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

public Set couldMatchKinds() {
return MATCH_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) {
//??? should be able to do better by finding all referenced types in type
return FuzzyBoolean.MAYBE;
}
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
if (shadow.getKind() != Shadow.ExceptionHandler) return FuzzyBoolean.NO;
// we know we have exactly one parameter since we're checking an exception handler
@@ -134,11 +145,13 @@ public class HandlerPointcut extends Pointcut {
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;
}
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 查看文件

@@ -18,7 +18,9 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Member;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.lang.JoinPoint;
@@ -54,15 +56,27 @@ public class IfPointcut extends Pointcut {
this.pointcutKind = IF;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) {
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}

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

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

// 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;
@@ -183,6 +204,7 @@ public class IfPointcut extends Pointcut {
return partiallyConcretized;
}
IfPointcut ret = new IfPointcut(testMethod, extraParameterFlags);
ret.copyLocationFrom(this);
partiallyConcretized = ret;
// It is possible to directly code your pointcut expression in a per clause
@@ -239,7 +261,15 @@ public class IfPointcut extends Pointcut {
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
}

@@ -247,7 +277,7 @@ public class IfPointcut extends Pointcut {
return FuzzyBoolean.NO;
}
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.NO;
}
@@ -304,8 +334,12 @@ public class IfPointcut extends Pointcut {
public IfTruePointcut() {
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
}

@@ -313,7 +347,7 @@ public class IfPointcut extends Pointcut {
return FuzzyBoolean.YES;
}
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.YES;
}

+ 14
- 2
weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java 查看文件

@@ -16,6 +16,8 @@ package org.aspectj.weaver.patterns;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.aspectj.bridge.ISourceLocation;
import org.aspectj.lang.JoinPoint;
@@ -36,6 +38,7 @@ import org.aspectj.weaver.ast.Test;
public class KindedPointcut extends Pointcut {
Shadow.Kind kind;
SignaturePattern signature;
private Set matchKinds;
private ShadowMunger munger = null; // only set after concretization

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

if (!signature.matches(shadow.getSignature(), shadow.getIWorld())){
@@ -265,7 +277,7 @@ public class KindedPointcut extends Pointcut {
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;
}

+ 4
- 1
weaver/src/org/aspectj/weaver/patterns/NameBindingPointcut.java 查看文件

@@ -13,6 +13,8 @@

package org.aspectj.weaver.patterns;

import java.util.List;

import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.World;
import org.aspectj.weaver.ast.Test;
@@ -40,7 +42,8 @@ public abstract class NameBindingPointcut extends Pointcut {
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 查看文件

@@ -17,6 +17,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Member;
import java.util.Set;

import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
@@ -39,13 +40,17 @@ public class NotPointcut extends Pointcut {
setLocation(pointcut.getSourceContext(), startPos, pointcut.getEnd());
}

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

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

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

@@ -118,12 +123,14 @@ public class NotPointcut extends Pointcut {
return ret;
}

public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
return Test.makeNot(body.findResidue(shadow, state));
}
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 查看文件

@@ -105,4 +105,19 @@ public class NotTypePattern extends TypePattern {
}
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 查看文件

@@ -17,6 +17,8 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Member;
import java.util.HashSet;
import java.util.Set;

import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
@@ -28,6 +30,7 @@ import org.aspectj.weaver.ast.Test;

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

public OrPointcut(Pointcut left, Pointcut right) {
super();
@@ -35,14 +38,19 @@ public class OrPointcut extends Pointcut {
this.right = right;
setLocation(left.getSourceContext(), left.getStart(), right.getEnd());
this.pointcutKind = OR;
this.couldMatchKinds = new HashSet(left.couldMatchKinds());
this.couldMatchKinds.addAll(right.couldMatchKinds());
}

public Set couldMatchKinds() {
return couldMatchKinds;
}

public FuzzyBoolean fastMatch(FastMatchInfo 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));
}
@@ -119,13 +127,15 @@ public class OrPointcut extends Pointcut {
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));
}
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));
ret.copyLocationFrom(this);
return ret;
}
public Pointcut getLeft() {

+ 19
- 0
weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java 查看文件

@@ -113,4 +113,23 @@ public class OrTypePattern extends TypePattern {
}
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 查看文件

@@ -20,6 +20,7 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.Advice;
@@ -47,11 +48,15 @@ public class PerCflow extends PerClause {
// -----
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE;
}
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.YES;
}

@@ -60,7 +65,7 @@ public class PerCflow extends PerClause {
entry.resolve(scope);
}
public Test findResidue(Shadow shadow, ExposedState state) {
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
Expr myInstance =
Expr.makeCallExpr(AjcMemberMaker.perCflowAspectOfMethod(inAspect),
Expr.NONE, inAspect);

+ 8
- 3
weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java 查看文件

@@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Set;

import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FuzzyBoolean;
@@ -31,12 +32,16 @@ public class PerFromSuper extends PerClause {
public PerFromSuper(PerClause.Kind kind) {
this.kind = kind;
}

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

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

@@ -44,7 +49,7 @@ public class PerFromSuper extends PerClause {
// this method intentionally left blank
}

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


+ 18
- 2
weaver/src/org/aspectj/weaver/patterns/PerObject.java 查看文件

@@ -16,6 +16,9 @@ package org.aspectj.weaver.patterns;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.Advice;
@@ -33,11 +36,24 @@ import org.aspectj.weaver.ast.Var;
public class PerObject extends PerClause {
private boolean isThis;
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) {
this.entry = entry;
this.isThis = isThis;
}

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

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

+ 8
- 3
weaver/src/org/aspectj/weaver/patterns/PerSingleton.java 查看文件

@@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Set;

import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AjcMemberMaker;
@@ -29,12 +30,16 @@ import org.aspectj.weaver.ast.Test;
public class PerSingleton extends PerClause {
public PerSingleton() {
}

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

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

@@ -42,7 +47,7 @@ public class PerSingleton extends PerClause {
// this method intentionally left blank
}

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

+ 84
- 9
weaver/src/org/aspectj/weaver/patterns/Pointcut.java 查看文件

@@ -17,6 +17,8 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Member;
import java.util.Collections;
import java.util.Set;

import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
@@ -40,6 +42,43 @@ import org.aspectj.weaver.ast.Test;
*
* @author Erik Hilsdale
* @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 static final class State extends TypeSafeEnum {
@@ -53,9 +92,13 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
public static final State CONCRETE = new State("concrete", 2);

protected byte pointcutKind;
public State state;

protected int lastMatchedShadowId;
private FuzzyBoolean lastMatchedShadowResult;
private Test lastMatchedShadowResidue;
/**
* Constructor for Pattern.
*/
@@ -69,12 +112,31 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
* Could I match any shadows in the code defined within this type?
*/
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?
* 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.
@@ -143,7 +205,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
/**
* Returns this pointcut mutated
*/
public Pointcut resolve(IScope scope) {
public final Pointcut resolve(IScope scope) {
assertState(SYMBOLIC);
Bindings bindingTable = new Bindings(scope.getFormalCount());
this.resolveBindings(scope, bindingTable);
@@ -164,14 +226,15 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
/**
* 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));
}
//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; //???
IntMap map = IntMap.idMap(arity);
map.setEnclosingAdvice(advice);
@@ -187,7 +250,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
}
public Pointcut concretize(ResolvedTypeX inAspect, IntMap bindings) {
public final Pointcut concretize(ResolvedTypeX inAspect, IntMap bindings) {
//!!! add this test -- assertState(RESOLVED);
Pointcut ret = this.concretize1(inAspect, bindings);
if (shouldCopyLocationForConcretize()) ret.copyLocationFrom(this);
@@ -221,7 +284,15 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
* This can be called from NotPointcut even for Pointcuts that
* 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 currently it's unused we're keeping it around as a stub
@@ -272,15 +343,19 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
}
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
}

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

+ 114
- 0
weaver/src/org/aspectj/weaver/patterns/PointcutEvaluationExpenseComparator.java 查看文件

@@ -0,0 +1,114 @@
/* *******************************************************************
* 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 查看文件

@@ -0,0 +1,277 @@
/* *******************************************************************
* 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 查看文件

@@ -17,6 +17,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageUtil;
@@ -58,6 +59,10 @@ public class ReferencePointcut extends Pointcut {
this.pointcutKind = REFERENCE;
}
public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}


//??? do either of these match methods make any sense???
public FuzzyBoolean fastMatch(FastMatchInfo type) {
@@ -67,7 +72,7 @@ public class ReferencePointcut extends Pointcut {
/**
* Do I really match this shadow?
*/
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
return FuzzyBoolean.NO;
}
@@ -210,7 +215,7 @@ public class ReferencePointcut extends Pointcut {
arguments.postRead(enclosingType);
}

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


+ 2
- 0
weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java 查看文件

@@ -488,6 +488,7 @@ public class SignaturePattern extends PatternNode {
&& o.declaringType.equals(this.declaringType)
&& o.name.equals(this.name)
&& o.parameterTypes.equals(this.parameterTypes)
&& o.throwsPattern.equals(this.throwsPattern)
&& o.annotationPattern.equals(this.annotationPattern);
}
public int hashCode() {
@@ -498,6 +499,7 @@ public class SignaturePattern extends PatternNode {
result = 37*result + declaringType.hashCode();
result = 37*result + name.hashCode();
result = 37*result + parameterTypes.hashCode();
result = 37*result + throwsPattern.hashCode();
result = 37*result + annotationPattern.hashCode();
return result;
}

+ 49
- 11
weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java 查看文件

@@ -12,6 +12,12 @@ package org.aspectj.weaver.patterns;
import java.io.DataInputStream;
import java.io.DataOutputStream;
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.ISourceLocation;
@@ -41,6 +47,15 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
private boolean alreadyWarnedAboutDEoW = false;
private ExactAnnotationTypePattern annotationTypePattern;
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);
}
}
/**
*
@@ -56,6 +71,10 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
this.munger = munger;
}
public Set couldMatchKinds() {
return isThis ? thisKindSet : targetKindSet;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/
@@ -66,7 +85,7 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
/* (non-Javadoc)
* @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;
ResolvedTypeX toMatchAgainst =
(isThis ? shadow.getThisType() : shadow.getTargetType() ).resolve(shadow.getIWorld());
@@ -136,7 +155,7 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
/* (non-Javadoc)
* @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;
boolean alwaysMatches = match(shadow).alwaysTrue();
Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar();
@@ -149,15 +168,15 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
shadow.getTargetAnnotationVar(annotationType);
if (annVar == null) return Literal.TRUE; // should be exception when we implement properly
// 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.set(btp.getFormalIndex(),annVar);
@@ -181,6 +200,25 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
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)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/

+ 55
- 14
weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java 查看文件

@@ -17,6 +17,12 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
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.ISourceLocation;
@@ -50,7 +56,17 @@ import org.aspectj.weaver.ast.Var;
public class ThisOrTargetPointcut extends NameBindingPointcut {
private boolean isThis;
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) {
this.isThis = isThis;
this.type = type;
@@ -58,7 +74,11 @@ public class ThisOrTargetPointcut extends NameBindingPointcut {
}
public boolean isThis() { return isThis; }

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

public FuzzyBoolean fastMatch(FastMatchInfo type) {
return FuzzyBoolean.MAYBE;
}
@@ -67,7 +87,7 @@ public class ThisOrTargetPointcut extends NameBindingPointcut {
return isThis ? shadow.hasThis() : shadow.hasTarget();
}
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
if (!couldMatch(shadow)) return FuzzyBoolean.NO;
TypeX typeToMatch = isThis ? shadow.getThisType() : shadow.getTargetType();
//if (typeToMatch == ResolvedTypeX.MISSING) return FuzzyBoolean.NO;
@@ -131,6 +151,25 @@ public class ThisOrTargetPointcut extends NameBindingPointcut {
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) {
if (!(other instanceof ThisOrTargetPointcut)) return false;
ThisOrTargetPointcut o = (ThisOrTargetPointcut)other;
@@ -146,7 +185,7 @@ public class ThisOrTargetPointcut extends NameBindingPointcut {
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 (type == TypePattern.ANY) return Literal.TRUE;
@@ -156,15 +195,15 @@ public class ThisOrTargetPointcut extends NameBindingPointcut {
if (type instanceof BindingTypePattern) {
BindingTypePattern btp = (BindingTypePattern)type;
// 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());
//return null;
}
@@ -186,7 +225,9 @@ public class ThisOrTargetPointcut extends NameBindingPointcut {
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 查看文件

@@ -49,8 +49,9 @@ public class ThrowsPattern extends PatternNode {
public boolean equals(Object other) {
if (!(other instanceof ThrowsPattern)) return false;
ThrowsPattern o = (ThrowsPattern)other;
return o.required.equals(this.required) &&
boolean ret = o.required.equals(this.required) &&
o.forbidden.equals(this.forbidden);
return ret;
}
public int hashCode() {
int result = 17;

+ 36
- 0
weaver/src/org/aspectj/weaver/patterns/TypePattern.java 查看文件

@@ -319,6 +319,20 @@ class EllipsisTypePattern extends TypePattern {
}
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 {
@@ -385,6 +399,14 @@ class AnyTypePattern extends TypePattern {
}
public String toString() { return "*"; }
public boolean equals(Object obj) {
return (obj instanceof AnyTypePattern);
}
public int hashCode() {
return 37;
}
}

class NoTypePattern extends TypePattern {
@@ -447,5 +469,19 @@ class NoTypePattern extends TypePattern {
}
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 查看文件

@@ -532,6 +532,9 @@ public class WildTypePattern extends TypePattern {
WildTypePattern o = (WildTypePattern)other;
int len = o.namePatterns.length;
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++) {
if (!o.namePatterns[i].equals(this.namePatterns[i])) return false;
}

+ 37
- 11
weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java 查看文件

@@ -12,6 +12,10 @@ package org.aspectj.weaver.patterns;
import java.io.DataInputStream;
import java.io.DataOutputStream;
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.ISourceLocation;
@@ -52,6 +56,10 @@ public class WithinAnnotationPointcut extends NameBindingPointcut {
this.munger = munger;
}

public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/
@@ -62,7 +70,7 @@ public class WithinAnnotationPointcut extends NameBindingPointcut {
/* (non-Javadoc)
* @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);
if (enclosingType == ResolvedTypeX.MISSING) {
IMessage msg = new Message(
@@ -104,22 +112,22 @@ public class WithinAnnotationPointcut extends NameBindingPointcut {
/* (non-Javadoc)
* @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) {
BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
TypeX annotationType = btp.annotationType;
Var var = shadow.getWithinAnnotationVar(annotationType);
if (var == null) return Literal.FALSE;
// 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.set(btp.getFormalIndex(),var);
@@ -127,6 +135,24 @@ public class WithinAnnotationPointcut extends NameBindingPointcut {
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)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/

+ 47
- 11
weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java 查看文件

@@ -12,6 +12,11 @@ package org.aspectj.weaver.patterns;
import java.io.DataInputStream;
import java.io.DataOutputStream;
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.Message;
@@ -40,6 +45,14 @@ public class WithinCodeAnnotationPointcut extends NameBindingPointcut {

private ExactAnnotationTypePattern annotationTypePattern;
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) {
super();
@@ -52,6 +65,10 @@ public class WithinCodeAnnotationPointcut extends NameBindingPointcut {
this.munger = munger;
}

public Set couldMatchKinds() {
return matchedShadowKinds;
}

/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
*/
@@ -62,7 +79,7 @@ public class WithinCodeAnnotationPointcut extends NameBindingPointcut {
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
*/
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
AnnotatedElement toMatchAgainst = null;
Member member = shadow.getEnclosingCodeSignature();
ResolvedMember rMember = member.resolve(shadow.getIWorld());
@@ -109,7 +126,7 @@ public class WithinCodeAnnotationPointcut extends NameBindingPointcut {
/* (non-Javadoc)
* @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) {
BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
@@ -117,15 +134,15 @@ public class WithinCodeAnnotationPointcut extends NameBindingPointcut {
Var var = shadow.getWithinCodeAnnotationVar(annotationType);
if (var == null) return Literal.FALSE;
// 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.set(btp.getFormalIndex(),var);
@@ -133,6 +150,25 @@ public class WithinCodeAnnotationPointcut extends NameBindingPointcut {
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)
* @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
*/

+ 10
- 3
weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java 查看文件

@@ -17,6 +17,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Member;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
@@ -48,12 +49,16 @@ public class WithinPointcut extends Pointcut {
}
return FuzzyBoolean.NO;
}

public Set couldMatchKinds() {
return Shadow.ALL_SHADOW_KINDS;
}
public FuzzyBoolean fastMatch(FastMatchInfo info) {
return isWithinType(info.getType());
}
public FuzzyBoolean match(Shadow shadow) {
protected FuzzyBoolean matchInternal(Shadow shadow) {
ResolvedTypeX enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true);
if (enclosingType == ResolvedTypeX.MISSING) {
IMessage msg = new Message(
@@ -146,12 +151,14 @@ public class WithinPointcut extends Pointcut {
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;
}
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 查看文件

@@ -17,6 +17,8 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Member;
import java.util.HashSet;
import java.util.Set;

import org.aspectj.lang.JoinPoint;
import org.aspectj.runtime.reflect.Factory;
@@ -30,17 +32,32 @@ import org.aspectj.weaver.ast.Test;

public class WithincodePointcut extends Pointcut {
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) {
this.signature = signature;
this.pointcutKind = WITHINCODE;
}
public Set couldMatchKinds() {
return matchedShadowKinds;
}
public FuzzyBoolean fastMatch(FastMatchInfo type) {
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
//they were withincode of the outer signature
return FuzzyBoolean.fromBoolean(
@@ -107,12 +124,14 @@ public class WithincodePointcut extends Pointcut {
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;
}
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 查看文件

@@ -108,6 +108,12 @@ errorLoadingXLintDefault=problem loading XlintDefault.properties, {0}
invalidXLintKey=invalid Xlint key: {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

# Enum

+ 1
- 0
weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java 查看文件

@@ -39,6 +39,7 @@ public class PatternsTests extends TestCase {
suite.addTestSuite(WithinCodeTestCase.class);
suite.addTestSuite(AnnotationPatternTestCase.class);
suite.addTestSuite(AnnotationPatternMatchingTestCase.class);
suite.addTestSuite(PointcutRewriterTest.class);
//$JUnit-END$
return suite;
}

+ 366
- 0
weaver/testsrc/org/aspectj/weaver/patterns/PointcutRewriterTest.java 查看文件

@@ -0,0 +1,366 @@
/* *******************************************************************
* 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 查看文件

@@ -12,6 +12,7 @@ package org.aspectj.weaver.patterns;

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

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
@@ -30,11 +31,15 @@ public class PointcutTestCase extends TestCase {
public void testMatchJP() {
Pointcut p = new Pointcut() {

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

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

@@ -47,7 +52,7 @@ public class PointcutTestCase extends TestCase {
return null;
}

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


Loading…
取消
儲存