Browse Source

The BIG commit.

- Enhanced structure model support.
- *Incremental* structure model support written and tested (currently switched off, see incModelTests.xml)
- -showWeaveInfo compiler option
- existence of a 'runtimetest' surfaced through relationships
- UI can determine if errors/warnings came from DEOWs.
- Code to enable type mungers to remember source locations written (currently switched off)
tags/for_ajdt1_1_12
aclement 20 years ago
parent
commit
2982b4cc62
89 changed files with 2900 additions and 226 deletions
  1. 28
    6
      ajde/src/org/aspectj/ajde/internal/CompilerAdapter.java
  2. 55
    3
      ajde/src/org/aspectj/ajde/ui/StructureModelUtil.java
  3. 3
    1
      ajde/src/org/aspectj/ajde/ui/StructureViewNodeFactory.java
  4. 1
    0
      ajde/testsrc/org/aspectj/ajde/AjdeTests.java
  5. 5
    5
      ajde/testsrc/org/aspectj/ajde/AsmDeclarationsTest.java
  6. 4
    3
      ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java
  7. 39
    39
      ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java
  8. 376
    0
      ajde/testsrc/org/aspectj/ajde/ShowWeaveMessagesTestCase.java
  9. 481
    5
      asm/src/org/aspectj/asm/AsmManager.java
  10. 5
    0
      asm/src/org/aspectj/asm/IHierarchy.java
  11. 17
    0
      asm/src/org/aspectj/asm/IProgramElement.java
  12. 20
    4
      asm/src/org/aspectj/asm/IRelationship.java
  13. 18
    3
      asm/src/org/aspectj/asm/IRelationshipMap.java
  14. 27
    1
      asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java
  15. 40
    8
      asm/src/org/aspectj/asm/internal/ProgramElement.java
  16. 15
    2
      asm/src/org/aspectj/asm/internal/Relationship.java
  17. 54
    17
      asm/src/org/aspectj/asm/internal/RelationshipMap.java
  18. 5
    1
      bridge/src/org/aspectj/bridge/IMessage.java
  19. 23
    11
      bridge/src/org/aspectj/bridge/Message.java
  20. 3
    0
      bridge/src/org/aspectj/bridge/MessageHandler.java
  21. 75
    0
      bridge/src/org/aspectj/bridge/WeaveMessage.java
  22. 16
    0
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java
  23. 1
    0
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties
  24. 11
    1
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java
  25. 66
    10
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java
  26. 4
    4
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AsmInterTypeRelationshipProvider.java
  27. 3
    0
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java
  28. 17
    0
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
  29. 80
    19
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
  30. 1
    0
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java
  31. 44
    4
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java
  32. 86
    51
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java
  33. 13
    2
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java
  34. 7
    1
      org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java
  35. 34
    2
      org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java
  36. 16
    1
      testing/src/org/aspectj/testing/harness/bridge/IncCompilerRun.java
  37. 2
    0
      testing/src/org/aspectj/testing/xml/SoftMessage.java
  38. 1
    0
      tests/ajcTestSuite.dtd
  39. 102
    0
      tests/incModelTests.xml
  40. 7
    0
      tests/incremental/model/intertype/primary/Alpha.java
  41. 8
    0
      tests/incremental/model/intertype/secondary/BetaA.20.java
  42. 7
    0
      tests/incremental/model/intertype/secondary/BetaA.30.java
  43. 42
    0
      tests/incremental/model/introduction/introduction/CloneablePoint.20.java
  44. 42
    0
      tests/incremental/model/introduction/introduction/CloneablePoint.java
  45. 46
    0
      tests/incremental/model/introduction/introduction/ComparablePoint.java
  46. 47
    0
      tests/incremental/model/introduction/introduction/HashablePoint.30.java
  47. 47
    0
      tests/incremental/model/introduction/introduction/HashablePoint.java
  48. 98
    0
      tests/incremental/model/introduction/introduction/Point.30.java
  49. 98
    0
      tests/incremental/model/introduction/introduction/Point.java
  50. 7
    0
      tests/incremental/model/sourcefiles_addremove/primary/Alpha.java
  51. 11
    0
      tests/incremental/model/sourcefiles_addremove/primary/Beta.20.java
  52. 11
    0
      tests/incremental/model/sourcefiles_addremove/primary/Beta.delete.60.java
  53. 5
    0
      tests/incremental/model/sourcefiles_addremove/secondary/Delta.40.java
  54. 5
    0
      tests/incremental/model/sourcefiles_addremove/secondary/Delta.delete.60.java
  55. 7
    0
      tests/incremental/model/sourcefiles_addremove/secondary/Gamma.30.java
  56. 7
    0
      tests/incremental/model/sourcefiles_addremove/secondary/Gamma.delete.50.java
  57. 7
    0
      tests/incremental/model/sourcefiles_updating/primary/Alpha.java
  58. 13
    0
      tests/incremental/model/sourcefiles_updating/primary/Beta.20.java
  59. 7
    0
      tests/incremental/model/sourcefiles_updating/primary/Beta.java
  60. 10
    0
      tests/incremental/model/sourcefiles_updating/secondary/Delta.30.java
  61. 5
    0
      tests/incremental/model/sourcefiles_updating/secondary/Delta.java
  62. 10
    0
      tests/incremental/model/sourcefiles_updating/secondary/Gamma.40.java
  63. 13
    0
      tests/incremental/model/sourcefiles_updating/secondary/Gamma.50.java
  64. 8
    0
      tests/incremental/model/sourcefiles_updating/secondary/Gamma.60.java
  65. 7
    0
      tests/incremental/model/sourcefiles_updating/secondary/Gamma.java
  66. 21
    0
      tests/incremental/model/weaving/primary/Alpha.java
  67. 16
    0
      tests/incremental/model/weaving/primary/BetaA.20.java
  68. 10
    0
      tests/incremental/model/weaving/primary/BetaA.30.java
  69. 5
    0
      tests/incremental/model/weaving/primary/BetaA.40.java
  70. 10
    0
      tests/incremental/model/weaving/primary/BetaA.java
  71. 11
    0
      tests/incremental/model/weaving2/primary/Alpha.java
  72. 8
    0
      tests/incremental/model/weaving2/primary/BetaA.20.java
  73. 8
    0
      tests/incremental/model/weaving2/primary/BetaA.delete.40.java
  74. 4
    0
      tests/incremental/model/weaving2/primary/BetaA.java
  75. 8
    0
      tests/incremental/model/weaving2/secondary/GammaA.30.java
  76. 100
    10
      weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java
  77. 7
    3
      weaver/src/org/aspectj/weaver/Checker.java
  78. 2
    1
      weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java
  79. 5
    1
      weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java
  80. 4
    1
      weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java
  81. 4
    1
      weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
  82. 4
    1
      weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java
  83. 55
    0
      weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java
  84. 95
    1
      weaver/src/org/aspectj/weaver/Shadow.java
  85. 85
    0
      weaver/src/org/aspectj/weaver/WeaverMetrics.java
  86. 12
    2
      weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
  87. 43
    0
      weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java
  88. 6
    1
      weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
  89. 4
    0
      weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java

