aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ajde/src/org/aspectj/ajde/internal/CompilerAdapter.java34
-rw-r--r--ajde/src/org/aspectj/ajde/ui/StructureModelUtil.java58
-rw-r--r--ajde/src/org/aspectj/ajde/ui/StructureViewNodeFactory.java4
-rw-r--r--ajde/testsrc/org/aspectj/ajde/AjdeTests.java1
-rw-r--r--ajde/testsrc/org/aspectj/ajde/AsmDeclarationsTest.java10
-rw-r--r--ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java7
-rw-r--r--ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java78
-rw-r--r--ajde/testsrc/org/aspectj/ajde/ShowWeaveMessagesTestCase.java376
-rw-r--r--asm/src/org/aspectj/asm/AsmManager.java486
-rw-r--r--asm/src/org/aspectj/asm/IHierarchy.java5
-rw-r--r--asm/src/org/aspectj/asm/IProgramElement.java17
-rw-r--r--asm/src/org/aspectj/asm/IRelationship.java24
-rw-r--r--asm/src/org/aspectj/asm/IRelationshipMap.java21
-rw-r--r--asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java28
-rw-r--r--asm/src/org/aspectj/asm/internal/ProgramElement.java48
-rw-r--r--asm/src/org/aspectj/asm/internal/Relationship.java17
-rw-r--r--asm/src/org/aspectj/asm/internal/RelationshipMap.java71
-rw-r--r--bridge/src/org/aspectj/bridge/IMessage.java6
-rw-r--r--bridge/src/org/aspectj/bridge/Message.java34
-rw-r--r--bridge/src/org/aspectj/bridge/MessageHandler.java3
-rw-r--r--bridge/src/org/aspectj/bridge/WeaveMessage.java75
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java16
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties1
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java12
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java76
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AsmInterTypeRelationshipProvider.java8
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java3
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java17
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java99
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java1
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java48
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java137
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java15
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java8
-rw-r--r--org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java36
-rw-r--r--testing/src/org/aspectj/testing/harness/bridge/IncCompilerRun.java17
-rw-r--r--testing/src/org/aspectj/testing/xml/SoftMessage.java2
-rw-r--r--tests/ajcTestSuite.dtd1
-rw-r--r--tests/incModelTests.xml102
-rw-r--r--tests/incremental/model/intertype/primary/Alpha.java7
-rw-r--r--tests/incremental/model/intertype/secondary/BetaA.20.java8
-rw-r--r--tests/incremental/model/intertype/secondary/BetaA.30.java7
-rw-r--r--tests/incremental/model/introduction/introduction/CloneablePoint.20.java42
-rw-r--r--tests/incremental/model/introduction/introduction/CloneablePoint.java42
-rw-r--r--tests/incremental/model/introduction/introduction/ComparablePoint.java46
-rw-r--r--tests/incremental/model/introduction/introduction/HashablePoint.30.java47
-rw-r--r--tests/incremental/model/introduction/introduction/HashablePoint.java47
-rw-r--r--tests/incremental/model/introduction/introduction/Point.30.java98
-rw-r--r--tests/incremental/model/introduction/introduction/Point.java98
-rw-r--r--tests/incremental/model/sourcefiles_addremove/primary/Alpha.java7
-rw-r--r--tests/incremental/model/sourcefiles_addremove/primary/Beta.20.java11
-rw-r--r--tests/incremental/model/sourcefiles_addremove/primary/Beta.delete.60.java11
-rw-r--r--tests/incremental/model/sourcefiles_addremove/secondary/Delta.40.java5
-rw-r--r--tests/incremental/model/sourcefiles_addremove/secondary/Delta.delete.60.java5
-rw-r--r--tests/incremental/model/sourcefiles_addremove/secondary/Gamma.30.java7
-rw-r--r--tests/incremental/model/sourcefiles_addremove/secondary/Gamma.delete.50.java7
-rw-r--r--tests/incremental/model/sourcefiles_updating/primary/Alpha.java7
-rw-r--r--tests/incremental/model/sourcefiles_updating/primary/Beta.20.java13
-rw-r--r--tests/incremental/model/sourcefiles_updating/primary/Beta.java7
-rw-r--r--tests/incremental/model/sourcefiles_updating/secondary/Delta.30.java10
-rw-r--r--tests/incremental/model/sourcefiles_updating/secondary/Delta.java5
-rw-r--r--tests/incremental/model/sourcefiles_updating/secondary/Gamma.40.java10
-rw-r--r--tests/incremental/model/sourcefiles_updating/secondary/Gamma.50.java13
-rw-r--r--tests/incremental/model/sourcefiles_updating/secondary/Gamma.60.java8
-rw-r--r--tests/incremental/model/sourcefiles_updating/secondary/Gamma.java7
-rw-r--r--tests/incremental/model/weaving/primary/Alpha.java21
-rw-r--r--tests/incremental/model/weaving/primary/BetaA.20.java16
-rw-r--r--tests/incremental/model/weaving/primary/BetaA.30.java10
-rw-r--r--tests/incremental/model/weaving/primary/BetaA.40.java5
-rw-r--r--tests/incremental/model/weaving/primary/BetaA.java10
-rw-r--r--tests/incremental/model/weaving2/primary/Alpha.java11
-rw-r--r--tests/incremental/model/weaving2/primary/BetaA.20.java8
-rw-r--r--tests/incremental/model/weaving2/primary/BetaA.delete.40.java8
-rw-r--r--tests/incremental/model/weaving2/primary/BetaA.java4
-rw-r--r--tests/incremental/model/weaving2/secondary/GammaA.30.java8
-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
89 files changed, 2900 insertions, 226 deletions
diff --git a/ajde/src/org/aspectj/ajde/internal/CompilerAdapter.java b/ajde/src/org/aspectj/ajde/internal/CompilerAdapter.java
index 34637e24f..f98e08c0e 100644
--- a/ajde/src/org/aspectj/ajde/internal/CompilerAdapter.java
+++ b/ajde/src/org/aspectj/ajde/internal/CompilerAdapter.java
@@ -432,6 +432,16 @@ public class CompilerAdapter {
}
+ /** Local helper method for splitting option strings */
+ private static List tokenizeString(String str) {
+ List tokens = new ArrayList();
+ StringTokenizer tok = new StringTokenizer(str);
+ while ( tok.hasMoreTokens() ) {
+ tokens.add(tok.nextToken());
+ }
+ return tokens;
+ }
+
/**
* Helper method for configure build options.
* This reads all command-line options specified
@@ -448,13 +458,25 @@ public class CompilerAdapter {
return true;
}
- StringTokenizer tok = new StringTokenizer( nonStdOptions );
- String[] args = new String[ tok.countTokens() ];
- int argCount = 0;
- while ( tok.hasMoreTokens() ) {
- args[argCount++] = tok.nextToken();
+ // Break a string into a string array of non-standard options.
+ // Allows for one option to include a ' '. i.e. assuming it has been quoted, it
+ // won't accidentally get treated as a pair of options (can be needed for xlint props file option)
+ List tokens = new ArrayList();
+ int ind = nonStdOptions.indexOf('\"');
+ int ind2 = nonStdOptions.indexOf('\"',ind+1);
+ if ((ind > -1) && (ind2 > -1)) { // dont tokenize within double quotes
+ String pre = nonStdOptions.substring(0,ind);
+ String quoted = nonStdOptions.substring(ind+1,ind2);
+ String post = nonStdOptions.substring(ind2+1,nonStdOptions.length());
+ tokens.addAll(tokenizeString(pre));
+ tokens.add(quoted);
+ tokens.addAll(tokenizeString(post));
+ } else {
+ tokens.addAll(tokenizeString(nonStdOptions));
}
-
+ String[] args = (String[])tokens.toArray(new String[]{});
+
+
// set the non-standard options in an alternate build config
// (we don't want to lose the settings we already have)
CountingMessageHandler counter
diff --git a/ajde/src/org/aspectj/ajde/ui/StructureModelUtil.java b/ajde/src/org/aspectj/ajde/ui/StructureModelUtil.java
index fcc039e21..d9b1e8c97 100644
--- a/ajde/src/org/aspectj/ajde/ui/StructureModelUtil.java
+++ b/ajde/src/org/aspectj/ajde/ui/StructureModelUtil.java
@@ -14,17 +14,69 @@
package org.aspectj.ajde.ui;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
import org.aspectj.ajde.Ajde;
-import org.aspectj.asm.*;
+import org.aspectj.asm.AsmManager;
+import org.aspectj.asm.IHierarchy;
+import org.aspectj.asm.IProgramElement;
+import org.aspectj.asm.IRelationshipMap;
//import org.aspectj.asm.internal.*;
/**
* Prototype functionality for package view clients.
*/
public class StructureModelUtil {
-
+
+ public static class ModelIncorrectException extends Exception {
+ public ModelIncorrectException(String s) {
+ super(s);
+ }
+ }
+
+ /**
+ * Check the properties of the current model. The parameter string lists properties of the model
+ * that should be correct. If any of the properties are incorrect, a ModelIncorrectException is
+ * thrown.
+ *
+ * @param toCheck comma separated list of name=value pairs that should be found in the ModelInfo object
+ * @throws ModelIncorrectException thrown if any of the name=value pairs in toCheck are not found
+ */
+ public static void checkModel(String toCheck) throws ModelIncorrectException {
+ Properties modelProperties = AsmManager.ModelInfo.summarizeModel().getProperties();
+
+ // Break toCheck into pieces and check each exists
+ StringTokenizer st = new StringTokenizer(toCheck,",=");
+ while (st.hasMoreTokens()) {
+ String key = st.nextToken();
+ String expValue = st.nextToken();
+ boolean expectingZero = false;
+ try {
+ expectingZero = (Integer.parseInt(expValue)==0);
+ } catch (NumberFormatException nfe) {
+ // this is ok as expectingZero will be false
+ }
+ String value = modelProperties.getProperty(key);
+ if (value == null) {
+ if (!expectingZero)
+ throw new ModelIncorrectException("Couldn't find '"+key+"' property for the model");
+ } else if (!value.equals(expValue)) {
+ throw new ModelIncorrectException("Model property '"+key+"' incorrect: Expected "+expValue+" but found "+value);
+ }
+ }
+ }
+
/**
* This method returns a map from affected source lines in a class to
* a List of aspects affecting that line.
diff --git a/ajde/src/org/aspectj/ajde/ui/StructureViewNodeFactory.java b/ajde/src/org/aspectj/ajde/ui/StructureViewNodeFactory.java
index 4f32eedc7..2e6693d56 100644
--- a/ajde/src/org/aspectj/ajde/ui/StructureViewNodeFactory.java
+++ b/ajde/src/org/aspectj/ajde/ui/StructureViewNodeFactory.java
@@ -38,7 +38,9 @@ public abstract class StructureViewNodeFactory {
IStructureViewNode svNode = createDeclaration(node, icon, children);
String nodeHandle = node.getHandleIdentifier();
- if (nodeHandle != null) {
+ // Don't put relationships on fields as they can then appear twice when building the outline -
+ // once under clinit field-set nodes and once under the field declaration.
+ if (nodeHandle != null && !node.getKind().equals(IProgramElement.Kind.FIELD)) {
List relationships = AsmManager.getDefault().getRelationshipMap().get(nodeHandle);
if (relationships != null) {
for (Iterator it = relationships.iterator(); it.hasNext(); ) {
diff --git a/ajde/testsrc/org/aspectj/ajde/AjdeTests.java b/ajde/testsrc/org/aspectj/ajde/AjdeTests.java
index e70619504..a2155fd9b 100644
--- a/ajde/testsrc/org/aspectj/ajde/AjdeTests.java
+++ b/ajde/testsrc/org/aspectj/ajde/AjdeTests.java
@@ -38,6 +38,7 @@ public class AjdeTests extends TestCase {
suite.addTestSuite(BuildCancellingTest.class);
suite.addTestSuite(JarManifestTest.class);
suite.addTestSuite(DuplicateManifestTest.class);
+ suite.addTestSuite(ShowWeaveMessagesTestCase.class);
//$JUnit-END$
return suite;
diff --git a/ajde/testsrc/org/aspectj/ajde/AsmDeclarationsTest.java b/ajde/testsrc/org/aspectj/ajde/AsmDeclarationsTest.java
index d5902854b..bcf70db2e 100644
--- a/ajde/testsrc/org/aspectj/ajde/AsmDeclarationsTest.java
+++ b/ajde/testsrc/org/aspectj/ajde/AsmDeclarationsTest.java
@@ -73,16 +73,16 @@ public class AsmDeclarationsTest extends AjdeTestCase {
assertNotNull(decWarnNode);
assertEquals(decWarnNode.toLabelString(), decWarnMessage);
- String decParentsMessage = "declare parents: Point";
+ String decParentsMessage = "declare parents: implements Serializable";
IProgramElement decParentsNode = model.findElementForSignature(aspect, IProgramElement.Kind.DECLARE_PARENTS, "declare parents");
assertNotNull(decParentsNode);
assertEquals(decParentsNode.toLabelString(), decParentsMessage);
// check the next two relative to this one
int declareIndex = decParentsNode.getParent().getChildren().indexOf(decParentsNode);
- String decParentsPtnMessage = "declare parents: Point+";
- assertEquals(((IProgramElement)aspect.getChildren().get(declareIndex+1)).toLabelString(), decParentsPtnMessage);
- String decParentsTPMessage = "declare parents: <type pattern>";
- assertEquals(((IProgramElement)aspect.getChildren().get(declareIndex+2)).toLabelString(), decParentsTPMessage);
+ String decParentsPtnMessage = "declare parents: extends Observable";
+ assertEquals(decParentsPtnMessage,((IProgramElement)aspect.getChildren().get(declareIndex+1)).toLabelString());
+ String decParentsTPMessage = "declare parents: extends Observable";
+ assertEquals(decParentsTPMessage,((IProgramElement)aspect.getChildren().get(declareIndex+2)).toLabelString());
String decSoftMessage = "declare soft: SizeException";
IProgramElement decSoftNode = model.findElementForSignature(aspect, IProgramElement.Kind.DECLARE_SOFT, "declare soft");
diff --git a/ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java b/ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java
index 407ad1004..64b365276 100644
--- a/ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java
+++ b/ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java
@@ -35,12 +35,13 @@ public class AsmRelationshipsTest extends AjdeTestCase {
IProgramElement dp = manager.getHierarchy().findElementForLabel(
aspect,
IProgramElement.Kind.DECLARE_PARENTS,
- "declare parents: Point");
+ "declare parents: implements Serializable"/*Point"*/);
assertNotNull(dp);
List relations = manager.getRelationshipMap().get(dp);
-
-// assertTrue(false);
+
+ List rels = AsmManager.getDefault().getRelationshipMap().get(dp);
+ assertTrue(rels.size()>0);
// assertTrue(rel.getTargets().size() > 0);
//
diff --git a/ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java b/ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java
index 5d07718e1..007727ea1 100644
--- a/ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java
+++ b/ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java
@@ -217,7 +217,7 @@ public class BuildCancellingTest extends AjdeTestCase {
programmableBPM,
false);
-// Should just be A1 on the disk - uncomment this line to verify that!
+// Should just be A1 on the disk - uncomment this line to verify that! (and uncomment diskContents())
// assertTrue("Incorrect disk contents found",diskContents("A1"));
assertTrue("Should have cancelled after first class weave?:"+programmableBPM.numWovenClassMessages,
@@ -258,7 +258,7 @@ public class BuildCancellingTest extends AjdeTestCase {
programmableBPM,
false);
-// Uncomment this line to verify disk contents
+// Uncomment this line to verify disk contents(and uncomment diskContents())
// assertTrue("Incorrect disk contents found",diskContents("A1 Cl1 A2"));
assertTrue("Should have cancelled after first class weave?:"+programmableBPM.numWovenClassMessages,
@@ -350,43 +350,43 @@ public class BuildCancellingTest extends AjdeTestCase {
}
- private boolean diskContents(String shouldExist) {
- String[] fullList = new String[] { "A1","A2","A3","A4","Cl1","Cl2","Cl3","HW"};
- boolean isOK = true;
- for (int i = 0; i < fullList.length; i++) {
- String file = fullList[i];
- if (shouldExist.indexOf(file)!=-1) {
- // There should be a class file called this
- if (!openFile("bin/"+file+".class").exists()) {
- isOK=false;
- System.out.println("Couldn't find this expected file: "+file+".class");
- }
- } else {
- // There should NOT be a class file called this
- if (openFile("bin/"+file+".class").exists()) {
- isOK=false;
- System.out.println("Found this file when not expected: "+file+".class");
- }
- }
- }
- return isOK;
- }
-
- private int wovenClassesFound() {
- int found = 0;
- File fA1 = openFile("bin/A1.class");
- File fA2 = openFile("bin/A2.class");
- File fA3 = openFile("bin/A3.class");
- File fA4 = openFile("bin/A4.class");
- File fHW = openFile("bin/HW.class");
-
- found+=(fA1.exists()?1:0);
- found+=(fA2.exists()?1:0);
- found+=(fA3.exists()?1:0);
- found+=(fA4.exists()?1:0);
- found+=(fHW.exists()?1:0);
- return found;
- }
+// private boolean diskContents(String shouldExist) {
+// String[] fullList = new String[] { "A1","A2","A3","A4","Cl1","Cl2","Cl3","HW"};
+// boolean isOK = true;
+// for (int i = 0; i < fullList.length; i++) {
+// String file = fullList[i];
+// if (shouldExist.indexOf(file)!=-1) {
+// // There should be a class file called this
+// if (!openFile("bin/"+file+".class").exists()) {
+// isOK=false;
+// System.out.println("Couldn't find this expected file: "+file+".class");
+// }
+// } else {
+// // There should NOT be a class file called this
+// if (openFile("bin/"+file+".class").exists()) {
+// isOK=false;
+// System.out.println("Found this file when not expected: "+file+".class");
+// }
+// }
+// }
+// return isOK;
+// }
+//
+// private int wovenClassesFound() {
+// int found = 0;
+// File fA1 = openFile("bin/A1.class");
+// File fA2 = openFile("bin/A2.class");
+// File fA3 = openFile("bin/A3.class");
+// File fA4 = openFile("bin/A4.class");
+// File fHW = openFile("bin/HW.class");
+//
+// found+=(fA1.exists()?1:0);
+// found+=(fA2.exists()?1:0);
+// found+=(fA3.exists()?1:0);
+// found+=(fA4.exists()?1:0);
+// found+=(fHW.exists()?1:0);
+// return found;
+// }
private boolean checkFor(String what) {
diff --git a/ajde/testsrc/org/aspectj/ajde/ShowWeaveMessagesTestCase.java b/ajde/testsrc/org/aspectj/ajde/ShowWeaveMessagesTestCase.java
new file mode 100644
index 000000000..8127ad3cb
--- /dev/null
+++ b/ajde/testsrc/org/aspectj/ajde/ShowWeaveMessagesTestCase.java
@@ -0,0 +1,376 @@
+/* *******************************************************************
+ * Copyright (c) 2004 Contributors.
+ * 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 version
+ * ******************************************************************/
+
+package org.aspectj.ajde;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.aspectj.ajde.internal.CompilerAdapter;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.util.FileUtil;
+
+/**
+ * Weaving messages are complicated things. There are multiple places where weaving
+ * takes place and the places vary depending on whether we are doing a binary weave or
+ * going from source. All places that output weaving messages are tagged:
+ * // TAG: WeavingMessage
+ * so you can easily find them!
+ *
+ * Advice is the simplest to deal with as that is advice weaving is always done in the weaver.
+ *
+ * Next is intertype declarations. These are also always done in the weaver but in the case
+ * of a binary weave we don't know the originating source line for the ITD.
+ *
+ * Finally, declares.
+ * Declare Parents: extends Can only be done when going from source, if attempted by a
+ * binary weave then an error message (compiler limitation) is
+ * produced.
+ * Declare Parents: implements Is (currently!) done at both compile time and weave time.
+ * If going from source then the message is produced by the
+ * code in the compiler. if going from binary then the message
+ * is produced by the weaver.
+ * Declare Soft: Comes out with 'advice' as a special kind of advice: softener advice
+ *
+ *
+ * Q: Where are the messages turned on/off?
+ * A: It is a bit messy. See BuildArgParser.genBuildConfig(). Basically that method is the first time
+ * we parse the option set. Whether weaving messages are on or off is stored in the build config.
+ * As soon as we have parser the options and determined that weave messages are on, we grab the
+ * top level message handler and tell it not to ignore WeaveInfo messages.
+ *
+ *
+ * TODO - Other forms of declare? Do they need messages? e.g. declare precedence *
+ */
+public class ShowWeaveMessagesTestCase extends AjdeTestCase {
+
+ static {
+ // Switch this to true for a single iteration if you want to reconstruct the
+ // 'expected weaving messages' files.
+ regenerate = false;
+ }
+
+ private static boolean regenerate;
+ private CompilerAdapter compilerAdapter;
+ public static final String PROJECT_DIR = "WeaveInfoMessagesTest";
+
+ public static final String binDir = "bin";
+ public static final String expectedResultsDir = "expected";
+
+
+ public ShowWeaveMessagesTestCase(String arg0) {
+ super(arg0);
+ }
+
+ /*
+ * Ensure the output directory in clean
+ */
+ protected void setUp() throws Exception {
+ super.setUp(PROJECT_DIR);
+ FileUtil.deleteContents(openFile(binDir));
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ FileUtil.deleteContents(openFile(binDir));
+ }
+
+
+
+
+ /**
+ * Weave all the possible kinds of advice and verify the messages that come out.
+ */
+ public void testWeaveMessagesAdvice() {
+ System.out.println("testWeaveMessagesAdvice: Building with One.lst");
+ compilerAdapter = new CompilerAdapter();
+ compilerAdapter.showInfoMessages(true);
+ compilerAdapter.compile((String) openFile("One.lst").getAbsolutePath(),new BPM(),false);
+ verifyWeavingMessages("advice",true);
+ }
+
+
+
+
+ /**
+ * Weave field and method ITDs and check the weave messages that come out.
+ */
+ public void testWeaveMessagesITD() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesITD: Building with Two.lst");
+ compilerAdapter = new CompilerAdapter();
+ compilerAdapter.showInfoMessages(true);
+ compilerAdapter.compile((String) openFile("Two.lst").getAbsolutePath(),new BPM(),false);
+ verifyWeavingMessages("itd",true);
+ }
+
+
+ /**
+ * Weave "declare parents: implements" and check the weave messages that come out.
+ */
+ public void testWeaveMessagesDeclare() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesDeclare: Building with Three.lst");
+ compilerAdapter = new CompilerAdapter();
+ compilerAdapter.showInfoMessages(true);
+ compilerAdapter.compile((String) openFile("Three.lst").getAbsolutePath(),new BPM(),false);
+ verifyWeavingMessages("declare1",true);
+ }
+
+ /**
+ * Weave "declare parents: extends" and check the weave messages that come out.
+ * Can't do equivalent binary test - as can't do extends in binary.
+ */
+ public void testWeaveMessagesDeclareExtends() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesDeclareExtends: Building with Four.lst");
+ compilerAdapter = new CompilerAdapter();
+ compilerAdapter.showInfoMessages(true);
+ compilerAdapter.compile((String) openFile("Four.lst").getAbsolutePath(),new BPM(),false);
+ verifyWeavingMessages("declare.extends",true);
+ }
+
+ /**
+ * Weave "declare soft: type: pointcut" and check the weave messages that come out.
+ */
+ public void testWeaveMessagesDeclareSoft() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesDeclareSoft: Building with Five.lst");
+ compilerAdapter = new CompilerAdapter();
+ compilerAdapter.showInfoMessages(true);
+ compilerAdapter.compile((String) openFile("Five.lst").getAbsolutePath(),new BPM(),false);
+ verifyWeavingMessages("declare.soft",true);
+ }
+
+
+ // BINARY WEAVING TESTS
+
+ /**
+ * Binary weave variant of the advice weaving test above - to check messages are ok for
+ * binary weave. Unlike the source level weave, in this test we are using an aspect on
+ * the aspectpath - which means it has already had its necessary parts woven - so the list
+ * of weaving messages we expect is less.
+ */
+ public void testWeaveMessagesBinaryAdvice() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesBinaryAdvice: Simple.jar + AspectAdvice.jar");
+ Set inpath = new HashSet();
+ inpath.add(openFile("Simple.jar"));
+ ideManager.getProjectProperties().setInpath(inpath);
+ Set aspectpath = new HashSet();
+ aspectpath.add(openFile("AspectAdvice.jar"));
+ ideManager.getProjectProperties().setAspectPath(aspectpath);
+ assertTrue("Build failed", doSynchronousBuild("Empty.lst"));
+ List l = ideManager.getCompilationSourceLineTasks();
+ verifyWeavingMessages("advice.binary",true);
+ }
+
+ public void testWeaveMessagesBinaryITD() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesBinaryITD: Simple.jar + AspectITD.jar");
+ Set inpath = new HashSet();
+ inpath.add(openFile("Simple.jar"));
+ ideManager.getProjectProperties().setInpath(inpath);
+ Set aspectpath = new HashSet();
+ aspectpath.add(openFile("AspectITD.jar"));
+ ideManager.getProjectProperties().setAspectPath(aspectpath);
+ assertTrue("Build failed", doSynchronousBuild("Empty.lst"));
+ List l = ideManager.getCompilationSourceLineTasks();
+ verifyWeavingMessages("itd",false);
+ }
+
+
+ public void testWeaveMessagesBinaryDeclare() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesBinaryDeclare: Simple.jar + AspectDeclare.jar");
+ Set inpath = new HashSet();
+ inpath.add(openFile("Simple.jar"));
+ ideManager.getProjectProperties().setInpath(inpath);
+ Set aspectpath = new HashSet();
+ aspectpath.add(openFile("AspectDeclare.jar"));
+ ideManager.getProjectProperties().setAspectPath(aspectpath);
+ assertTrue("Build failed", doSynchronousBuild("Empty.lst"));
+ verifyWeavingMessages("declare1",false);
+ }
+
+ /**
+ * Weave "declare soft: type: pointcut" and check the weave messages that come out.
+ */
+ public void testWeaveMessagesBinaryDeclareSoft() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesBinaryDeclareSoft: Simple.jar + AspectDeclareSoft.jar");
+ Set inpath = new HashSet();
+ inpath.add(openFile("Simple.jar"));
+ ideManager.getProjectProperties().setInpath(inpath);
+ Set aspectpath = new HashSet();
+ aspectpath.add(openFile("AspectDeclareSoft.jar"));
+ ideManager.getProjectProperties().setAspectPath(aspectpath);
+ assertTrue("Build failed", doSynchronousBuild("Empty.lst"));
+ verifyWeavingMessages("declare.soft",false);
+ }
+
+
+
+
+ // BINARY WEAVING WHEN WE'VE LOST THE SOURCE POINTERS
+
+ public void testWeaveMessagesBinaryAdviceNoDebugInfo() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesBinaryAdvice: Simple.jar + AspectAdvice.jar");
+ Set inpath = new HashSet();
+ inpath.add(openFile("Simple_nodebug.jar"));
+ ideManager.getProjectProperties().setInpath(inpath);
+ Set aspectpath = new HashSet();
+ aspectpath.add(openFile("AspectAdvice_nodebug.jar"));
+ ideManager.getProjectProperties().setAspectPath(aspectpath);
+ assertTrue("Build failed", doSynchronousBuild("Empty.lst"));
+ List l = ideManager.getCompilationSourceLineTasks();
+ verifyWeavingMessages("advice.binary.nodebug",true);
+ }
+
+ public void testWeaveMessagesBinaryITDNoDebugInfo() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesBinaryITD: Simple.jar + AspectITD.jar");
+ Set inpath = new HashSet();
+ inpath.add(openFile("Simple_nodebug.jar"));
+ ideManager.getProjectProperties().setInpath(inpath);
+ Set aspectpath = new HashSet();
+ aspectpath.add(openFile("AspectITD_nodebug.jar"));
+ ideManager.getProjectProperties().setAspectPath(aspectpath);
+ assertTrue("Build failed", doSynchronousBuild("Empty.lst"));
+ List l = ideManager.getCompilationSourceLineTasks();
+ verifyWeavingMessages("itd.nodebug",true);
+ }
+
+ public void testWeaveMessagesBinaryDeclareNoDebugInfo() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesBinaryDeclareNoDebugInfo: Simple.jar + AspectDeclare.jar");
+ Set inpath = new HashSet();
+ inpath.add(openFile("Simple_nodebug.jar"));
+ ideManager.getProjectProperties().setInpath(inpath);
+ Set aspectpath = new HashSet();
+ aspectpath.add(openFile("AspectDeclare_nodebug.jar"));
+ ideManager.getProjectProperties().setAspectPath(aspectpath);
+ assertTrue("Build failed", doSynchronousBuild("Empty.lst"));
+ verifyWeavingMessages("declare1.nodebug",true);
+ }
+
+ /**
+ * Weave "declare soft: type: pointcut" and check the weave messages that come out.
+ */
+ public void testWeaveMessagesBinaryDeclareSoftNoDebugInfo() {
+ System.out.println("\n\n\n\n\n\ntestWeaveMessagesBinaryDeclareSoftNoDebugInfo: Simple.jar + AspectDeclareSoft.jar");
+ Set inpath = new HashSet();
+ inpath.add(openFile("Simple_nodebug.jar"));
+ ideManager.getProjectProperties().setInpath(inpath);
+ Set aspectpath = new HashSet();
+ aspectpath.add(openFile("AspectDeclareSoft_nodebug.jar"));
+ ideManager.getProjectProperties().setAspectPath(aspectpath);
+ assertTrue("Build failed", doSynchronousBuild("Empty.lst"));
+ verifyWeavingMessages("declare.soft.nodebug",true);
+ }
+
+
+ private class BPM implements BuildProgressMonitor {
+ public void start(String configFile) {}
+
+ public void setProgressText(String text) {}
+
+ public void setProgressBarVal(int newVal) { }
+
+ public void incrementProgressBarVal() {}
+
+ public void setProgressBarMax(int maxVal) { }
+
+ public int getProgressBarMax() {
+ return 0;
+ }
+
+ public void finish() {}
+
+ }
+
+
+ public void verifyWeavingMessages(String testid,boolean source) {
+ File expectedF = openFile(expectedResultsDir+File.separator+testid+".txt");
+ if (regenerate && source) {
+ // Create the file
+ saveWeaveMessages(expectedF);
+ } else {
+ // Verify the file matches what we have
+ compareWeaveMessages(expectedF);
+ }
+ }
+
+ /**
+ * Compare weaving messages with what is in the file
+ */
+ private void compareWeaveMessages(File f) {
+ List fileContents = new ArrayList();
+ BufferedReader fr;
+ try {
+ // Load the file in
+ fr = new BufferedReader(new FileReader(f));
+ String line = null;
+ while ((line=fr.readLine())!=null) fileContents.add(line);
+
+ // See if the messages match
+ int msgCount = 0;
+ List l = ideManager.getCompilationSourceLineTasks();
+ for (Iterator iter = l.iterator(); iter.hasNext();) {
+ IMessage msg = ((NullIdeTaskListManager.SourceLineTask) iter.next()).message;
+ if (msg.getKind().equals(IMessage.WEAVEINFO)) {
+ if (!fileContents.contains(msg.getMessage())) {
+ fail("Could not find message '"+msg.getMessage()+"' in the expected results\n"+
+ stringify(fileContents));
+ } else {
+ fileContents.remove(msg.getMessage());
+ }
+ msgCount++;
+ }
+ }
+ assertTrue("Didn't get these expected messages: "+fileContents,fileContents.size()==0);
+ System.out.println("Successfully verified "+msgCount+" weaving messages");
+ } catch (Exception e) {
+ fail("Unexpected exception saving weaving messages:"+e);
+ }
+ }
+
+ private String stringify(List l) {
+ StringBuffer result = new StringBuffer();
+ for (Iterator iter = l.iterator(); iter.hasNext();) {
+ String str = (String) iter.next();
+ result.append(str);result.append("\n");
+ }
+ return result.toString();
+ }
+
+ /**
+ * Store the weaving messages in the specified file.
+ */
+ private void saveWeaveMessages(File f) {
+ System.out.println("Saving weave messages into "+f.getName());
+ FileWriter fw;
+ try {
+ fw = new FileWriter(f);
+ List l = ideManager.getCompilationSourceLineTasks();
+ for (Iterator iter = l.iterator(); iter.hasNext();) {
+ IMessage msg = ((NullIdeTaskListManager.SourceLineTask) iter.next()).message;
+ if (msg.getKind().equals(IMessage.WEAVEINFO)) {
+ fw.write(msg.getMessage()+"\n");
+ }
+ }
+ fw.close();
+ } catch (Exception e) {
+ fail("Unexpected exception saving weaving messages:"+e);
+ }
+ }
+
+
+
+}
diff --git a/asm/src/org/aspectj/asm/AsmManager.java b/asm/src/org/aspectj/asm/AsmManager.java
index 91a166af6..0177bb4c2 100644
--- a/asm/src/org/aspectj/asm/AsmManager.java
+++ b/asm/src/org/aspectj/asm/AsmManager.java
@@ -37,7 +37,25 @@ public class AsmManager {
protected IHierarchy hierarchy;
private List structureListeners = new ArrayList();
private IRelationshipMap mapper;
+
+
+ public static boolean attemptIncrementalModelRepairs = false;
+// for debugging ...
+// static {
+// setReporting("c:/model.nfo",true,true,true,true);
+// }
+
+ // For offline debugging, you can now ask for the AsmManager to
+ // dump the model - see the method setReporting()
+ private static boolean dumpModel = false;
+ private static boolean dumpRelationships = false;
+ private static boolean dumpDeltaProcessing = false;
+ private static String dumpFilename = "";
+ private static boolean reporting = false;
+
+
+
protected AsmManager() {
hierarchy = new AspectJElementHierarchy();
// List relationships = new ArrayList();
@@ -144,11 +162,17 @@ public class AsmManager {
public void writeStructureModel(String configFilePath) {
try {
String filePath = genExternFilePath(configFilePath);
- ObjectOutputStream s = new ObjectOutputStream(new FileOutputStream(filePath));
- s.writeObject(hierarchy);
+ FileOutputStream fos = new FileOutputStream(filePath);
+ ObjectOutputStream s = new ObjectOutputStream(fos);
+ s.writeObject(hierarchy); // Store the program element tree
+ s.writeObject(mapper); // Store the relationships
s.flush();
+ fos.flush();
+ fos.close();
+ s.close();
} catch (Exception e) {
- // ignore
+ // System.err.println("AsmManager: Unable to write structure model: "+configFilePath+" because of:");
+ // e.printStackTrace();
}
}
@@ -157,6 +181,7 @@ public class AsmManager {
* @param configFilePath path to an ".lst" file
*/
public void readStructureModel(String configFilePath) {
+ boolean hierarchyReadOK = false;
try {
if (configFilePath == null) {
hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
@@ -165,9 +190,23 @@ public class AsmManager {
FileInputStream in = new FileInputStream(filePath);
ObjectInputStream s = new ObjectInputStream(in);
hierarchy = (AspectJElementHierarchy)s.readObject();
+ hierarchyReadOK = true;
+ mapper = (RelationshipMap)s.readObject();
+ ((RelationshipMap)mapper).setHierarchy(hierarchy);
}
+ } catch (FileNotFoundException fnfe) {
+ // That is OK
+ hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
+ } catch (EOFException eofe) {
+ // Might be an old format sym file that is missing its relationships
+ if (!hierarchyReadOK) {
+ System.err.println("AsmManager: Unable to read structure model: "+configFilePath+" because of:");
+ eofe.printStackTrace();
+ hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
+ }
} catch (Exception e) {
- //System.err.println("AJDE Message: could not read structure model: " + e);
+ // System.err.println("AsmManager: Unable to read structure model: "+configFilePath+" because of:");
+ // e.printStackTrace();
hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
} finally {
notifyListeners();
@@ -298,7 +337,444 @@ public class AsmManager {
}
return ret;
}
- };
+ }
+
+ public static void setReporting(String filename,boolean dModel,boolean dRels,boolean dDeltaProcessing,boolean deletefile) {
+ reporting = true;
+ dumpModel = dModel;
+ dumpRelationships = dRels;
+ dumpDeltaProcessing = dDeltaProcessing;
+ if (deletefile) new File(filename).delete();
+ dumpFilename = filename;
+ }
+
+ public static boolean isReporting() {
+ return reporting;
+ }
+
+
+
+ public void reportModelInfo(String reasonForReport) {
+ if (!dumpModel && !dumpRelationships) return;
+ try {
+ FileWriter fw = new FileWriter(dumpFilename,true);
+ BufferedWriter bw = new BufferedWriter(fw);
+ if (dumpModel) {
+ bw.write("=== MODEL STATUS REPORT ========= "+reasonForReport+"\n");
+ dumptree(bw,AsmManager.getDefault().getHierarchy().getRoot(),0);
+
+ bw.write("=== END OF MODEL REPORT =========\n");
+ }
+ if (dumpRelationships) {
+ bw.write("=== RELATIONSHIPS REPORT ========= "+reasonForReport+"\n");
+ dumprels(bw);
+ bw.write("=== END OF RELATIONSHIPS REPORT ==\n");
+ }
+ Properties p = ModelInfo.summarizeModel().getProperties();
+ Enumeration pkeyenum = p.keys();
+ bw.write("=== Properties of the model and relationships map =====\n");
+ while (pkeyenum.hasMoreElements()) {
+ String pkey = (String)pkeyenum.nextElement();
+ bw.write(pkey+"="+p.getProperty(pkey)+"\n");
+ }
+ bw.flush();
+ fw.close();
+ } catch (IOException e) {
+ System.err.println("InternalError: Unable to report model information:");
+ e.printStackTrace();
+ }
+ }
+
+
+ private void dumptree(Writer w,IProgramElement node,int indent) throws IOException {
+ for (int i =0 ;i<indent;i++) w.write(" ");
+ w.write(node+" ["+(node==null?"null":node.getKind().toString())+"]\n");
+ if (node!=null)
+ for (Iterator i = node.getChildren().iterator();i.hasNext();) {
+ dumptree(w,(IProgramElement)i.next(),indent+2);
+ }
+ }
+
+ private void dumprels(Writer w) throws IOException {
+ IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
+ int ctr = 1;
+ Set entries = irm.getEntries();
+ for (Iterator iter = entries.iterator(); iter.hasNext();) {
+ String hid = (String) iter.next();
+ List rels = irm.get(hid);
+ for (Iterator iterator = rels.iterator(); iterator.hasNext();) {
+ IRelationship ir = (IRelationship) iterator.next();
+ List targets = ir.getTargets();
+ for (Iterator iterator2 = targets.iterator();
+ iterator2.hasNext();
+ ) {
+ String thid = (String) iterator2.next();
+ w.write("Hid:"+(ctr++)+":(targets="+targets.size()+") "+hid+" ("+ir.getName()+") "+thid+"\n");
+ }
+ }
+ }
+ }
+
+ //===================== DELTA PROCESSING CODE ============== start ==========//
+
+ // This code is *SLOW* but it isnt worth fixing until we address the
+ // bugs in binary weaving.
+ public void fixupStructureModel(Writer fw,List filesToBeCompiled,Set files_added,Set files_deleted) throws IOException {
+ // Three kinds of things to worry about:
+ // 1. New files have been added since the last compile
+ // 2. Files have been deleted since the last compile
+ // 3. Files have 'changed' since the last compile (really just those in config.getFiles())
+
+ // List files = config.getFiles();
+ IHierarchy model = AsmManager.getDefault().getHierarchy();
+
+ boolean modelModified = false;
+ // Files to delete are: those to be compiled + those that have been deleted
+
+ Set filesToRemoveFromStructureModel = new HashSet(filesToBeCompiled);
+ filesToRemoveFromStructureModel.addAll(files_deleted);
+
+ for (Iterator iter = filesToRemoveFromStructureModel.iterator(); iter.hasNext();) {
+ File fileForCompilation = (File) iter.next();
+ String correctedPath = AsmManager.getDefault().getCanonicalFilePath(fileForCompilation);
+ IProgramElement progElem = (IProgramElement)model.findInFileMap(correctedPath);
+ if (progElem!=null) {
+ // Found it, let's remove it
+ if (dumpDeltaProcessing) {
+ fw.write("Deleting "+progElem+" node for file "+fileForCompilation+"\n");
+ }
+ removeNode(progElem);
+ verifyAssumption(
+ model.removeFromFileMap(correctedPath.toString()),
+ "Whilst repairing model, couldn't remove entry for file: "+correctedPath.toString()+" from the filemap");
+ modelModified = true;
+ }
+ }
+ if (modelModified) {
+ model.flushTypeMap();
+ model.flushHandleMap();
+ }
+ }
+
+ public void processDelta(List filesToBeCompiled,Set files_added,Set files_deleted) {
+
+ try {
+ Writer fw = null;
+
+ // Are we recording this ?
+ if (dumpDeltaProcessing) {
+ FileWriter filew = new FileWriter(dumpFilename,true);
+ fw = new BufferedWriter(filew);
+ fw.write("=== Processing delta changes for the model ===\n");
+ fw.write("Files for compilation:#"+filesToBeCompiled.size()+":"+filesToBeCompiled+"\n");
+ fw.write("Files added :#"+files_added.size()+":"+files_added+"\n");
+ fw.write("Files deleted :#"+files_deleted.size()+":"+files_deleted+"\n");
+ }
+
+ long stime = System.currentTimeMillis();
+
+ fixupStructureModel(fw,filesToBeCompiled,files_added,files_deleted);
+
+ long etime1 = System.currentTimeMillis(); // etime1-stime = time to fix up the model
+
+ IHierarchy model = AsmManager.getDefault().getHierarchy();
+
+ // Some of this code relies on the fact that relationships are always in pairs, so you know
+ // if you are the target of a relationship because you are also the source of a relationship
+ // This seems a valid assumption for now...
+
+ //TODO Speed this code up by making this assumption:
+ // the only piece of the handle that is interesting is the file name. We are working at file granularity, if the
+ // file does not exist (i.e. its not in the filemap) then any handle inside that file cannot exist.
+ if (dumpDeltaProcessing) fw.write("Repairing relationships map:\n");
+
+ // Now sort out the relationships map
+ IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
+ Set sourcesToRemove = new HashSet();
+ Set nonExistingHandles = new HashSet(); // Cache of handles that we *know* are invalid
+ int srchandlecounter = 0;
+ int tgthandlecounter = 0;
+
+ // Iterate over the source handles in the relationships map
+ Set keyset = irm.getEntries(); // These are source handles
+ for (Iterator keyiter = keyset.iterator(); keyiter.hasNext();) {
+ String hid = (String) keyiter.next();
+ srchandlecounter++;
+
+ // Do we already know this handle points to nowhere?
+ if (nonExistingHandles.contains(hid)) {
+ sourcesToRemove.add(hid);
+ } else {
+ // We better check if it actually exists
+ IProgramElement existingElement = model.getElement(hid);
+ if (dumpDeltaProcessing) fw.write("Looking for handle ["+hid+"] in model, found: "+existingElement+"\n");
+
+ // Did we find it?
+ if (existingElement == null) {
+ // No, so delete this relationship
+ sourcesToRemove.add(hid);
+ nonExistingHandles.add(hid); // Speed up a bit you swine
+ } else {
+ // Ok, so the source is valid, what about the targets?
+ List relationships = irm.get(hid);
+ List relationshipsToRemove = new ArrayList();
+ // Iterate through the relationships against this source handle
+ for (Iterator reliter = relationships.iterator();reliter.hasNext();) {
+ IRelationship rel = (IRelationship) reliter.next();
+ List targets = rel.getTargets();
+ List targetsToRemove = new ArrayList();
+
+ // Iterate through the targets for this relationship
+ for (Iterator targetIter = targets.iterator();targetIter.hasNext();) {
+ String targethid = (String) targetIter.next();
+ tgthandlecounter++;
+ // Do we already know it doesn't exist?
+ if (nonExistingHandles.contains(targethid)) {
+ if (dumpDeltaProcessing) fw.write("Target handle ["+targethid+"] for srchid["+hid+"]rel["+rel.getName()+"] does not exist\n");
+ targetsToRemove.add(targethid);
+ } else {
+ // We better check
+ IProgramElement existingTarget = model.getElement(targethid);
+ if (existingTarget == null) {
+ if (dumpDeltaProcessing) fw.write("Target handle ["+targethid+"] for srchid["+hid+"]rel["+rel.getName()+"] does not exist\n");
+ targetsToRemove.add(targethid);
+ nonExistingHandles.add(targethid);
+ }
+ }
+ }
+
+ // Do we have some targets that need removing?
+ if (targetsToRemove.size()!=0) {
+ // Are we removing *all* of the targets for this relationship (i.e. removing the relationship)
+ if (targetsToRemove.size()==targets.size()) {
+ if (dumpDeltaProcessing) fw.write("No targets remain for srchid["+hid+"] rel["+rel.getName()+"]: removing it\n");
+ relationshipsToRemove.add(rel);
+ } else {
+ // Remove all the targets that are no longer valid
+ for (Iterator targsIter = targetsToRemove.iterator();targsIter.hasNext();) {
+ String togo = (String) targsIter.next();
+ targets.remove(togo);
+ }
+ // Should have already been caught above, but lets double check ...
+ if (targets.size()==0) {
+ if (dumpDeltaProcessing) fw.write("No targets remain for srchid["+hid+"] rel["+rel.getName()+"]: removing it\n");
+ relationshipsToRemove.add(rel); // TODO Should only remove this relationship for the srchid?
+ }
+ }
+ }
+ }
+ // Now, were any relationships emptied during that processing and so need removing for this source handle
+ if (relationshipsToRemove.size()>0) {
+ // Are we removing *all* of the relationships for this source handle?
+ if (relationshipsToRemove.size() == relationships.size()) {
+ // We know they are all going to go, so just delete the source handle.
+ sourcesToRemove.add(hid);
+ } else {
+ for (int i = 0 ;i<relationshipsToRemove.size();i++) {
+ IRelationship irel = (IRelationship)relationshipsToRemove.get(i);
+ verifyAssumption(irm.remove(hid,irel),"Failed to remove relationship "+irel.getName()+" for shid "+hid);
+ }
+ List rels = irm.get(hid);
+ if (rels==null || rels.size()==0) sourcesToRemove.add(hid);
+ }
+ }
+ }
+ }
+ }
+ // Remove sources that have no valid relationships any more
+ for (Iterator srciter = sourcesToRemove.iterator(); srciter.hasNext();) {
+ String hid = (String) srciter.next();
+ irm.removeAll(hid);
+ IProgramElement ipe = model.getElement(hid);
+ if (ipe!=null) {
+ // If the relationship was hanging off a 'code' node, delete it.
+ if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
+ removeSingleNode(ipe);
+ }
+ }
+ }
+ long etime2 = System.currentTimeMillis(); // etime2-stime = time to repair the relationship map
+ if (dumpDeltaProcessing) {
+ fw.write("===== Delta Processing timing ==========\n");
+ fw.write("Hierarchy="+(etime1-stime)+"ms Relationshipmap="+(etime2-etime1)+"ms\n");
+ fw.write("===== Traversal ========================\n");
+ fw.write("Source handles processed="+srchandlecounter+"\n");
+ fw.write("Target handles processed="+tgthandlecounter+"\n");
+ fw.write("========================================\n");
+ fw.flush();fw.close();
+ }
+ reportModelInfo("After delta processing");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Removes a specified program element from the structure model.
+ * We go to the parent of the program element, ask for all its children
+ * and remove the node we want to delete from the list of children.
+ */
+ private void removeSingleNode(IProgramElement progElem) {
+ verifyAssumption(progElem!=null);
+ boolean deleteOK = false;
+ IProgramElement parent = progElem.getParent();
+ List kids = parent.getChildren();
+ for (int i =0 ;i<kids.size();i++) {
+ if (kids.get(i).equals(progElem)) {
+ kids.remove(i);
+ deleteOK=true;
+ break;
+ }
+ }
+ verifyAssumption(deleteOK);
+ }
+
+
+ /**
+ * Removes a specified program element from the structure model.
+ * Two processing stages:
+ * <p>First: We go to the parent of the program element, ask for all its children
+ * and remove the node we want to delete from the list of children.
+ * <p>Second:We check if that parent has any other children. If it has no other
+ * children and it is either a CODE node or a PACKAGE node, we delete it too.
+ */
+ private void removeNode(IProgramElement progElem) {
+
+ StringBuffer flightrecorder = new StringBuffer();
+ try {
+ flightrecorder.append("In removeNode, about to chuck away: "+progElem+"\n");
+
+ verifyAssumption(progElem!=null);
+ boolean deleteOK = false;
+ IProgramElement parent = progElem.getParent();
+ flightrecorder.append("Parent of it is "+parent+"\n");
+ List kids = parent.getChildren();
+ flightrecorder.append("Which has "+kids.size()+" kids\n");
+ for (int i =0 ;i<kids.size();i++) {
+ flightrecorder.append("Comparing with "+kids.get(i)+"\n");
+ if (kids.get(i).equals(progElem)) {
+ kids.remove(i);
+ flightrecorder.append("Removing it\n");
+ deleteOK=true;
+ break;
+ }
+ }
+ verifyAssumption(deleteOK,flightrecorder.toString());
+ // Are there any kids left for this node?
+ if (parent.getChildren().size()==0 && parent.getParent()!=null &&
+ (parent.getKind().equals(IProgramElement.Kind.CODE) ||
+ parent.getKind().equals(IProgramElement.Kind.PACKAGE))) {
+ // This node is on its own, we should trim it too *as long as its not a structural node* which we currently check by making sure its a code node
+ // We should trim if it
+ // System.err.println("Deleting parent:"+parent);
+ removeNode(parent);
+ }
+ } catch (NullPointerException npe ){
+ // Occurred when commenting out other 2 ras classes in wsif?? reproducable?
+ System.err.println(flightrecorder.toString());
+ npe.printStackTrace();
+ }
+ }
+
+
+ public static void verifyAssumption(boolean b,String info) {
+ if (!b) {
+ System.err.println("=========== ASSERTION IS NOT TRUE =========v");
+ System.err.println(info);
+ Thread.dumpStack();
+ System.err.println("=========== ASSERTION IS NOT TRUE =========^");
+ throw new RuntimeException("Assertion is false");
+ }
+ }
+
+ public static void verifyAssumption(boolean b) {
+ if (!b) {
+ Thread.dumpStack();
+ throw new RuntimeException("Assertion is false");
+ }
+ }
+
+
+ //===================== DELTA PROCESSING CODE ============== end ==========//
+
+ /**
+ * A ModelInfo object captures basic information about the structure model.
+ * It is used for testing and producing debug info.
+ */
+ public static class ModelInfo {
+ private Hashtable nodeTypeCount = new Hashtable();
+ private Properties extraProperties = new Properties();
+
+ private ModelInfo(IHierarchy hierarchy,IRelationshipMap relationshipMap) {
+ IProgramElement ipe = hierarchy.getRoot();
+ walkModel(ipe);
+ recordStat("FileMapSize",
+ new Integer(hierarchy.getFileMapEntrySet().size()).toString());
+ recordStat("RelationshipMapSize",
+ new Integer(relationshipMap.getEntries().size()).toString());
+ }
+
+ private void walkModel(IProgramElement ipe) {
+ countNode(ipe);
+ List kids = ipe.getChildren();
+ for (Iterator iter = kids.iterator(); iter.hasNext();) {
+ IProgramElement nextElement = (IProgramElement) iter.next();
+ walkModel(nextElement);
+ }
+ }
+
+ private void countNode(IProgramElement ipe) {
+ String node = ipe.getKind().toString();
+ Integer ctr = (Integer)nodeTypeCount.get(node);
+ if (ctr==null) {
+ nodeTypeCount.put(node,new Integer(1));
+ } else {
+ ctr = new Integer(ctr.intValue()+1);
+ nodeTypeCount.put(node,ctr);
+ }
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Model node summary:\n");
+ Enumeration nodeKeys = nodeTypeCount.keys();
+ while (nodeKeys.hasMoreElements()) {
+ String key = (String)nodeKeys.nextElement();
+ Integer ct = (Integer)nodeTypeCount.get(key);
+ sb.append(key+"="+ct+"\n");
+ }
+ sb.append("Model stats:\n");
+ Enumeration ks = extraProperties.keys();
+ while (ks.hasMoreElements()) {
+ String k = (String)ks.nextElement();
+ String v = extraProperties.getProperty(k);
+ sb.append(k+"="+v+"\n");
+ }
+ return sb.toString();
+ }
+
+ public Properties getProperties() {
+ Properties p = new Properties();
+ Enumeration nodeKeys = nodeTypeCount.keys();
+ while (nodeKeys.hasMoreElements()) {
+ String key = (String)nodeKeys.nextElement();
+ Integer ct = (Integer)nodeTypeCount.get(key);
+ p.setProperty(key,ct.toString());
+ }
+ p.putAll(extraProperties);
+ return p;
+ }
+
+ public void recordStat(String string, String string2) {
+ extraProperties.setProperty(string,string2);
+ }
+
+ public static ModelInfo summarizeModel() {
+ return new ModelInfo(AsmManager.getDefault().getHierarchy(),
+ AsmManager.getDefault().getRelationshipMap());
+ }
+ }
}
diff --git a/asm/src/org/aspectj/asm/IHierarchy.java b/asm/src/org/aspectj/asm/IHierarchy.java
index 793b01420..95b00996b 100644
--- a/asm/src/org/aspectj/asm/IHierarchy.java
+++ b/asm/src/org/aspectj/asm/IHierarchy.java
@@ -31,6 +31,7 @@ public interface IHierarchy extends Serializable {
public IProgramElement getRoot();
public void setRoot(IProgramElement root);
public void addToFileMap(Object key, Object value);
+ public boolean removeFromFileMap(Object key);
public void setFileMap(HashMap fileMap);
public Object findInFileMap(Object key);
public Set getFileMapEntrySet();
@@ -94,4 +95,8 @@ public interface IHierarchy extends Serializable {
public String getConfigFile();
public void setConfigFile(String configFile);
+
+ public void flushTypeMap();
+
+ public void flushHandleMap();
} \ No newline at end of file
diff --git a/asm/src/org/aspectj/asm/IProgramElement.java b/asm/src/org/aspectj/asm/IProgramElement.java
index 83374889a..476b6aaa0 100644
--- a/asm/src/org/aspectj/asm/IProgramElement.java
+++ b/asm/src/org/aspectj/asm/IProgramElement.java
@@ -28,6 +28,23 @@ public interface IProgramElement extends Serializable {
public void setChildren(List children);
public void addChild(IProgramElement child);
+
+ // Extra stuff
+ // Could be just a string but may prove more useful as an object in the long run ...
+ public static class ExtraInformation implements Serializable {
+ private String extraInfo;
+ public ExtraInformation() { extraInfo = "";}
+
+ public void setExtraAdviceInformation(String string) {extraInfo = string;}
+ public String getExtraAdviceInformation() {return extraInfo;}
+
+ public String toString() {
+ return "ExtraInformation: ["+extraInfo+"]";
+ }
+ }
+
+ public void setExtraInfo(ExtraInformation info);
+ public ExtraInformation getExtraInfo();
public IProgramElement getParent();
public void setParent(IProgramElement parent);
diff --git a/asm/src/org/aspectj/asm/IRelationship.java b/asm/src/org/aspectj/asm/IRelationship.java
index 18a11da0e..53b118262 100644
--- a/asm/src/org/aspectj/asm/IRelationship.java
+++ b/asm/src/org/aspectj/asm/IRelationship.java
@@ -27,17 +27,33 @@ public interface IRelationship extends Serializable {
public String getSourceHandle();
+ public boolean addTarget(String handle);
+
public Kind getKind();
+
+ public boolean hasRuntimeTest();
/**
* Uses "typesafe enum" pattern.
*/
public static class Kind implements Serializable {
- public static final Kind ADVICE = new Kind("advice");
- public static final Kind DECLARE = new Kind("declare");
- public static final Kind DECLARE_INTER_TYPE = new Kind("inter-type declaration");
- public static final Kind[] ALL = { ADVICE, DECLARE, DECLARE_INTER_TYPE };
+ public static final Kind DECLARE_WARNING = new Kind("declare warning");
+ public static final Kind DECLARE_ERROR = new Kind("declare error");
+ public static final Kind ADVICE_AROUND = new Kind("around advice");
+ public static final Kind ADVICE_AFTERRETURNING = new Kind("after returning advice");
+ public static final Kind ADVICE_AFTERTHROWING = new Kind("after throwing advice");
+ public static final Kind ADVICE_AFTER = new Kind("after advice");
+ public static final Kind ADVICE_BEFORE = new Kind("before advice");
+ public static final Kind ADVICE = new Kind("advice");
+ public static final Kind DECLARE = new Kind("declare");
+ public static final Kind DECLARE_INTER_TYPE = new Kind("inter-type declaration");
+
+ public static final Kind[] ALL = {
+ DECLARE_WARNING, DECLARE_ERROR,
+ ADVICE_AROUND,ADVICE_AFTERRETURNING,ADVICE_AFTERTHROWING,ADVICE_AFTER,ADVICE_BEFORE,
+ ADVICE, DECLARE, DECLARE_INTER_TYPE };
+
private final String name;
private Kind(String name) {
diff --git a/asm/src/org/aspectj/asm/IRelationshipMap.java b/asm/src/org/aspectj/asm/IRelationshipMap.java
index 7eb31335f..ff88efbc5 100644
--- a/asm/src/org/aspectj/asm/IRelationshipMap.java
+++ b/asm/src/org/aspectj/asm/IRelationshipMap.java
@@ -14,6 +14,7 @@ package org.aspectj.asm;
import java.io.Serializable;
import java.util.List;
+import java.util.Set;
//import org.aspectj.asm.IRelationship.Kind;
@@ -50,21 +51,33 @@ public interface IRelationshipMap extends Serializable {
*
* @return null if the relationship is not found.
*/
- public IRelationship get(IProgramElement source, IRelationship.Kind kind, String relationshipName);
+ public IRelationship get(IProgramElement source, IRelationship.Kind kind,
+ String relationshipName,boolean runtimeTest,
+ boolean createIfMissing);
/**
+ * Return a relationship matching the kind and name for the given element.
+ *
+ * @return null if the relationship is not found.
+ */
+ public IRelationship get(IProgramElement source, IRelationship.Kind kind,
+ String relationshipName);
+
+ /**
* Return a relationship matching the kind and name for the given element.
* Creates the relationship if not found.
*
* @return null if the relationship is not found.
*/
- public IRelationship get(String source, IRelationship.Kind kind, String relationshipName);
+ public IRelationship get(String source, IRelationship.Kind kind,
+ String relationshipName, boolean runtimeTest,
+ boolean createIfMissing);
public void put(IProgramElement source, IRelationship relationship);
public void put(String handle, IRelationship relationship);
- public void remove(String handle, IRelationship relationship);
+ public boolean remove(String handle, IRelationship relationship);
public void removeAll(String source);
@@ -72,5 +85,7 @@ public interface IRelationshipMap extends Serializable {
* Clear all of the relationships in the map.
*/
public void clear();
+
+ public Set getEntries();
}
diff --git a/asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java b/asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java
index 0a36642ab..da1b09e38 100644
--- a/asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java
+++ b/asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java
@@ -8,6 +8,7 @@
*
* Contributors:
* Mik Kersten initial implementation
+ * Andy Clement Extensions for better IDE representation
* ******************************************************************/
@@ -32,7 +33,19 @@ public class AspectJElementHierarchy implements IHierarchy {
private Map typeMap = null;
public IProgramElement getElement(String handle) {
- throw new RuntimeException("unimplemented");
+ IProgramElement cachedEntry = (IProgramElement)handleMap.get(handle);
+ if (cachedEntry!=null) return cachedEntry;
+
+ StringTokenizer st = new StringTokenizer(handle, ProgramElement.ID_DELIM);
+ String file = st.nextToken();
+ int line = new Integer(st.nextToken()).intValue();
+ // int col = new Integer(st.nextToken()).intValue(); TODO: use column number when available
+ String canonicalSFP = AsmManager.getDefault().getCanonicalFilePath(new File(file));
+ IProgramElement ret = findNodeForSourceLineHelper(root,canonicalSFP, line);
+ if (ret!=null) {
+ handleMap.put(handle,ret);
+ }
+ return ret;
}
public IProgramElement getRoot() {
@@ -48,6 +61,10 @@ public class AspectJElementHierarchy implements IHierarchy {
public void addToFileMap( Object key, Object value ){
fileMap.put( key, value );
}
+
+ public boolean removeFromFileMap(Object key) {
+ return (fileMap.remove(key)!=null);
+ }
public void setFileMap(HashMap fileMap) {
this.fileMap = fileMap;
@@ -336,5 +353,14 @@ public class AspectJElementHierarchy implements IHierarchy {
protected void cache(String handle, ProgramElement pe) {
handleMap.put(handle,pe);
}
+
+ public void flushTypeMap() {
+ typeMap.clear();
+
+ }
+
+ public void flushHandleMap() {
+ handleMap.clear();
+ }
}
diff --git a/asm/src/org/aspectj/asm/internal/ProgramElement.java b/asm/src/org/aspectj/asm/internal/ProgramElement.java
index 3cff3287d..913a1cebc 100644
--- a/asm/src/org/aspectj/asm/internal/ProgramElement.java
+++ b/asm/src/org/aspectj/asm/internal/ProgramElement.java
@@ -8,16 +8,22 @@
*
* Contributors:
* Mik Kersten initial implementation
+ * Andy Clement Extensions for better IDE representation
* ******************************************************************/
package org.aspectj.asm.internal;
-import java.io.*;
-import java.util.*;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
-import org.aspectj.asm.*;
-import org.aspectj.bridge.*;
+import org.aspectj.asm.AsmManager;
+import org.aspectj.asm.HierarchyWalker;
+import org.aspectj.asm.IProgramElement;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
/**
@@ -55,6 +61,8 @@ public class ProgramElement implements IProgramElement {
private List parameterTypes = null;
private String details = null;
+
+ private ExtraInformation info;
/**
* Used during de-externalization.
@@ -126,6 +134,10 @@ public class ProgramElement implements IProgramElement {
public Accessibility getAccessibility() {
return accessibility;
}
+
+ public void setAccessibility(Accessibility a) {
+ accessibility=a;
+ }
public String getDeclaringType() {
return declaringType;
@@ -388,6 +400,9 @@ public class ProgramElement implements IProgramElement {
return sb.toString();
}
+
+ public static boolean shortITDNames = true;
+
/**
* TODO: move the "parent != null"==>injar heuristic to more explicit
*/
@@ -396,13 +411,20 @@ public class ProgramElement implements IProgramElement {
if (kind == Kind.CODE || kind == Kind.INITIALIZER) {
label = parent.getParent().getName() + ": ";
} else if (kind.isInterTypeMember()) {
- int dotIndex = name.indexOf('.');
- if (dotIndex != -1) {
- return parent.getName() + ": " + toLabelString().substring(dotIndex+1);
+ if (shortITDNames) {
+ // if (name.indexOf('.')!=-1) return toLabelString().substring(name.indexOf('.')+1);
+ label="";
} else {
+ int dotIndex = name.indexOf('.');
+ if (dotIndex != -1) {
+ return parent.getName() + ": " + toLabelString().substring(dotIndex+1);
+ } else {
label = parent.getName() + '.';
+ }
}
- } else if (kind == Kind.CLASS || kind == Kind.ASPECT) {
+ } else if (kind == Kind.CLASS || kind == Kind.ASPECT || kind == Kind.INTERFACE) {
+ label = "";
+ } else if (kind.equals(Kind.DECLARE_PARENTS)) {
label = "";
} else {
if (parent != null) {
@@ -487,5 +509,15 @@ public class ProgramElement implements IProgramElement {
hierarchy.cache(handle,this);
}
}
+
+ public void setExtraInfo(ExtraInformation info) {
+ this.info = info;
+
+ }
+
+ public ExtraInformation getExtraInfo() {
+ return info;
+ }
+
}
diff --git a/asm/src/org/aspectj/asm/internal/Relationship.java b/asm/src/org/aspectj/asm/internal/Relationship.java
index 68ee50e3f..c47fb159e 100644
--- a/asm/src/org/aspectj/asm/internal/Relationship.java
+++ b/asm/src/org/aspectj/asm/internal/Relationship.java
@@ -8,6 +8,7 @@
*
* Contributors:
* Mik Kersten initial implementation
+ * Andy Clement Extensions for better IDE representation
* ******************************************************************/
@@ -15,7 +16,6 @@ package org.aspectj.asm.internal;
import java.util.List;
-//import org.aspectj.asm.*;
import org.aspectj.asm.IRelationship;
//import org.aspectj.asm.IRelationship.Kind;
@@ -29,17 +29,20 @@ public class Relationship implements IRelationship {
private Kind kind;
private String sourceHandle;
private List targets;
+ private boolean hasRuntimeTest;
public Relationship(
String name,
Kind kind,
String sourceHandle,
- List targets) {
+ List targets,
+ boolean runtimeTest) {
this.name = name;
this.kind = kind;
this.sourceHandle = sourceHandle;
this.targets = targets;
+ this.hasRuntimeTest = runtimeTest;
}
public String getName() {
@@ -61,5 +64,15 @@ public class Relationship implements IRelationship {
public List getTargets() {
return targets;
}
+
+ public boolean addTarget(String handle) {
+ if (targets.contains(handle)) return false;
+ targets.add(handle);
+ return true;
+ }
+
+ public boolean hasRuntimeTest() {
+ return hasRuntimeTest;
+ }
}
diff --git a/asm/src/org/aspectj/asm/internal/RelationshipMap.java b/asm/src/org/aspectj/asm/internal/RelationshipMap.java
index ce05fd5c6..b70887af6 100644
--- a/asm/src/org/aspectj/asm/internal/RelationshipMap.java
+++ b/asm/src/org/aspectj/asm/internal/RelationshipMap.java
@@ -15,6 +15,7 @@ package org.aspectj.asm.internal;
import java.util.*;
import org.aspectj.asm.*;
+import org.aspectj.asm.IRelationship.Kind;
/**
* TODO: add a remove, and a clear all
@@ -24,12 +25,20 @@ import org.aspectj.asm.*;
*/
public class RelationshipMap extends HashMap implements IRelationshipMap {
- private IHierarchy hierarchy;
+ // As this gets serialized, make the hierarchy transient and
+ // settable
+ private transient IHierarchy hierarchy;
+
+ public RelationshipMap() { }
public RelationshipMap(IHierarchy hierarchy) {
this.hierarchy = hierarchy;
}
+ public void setHierarchy(IHierarchy hierarchy) {
+ this.hierarchy = hierarchy;
+ }
+
public List get(String handle) {
List relationships = (List)super.get(handle);
if (relationships == null) {
@@ -43,48 +52,67 @@ public class RelationshipMap extends HashMap implements IRelationshipMap {
return get(source.getHandleIdentifier());
}
- public IRelationship get(String source, IRelationship.Kind kind, String relationshipName) {
+ public IRelationship get(String source, IRelationship.Kind kind,
+ String relationshipName,boolean runtimeTest,boolean createIfMissing) {
List relationships = get(source);
if (relationships == null) {
+ if (!createIfMissing) return null;
relationships = new ArrayList();
- IRelationship rel = new Relationship(relationshipName, kind, source, new ArrayList());
+ IRelationship rel = new Relationship(relationshipName, kind, source, new ArrayList(),runtimeTest);
relationships.add(rel);
super.put(source, relationships);
return rel;
} else {
for (Iterator it = relationships.iterator(); it.hasNext(); ) {
IRelationship curr = (IRelationship)it.next();
- if (curr.getKind() == kind && curr.getName().equals(relationshipName)) {
+ if (curr.getKind() == kind &&
+ curr.getName().equals(relationshipName) &&
+ curr.hasRuntimeTest() == runtimeTest) {
return curr;
}
}
+ if (createIfMissing) {
+ // At this point we did find some relationships for 'source' but not one that looks like what we are
+ // after (either the kind or the name or the dynamictests setting don't match)
+ IRelationship rel = new Relationship(relationshipName, kind, source, new ArrayList(),runtimeTest);
+ relationships.add(rel);
+ return rel;
+ }
}
return null;
}
- public IRelationship get(IProgramElement source, IRelationship.Kind kind, String relationshipName) {
- return get(source.getHandleIdentifier(), kind, relationshipName);
+ public IRelationship get(IProgramElement source, IRelationship.Kind kind, String relationshipName, boolean runtimeTest,boolean createIfMissing) {
+ return get(source.getHandleIdentifier(), kind, relationshipName,runtimeTest,createIfMissing);
}
- public void remove(String source, IRelationship relationship) {
+ public IRelationship get(IProgramElement source, Kind kind, String relationshipName) {
+ return get(source,kind,relationshipName,false,true);
+ }
+
+ public boolean remove(String source, IRelationship relationship) {
List list = (List)super.get(source);
if (list != null) {
- boolean matched = false;
- for (Iterator it = list.iterator(); it.hasNext(); ) {
- IRelationship curr = (IRelationship)it.next();
- if (curr.getName().equals(relationship.getName())) {
- curr.getTargets().addAll(relationship.getTargets());
- matched = true;
- }
- }
- if (!matched) list.remove(relationship);
+ return list.remove(relationship);
+// boolean matched = false;
+// for (Iterator it = list.iterator(); it.hasNext(); ) {
+// IRelationship curr = (IRelationship)it.next();
+// if (curr.getName().equals(relationship.getName())) {
+// curr.getTargets().addAll(relationship.getTargets());
+// matched = true;
+// }
+// }
+// if (!matched) list.remove(relationship);
}
+ return false;
}
public void removeAll(String source) {
super.remove(source);
}
+ public Object put(Object o, Object p) {throw new RuntimeException("Fuck off!");
+ }
public void put(String source, IRelationship relationship) {
System.err.println(">> for: " + source + ", put::" + relationship);
@@ -103,7 +131,11 @@ public class RelationshipMap extends HashMap implements IRelationshipMap {
matched = true;
}
}
- if (matched) list.add(relationship);
+ if (matched) {
+ // bug?
+ System.err.println("matched = true");
+ }
+ if (matched) list.add(relationship); // Is this a bug, will it give us double entries?
}
}
@@ -115,4 +147,9 @@ public class RelationshipMap extends HashMap implements IRelationshipMap {
super.clear();
}
+ public Set getEntries() {
+ return keySet();
+ }
+
+
}
diff --git a/bridge/src/org/aspectj/bridge/IMessage.java b/bridge/src/org/aspectj/bridge/IMessage.java
index 2bafc7d7a..fcb807016 100644
--- a/bridge/src/org/aspectj/bridge/IMessage.java
+++ b/bridge/src/org/aspectj/bridge/IMessage.java
@@ -27,6 +27,7 @@ public interface IMessage {
public static final IMessage[] RA_IMessage = new IMessage[0];
// int values must sync with KINDS order below
+ public static final Kind WEAVEINFO = new Kind("weaveinfo",5);
public static final Kind INFO = new Kind("info", 10);
public static final Kind DEBUG = new Kind("debug", 20);
public static final Kind WARNING = new Kind("warning", 30);
@@ -43,7 +44,7 @@ public interface IMessage {
public static final List KINDS =
Collections.unmodifiableList(
Arrays.asList(
- new Kind[] { INFO, DEBUG, WARNING, ERROR, FAIL, ABORT }));
+ new Kind[] { WEAVEINFO, INFO, DEBUG, WARNING, ERROR, FAIL, ABORT }));
/** @return non-null String with simple message */
String getMessage();
@@ -69,6 +70,9 @@ public interface IMessage {
/** @return true if something failed */
boolean isFailed();
+ /** Caller can verify if this message came about because of a DEOW */
+ boolean getDeclared();
+
/** @return Throwable associated with this message, or null if none */
Throwable getThrown();
diff --git a/bridge/src/org/aspectj/bridge/Message.java b/bridge/src/org/aspectj/bridge/Message.java
index af032b6de..1ddb18d69 100644
--- a/bridge/src/org/aspectj/bridge/Message.java
+++ b/bridge/src/org/aspectj/bridge/Message.java
@@ -30,6 +30,7 @@ public class Message implements IMessage {
private final ISourceLocation sourceLocation;
private final String details;
private final List/*SourceLocation*/ extraSourceLocations;
+ private final boolean declared; // Is it a DEOW ?
/**
* Create a (compiler) error or warning message
@@ -46,7 +47,7 @@ public class Message implements IMessage {
this(message, "",(isError ? IMessage.ERROR : IMessage.WARNING), location, null,
(extraSourceLocations.length > 0 ? extraSourceLocations : null));
}
-
+
/**
* Create a message, handling null values for message and kind
* if thrown is not null.
@@ -61,25 +62,31 @@ public class Message implements IMessage {
*/
public Message(String message, String details, IMessage.Kind kind,
ISourceLocation sourceLocation, Throwable thrown, ISourceLocation[] extraSourceLocations) {
+ this(message,details,kind,sourceLocation,thrown,extraSourceLocations,false);
+ }
+
+ public Message(String message, String details, IMessage.Kind kind,
+ ISourceLocation sLoc, Throwable thrown, ISourceLocation[] otherLocs,
+ boolean declared) {
this.details = details;
this.message = ((message!=null) ? message : ((thrown==null) ? null : thrown.getMessage()));
this.kind = kind;
- this.sourceLocation = sourceLocation;
+ this.sourceLocation = sLoc;
this.thrown = thrown;
-
- if (extraSourceLocations != null) {
+ if (otherLocs != null) {
this.extraSourceLocations
- = Collections.unmodifiableList(Arrays.asList(extraSourceLocations));
+ = Collections.unmodifiableList(Arrays.asList(otherLocs));
+ }
+ else {
+ this.extraSourceLocations = Collections.EMPTY_LIST;
}
- else {
- this.extraSourceLocations = Collections.EMPTY_LIST;
- }
if (null == this.kind) {
throw new IllegalArgumentException("null kind");
}
- if (null == this.message) {
- throw new IllegalArgumentException("null message");
- }
+ if (null == this.message) {
+ throw new IllegalArgumentException("null message");
+ }
+ this.declared = declared;
}
/**
@@ -130,6 +137,11 @@ public class Message implements IMessage {
return kind == IMessage.ABORT;
}
+ /** Caller can verify if this message came about because of a DEOW */
+ public boolean getDeclared() {
+ return declared;
+ }
+
/**
* @return true if kind == IMessage.FAIL
*/
diff --git a/bridge/src/org/aspectj/bridge/MessageHandler.java b/bridge/src/org/aspectj/bridge/MessageHandler.java
index 6882306e8..7187b2c46 100644
--- a/bridge/src/org/aspectj/bridge/MessageHandler.java
+++ b/bridge/src/org/aspectj/bridge/MessageHandler.java
@@ -55,6 +55,7 @@ public class MessageHandler implements IMessageHolder {
messages = new ArrayList();
ignoring = new ArrayList();
init(accumulateOnly);
+ ignore(IMessage.WEAVEINFO); // Off by default, need to explicitly be enabled (see -showWeaveInfo)
}
/**
@@ -76,7 +77,9 @@ public class MessageHandler implements IMessageHolder {
messages.clear();
}
if (0 < ignoring.size()) {
+ boolean ignoringWeaveMessages = isIgnoring(IMessage.WEAVEINFO);
ignoring.clear();
+ if (ignoringWeaveMessages) ignore(IMessage.WEAVEINFO);
}
if (null != interceptor) {
interceptor = null;
diff --git a/bridge/src/org/aspectj/bridge/WeaveMessage.java b/bridge/src/org/aspectj/bridge/WeaveMessage.java
new file mode 100644
index 000000000..e15abeae7
--- /dev/null
+++ b/bridge/src/org/aspectj/bridge/WeaveMessage.java
@@ -0,0 +1,75 @@
+/* *******************************************************************
+ * 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
+ *
+ * Contributors:
+ * Andy Clement IBM initial implementation 30-May-2004
+ * ******************************************************************/
+
+package org.aspectj.bridge;
+
+public class WeaveMessage extends Message {
+
+ // Kinds of weaving message we can produce
+
+ public static WeaveMessageKind WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS =
+ new WeaveMessageKind(1,"Extending interface set for type '%1' (%2) to include '%3' (%4)");
+
+ public static WeaveMessageKind WEAVEMESSAGE_ITD =
+ new WeaveMessageKind(2,"Type '%1' (%2) has intertyped %3 from '%4' (%5)");
+
+ // %6 is information like "[with runtime test]"
+ public static WeaveMessageKind WEAVEMESSAGE_ADVISES =
+ new WeaveMessageKind(3,"Type '%1' (%2) advised by %3 advice from '%4' (%5)%6");
+
+ public static WeaveMessageKind WEAVEMESSAGE_DECLAREPARENTSEXTENDS =
+ new WeaveMessageKind(4,"Setting superclass of type '%1' (%2) to '%3' (%4)");
+
+ public static WeaveMessageKind WEAVEMESSAGE_SOFTENS =
+ new WeaveMessageKind(5,"Softening exceptions in type '%1' (%2) as defined by aspect '%3' (%4)");
+
+
+ // private ctor - use the static factory method
+ private WeaveMessage(String message) {
+ super(message, IMessage.WEAVEINFO, null, null);
+ }
+
+ /**
+ * Static helper method for constructing weaving messages.
+ * @param kind what kind of message (e.g. declare parents)
+ * @param inserts inserts for the message (inserts are marked %n in the message)
+ * @param affectedtypename the type which is being advised/declaredUpon
+ * @param aspectname the aspect that defined the advice or declares
+ * @return new weaving message
+ */
+ public static WeaveMessage constructWeavingMessage(
+ WeaveMessageKind kind,
+ String[] inserts) {
+ StringBuffer str = new StringBuffer(kind.getMessage());
+ int pos = -1;
+ while ((pos=str.indexOf("%"))!=-1) {
+ int n = Character.getNumericValue(str.charAt(pos+1));
+ str.replace(pos,pos+2,inserts[n-1]);
+ }
+ return new WeaveMessage(str.toString());
+ }
+
+
+
+ public static class WeaveMessageKind {
+
+ private int id;
+ private String message;
+
+ public WeaveMessageKind(int id,String message) {
+ this.id = id;
+ this.message = message;
+ }
+
+ public String getMessage() { return message; }
+ }
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java
index 3d795f25f..3928ddc44 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java
@@ -114,6 +114,20 @@ public class BuildArgParser extends Main {
AjcConfigParser parser = new AjcConfigParser(buildConfig, handler);
parser.parseCommandLine(args);
+
+ boolean swi = buildConfig.getShowWeavingInformation();
+ // Now jump through firey hoops to turn them on/off
+ if (handler instanceof CountingMessageHandler) {
+ IMessageHandler delegate = ((CountingMessageHandler)handler).delegate;
+ // Without dontIgnore() on the IMessageHandler interface, we have to do this *blurgh*
+ if (delegate instanceof MessageHandler) {
+ if (swi)
+ ((MessageHandler)delegate).dontIgnore(IMessage.WEAVEINFO);
+ else
+ ((MessageHandler)delegate).ignore(IMessage.WEAVEINFO);
+ }
+ }
+
boolean incrementalMode = buildConfig.isIncrementalMode()
|| buildConfig.isIncrementalFileMode();
@@ -460,6 +474,8 @@ public class BuildArgParser extends Main {
}
} else if (arg.equals("-XnoInline")) {
buildConfig.setXnoInline(true);
+ } else if (arg.startsWith("-showWeaveInfo")) {
+ buildConfig.setShowWeavingInformation(true);
} else if (arg.equals("-Xlintfile")) {
if (args.size() > nextArgIndex) {
File lintSpecFile = makeFile(((ConfigParser.Arg)args.get(nextArgIndex)).getValue());
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties
index 306813e8d..0dd92150a 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties
@@ -26,6 +26,7 @@ AspectJ-specific options:\n\
\t (<list> uses classpath delimiter)\n\
\t-outjar <file> put output classes in zip file <file>\n\
\t-argfile <file> specify line-delimited list of source files\n\
+\t-showWeaveInfo display information about weaving\n\
\t-incremental continuously-running compiler, needs -sourceroots\n\
\t (reads stdin: enter to recompile and ''q'' to quit)\n\
\t-sourceroots <dirs> compile all .aj and .java files in <dirs>\n\
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java
index 734fd8816..d7925cb8f 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java
@@ -100,8 +100,18 @@ public class WeaverMessageHandler implements IMessageHandler {
problemSource,
usedBinarySourceFileName);
problem.setSeeAlsoProblems(seeAlso);
+
+ StringBuffer details = new StringBuffer();
+ // Stick more info in supplementary message info
if (message.getDetails() != null) {
- problem.setSupplementaryMessageInfo(message.getDetails());
+ details.append(message.getDetails());
+ }
+ // Remember if this message was due to a deow
+ if (message.getDeclared()) {
+ details.append("[deow=true]");
+ }
+ if (details.length()!=0) {
+ problem.setSupplementaryMessageInfo(details.toString());
}
compiler.problemReporter.record(problem, problemSource, referenceContext);
return true;
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java
index 05465c469..6612e66ce 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java
@@ -13,25 +13,42 @@
package org.aspectj.ajdt.internal.compiler.lookup;
-import java.util.*;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
-//import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
-//import org.aspectj.asm.*;
-//import org.aspectj.asm.IProgramElement;
-//import org.aspectj.asm.internal.Relationship;
+import org.aspectj.asm.AsmManager;
import org.aspectj.bridge.IMessage;
-import org.aspectj.weaver.*;
+import org.aspectj.bridge.WeaveMessage;
+import org.aspectj.weaver.AsmRelationshipProvider;
+import org.aspectj.weaver.ConcreteTypeMunger;
+import org.aspectj.weaver.ResolvedTypeMunger;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.WeaverStateInfo;
+import org.aspectj.weaver.World;
import org.aspectj.weaver.bcel.LazyClassGen;
-import org.aspectj.weaver.patterns.*;
+import org.aspectj.weaver.patterns.DeclareParents;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
-import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
/**
@@ -304,8 +321,17 @@ public class AjLookupEnvironment extends LookupEnvironment {
needOldStyleWarning = false;
}
onType.addInterTypeMunger(munger);
-
- AsmInterTypeRelationshipProvider.addRelationship(onType, munger);
+ //TODO: Andy Should be done at weave time.
+ // Unfortunately we can't do it at weave time unless the type mungers remember where
+ // they came from. Thats why we do it here during complation because at this time
+ // they do know their source location. I've put a flag in ResolvedTypeMunger that
+ // records whether type mungers are currently set to remember their source location.
+ // The flag is currently set to false, it should be set to true when we do the
+ // work to version all AspectJ attributes.
+ // (When done at weave time, it is done by invoking addRelationship() on
+ // AsmRelationshipProvider (see BCELTypeMunger)
+ if (!ResolvedTypeMunger.persistSourceLocation) // Do it up front if we bloody have to
+ AsmInterTypeRelationshipProvider.addRelationship(onType, munger);
}
}
@@ -338,15 +364,39 @@ public class AjLookupEnvironment extends LookupEnvironment {
onType + ": " + dangerousInterfaces.get(parent),
onType.getSourceLocation(), null);
}
+ AsmRelationshipProvider.addDeclareParentsRelationship(declareParents.getSourceLocation(),factory.fromEclipse(sourceType));
addParent(sourceType, parent);
}
}
}
+ private void reportDeclareParentsMessage(WeaveMessage.WeaveMessageKind wmk,SourceTypeBinding sourceType,ResolvedTypeX parent) {
+ if (!factory.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
+ String filename = new String(sourceType.getFileName());
+ if (filename.lastIndexOf(File.separator)!=-1)
+ filename = filename.substring(filename.lastIndexOf(File.separator)+1);
+
+ factory.getWorld().getMessageHandler().handleMessage(
+ WeaveMessage.constructWeavingMessage(wmk,
+ new String[]{CharOperation.toString(sourceType.compoundName),
+ filename,
+ parent.getClassName(),
+ parent.getSourceLocation().getSourceFile().getName()}));
+ }
+ }
+
+
private void addParent(SourceTypeBinding sourceType, ResolvedTypeX parent) {
ReferenceBinding parentBinding = (ReferenceBinding)factory.makeTypeBinding(parent);
+
if (parentBinding.isClass()) {
sourceType.superclass = parentBinding;
+
+ // TAG: WeavingMessage DECLARE PARENTS: EXTENDS
+ // Compiler restriction: Can't do EXTENDS at weave time
+ // So, only see this message if doing a source compilation
+ reportDeclareParentsMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent);
+
} else {
ReferenceBinding[] oldI = sourceType.superInterfaces;
ReferenceBinding[] newI;
@@ -361,6 +411,12 @@ public class AjLookupEnvironment extends LookupEnvironment {
}
sourceType.superInterfaces = newI;
warnOnAddedInterface(factory.fromEclipse(sourceType),parent);
+
+
+ // TAG: WeavingMessage DECLARE PARENTS: IMPLEMENTS
+ // This message will come out of BcelTypeMunger.munge if doing a binary weave
+ reportDeclareParentsMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,sourceType,parent);
+
}
}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AsmInterTypeRelationshipProvider.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AsmInterTypeRelationshipProvider.java
index 9bb093190..bb97a6ddd 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AsmInterTypeRelationshipProvider.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AsmInterTypeRelationshipProvider.java
@@ -55,11 +55,11 @@ public class AsmInterTypeRelationshipProvider {
IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap();
if (sourceHandle != null && targetHandle != null) {
- IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES);
- foreward.getTargets().add(targetHandle);
+ 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);
- back.getTargets().add(sourceHandle);
+ IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY,false,true);
+ back.addTarget(sourceHandle);
}
}
}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java
index 33a4f2a78..f9300e7cc 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java
@@ -48,6 +48,9 @@ public class EclipseTypeMunger extends ConcreteTypeMunger {
this.sourceLocation =
new EclipseSourceLocation(sourceMethod.compilationResult,
sourceMethod.sourceStart, sourceMethod.sourceEnd);
+ // Piece of magic that tells type mungers where they came from.
+ // Won't be persisted unless ResolvedTypeMunger.persistSourceLocation is true.
+ munger.setSourceLocation(sourceLocation);
}
targetTypeX = munger.getSignature().getDeclaringType().resolve(world.getWorld());
//targetBinding = (ReferenceBinding)world.makeTypeBinding(targetTypeX);
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
index 74f5c4767..34474602d 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
@@ -348,6 +348,15 @@ public class AjBuildConfig { // XXX needs bootclasspath?
if (!isXserializableAspects() && global.isXserializableAspects()) {
setXserializableAspects(true);
}
+ if (!isXlazyTjp() && global.isXlazyTjp()) {
+ setXlazyTjp(true);
+ }
+ if (!isXreweavable() && global.isXreweavable()) {
+ setXreweavable(true);
+ }
+ if (!getXreweavableCompressClasses() && global.getXreweavableCompressClasses()) {
+ setXreweavableCompressClasses(true);
+ }
}
void join(Collection local, Collection global) {
@@ -490,4 +499,12 @@ public class AjBuildConfig { // XXX needs bootclasspath?
options.generateModel = structureModelMode;
}
+
+ public void setShowWeavingInformation(boolean b) {
+ options.showWeavingInformation = true;
+ }
+
+ public boolean getShowWeavingInformation() {
+ return options.showWeavingInformation;
+ }
}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
index ab428758a..3ca85e0a6 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
@@ -141,11 +141,11 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
// if (batch) {
setBuildConfig(buildConfig);
//}
-// if (batch) {
-// if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) {
- setupModel();
+ if (batch || !AsmManager.attemptIncrementalModelRepairs) {
+// if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) {
+ setupModel(buildConfig);
// }
-// }
+ }
if (batch) {
initBcelWorld(handler);
}
@@ -168,6 +168,10 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
if (handler.hasErrors()) {
return false;
}
+
+ if (AsmManager.isReporting())
+ AsmManager.getDefault().reportModelInfo("After a batch build");
+
} else {
// done already?
// if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) {
@@ -176,9 +180,13 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
// System.err.println("XXXX start inc ");
binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(true);
List files = state.getFilesToCompile(true);
- boolean hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty());
+ if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode())
+ if (AsmManager.attemptIncrementalModelRepairs)
+ AsmManager.getDefault().processDelta(files,state.addedFiles,state.deletedFiles);
+ boolean hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty());
for (int i = 0; (i < 5) && hereWeGoAgain; i++) {
// System.err.println("XXXX inc: " + files);
+
performCompilation(files);
if (handler.hasErrors() || (progressListener!=null && progressListener.isCancelledRequested())) {
return false;
@@ -186,9 +194,21 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(false);
files = state.getFilesToCompile(false);
hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty());
+ // TODO Andy - Needs some thought here...
+ // I think here we might want to pass empty addedFiles/deletedFiles as they were
+ // dealt with on the first call to processDelta - we are going through this loop
+ // again because in compiling something we found something else we needed to
+ // rebuild. But what case causes this?
+ if (hereWeGoAgain)
+ if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode())
+ if (AsmManager.attemptIncrementalModelRepairs)
+ AsmManager.getDefault().processDelta(files,state.addedFiles,state.deletedFiles);
}
if (!files.isEmpty()) {
return batchBuild(buildConfig, baseHandler);
+ } else {
+ if (AsmManager.isReporting())
+ AsmManager.getDefault().reportModelInfo("After an incremental build");
}
}
@@ -391,31 +411,72 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
}
}
+
+// public static void dumprels() {
+// IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
+// int ctr = 1;
+// Set entries = irm.getEntries();
+// for (Iterator iter = entries.iterator(); iter.hasNext();) {
+// String hid = (String) iter.next();
+// List rels = irm.get(hid);
+// for (Iterator iterator = rels.iterator(); iterator.hasNext();) {
+// IRelationship ir = (IRelationship) iterator.next();
+// List targets = ir.getTargets();
+// for (Iterator iterator2 = targets.iterator();
+// iterator2.hasNext();
+// ) {
+// String thid = (String) iterator2.next();
+// System.err.println("Hid:"+(ctr++)+":(targets="+targets.size()+") "+hid+" ("+ir.getName()+") "+thid);
+// }
+// }
+// }
+// }
+
+
/**
* Responsible for managing the ASM model between builds. Contains the policy for
* maintaining the persistance of elements in the model.
*
* TODO: implement incremental policy.
*/
- private void setupModel() {
- String rootLabel = "<root>";
+ private void setupModel(AjBuildConfig config) {
IHierarchy model = AsmManager.getDefault().getHierarchy();
- AsmManager.getDefault().getRelationshipMap().clear();
+ String rootLabel = "<root>";
+
+ AsmManager.getDefault().getRelationshipMap().clear();
- IProgramElement.Kind kind = IProgramElement.Kind.FILE_JAVA;
- if (buildConfig.getConfigFile() != null) {
- rootLabel = buildConfig.getConfigFile().getName();
- model.setConfigFile(
- buildConfig.getConfigFile().getAbsolutePath()
- );
- kind = IProgramElement.Kind.FILE_LST;
- }
- model.setRoot(new ProgramElement(rootLabel, kind, new ArrayList()));
+ IProgramElement.Kind kind = IProgramElement.Kind.FILE_JAVA;
+ if (buildConfig.getConfigFile() != null) {
+ rootLabel = buildConfig.getConfigFile().getName();
+ model.setConfigFile(
+ buildConfig.getConfigFile().getAbsolutePath()
+ );
+ kind = IProgramElement.Kind.FILE_LST;
+ }
+ model.setRoot(new ProgramElement(rootLabel, kind, new ArrayList()));
- model.setFileMap(new HashMap());
- setStructureModel(model);
+ model.setFileMap(new HashMap());
+ setStructureModel(model);
}
+//
+// private void dumplist(List l) {
+// System.err.println("---- "+l.size());
+// for (int i =0 ;i<l.size();i++) System.err.println(i+"\t "+l.get(i));
+// }
+// private void accumulateFileNodes(IProgramElement ipe,List store) {
+// if (ipe.getKind()==IProgramElement.Kind.FILE_JAVA ||
+// ipe.getKind()==IProgramElement.Kind.FILE_ASPECTJ) {
+// if (!ipe.getName().equals("<root>")) {
+// store.add(ipe);
+// return;
+// }
+// }
+// for (Iterator i = ipe.getChildren().iterator();i.hasNext();) {
+// accumulateFileNodes((IProgramElement)i.next(),store);
+// }
+// }
+
/** init only on initial batch compile? no file-specific options */
private void initBcelWorld(IMessageHandler handler) throws IOException {
bcelWorld = new BcelWorld(buildConfig.getClasspath(), handler, null);
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java
index 3c7ae7c38..f65ad2b3e 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java
@@ -64,6 +64,7 @@ public class AjCompilerOptions extends CompilerOptions {
public boolean xNoInline = false;
public boolean xReweavable = false;
public boolean xReweavableCompress = false;
+ public boolean showWeavingInformation = false;
// these next three not exposed by IDEs
public boolean generateModel = false;
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java
index 1f8a81a7d..4a2620873 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java
@@ -15,7 +15,9 @@ package org.aspectj.ajdt.internal.core.builder;
import java.util.*;
import org.aspectj.ajdt.internal.compiler.ast.*;
+import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
import org.aspectj.asm.IProgramElement;
+import org.aspectj.asm.internal.ProgramElement;
import org.aspectj.weaver.*;
import org.aspectj.weaver.patterns.*;
import org.eclipse.jdt.internal.compiler.ast.*;
@@ -98,11 +100,36 @@ public class AsmElementFormatter {
node.setDetails("\"" + genDeclareMessage(deow.getMessage()) + "\"");
} else if (declare.declareDecl instanceof DeclareParents) {
+
node.setKind( IProgramElement.Kind.DECLARE_PARENTS);
DeclareParents dp = (DeclareParents)declare.declareDecl;
node.setName(name + DECLARE_PARENTS);
- node.setDetails(genTypePatternLabel(dp.getChild()));
+ String kindOfDP = null;
+ StringBuffer details = new StringBuffer("");
+ TypePattern[] newParents = dp.getParents().getTypePatterns();
+ for (int i = 0; i < newParents.length; i++) {
+ TypePattern tp = newParents[i];
+ TypeX tx = tp.getExactType();
+ if (kindOfDP == null) {
+ kindOfDP = "implements ";
+ try {
+ ResolvedTypeX rtx = tx.resolve(((AjLookupEnvironment)declare.scope.environment()).factory.getWorld());
+ if (!rtx.isInterface()) kindOfDP = "extends ";
+ } catch (Throwable t) {
+ // What can go wrong???? who knows!
+ }
+
+ }
+ String typename= tp.toString();
+ if (typename.lastIndexOf(".")!=-1) {
+ typename=typename.substring(typename.lastIndexOf(".")+1);
+ }
+ details.append(typename);
+ if ((i+1)<newParents.length) details.append(",");
+ }
+ node.setDetails(kindOfDP+details.toString());
+
} else if (declare.declareDecl instanceof DeclareSoft) {
node.setKind( IProgramElement.Kind.DECLARE_SOFT);
DeclareSoft ds = (DeclareSoft)declare.declareDecl;
@@ -125,17 +152,30 @@ public class AsmElementFormatter {
InterTypeDeclaration itd = (InterTypeDeclaration)methodDeclaration;
String name = itd.onType.toString() + "." + new String(itd.getDeclaredSelector());
if (methodDeclaration instanceof InterTypeFieldDeclaration) {
- node.setKind(IProgramElement.Kind.INTER_TYPE_FIELD);
+ node.setKind(IProgramElement.Kind.INTER_TYPE_FIELD);
+ node.setName(name);
} else if (methodDeclaration instanceof InterTypeMethodDeclaration) {
node.setKind(IProgramElement.Kind.INTER_TYPE_METHOD);
-// InterTypeMethodDeclaration itmd = (InterTypeMethodDeclaration)methodDeclaration;
+ node.setName(name);
} else if (methodDeclaration instanceof InterTypeConstructorDeclaration) {
node.setKind(IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR);
+
+ // StringBuffer argumentsSignature = new StringBuffer("fubar");
+// argumentsSignature.append("(");
+// if (methodDeclaration.arguments!=null && methodDeclaration.arguments.length>1) {
+//
+// for (int i = 1;i<methodDeclaration.arguments.length;i++) {
+// argumentsSignature.append(methodDeclaration.arguments[i]);
+// if (i+1<methodDeclaration.arguments.length) argumentsSignature.append(",");
+// }
+// }
+// argumentsSignature.append(")");
// InterTypeConstructorDeclaration itcd = (InterTypeConstructorDeclaration)methodDeclaration;
+ node.setName(itd.onType.toString() + "." + itd.onType.toString()/*+argumentsSignature.toString()*/);
} else {
node.setKind(IProgramElement.Kind.ERROR);
+ node.setName(name);
}
- node.setName(name);
node.setCorrespondingType(itd.returnType.toString());
if (node.getKind() != IProgramElement.Kind.INTER_TYPE_FIELD) {
setParameters(methodDeclaration, node);
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java
index f4aa53488..ec4aa6c63 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java
@@ -13,40 +13,25 @@
package org.aspectj.ajdt.internal.core.builder;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.ListIterator;
-import java.util.Stack;
+import java.io.*;
+import java.util.*;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration;
+import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
-import org.aspectj.asm.IHierarchy;
-import org.aspectj.asm.IProgramElement;
+import org.aspectj.asm.*;
import org.aspectj.asm.internal.ProgramElement;
-import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.SourceLocation;
+import org.aspectj.bridge.*;
import org.aspectj.util.LangUtil;
import org.aspectj.weaver.Member;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.ASTNode;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.Initializer;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
-import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.aspectj.weaver.ResolvedMember;
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
/**
@@ -140,7 +125,8 @@ public class AsmHierarchyBuilder extends ASTVisitor {
final IProgramElement addToNode = genAddToNode(unit, structureModel);
// -- remove duplicates before adding (XXX use them instead?)
- for (ListIterator itt = addToNode.getChildren().listIterator(); itt.hasNext(); ) {
+ if (addToNode!=null && addToNode.getChildren()!=null) {
+ for (ListIterator itt = addToNode.getChildren().listIterator(); itt.hasNext(); ) {
IProgramElement child = (IProgramElement)itt.next();
ISourceLocation childLoc = child.getSourceLocation();
if (null == childLoc) {
@@ -149,6 +135,7 @@ public class AsmHierarchyBuilder extends ASTVisitor {
} else if (childLoc.getSourceFile().equals(file)) {
itt.remove();
}
+ }
}
// -- add and traverse
addToNode.addChild(cuNode);
@@ -193,14 +180,16 @@ public class AsmHierarchyBuilder extends ASTVisitor {
}
IProgramElement pkgNode = null;
- for (Iterator it = structureModel.getRoot().getChildren().iterator();
- it.hasNext(); ) {
- IProgramElement currNode = (IProgramElement)it.next();
- if (pkgName.equals(currNode.getName())) {
- pkgNode = currNode;
- break;
- }
- }
+ if (structureModel!=null && structureModel.getRoot()!=null && structureModel.getRoot().getChildren()!=null) {
+ for (Iterator it = structureModel.getRoot().getChildren().iterator();
+ it.hasNext(); ) {
+ IProgramElement currNode = (IProgramElement)it.next();
+ if (pkgName.equals(currNode.getName())) {
+ pkgNode = currNode;
+ break;
+ }
+ }
+ }
if (pkgNode == null) {
// note packages themselves have no source location
pkgNode = new ProgramElement(
@@ -318,19 +307,40 @@ public class AsmHierarchyBuilder extends ASTVisitor {
return (IProgramElement)stack.peek();
}
- public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
- IProgramElement peNode = new ProgramElement(
- "",
- IProgramElement.Kind.ERROR,
- makeLocation(methodDeclaration),
- methodDeclaration.modifiers,
- "",
- new ArrayList());
+ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
+ IProgramElement peNode = null;
+
+ // For intertype decls, use the modifiers from the original signature, not the generated method
+ if (methodDeclaration instanceof InterTypeDeclaration) {
+ InterTypeDeclaration itd = (InterTypeDeclaration) methodDeclaration;
+ ResolvedMember sig = itd.getSignature();
+ peNode = new ProgramElement(
+ "",
+ IProgramElement.Kind.ERROR,
+ makeLocation(methodDeclaration),
+ (sig!=null?sig.getModifiers():0),
+ "",
+ new ArrayList());
+
+ } else {
+
+ peNode = new ProgramElement(
+ "",
+ IProgramElement.Kind.ERROR,
+ makeLocation(methodDeclaration),
+ methodDeclaration.modifiers,
+ "",
+ new ArrayList());
+ }
formatter.genLabelAndKind(methodDeclaration, peNode);
genBytecodeInfo(methodDeclaration, peNode);
- peNode.setModifiers(methodDeclaration.modifiers);
- peNode.setCorrespondingType(methodDeclaration.returnType.toString());
+
+ if (methodDeclaration.returnType!=null) {
+ peNode.setCorrespondingType(methodDeclaration.returnType.toString());
+ } else {
+ peNode.setCorrespondingType(null);
+ }
peNode.setSourceSignature(genSourceSignature(methodDeclaration));
peNode.setFormalComment(generateJavadocComment(methodDeclaration));
@@ -349,7 +359,7 @@ public class AsmHierarchyBuilder extends ASTVisitor {
private String genSourceSignature(MethodDeclaration methodDeclaration) {
StringBuffer output = new StringBuffer();
- methodDeclaration.printModifiers(methodDeclaration.modifiers, output);
+ ASTNode.printModifiers(methodDeclaration.modifiers, output);
methodDeclaration.printReturnType(0, output).append(methodDeclaration.selector).append('(');
if (methodDeclaration.arguments != null) {
for (int i = 0; i < methodDeclaration.arguments.length; i++) {
@@ -485,7 +495,7 @@ public class AsmHierarchyBuilder extends ASTVisitor {
*/
private String genSourceSignature(FieldDeclaration fieldDeclaration) {
StringBuffer output = new StringBuffer();
- fieldDeclaration.printModifiers(fieldDeclaration.modifiers, output);
+ FieldDeclaration.printModifiers(fieldDeclaration.modifiers, output);
fieldDeclaration.type.print(0, output).append(' ').append(fieldDeclaration.name);
if (fieldDeclaration.initialization != null
@@ -524,8 +534,17 @@ public class AsmHierarchyBuilder extends ASTVisitor {
stack.push(null); // a little wierd but does the job
return true;
}
+ StringBuffer argumentsSignature = new StringBuffer();
+ argumentsSignature.append("(");
+ if (constructorDeclaration.arguments!=null) {
+ for (int i = 0;i<constructorDeclaration.arguments.length;i++) {
+ argumentsSignature.append(constructorDeclaration.arguments[i]);
+ if (i+1<constructorDeclaration.arguments.length) argumentsSignature.append(",");
+ }
+ }
+ argumentsSignature.append(")");
IProgramElement peNode = new ProgramElement(
- new String(constructorDeclaration.selector),
+ new String(constructorDeclaration.selector)+argumentsSignature,
IProgramElement.Kind.CONSTRUCTOR,
makeLocation(constructorDeclaration),
constructorDeclaration.modifiers,
@@ -535,6 +554,22 @@ public class AsmHierarchyBuilder extends ASTVisitor {
peNode.setModifiers(constructorDeclaration.modifiers);
peNode.setSourceSignature(genSourceSignature(constructorDeclaration));
+ // Fix to enable us to anchor things from ctor nodes
+ if (constructorDeclaration.binding != null) {
+ String memberName = "";
+ String memberBytecodeSignature = "";
+ try {
+ Member member = EclipseFactory.makeResolvedMember(constructorDeclaration.binding);
+ memberName = member.getName();
+ memberBytecodeSignature = member.getSignature();
+ } catch (NullPointerException npe) {
+ memberName = "<undefined>";
+ }
+ peNode.setBytecodeName(memberName);
+ peNode.setBytecodeSignature(memberBytecodeSignature);
+ }
+
+
((IProgramElement)stack.peek()).addChild(peNode);
stack.push(peNode);
return true;
@@ -544,7 +579,7 @@ public class AsmHierarchyBuilder extends ASTVisitor {
}
private String genSourceSignature(ConstructorDeclaration constructorDeclaration) {
StringBuffer output = new StringBuffer();
- constructorDeclaration.printModifiers(constructorDeclaration.modifiers, output);
+ ASTNode.printModifiers(constructorDeclaration.modifiers, output);
output.append(constructorDeclaration.selector).append('(');
if (constructorDeclaration.arguments != null) {
for (int i = 0; i < constructorDeclaration.arguments.length; i++) {
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java
index b2b4d9c66..fa79a8360 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java
@@ -135,12 +135,23 @@ public class EclipseAdapterUtils {
seeAlso[i].getSourceLineNumber());
}
+ // We transform messages from AJ types to eclipse IProblems
+ // and back to AJ types. During their time as eclipse problems,
+ // we remember whether the message originated from a declare
+ // in the extraDetails.
+ String extraDetails = problem.getSupplementaryMessageInfo();
+ boolean declared = false;
+ if (extraDetails!=null && extraDetails.endsWith("[deow=true]")) {
+ declared = true;
+ extraDetails = extraDetails.substring(0,extraDetails.length()-"[deow=true]".length());
+ }
+
IMessage msg = new Message(problem.getMessage(),
- problem.getSupplementaryMessageInfo(),
+ extraDetails,
problem.isError() ? IMessage.ERROR : IMessage.WARNING,
sourceLocation,
null,
- seeAlsoLocations);
+ seeAlsoLocations,declared);
return msg;
}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java b/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java
index de8395967..1ec80de03 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java
@@ -188,6 +188,10 @@ public class Main {
ourHandler = new MessageHandler(true);
}
+ public MessageHandler getMessageHandler() {
+ return ourHandler;
+ }
+
/**
* Run without throwing exceptions but optionally using System.exit(..).
* This sets up a message handler which emits messages immediately,
@@ -525,13 +529,15 @@ public class Main {
}
/** @return System.err for FAIL, ABORT, ERROR, and WARNING,
- * System.out for INFO if verbose.
+ * System.out for INFO if -verbose and WEAVEINFO if -showWeaveInfo.
*/
protected PrintStream getStreamFor(IMessage.Kind kind) {
if (IMessage.WARNING.isSameOrLessThan(kind)) {
return System.err;
} else if (verbose && IMessage.INFO.equals(kind)) {
return System.out;
+ } else if (IMessage.WEAVEINFO.equals(kind)) {
+ return System.out;
} else {
return null;
}
diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java
index 96a5021ae..4205b733c 100644
--- a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java
+++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java
@@ -191,7 +191,9 @@ public class BcweaverJarMaker {
args.add("../tests/bugs/StringToString/helloworld.jar");
args.add("../tests/bugs/StringToString/HW.java");
CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS);
- }
+
+ buildShowWeaveInfoTestingJars();
+ }
public static void makeURLWeavingClassLoaderJars() throws IOException {
List args = new ArrayList();
@@ -296,7 +298,37 @@ public class BcweaverJarMaker {
args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWPerthis.aj");
CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS);
}
-
+
+ private static void buildJarWithClasspath(String outjar,String input,String deps,boolean nodebug) {
+ System.out.println(" Building "+outjar);
+ List args = new ArrayList();
+ if (nodebug) args.add("-g:none");
+ args.add("-classpath");
+ args.add("../lib/test/aspectjrt.jar;../lib/test/testing-client.jar" +
+ File.pathSeparator + System.getProperty("aspectjrt.path") +
+ (deps!=null?File.pathSeparator + "../ajde/testdata/WeaveInfoMessagesTest/"+deps:""));
+ args.add("-outjar");
+ args.add("../ajde/testdata/WeaveInfoMessagesTest/"+outjar);
+ args.add("../ajde/testdata/WeaveInfoMessagesTest/"+input);
+
+ System.err.println(args);
+ CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS);
+ }
+
+ private static void buildShowWeaveInfoTestingJars() {
+ System.out.println("For binary weave info message testing (ShowWeaveMessagesTestCase.java)");
+ buildJarWithClasspath("Simple.jar","Simple.java",null,false);
+ // Build with javac and jar
+ // buildJarWithClasspath("Simple_nodebug.jar","Simple.java",null,true);
+ buildJarWithClasspath("AspectAdvice.jar","AspectAdvice.aj",null,false);
+ buildJarWithClasspath("AspectAdvice_nodebug.jar","AspectAdvice.aj","Simple.jar",true);
+ buildJarWithClasspath("AspectDeclare.jar","AspectDeclare.aj","Simple.jar",false);
+ buildJarWithClasspath("AspectDeclare_nodebug.jar","AspectDeclare.aj","Simple.jar",true);
+ buildJarWithClasspath("AspectITD.jar","AspectITD.aj","Simple.jar",false);
+ buildJarWithClasspath("AspectITD_nodebug.jar","AspectITD.aj","Simple.jar",true);
+ buildJarWithClasspath("AspectDeclareSoft.jar","AspectDeclareSoft.aj","Simple.jar",false);
+ buildJarWithClasspath("AspectDeclareSoft_nodebug.jar","AspectDeclareSoft.aj","Simple.jar",true);
+ }
public static void makeDuplicateManifestTestJars() throws IOException {
List args = new ArrayList();
diff --git a/testing/src/org/aspectj/testing/harness/bridge/IncCompilerRun.java b/testing/src/org/aspectj/testing/harness/bridge/IncCompilerRun.java
index f226d00d9..485dfe3d4 100644
--- a/testing/src/org/aspectj/testing/harness/bridge/IncCompilerRun.java
+++ b/testing/src/org/aspectj/testing/harness/bridge/IncCompilerRun.java
@@ -23,6 +23,8 @@ import java.util.List;
//import java.util.Collections;
//import java.util.List;
+import org.aspectj.ajde.ui.StructureModelUtil;
+import org.aspectj.ajde.ui.StructureModelUtil.ModelIncorrectException;
import org.aspectj.bridge.ICommand;
//import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageUtil;
@@ -241,6 +243,9 @@ public class IncCompilerRun implements IAjcRun {
}
// final long startTime = System.currentTimeMillis();
commandResult = compiler.repeatCommand(handler);
+ if (!spec.checkModel.equals("")) {
+ StructureModelUtil.checkModel(spec.checkModel);
+ }
// XXX disabled LangUtil.throwIaxIfNotAllAssignable(actualRecompiled, File.class, "recompiled");
report = true;
// handler does not verify sandbox...
@@ -258,6 +263,8 @@ public class IncCompilerRun implements IAjcRun {
result = dirChanges.end(status, sandbox.testBaseDir);
}
}
+ } catch (ModelIncorrectException e) {
+ MessageUtil.fail(status,e.getMessage());
} finally {
if (!result || spec.runtime.isVerbose()) { // more debugging context in case of failure
MessageUtil.info(handler, "spec: " + spec.toLongString());
@@ -293,6 +300,8 @@ public class IncCompilerRun implements IAjcRun {
protected ArrayList classesAdded;
protected ArrayList classesRemoved;
protected ArrayList classesUpdated;
+
+ protected String checkModel;
/**
* skip description, skip sourceLocation,
@@ -312,6 +321,7 @@ public class IncCompilerRun implements IAjcRun {
classesAdded = new ArrayList();
classesRemoved = new ArrayList();
classesUpdated = new ArrayList();
+ checkModel="";
}
protected void initClone(Spec spec)
@@ -341,8 +351,13 @@ public class IncCompilerRun implements IAjcRun {
public void setTag(String input) {
tag = input;
}
+
+ public void setCheckModel(String thingsToCheck) {
+ this.checkModel=thingsToCheck;
+ }
+
public String toString() {
- return "IncCompile.Spec(" + tag + ", " + super.toString() + ")";
+ return "IncCompile.Spec(" + tag + ", " + super.toString() + ",["+checkModel+"])";
}
/** override to set dirToken to Sandbox.CLASSES and default suffix to ".class" */
diff --git a/testing/src/org/aspectj/testing/xml/SoftMessage.java b/testing/src/org/aspectj/testing/xml/SoftMessage.java
index 9c8ca57e1..88869e757 100644
--- a/testing/src/org/aspectj/testing/xml/SoftMessage.java
+++ b/testing/src/org/aspectj/testing/xml/SoftMessage.java
@@ -222,6 +222,8 @@ public class SoftMessage implements IMessage {
public boolean isFailed() {
return kind == IMessage.FAIL;
}
+
+ public boolean getDeclared() { return false; }
/** @return non-null String with simple message */
final public String getMessage() {
diff --git a/tests/ajcTestSuite.dtd b/tests/ajcTestSuite.dtd
index 45c00f0c0..c324963d7 100644
--- a/tests/ajcTestSuite.dtd
+++ b/tests/ajcTestSuite.dtd
@@ -30,6 +30,7 @@
<!ELEMENT inc-compile (dir-changes*,message*)>
<!ATTLIST inc-compile tag CDATA #REQUIRED >
<!ATTLIST inc-compile fresh CDATA #IMPLIED >
+ <!ATTLIST inc-compile checkModel CDATA #IMPLIED >
<!ELEMENT run (dir-changes*,message*)>
<!ATTLIST run class CDATA #REQUIRED >
diff --git a/tests/incModelTests.xml b/tests/incModelTests.xml
new file mode 100644
index 000000000..e8104794e
--- /dev/null
+++ b/tests/incModelTests.xml
@@ -0,0 +1,102 @@
+
+<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd">
+
+<suite>
+<!--
+ In order for these tests to pass you have to flip this flag to true:
+ AsmManager.attemptIncrementalModelRepairs
+
+ If you want to debug the output from the tests, you might want uncomment
+ the static initializer in AsmManager which will enable you to collect
+ detailed information on model processing.
+-->
+
+<!--
+ These tests utilise the inc-compile test harness option but I've extended it
+ with a checkModel option which enables me to check information about the model
+ after a incremental compilation step.
+-->
+
+<!--
+ asm relationships for inter type declarations are tricky things.
+ Today, because type mungers don't remember where they came from in attribute form,
+ the relationships for ITDs are created during source compilation. When building incrementally,
+ we are really doing a binary weave of 'everything else' with the source for the file that
+ has changed. In this case the relationships for ITDs are not added. This makes managing
+ them incrementally in the model rather tough!
+
+ The solution is to make them remember where they came from. This would mean we can create
+ the relationships during weave time and so they will be created when either doing a
+ source compilation or a binary weave. The support is in ResolvedTypeMunger to remember
+ where they came from (you just have to flick a switch) but I haven't switched it on
+ because we need to version *all* aspectj attributes properly so that we don't end up with
+ a migration nightmare. If ITD attributes remembered their location in a particular version
+ of AspectJ then everyone would need to recompile their code from source with that version.
+ If we keep changing the attributes, we keep having this problem. If we include a *version*
+ number in every attribute we can make the compiler more robust to coping with 'old' attributes
+ that might be missing certain options or values.
+
+ Hence the first test here is not complete...
+
+-->
+ <ajc-test dir="incremental/model/introduction"
+ title="Testing incremental structure model: Intertype declarations (and a declare parents)"
+ keywords="incremental-test,model-test" >
+ <compile staging="true" options="-incremental,-emacssym" sourceroots="."/>
+ <inc-compile tag="20"/> <!-- Just 'touched' one file -->
+ <inc-compile tag="30"/> <!-- Just 'touched another aspect -->
+ </ajc-test>
+
+ <ajc-test dir="incremental/model/intertype"
+ title="Testing incremental structure model: Intertype field declarations"
+ keywords="incremental-test,model-test" >
+ <compile staging="true" options="-incremental,-emacssym" sourceroots="."/>
+ <inc-compile tag="20" checkModel="inter-type field=2,RelationshipMapSize=3"/> <!-- BetaA intertypes int i and String s -->
+ <inc-compile tag="30" checkModel="inter-type field=1,RelationshipMapSize=2"/> <!-- BetaA takes the String intertype away -->
+ </ajc-test>
+
+ <ajc-test dir="incremental/model/weaving2"
+ title="Testing incremental structure model: Weaving handlers"
+ keywords="incremental-test,model-test" >
+ <compile staging="true" options="-incremental,-emacssym" sourceroots="."/>
+ <inc-compile tag="20" checkModel="code=1,advice=1,RelationshipMapSize=2"/> <!-- BetaA has a new piece of handler advice added -->
+ <inc-compile tag="30" checkModel="code=1,advice=2,RelationshipMapSize=3"/> <!-- secondary.GammaA added, also advises the same handler -->
+ <inc-compile tag="40" checkModel="code=1,advice=1,RelationshipMapSize=2"/> <!-- primary.BetaA deleted -->
+ </ajc-test>
+
+ <ajc-test dir="incremental/model/weaving"
+ title="Testing incremental structure model: Weaving"
+ keywords="incremental-test,model-test" >
+ <compile staging="true" options="-incremental,-emacssym" sourceroots="."/>
+ <inc-compile tag="20" checkModel="code=2,advice=2,java source file=3,RelationshipMapSize=4"/> <!-- BetaA has a new piece of advice added -->
+ <inc-compile tag="30" checkModel="code=1,advice=1,RelationshipMapSize=2"/> <!-- BetaA has a piece of advice removed -->
+ <inc-compile tag="40" checkModel="code=0,RelationshipMapSize=0,advice=0"/> <!-- BetaA other piece of advice removed (now empty) -->
+ </ajc-test>
+
+
+ <ajc-test dir="incremental/model/sourcefiles_updating"
+ title="Testing incremental structure model: Updating files"
+ keywords="incremental-test,model-test" >
+ <compile staging="true" options="-incremental,-emacssym" sourceroots="."/>
+ <!-- On first compile, 5 source files in model, 'root','Alpha','Beta','Gamma','Delta' -->
+ <inc-compile tag="20" checkModel="java source file=5,method=4,class=3,FileMapSize=4"/> <!-- Beta changed, method added -->
+ <inc-compile tag="30" checkModel="java source file=5,method=4,class=4,advice=1"/> <!-- Delta changed, class added -->
+ <inc-compile tag="40" checkModel="advice=2"/> <!-- Gamma changed, advice added -->
+ <inc-compile tag="50" checkModel="advice=2,pointcut=1"/> <!-- Gamma changed, pointcut added -->
+ <inc-compile tag="60" checkModel="advice=0,pointcut=1"/> <!-- Gamma changed, both advice removed -->
+ </ajc-test>
+
+ <ajc-test dir="incremental/model/sourcefiles_addremove"
+ title="Testing incremental structure model: Adding and removing files"
+ keywords="incremental-test,model-test" >
+ <compile staging="true" options="-incremental,-emacssym" sourceroots="."/>
+ <!-- On first compile, two source files in model, 'root' and 'Alpha' -->
+ <inc-compile tag="20" checkModel="java source file=3,FileMapSize=2"/> <!-- Adds primary.Beta class -->
+ <inc-compile tag="30" checkModel="java source file=4"/> <!-- Adds secondary.Gamma aspect -->
+ <inc-compile tag="40" checkModel="java source file=5,package=2,FileMapSize=4"/> <!-- Adds seconday.Delta class -->
+ <inc-compile tag="50" checkModel="java source file=4,package=2"/> <!-- Deletes Gamma aspect -->
+ <inc-compile tag="60" checkModel="java source file=2,FileMapSize=1"/> <!-- Deletes Beta and Delta classes -->
+ </ajc-test>
+
+
+</suite> \ No newline at end of file
diff --git a/tests/incremental/model/intertype/primary/Alpha.java b/tests/incremental/model/intertype/primary/Alpha.java
new file mode 100644
index 000000000..4f77e13d2
--- /dev/null
+++ b/tests/incremental/model/intertype/primary/Alpha.java
@@ -0,0 +1,7 @@
+package primary;
+
+public class Alpha {
+ public static void main(String [] argv) {
+ }
+}
+
diff --git a/tests/incremental/model/intertype/secondary/BetaA.20.java b/tests/incremental/model/intertype/secondary/BetaA.20.java
new file mode 100644
index 000000000..abe370ecd
--- /dev/null
+++ b/tests/incremental/model/intertype/secondary/BetaA.20.java
@@ -0,0 +1,8 @@
+package secondary;
+
+import primary.Alpha;
+
+public aspect BetaA {
+ int Alpha.i;
+ String Alpha.s;
+}
diff --git a/tests/incremental/model/intertype/secondary/BetaA.30.java b/tests/incremental/model/intertype/secondary/BetaA.30.java
new file mode 100644
index 000000000..394c7a925
--- /dev/null
+++ b/tests/incremental/model/intertype/secondary/BetaA.30.java
@@ -0,0 +1,7 @@
+package secondary;
+
+import primary.Alpha;
+
+public aspect BetaA {
+ String Alpha.s;
+}
diff --git a/tests/incremental/model/introduction/introduction/CloneablePoint.20.java b/tests/incremental/model/introduction/introduction/CloneablePoint.20.java
new file mode 100644
index 000000000..c34509850
--- /dev/null
+++ b/tests/incremental/model/introduction/introduction/CloneablePoint.20.java
@@ -0,0 +1,42 @@
+/*
+
+Copyright (c) Xerox Corporation 1998-2002. All rights reserved.
+
+Use and copying of this software and preparation of derivative works based
+upon this software are permitted. Any distribution of this software or
+derivative works must comply with all applicable United States export control
+laws.
+
+This software is made available AS IS, and Xerox Corporation makes no warranty
+about the software, its performance or its conformity to any specification.
+
+*/
+package introduction;
+
+public aspect CloneablePoint {
+
+ declare parents: Point implements Cloneable;
+
+ public Object Point.clone() throws CloneNotSupportedException {
+ // we choose to bring all fields up to date before cloning.
+ makeRectangular();
+ makePolar();
+ return super.clone();
+ }
+
+ public static void main(String[] args){
+ Point p1 = new Point();
+ Point p2 = null;
+
+ p1.setPolar(Math.PI, 1.0);
+ try {
+ p2 = (Point)p1.clone();
+ } catch (CloneNotSupportedException e) {}
+ System.out.println("p1 =" + p1 );
+ System.out.println("p2 =" + p2 );
+
+ p1.rotate(Math.PI / -2);
+ System.out.println("p1 =" + p1 );
+ System.out.println("p2 =" + p2 );
+ }
+}
diff --git a/tests/incremental/model/introduction/introduction/CloneablePoint.java b/tests/incremental/model/introduction/introduction/CloneablePoint.java
new file mode 100644
index 000000000..c34509850
--- /dev/null
+++ b/tests/incremental/model/introduction/introduction/CloneablePoint.java
@@ -0,0 +1,42 @@
+/*
+
+Copyright (c) Xerox Corporation 1998-2002. All rights reserved.
+
+Use and copying of this software and preparation of derivative works based
+upon this software are permitted. Any distribution of this software or
+derivative works must comply with all applicable United States export control
+laws.
+
+This software is made available AS IS, and Xerox Corporation makes no warranty
+about the software, its performance or its conformity to any specification.
+
+*/
+package introduction;
+
+public aspect CloneablePoint {
+
+ declare parents: Point implements Cloneable;
+
+ public Object Point.clone() throws CloneNotSupportedException {
+ // we choose to bring all fields up to date before cloning.
+ makeRectangular();
+ makePolar();
+ return super.clone();
+ }
+
+ public static void main(String[] args){
+ Point p1 = new Point();
+ Point p2 = null;
+
+ p1.setPolar(Math.PI, 1.0);
+ try {
+ p2 = (Point)p1.clone();
+ } catch (CloneNotSupportedException e) {}
+ System.out.println("p1 =" + p1 );
+ System.out.println("p2 =" + p2 );
+
+ p1.rotate(Math.PI / -2);
+ System.out.println("p1 =" + p1 );
+ System.out.println("p2 =" + p2 );
+ }
+}
diff --git a/tests/incremental/model/introduction/introduction/ComparablePoint.java b/tests/incremental/model/introduction/introduction/ComparablePoint.java
new file mode 100644
index 000000000..a2893dba0
--- /dev/null
+++ b/tests/incremental/model/introduction/introduction/ComparablePoint.java
@@ -0,0 +1,46 @@
+/*
+Copyright (c) Xerox Corporation 1998-2002. All rights reserved.
+
+Use and copying of this software and preparation of derivative works based
+upon this software are permitted. Any distribution of this software or
+derivative works must comply with all applicable United States export control
+laws.
+
+This software is made available AS IS, and Xerox Corporation makes no warranty
+about the software, its performance or its conformity to any specification.
+*/
+
+package introduction;
+
+public aspect ComparablePoint {
+
+ declare parents: Point implements Comparable;
+
+ public int Point.compareTo(Object o) {
+ return (int) (this.getRho() - ((Point)o).getRho());
+ }
+
+ public static void main(String[] args){
+ Point p1 = new Point();
+ Point p2 = new Point();
+
+ System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
+
+ p1.setRectangular(2,5);
+ p2.setRectangular(2,5);
+ System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
+
+ p2.setRectangular(3,6);
+ System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
+
+ p1.setPolar(Math.PI, 4);
+ p2.setPolar(Math.PI, 4);
+ System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
+
+ p1.rotate(Math.PI / 4.0);
+ System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
+
+ p1.offset(1,1);
+ System.out.println("p1 =?= p2 :" + p1.compareTo(p2));
+ }
+}
diff --git a/tests/incremental/model/introduction/introduction/HashablePoint.30.java b/tests/incremental/model/introduction/introduction/HashablePoint.30.java
new file mode 100644
index 000000000..39eb33ba4
--- /dev/null
+++ b/tests/incremental/model/introduction/introduction/HashablePoint.30.java
@@ -0,0 +1,47 @@
+/*
+Copyright (c) Xerox Corporation 1998-2002. All rights reserved.
+
+Use and copying of this software and preparation of derivative works based
+upon this software are permitted. Any distribution of this software or
+derivative works must comply with all applicable United States export control
+laws.
+
+This software is made available AS IS, and Xerox Corporation makes no warranty
+about the software, its performance or its conformity to any specification.
+*/
+
+package introduction;
+
+import java.util.Hashtable;
+
+public aspect HashablePoint {
+
+ public int Point.hashCode() {
+ return (int) (getX() + getY() % Integer.MAX_VALUE);
+ }
+
+ public boolean Point.equals(Object o) {
+ if (o == this) { return true; }
+ if (!(o instanceof Point)) { return false; }
+ Point other = (Point)o;
+ return (getX() == other.getX()) && (getY() == other.getY());
+ }
+
+ public static void main(String[] args) {
+ Hashtable h = new Hashtable();
+ Point p1 = new Point();
+
+ p1.setRectangular(10, 10);
+ Point p2 = new Point();
+
+ p2.setRectangular(10, 10);
+
+ System.out.println("p1 = " + p1);
+ System.out.println("p2 = " + p2);
+ System.out.println("p1.hashCode() = " + p1.hashCode());
+ System.out.println("p2.hashCode() = " + p2.hashCode());
+
+ h.put(p1, "P1");
+ System.out.println("Got: " + h.get(p2));
+ }
+}
diff --git a/tests/incremental/model/introduction/introduction/HashablePoint.java b/tests/incremental/model/introduction/introduction/HashablePoint.java
new file mode 100644
index 000000000..39eb33ba4
--- /dev/null
+++ b/tests/incremental/model/introduction/introduction/HashablePoint.java
@@ -0,0 +1,47 @@
+/*
+Copyright (c) Xerox Corporation 1998-2002. All rights reserved.
+
+Use and copying of this software and preparation of derivative works based
+upon this software are permitted. Any distribution of this software or
+derivative works must comply with all applicable United States export control
+laws.
+
+This software is made available AS IS, and Xerox Corporation makes no warranty
+about the software, its performance or its conformity to any specification.
+*/
+
+package introduction;
+
+import java.util.Hashtable;
+
+public aspect HashablePoint {
+
+ public int Point.hashCode() {
+ return (int) (getX() + getY() % Integer.MAX_VALUE);
+ }
+
+ public boolean Point.equals(Object o) {
+ if (o == this) { return true; }
+ if (!(o instanceof Point)) { return false; }
+ Point other = (Point)o;
+ return (getX() == other.getX()) && (getY() == other.getY());
+ }
+
+ public static void main(String[] args) {
+ Hashtable h = new Hashtable();
+ Point p1 = new Point();
+
+ p1.setRectangular(10, 10);
+ Point p2 = new Point();
+
+ p2.setRectangular(10, 10);
+
+ System.out.println("p1 = " + p1);
+ System.out.println("p2 = " + p2);
+ System.out.println("p1.hashCode() = " + p1.hashCode());
+ System.out.println("p2.hashCode() = " + p2.hashCode());
+
+ h.put(p1, "P1");
+ System.out.println("Got: " + h.get(p2));
+ }
+}
diff --git a/tests/incremental/model/introduction/introduction/Point.30.java b/tests/incremental/model/introduction/introduction/Point.30.java
new file mode 100644
index 000000000..609a0488c
--- /dev/null
+++ b/tests/incremental/model/introduction/introduction/Point.30.java
@@ -0,0 +1,98 @@
+/*
+ Copyright (c) Xerox Corporation 1998-2002. All rights reserved.
+
+ Use and copying of this software and preparation of derivative works based
+ upon this software are permitted. Any distribution of this software or
+ derivative works must comply with all applicable United States export control
+ laws.
+
+ This software is made available AS IS, and Xerox Corporation makes no warranty
+ about the software, its performance or its conformity to any specification.
+*/
+
+package introduction;
+
+public class Point {
+
+ protected double x = 0;
+ protected double y = 0;
+ protected double theta = 0;
+ protected double rho = 0;
+
+ protected boolean polar = true;
+ protected boolean rectangular = true;
+
+ public double getX(){
+ makeRectangular();
+ return x;
+ }
+
+ public double getY(){
+ makeRectangular();
+ return y;
+ }
+
+ public double getTheta(){
+ makePolar();
+ return theta;
+ }
+
+ public double getRho(){
+ makePolar();
+ return rho;
+ }
+
+ public void setRectangular(double newX, double newY){
+ x = newX;
+ y = newY;
+ rectangular = true;
+ polar = false;
+ }
+
+ public void setPolar(double newTheta, double newRho){
+ theta = newTheta;
+ rho = newRho;
+ rectangular = false;
+ polar = true;
+ }
+
+ public void rotate(double angle){
+ setPolar(theta + angle, rho);
+ }
+
+ public void offset(double deltaX, double deltaY){
+ setRectangular(x + deltaX, y + deltaY);
+ }
+
+ protected void makePolar(){
+ if (!polar){
+ theta = Math.atan2(y,x);
+ rho = y / Math.sin(theta);
+ polar = true;
+ }
+ }
+
+ protected void makeRectangular(){
+ if (!rectangular) {
+ x = rho * Math.sin(theta);
+ y = rho * Math.cos(theta);
+ rectangular = true;
+ }
+ }
+
+ public String toString(){
+ return "(" + getX() + ", " + getY() + ")["
+ + getTheta() + " : " + getRho() + "]";
+ }
+
+ public static void main(String[] args){
+ Point p1 = new Point();
+ System.out.println("p1 =" + p1);
+ p1.setRectangular(5,2);
+ System.out.println("p1 =" + p1);
+ p1.setPolar( Math.PI / 4.0 , 1.0);
+ System.out.println("p1 =" + p1);
+ p1.setPolar( 0.3805 , 5.385);
+ System.out.println("p1 =" + p1);
+ }
+}
diff --git a/tests/incremental/model/introduction/introduction/Point.java b/tests/incremental/model/introduction/introduction/Point.java
new file mode 100644
index 000000000..609a0488c
--- /dev/null
+++ b/tests/incremental/model/introduction/introduction/Point.java
@@ -0,0 +1,98 @@
+/*
+ Copyright (c) Xerox Corporation 1998-2002. All rights reserved.
+
+ Use and copying of this software and preparation of derivative works based
+ upon this software are permitted. Any distribution of this software or
+ derivative works must comply with all applicable United States export control
+ laws.
+
+ This software is made available AS IS, and Xerox Corporation makes no warranty
+ about the software, its performance or its conformity to any specification.
+*/
+
+package introduction;
+
+public class Point {
+
+ protected double x = 0;
+ protected double y = 0;
+ protected double theta = 0;
+ protected double rho = 0;
+
+ protected boolean polar = true;
+ protected boolean rectangular = true;
+
+ public double getX(){
+ makeRectangular();
+ return x;
+ }
+
+ public double getY(){
+ makeRectangular();
+ return y;
+ }
+
+ public double getTheta(){
+ makePolar();
+ return theta;
+ }
+
+ public double getRho(){
+ makePolar();
+ return rho;
+ }
+
+ public void setRectangular(double newX, double newY){
+ x = newX;
+ y = newY;
+ rectangular = true;
+ polar = false;
+ }
+
+ public void setPolar(double newTheta, double newRho){
+ theta = newTheta;
+ rho = newRho;
+ rectangular = false;
+ polar = true;
+ }
+
+ public void rotate(double angle){
+ setPolar(theta + angle, rho);
+ }
+
+ public void offset(double deltaX, double deltaY){
+ setRectangular(x + deltaX, y + deltaY);
+ }
+
+ protected void makePolar(){
+ if (!polar){
+ theta = Math.atan2(y,x);
+ rho = y / Math.sin(theta);
+ polar = true;
+ }
+ }
+
+ protected void makeRectangular(){
+ if (!rectangular) {
+ x = rho * Math.sin(theta);
+ y = rho * Math.cos(theta);
+ rectangular = true;
+ }
+ }
+
+ public String toString(){
+ return "(" + getX() + ", " + getY() + ")["
+ + getTheta() + " : " + getRho() + "]";
+ }
+
+ public static void main(String[] args){
+ Point p1 = new Point();
+ System.out.println("p1 =" + p1);
+ p1.setRectangular(5,2);
+ System.out.println("p1 =" + p1);
+ p1.setPolar( Math.PI / 4.0 , 1.0);
+ System.out.println("p1 =" + p1);
+ p1.setPolar( 0.3805 , 5.385);
+ System.out.println("p1 =" + p1);
+ }
+}
diff --git a/tests/incremental/model/sourcefiles_addremove/primary/Alpha.java b/tests/incremental/model/sourcefiles_addremove/primary/Alpha.java
new file mode 100644
index 000000000..5e60f4f34
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_addremove/primary/Alpha.java
@@ -0,0 +1,7 @@
+
+package primary;
+
+public class Alpha {
+ public static void main (String[] args) {
+ }
+}
diff --git a/tests/incremental/model/sourcefiles_addremove/primary/Beta.20.java b/tests/incremental/model/sourcefiles_addremove/primary/Beta.20.java
new file mode 100644
index 000000000..1ef401ca8
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_addremove/primary/Beta.20.java
@@ -0,0 +1,11 @@
+package primary;
+
+public class Beta {
+ public static void main(String[] argv) {
+ sayhi();
+ }
+
+ public static void sayhi() {
+ System.err.println("Hi");
+ }
+}
diff --git a/tests/incremental/model/sourcefiles_addremove/primary/Beta.delete.60.java b/tests/incremental/model/sourcefiles_addremove/primary/Beta.delete.60.java
new file mode 100644
index 000000000..1ef401ca8
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_addremove/primary/Beta.delete.60.java
@@ -0,0 +1,11 @@
+package primary;
+
+public class Beta {
+ public static void main(String[] argv) {
+ sayhi();
+ }
+
+ public static void sayhi() {
+ System.err.println("Hi");
+ }
+}
diff --git a/tests/incremental/model/sourcefiles_addremove/secondary/Delta.40.java b/tests/incremental/model/sourcefiles_addremove/secondary/Delta.40.java
new file mode 100644
index 000000000..ed410eda9
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_addremove/secondary/Delta.40.java
@@ -0,0 +1,5 @@
+package secondary;
+
+public class Delta {
+ public static void foo() { }
+}
diff --git a/tests/incremental/model/sourcefiles_addremove/secondary/Delta.delete.60.java b/tests/incremental/model/sourcefiles_addremove/secondary/Delta.delete.60.java
new file mode 100644
index 000000000..ed410eda9
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_addremove/secondary/Delta.delete.60.java
@@ -0,0 +1,5 @@
+package secondary;
+
+public class Delta {
+ public static void foo() { }
+}
diff --git a/tests/incremental/model/sourcefiles_addremove/secondary/Gamma.30.java b/tests/incremental/model/sourcefiles_addremove/secondary/Gamma.30.java
new file mode 100644
index 000000000..edbe7169f
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_addremove/secondary/Gamma.30.java
@@ -0,0 +1,7 @@
+package secondary;
+
+aspect Gamma {
+ before(): call(* *(..)) {
+ }
+}
+
diff --git a/tests/incremental/model/sourcefiles_addremove/secondary/Gamma.delete.50.java b/tests/incremental/model/sourcefiles_addremove/secondary/Gamma.delete.50.java
new file mode 100644
index 000000000..edbe7169f
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_addremove/secondary/Gamma.delete.50.java
@@ -0,0 +1,7 @@
+package secondary;
+
+aspect Gamma {
+ before(): call(* *(..)) {
+ }
+}
+
diff --git a/tests/incremental/model/sourcefiles_updating/primary/Alpha.java b/tests/incremental/model/sourcefiles_updating/primary/Alpha.java
new file mode 100644
index 000000000..5e60f4f34
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_updating/primary/Alpha.java
@@ -0,0 +1,7 @@
+
+package primary;
+
+public class Alpha {
+ public static void main (String[] args) {
+ }
+}
diff --git a/tests/incremental/model/sourcefiles_updating/primary/Beta.20.java b/tests/incremental/model/sourcefiles_updating/primary/Beta.20.java
new file mode 100644
index 000000000..4efd977e8
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_updating/primary/Beta.20.java
@@ -0,0 +1,13 @@
+package primary;
+
+// Method added beyond what was in Beta.java
+
+public class Beta {
+ public static void main(String[] argv) {
+ sayhi();
+ }
+
+ public static void sayhi() {
+ System.err.println("Hi");
+ }
+}
diff --git a/tests/incremental/model/sourcefiles_updating/primary/Beta.java b/tests/incremental/model/sourcefiles_updating/primary/Beta.java
new file mode 100644
index 000000000..86dc7dfd8
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_updating/primary/Beta.java
@@ -0,0 +1,7 @@
+package primary;
+
+public class Beta {
+ public static void main(String[] argv) {
+ }
+
+}
diff --git a/tests/incremental/model/sourcefiles_updating/secondary/Delta.30.java b/tests/incremental/model/sourcefiles_updating/secondary/Delta.30.java
new file mode 100644
index 000000000..f54b3f7f0
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_updating/secondary/Delta.30.java
@@ -0,0 +1,10 @@
+package secondary;
+
+// Extra class added over Delta.java
+
+public class Delta {
+ public static void foo() { }
+}
+
+class DeltaExtra {
+}
diff --git a/tests/incremental/model/sourcefiles_updating/secondary/Delta.java b/tests/incremental/model/sourcefiles_updating/secondary/Delta.java
new file mode 100644
index 000000000..ed410eda9
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_updating/secondary/Delta.java
@@ -0,0 +1,5 @@
+package secondary;
+
+public class Delta {
+ public static void foo() { }
+}
diff --git a/tests/incremental/model/sourcefiles_updating/secondary/Gamma.40.java b/tests/incremental/model/sourcefiles_updating/secondary/Gamma.40.java
new file mode 100644
index 000000000..7e508af0e
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_updating/secondary/Gamma.40.java
@@ -0,0 +1,10 @@
+package secondary;
+
+aspect Gamma {
+ before(): call(* *(..)) {
+ }
+
+ after(): call(* *(..)) {
+ }
+}
+
diff --git a/tests/incremental/model/sourcefiles_updating/secondary/Gamma.50.java b/tests/incremental/model/sourcefiles_updating/secondary/Gamma.50.java
new file mode 100644
index 000000000..a380f8651
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_updating/secondary/Gamma.50.java
@@ -0,0 +1,13 @@
+package secondary;
+
+aspect Gamma {
+
+ pointcut calls(): call(* *(..));
+
+ before(): calls() {
+ }
+
+ after(): calls() {
+ }
+}
+
diff --git a/tests/incremental/model/sourcefiles_updating/secondary/Gamma.60.java b/tests/incremental/model/sourcefiles_updating/secondary/Gamma.60.java
new file mode 100644
index 000000000..de4cf6d81
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_updating/secondary/Gamma.60.java
@@ -0,0 +1,8 @@
+package secondary;
+
+aspect Gamma {
+
+ pointcut calls(): call(* *(..));
+
+}
+
diff --git a/tests/incremental/model/sourcefiles_updating/secondary/Gamma.java b/tests/incremental/model/sourcefiles_updating/secondary/Gamma.java
new file mode 100644
index 000000000..edbe7169f
--- /dev/null
+++ b/tests/incremental/model/sourcefiles_updating/secondary/Gamma.java
@@ -0,0 +1,7 @@
+package secondary;
+
+aspect Gamma {
+ before(): call(* *(..)) {
+ }
+}
+
diff --git a/tests/incremental/model/weaving/primary/Alpha.java b/tests/incremental/model/weaving/primary/Alpha.java
new file mode 100644
index 000000000..e51f9f972
--- /dev/null
+++ b/tests/incremental/model/weaving/primary/Alpha.java
@@ -0,0 +1,21 @@
+package primary;
+
+public class Alpha {
+ public static void main(String[] argv) {
+ Alpha instance = new Alpha();
+ instance.m1();
+ instance.m2();
+ instance.m3();
+ }
+
+ public void m1() {
+ }
+
+ public boolean m2() {
+ return false;
+ }
+
+ public String m3() {
+ return "";
+ }
+}
diff --git a/tests/incremental/model/weaving/primary/BetaA.20.java b/tests/incremental/model/weaving/primary/BetaA.20.java
new file mode 100644
index 000000000..74ff7481f
--- /dev/null
+++ b/tests/incremental/model/weaving/primary/BetaA.20.java
@@ -0,0 +1,16 @@
+package primary;
+
+public aspect BetaA {
+
+ pointcut m1call(): call(* m1(..));
+
+ before(): m1call() {
+ System.err.println("m1 got called");
+ }
+
+ pointcut m2call(): call(* m2(..));
+
+ before(): m2call() {
+ System.err.println("m2 got called");
+ }
+}
diff --git a/tests/incremental/model/weaving/primary/BetaA.30.java b/tests/incremental/model/weaving/primary/BetaA.30.java
new file mode 100644
index 000000000..eeba653b7
--- /dev/null
+++ b/tests/incremental/model/weaving/primary/BetaA.30.java
@@ -0,0 +1,10 @@
+package primary;
+
+public aspect BetaA {
+
+ pointcut m2call(): call(* m2(..));
+
+ before(): m2call() {
+ System.err.println("m2 got called");
+ }
+}
diff --git a/tests/incremental/model/weaving/primary/BetaA.40.java b/tests/incremental/model/weaving/primary/BetaA.40.java
new file mode 100644
index 000000000..706cebb17
--- /dev/null
+++ b/tests/incremental/model/weaving/primary/BetaA.40.java
@@ -0,0 +1,5 @@
+package primary;
+
+public aspect BetaA {
+
+}
diff --git a/tests/incremental/model/weaving/primary/BetaA.java b/tests/incremental/model/weaving/primary/BetaA.java
new file mode 100644
index 000000000..333c5f187
--- /dev/null
+++ b/tests/incremental/model/weaving/primary/BetaA.java
@@ -0,0 +1,10 @@
+package primary;
+
+public aspect BetaA {
+
+ pointcut m1call(): call(* m1(..));
+
+ before(): m1call() {
+ System.err.println("m1 got called");
+ }
+}
diff --git a/tests/incremental/model/weaving2/primary/Alpha.java b/tests/incremental/model/weaving2/primary/Alpha.java
new file mode 100644
index 000000000..ab7e82c16
--- /dev/null
+++ b/tests/incremental/model/weaving2/primary/Alpha.java
@@ -0,0 +1,11 @@
+package primary;
+
+public class Alpha {
+ public static void main(String[]argv) {
+ try {
+ System.err.println("aaa");
+ } catch (Throwable t) {
+ System.err.println("Caught:"+t);
+ }
+ }
+}
diff --git a/tests/incremental/model/weaving2/primary/BetaA.20.java b/tests/incremental/model/weaving2/primary/BetaA.20.java
new file mode 100644
index 000000000..1c73c6b9d
--- /dev/null
+++ b/tests/incremental/model/weaving2/primary/BetaA.20.java
@@ -0,0 +1,8 @@
+package primary;
+
+public aspect BetaA {
+ pointcut handlers(): handler(Throwable);
+ before(): handlers() {
+ System.err.println("xxx");
+ }
+}
diff --git a/tests/incremental/model/weaving2/primary/BetaA.delete.40.java b/tests/incremental/model/weaving2/primary/BetaA.delete.40.java
new file mode 100644
index 000000000..1c73c6b9d
--- /dev/null
+++ b/tests/incremental/model/weaving2/primary/BetaA.delete.40.java
@@ -0,0 +1,8 @@
+package primary;
+
+public aspect BetaA {
+ pointcut handlers(): handler(Throwable);
+ before(): handlers() {
+ System.err.println("xxx");
+ }
+}
diff --git a/tests/incremental/model/weaving2/primary/BetaA.java b/tests/incremental/model/weaving2/primary/BetaA.java
new file mode 100644
index 000000000..1b8b1d7c8
--- /dev/null
+++ b/tests/incremental/model/weaving2/primary/BetaA.java
@@ -0,0 +1,4 @@
+package primary;
+
+public aspect BetaA {
+}
diff --git a/tests/incremental/model/weaving2/secondary/GammaA.30.java b/tests/incremental/model/weaving2/secondary/GammaA.30.java
new file mode 100644
index 000000000..be2bec758
--- /dev/null
+++ b/tests/incremental/model/weaving2/secondary/GammaA.30.java
@@ -0,0 +1,8 @@
+package primary;
+
+public aspect GammaA {
+ pointcut handlers(): handler(Throwable);
+ before(): handlers() {
+ System.err.println("xxx");
+ }
+}
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)+"]";
+ }
}