summaryrefslogtreecommitdiffstats
path: root/weaver
diff options
context:
space:
mode:
authoraclement <aclement>2004-08-03 12:31:29 +0000
committeraclement <aclement>2004-08-03 12:31:29 +0000
commit2982b4cc622a2a95429b16f0aa3c55b7e20d798a (patch)
treea1453e59e3356d36b7bacaf272298f91f6fa1407 /weaver
parentfe049bdf23ae91b938e64fc2106aebf72be34e3b (diff)
downloadaspectj-2982b4cc622a2a95429b16f0aa3c55b7e20d798a.tar.gz
aspectj-2982b4cc622a2a95429b16f0aa3c55b7e20d798a.zip
The BIG commit.
- Enhanced structure model support. - *Incremental* structure model support written and tested (currently switched off, see incModelTests.xml) - -showWeaveInfo compiler option - existence of a 'runtimetest' surfaced through relationships - UI can determine if errors/warnings came from DEOWs. - Code to enable type mungers to remember source locations written (currently switched off)
Diffstat (limited to 'weaver')
-rw-r--r--weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java110
-rw-r--r--weaver/src/org/aspectj/weaver/Checker.java10
-rw-r--r--weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java3
-rw-r--r--weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java6
-rw-r--r--weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java5
-rw-r--r--weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java5
-rw-r--r--weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java5
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java55
-rw-r--r--weaver/src/org/aspectj/weaver/Shadow.java96
-rw-r--r--weaver/src/org/aspectj/weaver/WeaverMetrics.java85
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java14
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java43
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java7
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java4
14 files changed, 426 insertions, 22 deletions
diff --git a/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java b/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java
index a1e1e4a06..b3adcba43 100644
--- a/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java
+++ b/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java
@@ -16,9 +16,11 @@ package org.aspectj.weaver;
import java.util.ArrayList;
import java.util.Iterator;
import org.aspectj.asm.*;
+import org.aspectj.asm.internal.AspectJElementHierarchy;
import org.aspectj.asm.internal.ProgramElement;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
+import org.aspectj.weaver.bcel.BcelAdvice;
public class AsmRelationshipProvider {
@@ -28,6 +30,8 @@ public class AsmRelationshipProvider {
public static final String DECLAREDY_BY = "declared by";
public static final String MATCHED_BY = "matched by";
public static final String MATCHES_DECLARE = "matches declare";
+ public static final String INTER_TYPE_DECLARES = "declared on";
+ public static final String INTER_TYPE_DECLARED_BY = "aspect declarations";
public static void checkerMunger(IHierarchy model, Shadow shadow, Checker checker) {
if (shadow.getSourceLocation() == null || checker.getSourceLocation() == null) return;
@@ -44,37 +48,116 @@ public class AsmRelationshipProvider {
IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
if (sourceHandle != null && targetHandle != null) {
- IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE, MATCHED_BY);
- foreward.getTargets().add(targetHandle);
+ IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE, MATCHED_BY,false,true);
+ foreward.addTarget(targetHandle);
+// foreward.getTargets().add(targetHandle);
- IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, MATCHES_DECLARE);
+ IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, MATCHES_DECLARE,false,true);
if (back != null && back.getTargets() != null) {
- back.getTargets().add(sourceHandle);
+ back.addTarget(sourceHandle);
+ //back.getTargets().add(sourceHandle);
}
}
}
+
+ // For ITDs
+ public static void addRelationship(
+ ResolvedTypeX onType,
+ ResolvedTypeMunger munger,
+ ResolvedTypeX originatingAspect) {
+
+ String sourceHandle = "";
+ if (munger.getSourceLocation()!=null) {
+ sourceHandle = ProgramElement.createHandleIdentifier(
+ munger.getSourceLocation().getSourceFile(),
+ munger.getSourceLocation().getLine(),
+ munger.getSourceLocation().getColumn());
+ } else {
+ sourceHandle = ProgramElement.createHandleIdentifier(
+ originatingAspect.getSourceLocation().getSourceFile(),
+ originatingAspect.getSourceLocation().getLine(),
+ originatingAspect.getSourceLocation().getColumn());
+ }
+ if (originatingAspect.getSourceLocation() != null) {
+
+ String targetHandle = ProgramElement.createHandleIdentifier(
+ onType.getSourceLocation().getSourceFile(),
+ onType.getSourceLocation().getLine(),
+ onType.getSourceLocation().getColumn());
+
+ IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
+ if (sourceHandle != null && targetHandle != null) {
+ IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES,false,true);
+ foreward.addTarget(targetHandle);
+// foreward.getTargets().add(targetHandle);
+
+ IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY,false,true);
+ back.addTarget(sourceHandle);
+// back.getTargets().add(sourceHandle);
+ }
+ }
+ }
+
+ public static void addDeclareParentsRelationship(ISourceLocation decp,ResolvedTypeX targetType) {
+
+ String sourceHandle = ProgramElement.createHandleIdentifier(decp.getSourceFile(),decp.getLine(),decp.getColumn());
+
+ IProgramElement ipe = AsmManager.getDefault().getHierarchy().findElementForHandle(sourceHandle);
+
+
+ String targetHandle = ProgramElement.createHandleIdentifier(
+ targetType.getSourceLocation().getSourceFile(),
+ targetType.getSourceLocation().getLine(),
+ targetType.getSourceLocation().getColumn());
+
+ IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
+ if (sourceHandle != null && targetHandle != null) {
+ IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES,false,true);
+ foreward.addTarget(targetHandle);
+
+ IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY,false,true);
+ back.addTarget(sourceHandle);
+ }
+
+ }
public static void adviceMunger(IHierarchy model, Shadow shadow, ShadowMunger munger) {
if (munger instanceof Advice) {
Advice advice = (Advice)munger;
+
if (advice.getKind().isPerEntry() || advice.getKind().isCflow()) {
// TODO: might want to show these in the future
return;
}
+
IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
- IProgramElement targetNode = getNode(AsmManager.getDefault().getHierarchy(), shadow);
+ IProgramElement targetNode = getNode(AsmManager.getDefault().getHierarchy(), shadow);
+ boolean runtimeTest = ((BcelAdvice)munger).hasDynamicTests();
+
+ // Work out extra info to inform interested UIs !
+ IProgramElement.ExtraInformation ai = new IProgramElement.ExtraInformation();
+
String adviceHandle = advice.getHandle();
+
+ // What kind of advice is it?
+ // TODO: Prob a better way to do this but I just want to
+ // get it into CVS !!!
+ AdviceKind ak = ((Advice)munger).getKind();
+ ai.setExtraAdviceInformation(ak.getName());
+ IProgramElement adviceElement = AsmManager.getDefault().getHierarchy().findElementForHandle(adviceHandle);
+ adviceElement.setExtraInfo(ai);
+
if (adviceHandle != null && targetNode != null) {
if (targetNode != null) {
String targetHandle = targetNode.getHandleIdentifier();
- IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.ADVICE, ADVISES);
- if (foreward != null) foreward.getTargets().add(targetHandle);
+ IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.ADVICE, ADVISES,runtimeTest,true);
+ if (foreward != null) foreward.addTarget(targetHandle);//foreward.getTargets().add(targetHandle);
- IRelationship back = mapper.get(targetHandle, IRelationship.Kind.ADVICE, ADVISED_BY);
- if (back != null) back.getTargets().add(adviceHandle);
+ IRelationship back = mapper.get(targetHandle, IRelationship.Kind.ADVICE, ADVISED_BY,runtimeTest,true);
+ if (back != null) back.addTarget(adviceHandle);//back.getTargets().add(adviceHandle);
}
}
@@ -102,12 +185,19 @@ public class AsmRelationshipProvider {
}
}
+ private static boolean sourceLinesMatch(ISourceLocation loc1,ISourceLocation loc2) {
+ if (loc1.getLine()!=loc2.getLine()) return false;
+ return true;
+ }
+
+
private static IProgramElement findOrCreateCodeNode(IProgramElement enclosingNode, Member shadowSig, Shadow shadow)
{
for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext(); ) {
IProgramElement node = (IProgramElement)it.next();
if (shadowSig.getName().equals(node.getBytecodeName()) &&
- shadowSig.getSignature().equals(node.getBytecodeSignature()))
+ shadowSig.getSignature().equals(node.getBytecodeSignature()) &&
+ sourceLinesMatch(node.getSourceLocation(),shadow.getSourceLocation()))
{
return node;
}
diff --git a/weaver/src/org/aspectj/weaver/Checker.java b/weaver/src/org/aspectj/weaver/Checker.java
index c87221bfa..e8f5266f7 100644
--- a/weaver/src/org/aspectj/weaver/Checker.java
+++ b/weaver/src/org/aspectj/weaver/Checker.java
@@ -52,11 +52,15 @@ public class Checker extends ShadowMunger {
isError ? IMessage.ERROR : IMessage.WARNING,
shadow.getSourceLocation(),
null,
- new ISourceLocation[]{this.getSourceLocation()});
- world.getMessageHandler().handleMessage(message);
+ new ISourceLocation[]{this.getSourceLocation()},true);
+
+ world.getMessageHandler().handleMessage(message);
if (world.xrefHandler != null) {
- world.xrefHandler.addCrossReference(this.getSourceLocation(),shadow.getSourceLocation(),IRelationship.Kind.DECLARE);
+ world.xrefHandler.addCrossReference(this.getSourceLocation(),
+ shadow.getSourceLocation(),
+ (this.isError?IRelationship.Kind.DECLARE_ERROR:IRelationship.Kind.DECLARE_WARNING),false);
+
}
if (world.getModel() != null) {
diff --git a/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java b/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java
index 0ce029a55..0f0ecf022 100644
--- a/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java
+++ b/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java
@@ -44,7 +44,8 @@ public abstract class ConcreteTypeMunger implements PartialOrder.PartialComparab
}
public ISourceLocation getSourceLocation() {
- return null; //XXX
+ if (munger == null) return null;
+ return munger.getSourceLocation(); //XXX
}
public boolean matches(ResolvedTypeX onType) {
diff --git a/weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java b/weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java
index c0ffeae40..cb2fe93c3 100644
--- a/weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java
+++ b/weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java
@@ -20,6 +20,10 @@ import org.aspectj.bridge.ISourceLocation;
*/
public interface ICrossReferenceHandler {
- void addCrossReference(ISourceLocation from, ISourceLocation to, IRelationship.Kind kind);
+ void addCrossReference(
+ ISourceLocation from,
+ ISourceLocation to,
+ IRelationship.Kind kind,
+ boolean runtimeTest);
}
diff --git a/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java b/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java
index 0f4ac0fb7..699ed9736 100644
--- a/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java
+++ b/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java
@@ -49,14 +49,17 @@ public class NewConstructorTypeMunger extends ResolvedTypeMunger {
syntheticConstructor.write(s);
explicitConstructor.write(s);
writeSuperMethodsCalled(s);
+ if (ResolvedTypeMunger.persistSourceLocation) writeSourceLocation(s);
}
public static ResolvedTypeMunger readConstructor(DataInputStream s, ISourceContext context) throws IOException {
- return new NewConstructorTypeMunger(
+ ResolvedTypeMunger munger = new NewConstructorTypeMunger(
ResolvedMember.readResolvedMember(s, context),
ResolvedMember.readResolvedMember(s, context),
ResolvedMember.readResolvedMember(s, context),
readSuperMethodsCalled(s));
+ if (ResolvedTypeMunger.persistSourceLocation) munger.setSourceLocation(readSourceLocation(s));
+ return munger;
}
public ResolvedMember getExplicitConstructor() {
diff --git a/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java b/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
index 8733a3b8d..3ef81e57b 100644
--- a/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
+++ b/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
@@ -32,12 +32,15 @@ public class NewFieldTypeMunger extends ResolvedTypeMunger {
kind.write(s);
signature.write(s);
writeSuperMethodsCalled(s);
+ if (ResolvedTypeMunger.persistSourceLocation) writeSourceLocation(s);
}
public static ResolvedTypeMunger readField(DataInputStream s, ISourceContext context) throws IOException {
- return new NewFieldTypeMunger(
+ ResolvedTypeMunger munger = new NewFieldTypeMunger(
ResolvedMember.readResolvedMember(s, context),
readSuperMethodsCalled(s));
+ if (ResolvedTypeMunger.persistSourceLocation) munger.setSourceLocation(readSourceLocation(s));
+ return munger;
}
public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedTypeX aspectType) {
diff --git a/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java b/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java
index 92fcb2c8e..f42f74458 100644
--- a/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java
+++ b/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java
@@ -37,12 +37,15 @@ public class NewMethodTypeMunger extends ResolvedTypeMunger {
kind.write(s);
signature.write(s);
writeSuperMethodsCalled(s);
+ if (ResolvedTypeMunger.persistSourceLocation) writeSourceLocation(s);
}
public static ResolvedTypeMunger readMethod(DataInputStream s, ISourceContext context) throws IOException {
- return new NewMethodTypeMunger(
+ ResolvedTypeMunger munger = new NewMethodTypeMunger(
ResolvedMember.readResolvedMember(s, context),
readSuperMethodsCalled(s));
+ if (ResolvedTypeMunger.persistSourceLocation) munger.setSourceLocation(readSourceLocation(s));
+ return munger;
}
public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedTypeX aspectType) {
diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java
index 55e0a4e3e..aa1ff7223 100644
--- a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java
+++ b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java
@@ -15,7 +15,10 @@ package org.aspectj.weaver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
+import java.io.File;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -23,6 +26,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.SourceLocation;
import org.aspectj.util.TypeSafeEnum;
/** This is an abstraction over method/field introduction. It might not have the chops
@@ -33,12 +38,24 @@ public abstract class ResolvedTypeMunger {
protected Kind kind;
protected ResolvedMember signature;
+ public static transient boolean persistSourceLocation = false;
+
private Set /* resolvedMembers */ superMethodsCalled = Collections.EMPTY_SET;
+
+ private ISourceLocation location; // Lost during serialize/deserialize !
public ResolvedTypeMunger(Kind kind, ResolvedMember signature) {
this.kind = kind;
this.signature = signature;
}
+
+ public void setSourceLocation(ISourceLocation isl) {
+ location = isl;
+ }
+
+ public ISourceLocation getSourceLocation() {
+ return location;
+ }
// ----
@@ -95,7 +112,10 @@ public abstract class ResolvedTypeMunger {
}
}
+
+
protected static Set readSuperMethodsCalled(DataInputStream s) throws IOException {
+
Set ret = new HashSet();
int n = s.readInt();
for (int i=0; i < n; i++) {
@@ -105,6 +125,7 @@ public abstract class ResolvedTypeMunger {
}
protected void writeSuperMethodsCalled(DataOutputStream s) throws IOException {
+
if (superMethodsCalled == null) {
s.writeInt(0);
return;
@@ -118,6 +139,40 @@ public abstract class ResolvedTypeMunger {
ResolvedMember m = (ResolvedMember)i.next();
m.write(s);
}
+
+ }
+
+ protected static ISourceLocation readSourceLocation(DataInputStream s) throws IOException {
+ if (!persistSourceLocation) return null;
+ ISourceLocation ret = null;
+ ObjectInputStream ois = new ObjectInputStream(s);
+ try {
+ Boolean validLocation = (Boolean)ois.readObject();
+ if (validLocation.booleanValue()) {
+ File f = (File) ois.readObject();
+ Integer ii = (Integer)ois.readObject();
+ ret = new SourceLocation(f,ii.intValue());
+ }
+ } catch (IOException ioe) {
+ // Something went wrong, maybe this is an 'old style' file that doesnt attach locations to mungers
+ ioe.printStackTrace();
+ return null;
+ } catch (ClassNotFoundException e) { }
+ ois.close();
+ return ret;
+ }
+
+ protected void writeSourceLocation(DataOutputStream s) throws IOException {
+ if (!persistSourceLocation) return;
+ ObjectOutputStream oos = new ObjectOutputStream(s);
+ // oos.writeObject(location);
+ oos.writeObject(new Boolean(location!=null));
+ if (location !=null) {
+ oos.writeObject(location.getSourceFile());
+ oos.writeObject(new Integer(location.getLine()));
+ }
+ oos.flush();
+ oos.close();
}
diff --git a/weaver/src/org/aspectj/weaver/Shadow.java b/weaver/src/org/aspectj/weaver/Shadow.java
index 42e2920e4..b34f62e7e 100644
--- a/weaver/src/org/aspectj/weaver/Shadow.java
+++ b/weaver/src/org/aspectj/weaver/Shadow.java
@@ -26,6 +26,7 @@ import org.aspectj.lang.JoinPoint;
import org.aspectj.util.PartialOrder;
import org.aspectj.util.TypeSafeEnum;
import org.aspectj.weaver.ast.Var;
+import org.aspectj.weaver.bcel.BcelAdvice;
/*
* The superclass of anything representing a the shadow of a join point. A shadow represents
@@ -345,6 +346,89 @@ public abstract class Shadow {
protected void prepareForMungers() {
throw new RuntimeException("Generic shadows cannot be prepared");
}
+
+ /*
+ * Ensure we report a nice source location - particular in the case
+ * where the source info is missing (binary weave).
+ */
+ private String beautifyLocation(ISourceLocation isl) {
+ StringBuffer nice = new StringBuffer();
+ if (isl==null || isl.getSourceFile()==null || isl.getSourceFile().getName().indexOf("no debug info available")!=-1) {
+ nice.append("no debug info available");
+ } else {
+ nice.append(isl.getSourceFile().getName());
+ if (isl.getLine()!=0) nice.append(":").append(isl.getLine());
+ }
+ return nice.toString();
+ }
+
+ /*
+ * Report a message about the advice weave that has occurred. Some messing about
+ * to make it pretty ! This code is just asking for an NPE to occur ...
+ */
+ private void reportWeavingMessage(ShadowMunger munger) {
+ Advice advice = (Advice)munger;
+ AdviceKind aKind = advice.getKind();
+ // Only report on interesting advice kinds ...
+ if (aKind == null || advice.getConcreteAspect()==null) {
+ // We suspect someone is programmatically driving the weaver
+ // (e.g. IdWeaveTestCase in the weaver testcases)
+ return;
+ }
+ if (!( aKind.equals(AdviceKind.Before) ||
+ aKind.equals(AdviceKind.After) ||
+ aKind.equals(AdviceKind.AfterReturning) ||
+ aKind.equals(AdviceKind.AfterThrowing) ||
+ aKind.equals(AdviceKind.Around) ||
+ aKind.equals(AdviceKind.Softener))) return;
+
+ String description = advice.getKind().toString();
+ String advisedType = this.getEnclosingType().getName();
+ String advisingType= advice.getConcreteAspect().getName();
+ Message msg = null;
+ if (advice.getKind().equals(AdviceKind.Softener)) {
+ msg = WeaveMessage.constructWeavingMessage(
+ WeaveMessage.WEAVEMESSAGE_SOFTENS,
+ new String[]{advisedType,beautifyLocation(getSourceLocation()),
+ advisingType,beautifyLocation(munger.getSourceLocation())});
+ } else {
+ boolean runtimeTest = ((BcelAdvice)advice).hasDynamicTests();
+ msg = WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ADVISES,
+ new String[]{ advisedType, beautifyLocation(getSourceLocation()),
+ description,
+ advisingType,beautifyLocation(munger.getSourceLocation()),
+ (runtimeTest?" [with runtime test]":"")});
+ // Boolean.toString(runtimeTest)});
+ }
+ getIWorld().getMessageHandler().handleMessage(msg);
+ }
+
+
+ public IRelationship.Kind determineRelKind(ShadowMunger munger) {
+ AdviceKind ak = ((Advice)munger).getKind();
+ if (ak.getKey()==AdviceKind.Before.getKey())
+ return IRelationship.Kind.ADVICE_BEFORE;
+ else if (ak.getKey()==AdviceKind.After.getKey())
+ return IRelationship.Kind.ADVICE_AFTER;
+ else if (ak.getKey()==AdviceKind.AfterThrowing.getKey())
+ return IRelationship.Kind.ADVICE_AFTERTHROWING;
+ else if (ak.getKey()==AdviceKind.AfterReturning.getKey())
+ return IRelationship.Kind.ADVICE_AFTERRETURNING;
+ else if (ak.getKey()==AdviceKind.Around.getKey())
+ return IRelationship.Kind.ADVICE_AROUND;
+ else if (ak.getKey()==AdviceKind.CflowEntry.getKey() ||
+ ak.getKey()==AdviceKind.CflowBelowEntry.getKey() ||
+ ak.getKey()==AdviceKind.InterInitializer.getKey() ||
+ ak.getKey()==AdviceKind.PerCflowEntry.getKey() ||
+ ak.getKey()==AdviceKind.PerCflowBelowEntry.getKey() ||
+ ak.getKey()==AdviceKind.PerThisEntry.getKey() ||
+ ak.getKey()==AdviceKind.PerTargetEntry.getKey() ||
+ ak.getKey()==AdviceKind.Softener.getKey()) {
+ System.err.println("Dont want a message about this: "+ak);
+ return null;
+ }
+ throw new RuntimeException("Shadow.determineRelKind: What the hell is it? "+ak);
+ }
/** Actually implement the (non-empty) mungers associated with this shadow */
private void implementMungers() {
@@ -354,9 +438,19 @@ public abstract class Shadow {
munger.implementOn(this);
if (world.xrefHandler != null) {
- world.xrefHandler.addCrossReference(munger.getSourceLocation(),this.getSourceLocation(),IRelationship.Kind.ADVICE);
+ world.xrefHandler.addCrossReference(
+ munger.getSourceLocation(), // What is being applied
+ this.getSourceLocation(), // Where is it being applied
+ determineRelKind(munger), // What kind of advice?
+ ((BcelAdvice)munger).hasDynamicTests() // Is a runtime test being stuffed in the code?
+ );
}
+ // TAG: WeavingMessage
+ if (!getIWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
+ reportWeavingMessage(munger);
+ }
+
if (world.getModel() != null) {
//System.err.println("munger: " + munger + " on " + this);
AsmRelationshipProvider.adviceMunger(world.getModel(), this, munger);
diff --git a/weaver/src/org/aspectj/weaver/WeaverMetrics.java b/weaver/src/org/aspectj/weaver/WeaverMetrics.java
new file mode 100644
index 000000000..113be2943
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/WeaverMetrics.java
@@ -0,0 +1,85 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * 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
+ *
+ * Contributors:
+ * Andy Clement initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.patterns.FastMatchInfo;
+
+
+/**
+ * Records stats about the weaver. Information like 'how many types are dismissed during fast match' that
+ * may be useful for trying to tune pointcuts. Not publicised.
+ */
+public class WeaverMetrics {
+
+ // Level 1 of matching is at the type level, which types can be dismissed?
+ public static int fastMatchOnTypeAttempted = 0;
+ public static int fastMatchOnTypeTrue = 0;
+ public static int fastMatchOnTypeFalse = 0;
+
+ // Level 2 of matching is fast matching on the shadows in the remaining types
+ public static int fastMatchOnShadowsAttempted = 0;
+ public static int fastMatchOnShadowsTrue = 0;
+ public static int fastMatchOnShadowsFalse = 0;
+
+ // Level 3 of matching is slow matching on the shadows (more shadows than were fast matched on!)
+ public static int matchTrue = 0;
+ public static int matchAttempted = 0;
+
+
+
+ public static void reset() {
+
+ fastMatchOnShadowsAttempted = 0;
+ fastMatchOnShadowsTrue = 0;
+ fastMatchOnShadowsFalse = 0;
+
+ fastMatchOnTypeAttempted = 0;
+ fastMatchOnTypeTrue = 0;
+ fastMatchOnTypeFalse = 0;
+
+ matchTrue = 0;
+ matchAttempted = 0;
+ }
+
+
+ public static void dumpInfo() {
+ System.err.println("Match summary:");
+ int fastMatchOnTypeMaybe = (fastMatchOnTypeAttempted-fastMatchOnTypeTrue-fastMatchOnTypeFalse);
+ System.err.print("At the type level, we attempted #"+fastMatchOnTypeAttempted+" fast matches:");
+ System.err.println(" YES/NO/MAYBE = "+fastMatchOnTypeTrue+"/"+fastMatchOnTypeFalse+"/"+fastMatchOnTypeMaybe);
+ int fastMatchMaybe = (fastMatchOnShadowsAttempted-fastMatchOnShadowsFalse-fastMatchOnShadowsTrue);
+ System.err.print("Within those #"+(fastMatchOnTypeTrue+fastMatchOnTypeMaybe)+" possible types, ");
+ System.err.print("we fast matched on #"+fastMatchOnShadowsAttempted+" shadows:");
+ System.err.println(" YES/NO/MAYBE = "+fastMatchOnShadowsTrue+"/"+fastMatchOnShadowsFalse+"/"+fastMatchMaybe);
+ System.err.println("Shadow (non-fast) matches attempted #"+matchAttempted+" of which "+matchTrue+" successful");
+ }
+
+
+ public static void recordFastMatchTypeResult(FuzzyBoolean fb) {
+ fastMatchOnTypeAttempted++;
+ if (fb.alwaysTrue()) fastMatchOnTypeTrue++;
+ if (fb.alwaysFalse()) fastMatchOnTypeFalse++;
+ }
+
+ public static void recordFastMatchResult(FuzzyBoolean fb) {
+ fastMatchOnShadowsAttempted++;
+ if (fb.alwaysTrue()) fastMatchOnShadowsTrue++;
+ if (fb.alwaysFalse()) fastMatchOnShadowsFalse++;
+ }
+
+ public static void recordMatchResult(boolean b) {
+ matchAttempted++;
+ if (b) matchTrue++;
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
index ad561a98e..92e83c874 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
@@ -48,6 +48,7 @@ import org.apache.bcel.generic.ReturnInstruction;
import org.apache.bcel.generic.Select;
import org.apache.bcel.generic.Type;
import org.aspectj.bridge.IMessage;
+import org.aspectj.util.FuzzyBoolean;
import org.aspectj.util.PartialOrder;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AjcMemberMaker;
@@ -56,6 +57,7 @@ import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.IClassWeaver;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.Member;
+import org.aspectj.weaver.WeaverMetrics;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.NewFieldTypeMunger;
import org.aspectj.weaver.ResolvedMember;
@@ -172,7 +174,9 @@ class BcelClassWeaver implements IClassWeaver {
FastMatchInfo info = new FastMatchInfo(clazz.getType(), kind);
for (Iterator i = shadowMungers.iterator(); i.hasNext();) {
ShadowMunger munger = (ShadowMunger) i.next();
- if (munger.getPointcut().fastMatch(info).maybeTrue()) mungers.add(munger);
+ FuzzyBoolean fb = munger.getPointcut().fastMatch(info);
+ WeaverMetrics.recordFastMatchResult(fb);// Could pass: munger.getPointcut().toString()
+ if (fb.maybeTrue()) mungers.add(munger);
}
}
@@ -1120,13 +1124,19 @@ class BcelClassWeaver implements IClassWeaver {
for (Iterator i = shadowMungers.iterator(); i.hasNext(); ) {
ShadowMunger munger = (ShadowMunger)i.next();
if (munger.match(shadow, world)) {
+
+ WeaverMetrics.recordMatchResult(true);// Could pass: munger
shadow.addMunger(munger);
isMatched = true;
if (shadow.getKind() == Shadow.StaticInitialization) {
clazz.warnOnAddedStaticInitializer(shadow,munger.getSourceLocation());
}
- }
+
+ } else {
+ WeaverMetrics.recordMatchResult(false); // Could pass: munger
+ }
}
+
if (isMatched) shadowAccumulator.add(shadow);
return isMatched;
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
index 2fef3a0c1..4d031bcb9 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
@@ -23,7 +23,10 @@ import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.Type;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.WeaveMessage;
import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.AsmRelationshipProvider;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.NameMangler;
@@ -54,6 +57,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
public boolean munge(BcelClassWeaver weaver) {
boolean changed = false;
+ boolean worthReporting = true;
if (munger.getKind() == ResolvedTypeMunger.Field) {
changed = mungeNewField(weaver, (NewFieldTypeMunger)munger);
@@ -61,8 +65,10 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
changed = mungeNewMethod(weaver, (NewMethodTypeMunger)munger);
} else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) {
changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger);
+ worthReporting = false;
} else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) {
changed = mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger);
+ worthReporting = false;
} else if (munger.getKind() == ResolvedTypeMunger.Constructor) {
changed = mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger);
} else if (munger.getKind() == ResolvedTypeMunger.Parent) {
@@ -76,6 +82,43 @@ public class BcelTypeMunger extends ConcreteTypeMunger {
weaver.getLazyClassGen().getOrCreateWeaverStateInfo();
info.addConcreteMunger(this);
}
+ // Whilst type mungers aren't persisting their source locations, we add this relationship during
+ // compilation time (see other reference to ResolvedTypeMunger.persist)
+ if (ResolvedTypeMunger.persistSourceLocation) {
+ if (changed) {
+ if (munger.getKind().equals(ResolvedTypeMunger.Parent)) {
+ AsmRelationshipProvider.addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType());
+ } else {
+ AsmRelationshipProvider.addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType());
+ }
+ }
+ }
+
+ // TAG: WeavingMessage
+ if (worthReporting && munger!=null && !weaver.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
+ String tName = weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getName();
+ if (tName.indexOf("no debug info available")!=-1) tName = "no debug info available";
+ String fName = getAspectType().getSourceLocation().getSourceFile().getName();
+ if (munger.getKind().equals(ResolvedTypeMunger.Parent)) {
+ // This message will come out of AjLookupEnvironment.addParent if doing a source
+ // compilation.
+ NewParentTypeMunger parentTM = (NewParentTypeMunger)munger;
+ if (parentTM.getNewParent().isInterface()) {
+ weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,
+ new String[]{weaver.getLazyClassGen().getType().getName(),
+ tName,parentTM.getNewParent().getName(),fName}));
+ } else {
+ System.err.println("BANG, you need to fix this. BcelTypeMunger");
+ }
+ } else {
+ weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ITD,
+ new String[]{weaver.getLazyClassGen().getType().getName(),
+ tName,munger.getKind().toString().toLowerCase(),
+ getAspectType().getName(),
+ fName+":'"+munger.getSignature()+"'"}));
+ // ??? If only type mungers knew their originating line numbers ...
+ }
+ }
return changed;
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
index 19beb0f62..653510ddd 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
@@ -48,11 +48,13 @@ import org.aspectj.bridge.IProgressListener;
import org.aspectj.bridge.Message;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.util.FileUtil;
+import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.CrosscuttingMembersSet;
import org.aspectj.weaver.IClassFileProvider;
import org.aspectj.weaver.IWeaveRequestor;
import org.aspectj.weaver.IWeaver;
+import org.aspectj.weaver.WeaverMetrics;
import org.aspectj.weaver.NewParentTypeMunger;
import org.aspectj.weaver.ResolvedTypeMunger;
import org.aspectj.weaver.ResolvedTypeX;
@@ -75,6 +77,7 @@ public class BcelWeaver implements IWeaver {
public BcelWeaver(BcelWorld world) {
super();
+ WeaverMetrics.reset();
this.world = world;
this.xcutSet = world.getCrosscuttingMembersSet();
}
@@ -815,7 +818,9 @@ public class BcelWeaver implements IWeaver {
Iterator iter = list.iterator();
while (iter.hasNext()) {
ShadowMunger munger = (ShadowMunger)iter.next();
- if (munger.getPointcut().fastMatch(info).maybeTrue()) {
+ FuzzyBoolean fb = munger.getPointcut().fastMatch(info);
+ WeaverMetrics.recordFastMatchTypeResult(fb); // Could pass: munger.getPointcut().toString(),info
+ if (fb.maybeTrue()) {
result.add(munger);
}
}
diff --git a/weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java b/weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java
index c2b6121d0..8d5434f27 100644
--- a/weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java
+++ b/weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java
@@ -39,5 +39,9 @@ public class FastMatchInfo {
public ResolvedTypeX getType() {
return type;
}
+
+ public String toString() {
+ return "FastMatchInfo [type="+type.getName()+"] ["+(kind==null?"AllKinds":"Kind="+kind)+"]";
+ }
}