+ 28
- 6
ajde/src/org/aspectj/ajde/internal/CompilerAdapter.java View File

@@ -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

+ 55
- 3
ajde/src/org/aspectj/ajde/ui/StructureModelUtil.java View File

@@ -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.

+ 3
- 1
ajde/src/org/aspectj/ajde/ui/StructureViewNodeFactory.java View File

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

+ 1
- 0
ajde/testsrc/org/aspectj/ajde/AjdeTests.java View File

@@ -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;

+ 5
- 5
ajde/testsrc/org/aspectj/ajde/AsmDeclarationsTest.java View File

@@ -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");

+ 4
- 3
ajde/testsrc/org/aspectj/ajde/AsmRelationshipsTest.java View File

@@ -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);
//

+ 39
- 39
ajde/testsrc/org/aspectj/ajde/BuildCancellingTest.java View File

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

+ 376
- 0
ajde/testsrc/org/aspectj/ajde/ShowWeaveMessagesTestCase.java View File

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

}

+ 481
- 5
asm/src/org/aspectj/asm/AsmManager.java View File

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


+ 5
- 0
asm/src/org/aspectj/asm/IHierarchy.java View File

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

+ 17
- 0
asm/src/org/aspectj/asm/IProgramElement.java View File

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

+ 20
- 4
asm/src/org/aspectj/asm/IRelationship.java View File

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

+ 18
- 3
asm/src/org/aspectj/asm/IRelationshipMap.java View File

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

+ 27
- 1
asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java View File

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


+ 40
- 8
asm/src/org/aspectj/asm/internal/ProgramElement.java View File

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

}


+ 15
- 2
asm/src/org/aspectj/asm/internal/Relationship.java View File

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

}

+ 54
- 17
asm/src/org/aspectj/asm/internal/RelationshipMap.java View File

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


}

+ 5
- 1
bridge/src/org/aspectj/bridge/IMessage.java View File

@@ -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();


+ 23
- 11
bridge/src/org/aspectj/bridge/Message.java View File

@@ -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
*/

+ 3
- 0
bridge/src/org/aspectj/bridge/MessageHandler.java View File

@@ -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;

+ 75
- 0
bridge/src/org/aspectj/bridge/WeaveMessage.java View File

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

+ 16
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java View File

@@ -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());

+ 1
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties View File

@@ -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\

+ 11
- 1
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java View File

@@ -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;

+ 66
- 10
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java View File

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

+ 4
- 4
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AsmInterTypeRelationshipProvider.java View File

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

+ 3
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseTypeMunger.java View File

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

+ 17
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java View File

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

+ 80
- 19
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java View File

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

+ 1
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java View File

@@ -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;

+ 44
- 4
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmElementFormatter.java View File

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

+ 86
- 51
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmHierarchyBuilder.java View File

@@ -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++) {

+ 13
- 2
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseAdapterUtils.java View File

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


+ 7
- 1
org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java View File

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

+ 34
- 2
org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java View File

@@ -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();

+ 16
- 1
testing/src/org/aspectj/testing/harness/bridge/IncCompilerRun.java View File

@@ -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" */

+ 2
- 0
testing/src/org/aspectj/testing/xml/SoftMessage.java View File

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

+ 1
- 0
tests/ajcTestSuite.dtd View File

@@ -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 >

+ 102
- 0
tests/incModelTests.xml View File

@@ -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>

+ 7
- 0
tests/incremental/model/intertype/primary/Alpha.java View File

@@ -0,0 +1,7 @@
package primary;

public class Alpha {
public static void main(String [] argv) {
}
}


+ 8
- 0
tests/incremental/model/intertype/secondary/BetaA.20.java View File

@@ -0,0 +1,8 @@
package secondary;

import primary.Alpha;

public aspect BetaA {
int Alpha.i;
String Alpha.s;
}

+ 7
- 0
tests/incremental/model/intertype/secondary/BetaA.30.java View File

@@ -0,0 +1,7 @@
package secondary;

import primary.Alpha;

public aspect BetaA {
String Alpha.s;
}

+ 42
- 0
tests/incremental/model/introduction/introduction/CloneablePoint.20.java View File

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

+ 42
- 0
tests/incremental/model/introduction/introduction/CloneablePoint.java View File

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

+ 46
- 0
tests/incremental/model/introduction/introduction/ComparablePoint.java View File

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

+ 47
- 0
tests/incremental/model/introduction/introduction/HashablePoint.30.java View File

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

+ 47
- 0
tests/incremental/model/introduction/introduction/HashablePoint.java View File

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

+ 98
- 0
tests/incremental/model/introduction/introduction/Point.30.java View File

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

+ 98
- 0
tests/incremental/model/introduction/introduction/Point.java View File

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

+ 7
- 0
tests/incremental/model/sourcefiles_addremove/primary/Alpha.java View File

@@ -0,0 +1,7 @@

package primary;

public class Alpha {
public static void main (String[] args) {
}
}

+ 11
- 0
tests/incremental/model/sourcefiles_addremove/primary/Beta.20.java View File

@@ -0,0 +1,11 @@
package primary;

public class Beta {
public static void main(String[] argv) {
sayhi();
}

public static void sayhi() {
System.err.println("Hi");
}
}

+ 11
- 0
tests/incremental/model/sourcefiles_addremove/primary/Beta.delete.60.java View File

@@ -0,0 +1,11 @@
package primary;

public class Beta {
public static void main(String[] argv) {
sayhi();
}

public static void sayhi() {
System.err.println("Hi");
}
}

+ 5
- 0
tests/incremental/model/sourcefiles_addremove/secondary/Delta.40.java View File

@@ -0,0 +1,5 @@
package secondary;

public class Delta {
public static void foo() { }
}

+ 5
- 0
tests/incremental/model/sourcefiles_addremove/secondary/Delta.delete.60.java View File

@@ -0,0 +1,5 @@
package secondary;

public class Delta {
public static void foo() { }
}

+ 7
- 0
tests/incremental/model/sourcefiles_addremove/secondary/Gamma.30.java View File

@@ -0,0 +1,7 @@
package secondary;

aspect Gamma {
before(): call(* *(..)) {
}
}


+ 7
- 0
tests/incremental/model/sourcefiles_addremove/secondary/Gamma.delete.50.java View File

@@ -0,0 +1,7 @@
package secondary;

aspect Gamma {
before(): call(* *(..)) {
}
}


+ 7
- 0
tests/incremental/model/sourcefiles_updating/primary/Alpha.java View File

@@ -0,0 +1,7 @@

package primary;

public class Alpha {
public static void main (String[] args) {
}
}

+ 13
- 0
tests/incremental/model/sourcefiles_updating/primary/Beta.20.java View File

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

+ 7
- 0
tests/incremental/model/sourcefiles_updating/primary/Beta.java View File

@@ -0,0 +1,7 @@
package primary;

public class Beta {
public static void main(String[] argv) {
}

}

+ 10
- 0
tests/incremental/model/sourcefiles_updating/secondary/Delta.30.java View File

@@ -0,0 +1,10 @@
package secondary;

// Extra class added over Delta.java

public class Delta {
public static void foo() { }
}

class DeltaExtra {
}

+ 5
- 0
tests/incremental/model/sourcefiles_updating/secondary/Delta.java View File

@@ -0,0 +1,5 @@
package secondary;

public class Delta {
public static void foo() { }
}

+ 10
- 0
tests/incremental/model/sourcefiles_updating/secondary/Gamma.40.java View File

@@ -0,0 +1,10 @@
package secondary;

aspect Gamma {
before(): call(* *(..)) {
}

after(): call(* *(..)) {
}
}


+ 13
- 0
tests/incremental/model/sourcefiles_updating/secondary/Gamma.50.java View File

@@ -0,0 +1,13 @@
package secondary;

aspect Gamma {

pointcut calls(): call(* *(..));

before(): calls() {
}

after(): calls() {
}
}


+ 8
- 0
tests/incremental/model/sourcefiles_updating/secondary/Gamma.60.java View File

@@ -0,0 +1,8 @@
package secondary;

aspect Gamma {

pointcut calls(): call(* *(..));

}


+ 7
- 0
tests/incremental/model/sourcefiles_updating/secondary/Gamma.java View File

@@ -0,0 +1,7 @@
package secondary;

aspect Gamma {
before(): call(* *(..)) {
}
}


+ 21
- 0
tests/incremental/model/weaving/primary/Alpha.java View File

@@ -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 "";
}
}

+ 16
- 0
tests/incremental/model/weaving/primary/BetaA.20.java View File

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

+ 10
- 0
tests/incremental/model/weaving/primary/BetaA.30.java View File

@@ -0,0 +1,10 @@
package primary;

public aspect BetaA {

pointcut m2call(): call(* m2(..));

before(): m2call() {
System.err.println("m2 got called");
}
}

+ 5
- 0
tests/incremental/model/weaving/primary/BetaA.40.java View File

@@ -0,0 +1,5 @@
package primary;

public aspect BetaA {

}

+ 10
- 0
tests/incremental/model/weaving/primary/BetaA.java View File

@@ -0,0 +1,10 @@
package primary;

public aspect BetaA {

pointcut m1call(): call(* m1(..));

before(): m1call() {
System.err.println("m1 got called");
}
}

+ 11
- 0
tests/incremental/model/weaving2/primary/Alpha.java View File

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

+ 8
- 0
tests/incremental/model/weaving2/primary/BetaA.20.java View File

@@ -0,0 +1,8 @@
package primary;

public aspect BetaA {
pointcut handlers(): handler(Throwable);
before(): handlers() {
System.err.println("xxx");
}
}

+ 8
- 0
tests/incremental/model/weaving2/primary/BetaA.delete.40.java View File

@@ -0,0 +1,8 @@
package primary;

public aspect BetaA {
pointcut handlers(): handler(Throwable);
before(): handlers() {
System.err.println("xxx");
}
}

+ 4
- 0
tests/incremental/model/weaving2/primary/BetaA.java View File

@@ -0,0 +1,4 @@
package primary;

public aspect BetaA {
}

+ 8
- 0
tests/incremental/model/weaving2/secondary/GammaA.30.java View File

@@ -0,0 +1,8 @@
package primary;

public aspect GammaA {
pointcut handlers(): handler(Throwable);
before(): handlers() {
System.err.println("xxx");
}
}

+ 100
- 10
weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java View File

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

+ 7
- 3
weaver/src/org/aspectj/weaver/Checker.java View File

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

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

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

+ 5
- 1
weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java View File

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

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

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

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

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

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

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

+ 55
- 0
weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java View File

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


+ 95
- 1
weaver/src/org/aspectj/weaver/Shadow.java View File

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

+ 85
- 0
weaver/src/org/aspectj/weaver/WeaverMetrics.java View File

@@ -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++;
}

}

+ 12
- 2
weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java View File

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

+ 43
- 0
weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java View File

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

+ 6
- 1
weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java View File

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

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

@@ -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)+"]";
}

}

Loading…
Cancel
Save