aboutsummaryrefslogtreecommitdiffstats
path: root/asm
diff options
context:
space:
mode:
authoraclement <aclement>2004-08-03 12:31:29 +0000
committeraclement <aclement>2004-08-03 12:31:29 +0000
commit2982b4cc622a2a95429b16f0aa3c55b7e20d798a (patch)
treea1453e59e3356d36b7bacaf272298f91f6fa1407 /asm
parentfe049bdf23ae91b938e64fc2106aebf72be34e3b (diff)
downloadaspectj-2982b4cc622a2a95429b16f0aa3c55b7e20d798a.tar.gz
aspectj-2982b4cc622a2a95429b16f0aa3c55b7e20d798a.zip
The BIG commit.
- Enhanced structure model support. - *Incremental* structure model support written and tested (currently switched off, see incModelTests.xml) - -showWeaveInfo compiler option - existence of a 'runtimetest' surfaced through relationships - UI can determine if errors/warnings came from DEOWs. - Code to enable type mungers to remember source locations written (currently switched off)
Diffstat (limited to 'asm')
-rw-r--r--asm/src/org/aspectj/asm/AsmManager.java486
-rw-r--r--asm/src/org/aspectj/asm/IHierarchy.java5
-rw-r--r--asm/src/org/aspectj/asm/IProgramElement.java17
-rw-r--r--asm/src/org/aspectj/asm/IRelationship.java24
-rw-r--r--asm/src/org/aspectj/asm/IRelationshipMap.java21
-rw-r--r--asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java28
-rw-r--r--asm/src/org/aspectj/asm/internal/ProgramElement.java48
-rw-r--r--asm/src/org/aspectj/asm/internal/Relationship.java17
-rw-r--r--asm/src/org/aspectj/asm/internal/RelationshipMap.java71
9 files changed, 677 insertions, 40 deletions
diff --git a/asm/src/org/aspectj/asm/AsmManager.java b/asm/src/org/aspectj/asm/AsmManager.java
index 91a166af6..0177bb4c2 100644
--- a/asm/src/org/aspectj/asm/AsmManager.java
+++ b/asm/src/org/aspectj/asm/AsmManager.java
@@ -37,7 +37,25 @@ public class AsmManager {
protected IHierarchy hierarchy;
private List structureListeners = new ArrayList();
private IRelationshipMap mapper;
+
+
+ public static boolean attemptIncrementalModelRepairs = false;
+// for debugging ...
+// static {
+// setReporting("c:/model.nfo",true,true,true,true);
+// }
+
+ // For offline debugging, you can now ask for the AsmManager to
+ // dump the model - see the method setReporting()
+ private static boolean dumpModel = false;
+ private static boolean dumpRelationships = false;
+ private static boolean dumpDeltaProcessing = false;
+ private static String dumpFilename = "";
+ private static boolean reporting = false;
+
+
+
protected AsmManager() {
hierarchy = new AspectJElementHierarchy();
// List relationships = new ArrayList();
@@ -144,11 +162,17 @@ public class AsmManager {
public void writeStructureModel(String configFilePath) {
try {
String filePath = genExternFilePath(configFilePath);
- ObjectOutputStream s = new ObjectOutputStream(new FileOutputStream(filePath));
- s.writeObject(hierarchy);
+ FileOutputStream fos = new FileOutputStream(filePath);
+ ObjectOutputStream s = new ObjectOutputStream(fos);
+ s.writeObject(hierarchy); // Store the program element tree
+ s.writeObject(mapper); // Store the relationships
s.flush();
+ fos.flush();
+ fos.close();
+ s.close();
} catch (Exception e) {
- // ignore
+ // System.err.println("AsmManager: Unable to write structure model: "+configFilePath+" because of:");
+ // e.printStackTrace();
}
}
@@ -157,6 +181,7 @@ public class AsmManager {
* @param configFilePath path to an ".lst" file
*/
public void readStructureModel(String configFilePath) {
+ boolean hierarchyReadOK = false;
try {
if (configFilePath == null) {
hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
@@ -165,9 +190,23 @@ public class AsmManager {
FileInputStream in = new FileInputStream(filePath);
ObjectInputStream s = new ObjectInputStream(in);
hierarchy = (AspectJElementHierarchy)s.readObject();
+ hierarchyReadOK = true;
+ mapper = (RelationshipMap)s.readObject();
+ ((RelationshipMap)mapper).setHierarchy(hierarchy);
}
+ } catch (FileNotFoundException fnfe) {
+ // That is OK
+ hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
+ } catch (EOFException eofe) {
+ // Might be an old format sym file that is missing its relationships
+ if (!hierarchyReadOK) {
+ System.err.println("AsmManager: Unable to read structure model: "+configFilePath+" because of:");
+ eofe.printStackTrace();
+ hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
+ }
} catch (Exception e) {
- //System.err.println("AJDE Message: could not read structure model: " + e);
+ // System.err.println("AsmManager: Unable to read structure model: "+configFilePath+" because of:");
+ // e.printStackTrace();
hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
} finally {
notifyListeners();
@@ -298,7 +337,444 @@ public class AsmManager {
}
return ret;
}
- };
+ }
+
+ public static void setReporting(String filename,boolean dModel,boolean dRels,boolean dDeltaProcessing,boolean deletefile) {
+ reporting = true;
+ dumpModel = dModel;
+ dumpRelationships = dRels;
+ dumpDeltaProcessing = dDeltaProcessing;
+ if (deletefile) new File(filename).delete();
+ dumpFilename = filename;
+ }
+
+ public static boolean isReporting() {
+ return reporting;
+ }
+
+
+
+ public void reportModelInfo(String reasonForReport) {
+ if (!dumpModel && !dumpRelationships) return;
+ try {
+ FileWriter fw = new FileWriter(dumpFilename,true);
+ BufferedWriter bw = new BufferedWriter(fw);
+ if (dumpModel) {
+ bw.write("=== MODEL STATUS REPORT ========= "+reasonForReport+"\n");
+ dumptree(bw,AsmManager.getDefault().getHierarchy().getRoot(),0);
+
+ bw.write("=== END OF MODEL REPORT =========\n");
+ }
+ if (dumpRelationships) {
+ bw.write("=== RELATIONSHIPS REPORT ========= "+reasonForReport+"\n");
+ dumprels(bw);
+ bw.write("=== END OF RELATIONSHIPS REPORT ==\n");
+ }
+ Properties p = ModelInfo.summarizeModel().getProperties();
+ Enumeration pkeyenum = p.keys();
+ bw.write("=== Properties of the model and relationships map =====\n");
+ while (pkeyenum.hasMoreElements()) {
+ String pkey = (String)pkeyenum.nextElement();
+ bw.write(pkey+"="+p.getProperty(pkey)+"\n");
+ }
+ bw.flush();
+ fw.close();
+ } catch (IOException e) {
+ System.err.println("InternalError: Unable to report model information:");
+ e.printStackTrace();
+ }
+ }
+
+
+ private void dumptree(Writer w,IProgramElement node,int indent) throws IOException {
+ for (int i =0 ;i<indent;i++) w.write(" ");
+ w.write(node+" ["+(node==null?"null":node.getKind().toString())+"]\n");
+ if (node!=null)
+ for (Iterator i = node.getChildren().iterator();i.hasNext();) {
+ dumptree(w,(IProgramElement)i.next(),indent+2);
+ }
+ }
+
+ private void dumprels(Writer w) throws IOException {
+ IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
+ int ctr = 1;
+ Set entries = irm.getEntries();
+ for (Iterator iter = entries.iterator(); iter.hasNext();) {
+ String hid = (String) iter.next();
+ List rels = irm.get(hid);
+ for (Iterator iterator = rels.iterator(); iterator.hasNext();) {
+ IRelationship ir = (IRelationship) iterator.next();
+ List targets = ir.getTargets();
+ for (Iterator iterator2 = targets.iterator();
+ iterator2.hasNext();
+ ) {
+ String thid = (String) iterator2.next();
+ w.write("Hid:"+(ctr++)+":(targets="+targets.size()+") "+hid+" ("+ir.getName()+") "+thid+"\n");
+ }
+ }
+ }
+ }
+
+ //===================== DELTA PROCESSING CODE ============== start ==========//
+
+ // This code is *SLOW* but it isnt worth fixing until we address the
+ // bugs in binary weaving.
+ public void fixupStructureModel(Writer fw,List filesToBeCompiled,Set files_added,Set files_deleted) throws IOException {
+ // Three kinds of things to worry about:
+ // 1. New files have been added since the last compile
+ // 2. Files have been deleted since the last compile
+ // 3. Files have 'changed' since the last compile (really just those in config.getFiles())
+
+ // List files = config.getFiles();
+ IHierarchy model = AsmManager.getDefault().getHierarchy();
+
+ boolean modelModified = false;
+ // Files to delete are: those to be compiled + those that have been deleted
+
+ Set filesToRemoveFromStructureModel = new HashSet(filesToBeCompiled);
+ filesToRemoveFromStructureModel.addAll(files_deleted);
+
+ for (Iterator iter = filesToRemoveFromStructureModel.iterator(); iter.hasNext();) {
+ File fileForCompilation = (File) iter.next();
+ String correctedPath = AsmManager.getDefault().getCanonicalFilePath(fileForCompilation);
+ IProgramElement progElem = (IProgramElement)model.findInFileMap(correctedPath);
+ if (progElem!=null) {
+ // Found it, let's remove it
+ if (dumpDeltaProcessing) {
+ fw.write("Deleting "+progElem+" node for file "+fileForCompilation+"\n");
+ }
+ removeNode(progElem);
+ verifyAssumption(
+ model.removeFromFileMap(correctedPath.toString()),
+ "Whilst repairing model, couldn't remove entry for file: "+correctedPath.toString()+" from the filemap");
+ modelModified = true;
+ }
+ }
+ if (modelModified) {
+ model.flushTypeMap();
+ model.flushHandleMap();
+ }
+ }
+
+ public void processDelta(List filesToBeCompiled,Set files_added,Set files_deleted) {
+
+ try {
+ Writer fw = null;
+
+ // Are we recording this ?
+ if (dumpDeltaProcessing) {
+ FileWriter filew = new FileWriter(dumpFilename,true);
+ fw = new BufferedWriter(filew);
+ fw.write("=== Processing delta changes for the model ===\n");
+ fw.write("Files for compilation:#"+filesToBeCompiled.size()+":"+filesToBeCompiled+"\n");
+ fw.write("Files added :#"+files_added.size()+":"+files_added+"\n");
+ fw.write("Files deleted :#"+files_deleted.size()+":"+files_deleted+"\n");
+ }
+
+ long stime = System.currentTimeMillis();
+
+ fixupStructureModel(fw,filesToBeCompiled,files_added,files_deleted);
+
+ long etime1 = System.currentTimeMillis(); // etime1-stime = time to fix up the model
+
+ IHierarchy model = AsmManager.getDefault().getHierarchy();
+
+ // Some of this code relies on the fact that relationships are always in pairs, so you know
+ // if you are the target of a relationship because you are also the source of a relationship
+ // This seems a valid assumption for now...
+
+ //TODO Speed this code up by making this assumption:
+ // the only piece of the handle that is interesting is the file name. We are working at file granularity, if the
+ // file does not exist (i.e. its not in the filemap) then any handle inside that file cannot exist.
+ if (dumpDeltaProcessing) fw.write("Repairing relationships map:\n");
+
+ // Now sort out the relationships map
+ IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
+ Set sourcesToRemove = new HashSet();
+ Set nonExistingHandles = new HashSet(); // Cache of handles that we *know* are invalid
+ int srchandlecounter = 0;
+ int tgthandlecounter = 0;
+
+ // Iterate over the source handles in the relationships map
+ Set keyset = irm.getEntries(); // These are source handles
+ for (Iterator keyiter = keyset.iterator(); keyiter.hasNext();) {
+ String hid = (String) keyiter.next();
+ srchandlecounter++;
+
+ // Do we already know this handle points to nowhere?
+ if (nonExistingHandles.contains(hid)) {
+ sourcesToRemove.add(hid);
+ } else {
+ // We better check if it actually exists
+ IProgramElement existingElement = model.getElement(hid);
+ if (dumpDeltaProcessing) fw.write("Looking for handle ["+hid+"] in model, found: "+existingElement+"\n");
+
+ // Did we find it?
+ if (existingElement == null) {
+ // No, so delete this relationship
+ sourcesToRemove.add(hid);
+ nonExistingHandles.add(hid); // Speed up a bit you swine
+ } else {
+ // Ok, so the source is valid, what about the targets?
+ List relationships = irm.get(hid);
+ List relationshipsToRemove = new ArrayList();
+ // Iterate through the relationships against this source handle
+ for (Iterator reliter = relationships.iterator();reliter.hasNext();) {
+ IRelationship rel = (IRelationship) reliter.next();
+ List targets = rel.getTargets();
+ List targetsToRemove = new ArrayList();
+
+ // Iterate through the targets for this relationship
+ for (Iterator targetIter = targets.iterator();targetIter.hasNext();) {
+ String targethid = (String) targetIter.next();
+ tgthandlecounter++;
+ // Do we already know it doesn't exist?
+ if (nonExistingHandles.contains(targethid)) {
+ if (dumpDeltaProcessing) fw.write("Target handle ["+targethid+"] for srchid["+hid+"]rel["+rel.getName()+"] does not exist\n");
+ targetsToRemove.add(targethid);
+ } else {
+ // We better check
+ IProgramElement existingTarget = model.getElement(targethid);
+ if (existingTarget == null) {
+ if (dumpDeltaProcessing) fw.write("Target handle ["+targethid+"] for srchid["+hid+"]rel["+rel.getName()+"] does not exist\n");
+ targetsToRemove.add(targethid);
+ nonExistingHandles.add(targethid);
+ }
+ }
+ }
+
+ // Do we have some targets that need removing?
+ if (targetsToRemove.size()!=0) {
+ // Are we removing *all* of the targets for this relationship (i.e. removing the relationship)
+ if (targetsToRemove.size()==targets.size()) {
+ if (dumpDeltaProcessing) fw.write("No targets remain for srchid["+hid+"] rel["+rel.getName()+"]: removing it\n");
+ relationshipsToRemove.add(rel);
+ } else {
+ // Remove all the targets that are no longer valid
+ for (Iterator targsIter = targetsToRemove.iterator();targsIter.hasNext();) {
+ String togo = (String) targsIter.next();
+ targets.remove(togo);
+ }
+ // Should have already been caught above, but lets double check ...
+ if (targets.size()==0) {
+ if (dumpDeltaProcessing) fw.write("No targets remain for srchid["+hid+"] rel["+rel.getName()+"]: removing it\n");
+ relationshipsToRemove.add(rel); // TODO Should only remove this relationship for the srchid?
+ }
+ }
+ }
+ }
+ // Now, were any relationships emptied during that processing and so need removing for this source handle
+ if (relationshipsToRemove.size()>0) {
+ // Are we removing *all* of the relationships for this source handle?
+ if (relationshipsToRemove.size() == relationships.size()) {
+ // We know they are all going to go, so just delete the source handle.
+ sourcesToRemove.add(hid);
+ } else {
+ for (int i = 0 ;i<relationshipsToRemove.size();i++) {
+ IRelationship irel = (IRelationship)relationshipsToRemove.get(i);
+ verifyAssumption(irm.remove(hid,irel),"Failed to remove relationship "+irel.getName()+" for shid "+hid);
+ }
+ List rels = irm.get(hid);
+ if (rels==null || rels.size()==0) sourcesToRemove.add(hid);
+ }
+ }
+ }
+ }
+ }
+ // Remove sources that have no valid relationships any more
+ for (Iterator srciter = sourcesToRemove.iterator(); srciter.hasNext();) {
+ String hid = (String) srciter.next();
+ irm.removeAll(hid);
+ IProgramElement ipe = model.getElement(hid);
+ if (ipe!=null) {
+ // If the relationship was hanging off a 'code' node, delete it.
+ if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
+ removeSingleNode(ipe);
+ }
+ }
+ }
+ long etime2 = System.currentTimeMillis(); // etime2-stime = time to repair the relationship map
+ if (dumpDeltaProcessing) {
+ fw.write("===== Delta Processing timing ==========\n");
+ fw.write("Hierarchy="+(etime1-stime)+"ms Relationshipmap="+(etime2-etime1)+"ms\n");
+ fw.write("===== Traversal ========================\n");
+ fw.write("Source handles processed="+srchandlecounter+"\n");
+ fw.write("Target handles processed="+tgthandlecounter+"\n");
+ fw.write("========================================\n");
+ fw.flush();fw.close();
+ }
+ reportModelInfo("After delta processing");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Removes a specified program element from the structure model.
+ * We go to the parent of the program element, ask for all its children
+ * and remove the node we want to delete from the list of children.
+ */
+ private void removeSingleNode(IProgramElement progElem) {
+ verifyAssumption(progElem!=null);
+ boolean deleteOK = false;
+ IProgramElement parent = progElem.getParent();
+ List kids = parent.getChildren();
+ for (int i =0 ;i<kids.size();i++) {
+ if (kids.get(i).equals(progElem)) {
+ kids.remove(i);
+ deleteOK=true;
+ break;
+ }
+ }
+ verifyAssumption(deleteOK);
+ }
+
+
+ /**
+ * Removes a specified program element from the structure model.
+ * Two processing stages:
+ * <p>First: We go to the parent of the program element, ask for all its children
+ * and remove the node we want to delete from the list of children.
+ * <p>Second:We check if that parent has any other children. If it has no other
+ * children and it is either a CODE node or a PACKAGE node, we delete it too.
+ */
+ private void removeNode(IProgramElement progElem) {
+
+ StringBuffer flightrecorder = new StringBuffer();
+ try {
+ flightrecorder.append("In removeNode, about to chuck away: "+progElem+"\n");
+
+ verifyAssumption(progElem!=null);
+ boolean deleteOK = false;
+ IProgramElement parent = progElem.getParent();
+ flightrecorder.append("Parent of it is "+parent+"\n");
+ List kids = parent.getChildren();
+ flightrecorder.append("Which has "+kids.size()+" kids\n");
+ for (int i =0 ;i<kids.size();i++) {
+ flightrecorder.append("Comparing with "+kids.get(i)+"\n");
+ if (kids.get(i).equals(progElem)) {
+ kids.remove(i);
+ flightrecorder.append("Removing it\n");
+ deleteOK=true;
+ break;
+ }
+ }
+ verifyAssumption(deleteOK,flightrecorder.toString());
+ // Are there any kids left for this node?
+ if (parent.getChildren().size()==0 && parent.getParent()!=null &&
+ (parent.getKind().equals(IProgramElement.Kind.CODE) ||
+ parent.getKind().equals(IProgramElement.Kind.PACKAGE))) {
+ // This node is on its own, we should trim it too *as long as its not a structural node* which we currently check by making sure its a code node
+ // We should trim if it
+ // System.err.println("Deleting parent:"+parent);
+ removeNode(parent);
+ }
+ } catch (NullPointerException npe ){
+ // Occurred when commenting out other 2 ras classes in wsif?? reproducable?
+ System.err.println(flightrecorder.toString());
+ npe.printStackTrace();
+ }
+ }
+
+
+ public static void verifyAssumption(boolean b,String info) {
+ if (!b) {
+ System.err.println("=========== ASSERTION IS NOT TRUE =========v");
+ System.err.println(info);
+ Thread.dumpStack();
+ System.err.println("=========== ASSERTION IS NOT TRUE =========^");
+ throw new RuntimeException("Assertion is false");
+ }
+ }
+
+ public static void verifyAssumption(boolean b) {
+ if (!b) {
+ Thread.dumpStack();
+ throw new RuntimeException("Assertion is false");
+ }
+ }
+
+
+ //===================== DELTA PROCESSING CODE ============== end ==========//
+
+ /**
+ * A ModelInfo object captures basic information about the structure model.
+ * It is used for testing and producing debug info.
+ */
+ public static class ModelInfo {
+ private Hashtable nodeTypeCount = new Hashtable();
+ private Properties extraProperties = new Properties();
+
+ private ModelInfo(IHierarchy hierarchy,IRelationshipMap relationshipMap) {
+ IProgramElement ipe = hierarchy.getRoot();
+ walkModel(ipe);
+ recordStat("FileMapSize",
+ new Integer(hierarchy.getFileMapEntrySet().size()).toString());
+ recordStat("RelationshipMapSize",
+ new Integer(relationshipMap.getEntries().size()).toString());
+ }
+
+ private void walkModel(IProgramElement ipe) {
+ countNode(ipe);
+ List kids = ipe.getChildren();
+ for (Iterator iter = kids.iterator(); iter.hasNext();) {
+ IProgramElement nextElement = (IProgramElement) iter.next();
+ walkModel(nextElement);
+ }
+ }
+
+ private void countNode(IProgramElement ipe) {
+ String node = ipe.getKind().toString();
+ Integer ctr = (Integer)nodeTypeCount.get(node);
+ if (ctr==null) {
+ nodeTypeCount.put(node,new Integer(1));
+ } else {
+ ctr = new Integer(ctr.intValue()+1);
+ nodeTypeCount.put(node,ctr);
+ }
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Model node summary:\n");
+ Enumeration nodeKeys = nodeTypeCount.keys();
+ while (nodeKeys.hasMoreElements()) {
+ String key = (String)nodeKeys.nextElement();
+ Integer ct = (Integer)nodeTypeCount.get(key);
+ sb.append(key+"="+ct+"\n");
+ }
+ sb.append("Model stats:\n");
+ Enumeration ks = extraProperties.keys();
+ while (ks.hasMoreElements()) {
+ String k = (String)ks.nextElement();
+ String v = extraProperties.getProperty(k);
+ sb.append(k+"="+v+"\n");
+ }
+ return sb.toString();
+ }
+
+ public Properties getProperties() {
+ Properties p = new Properties();
+ Enumeration nodeKeys = nodeTypeCount.keys();
+ while (nodeKeys.hasMoreElements()) {
+ String key = (String)nodeKeys.nextElement();
+ Integer ct = (Integer)nodeTypeCount.get(key);
+ p.setProperty(key,ct.toString());
+ }
+ p.putAll(extraProperties);
+ return p;
+ }
+
+ public void recordStat(String string, String string2) {
+ extraProperties.setProperty(string,string2);
+ }
+
+ public static ModelInfo summarizeModel() {
+ return new ModelInfo(AsmManager.getDefault().getHierarchy(),
+ AsmManager.getDefault().getRelationshipMap());
+ }
+ }
}
diff --git a/asm/src/org/aspectj/asm/IHierarchy.java b/asm/src/org/aspectj/asm/IHierarchy.java
index 793b01420..95b00996b 100644
--- a/asm/src/org/aspectj/asm/IHierarchy.java
+++ b/asm/src/org/aspectj/asm/IHierarchy.java
@@ -31,6 +31,7 @@ public interface IHierarchy extends Serializable {
public IProgramElement getRoot();
public void setRoot(IProgramElement root);
public void addToFileMap(Object key, Object value);
+ public boolean removeFromFileMap(Object key);
public void setFileMap(HashMap fileMap);
public Object findInFileMap(Object key);
public Set getFileMapEntrySet();
@@ -94,4 +95,8 @@ public interface IHierarchy extends Serializable {
public String getConfigFile();
public void setConfigFile(String configFile);
+
+ public void flushTypeMap();
+
+ public void flushHandleMap();
} \ No newline at end of file
diff --git a/asm/src/org/aspectj/asm/IProgramElement.java b/asm/src/org/aspectj/asm/IProgramElement.java
index 83374889a..476b6aaa0 100644
--- a/asm/src/org/aspectj/asm/IProgramElement.java
+++ b/asm/src/org/aspectj/asm/IProgramElement.java
@@ -28,6 +28,23 @@ public interface IProgramElement extends Serializable {
public void setChildren(List children);
public void addChild(IProgramElement child);
+
+ // Extra stuff
+ // Could be just a string but may prove more useful as an object in the long run ...
+ public static class ExtraInformation implements Serializable {
+ private String extraInfo;
+ public ExtraInformation() { extraInfo = "";}
+
+ public void setExtraAdviceInformation(String string) {extraInfo = string;}
+ public String getExtraAdviceInformation() {return extraInfo;}
+
+ public String toString() {
+ return "ExtraInformation: ["+extraInfo+"]";
+ }
+ }
+
+ public void setExtraInfo(ExtraInformation info);
+ public ExtraInformation getExtraInfo();
public IProgramElement getParent();
public void setParent(IProgramElement parent);
diff --git a/asm/src/org/aspectj/asm/IRelationship.java b/asm/src/org/aspectj/asm/IRelationship.java
index 18a11da0e..53b118262 100644
--- a/asm/src/org/aspectj/asm/IRelationship.java
+++ b/asm/src/org/aspectj/asm/IRelationship.java
@@ -27,17 +27,33 @@ public interface IRelationship extends Serializable {
public String getSourceHandle();
+ public boolean addTarget(String handle);
+
public Kind getKind();
+
+ public boolean hasRuntimeTest();
/**
* Uses "typesafe enum" pattern.
*/
public static class Kind implements Serializable {
- public static final Kind ADVICE = new Kind("advice");
- public static final Kind DECLARE = new Kind("declare");
- public static final Kind DECLARE_INTER_TYPE = new Kind("inter-type declaration");
- public static final Kind[] ALL = { ADVICE, DECLARE, DECLARE_INTER_TYPE };
+ public static final Kind DECLARE_WARNING = new Kind("declare warning");
+ public static final Kind DECLARE_ERROR = new Kind("declare error");
+ public static final Kind ADVICE_AROUND = new Kind("around advice");
+ public static final Kind ADVICE_AFTERRETURNING = new Kind("after returning advice");
+ public static final Kind ADVICE_AFTERTHROWING = new Kind("after throwing advice");
+ public static final Kind ADVICE_AFTER = new Kind("after advice");
+ public static final Kind ADVICE_BEFORE = new Kind("before advice");
+ public static final Kind ADVICE = new Kind("advice");
+ public static final Kind DECLARE = new Kind("declare");
+ public static final Kind DECLARE_INTER_TYPE = new Kind("inter-type declaration");
+
+ public static final Kind[] ALL = {
+ DECLARE_WARNING, DECLARE_ERROR,
+ ADVICE_AROUND,ADVICE_AFTERRETURNING,ADVICE_AFTERTHROWING,ADVICE_AFTER,ADVICE_BEFORE,
+ ADVICE, DECLARE, DECLARE_INTER_TYPE };
+
private final String name;
private Kind(String name) {
diff --git a/asm/src/org/aspectj/asm/IRelationshipMap.java b/asm/src/org/aspectj/asm/IRelationshipMap.java
index 7eb31335f..ff88efbc5 100644
--- a/asm/src/org/aspectj/asm/IRelationshipMap.java
+++ b/asm/src/org/aspectj/asm/IRelationshipMap.java
@@ -14,6 +14,7 @@ package org.aspectj.asm;
import java.io.Serializable;
import java.util.List;
+import java.util.Set;
//import org.aspectj.asm.IRelationship.Kind;
@@ -50,21 +51,33 @@ public interface IRelationshipMap extends Serializable {
*
* @return null if the relationship is not found.
*/
- public IRelationship get(IProgramElement source, IRelationship.Kind kind, String relationshipName);
+ public IRelationship get(IProgramElement source, IRelationship.Kind kind,
+ String relationshipName,boolean runtimeTest,
+ boolean createIfMissing);
/**
+ * Return a relationship matching the kind and name for the given element.
+ *
+ * @return null if the relationship is not found.
+ */
+ public IRelationship get(IProgramElement source, IRelationship.Kind kind,
+ String relationshipName);
+
+ /**
* Return a relationship matching the kind and name for the given element.
* Creates the relationship if not found.
*
* @return null if the relationship is not found.
*/
- public IRelationship get(String source, IRelationship.Kind kind, String relationshipName);
+ public IRelationship get(String source, IRelationship.Kind kind,
+ String relationshipName, boolean runtimeTest,
+ boolean createIfMissing);
public void put(IProgramElement source, IRelationship relationship);
public void put(String handle, IRelationship relationship);
- public void remove(String handle, IRelationship relationship);
+ public boolean remove(String handle, IRelationship relationship);
public void removeAll(String source);
@@ -72,5 +85,7 @@ public interface IRelationshipMap extends Serializable {
* Clear all of the relationships in the map.
*/
public void clear();
+
+ public Set getEntries();
}
diff --git a/asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java b/asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java
index 0a36642ab..da1b09e38 100644
--- a/asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java
+++ b/asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java
@@ -8,6 +8,7 @@
*
* Contributors:
* Mik Kersten initial implementation
+ * Andy Clement Extensions for better IDE representation
* ******************************************************************/
@@ -32,7 +33,19 @@ public class AspectJElementHierarchy implements IHierarchy {
private Map typeMap = null;
public IProgramElement getElement(String handle) {
- throw new RuntimeException("unimplemented");
+ IProgramElement cachedEntry = (IProgramElement)handleMap.get(handle);
+ if (cachedEntry!=null) return cachedEntry;
+
+ StringTokenizer st = new StringTokenizer(handle, ProgramElement.ID_DELIM);
+ String file = st.nextToken();
+ int line = new Integer(st.nextToken()).intValue();
+ // int col = new Integer(st.nextToken()).intValue(); TODO: use column number when available
+ String canonicalSFP = AsmManager.getDefault().getCanonicalFilePath(new File(file));
+ IProgramElement ret = findNodeForSourceLineHelper(root,canonicalSFP, line);
+ if (ret!=null) {
+ handleMap.put(handle,ret);
+ }
+ return ret;
}
public IProgramElement getRoot() {
@@ -48,6 +61,10 @@ public class AspectJElementHierarchy implements IHierarchy {
public void addToFileMap( Object key, Object value ){
fileMap.put( key, value );
}
+
+ public boolean removeFromFileMap(Object key) {
+ return (fileMap.remove(key)!=null);
+ }
public void setFileMap(HashMap fileMap) {
this.fileMap = fileMap;
@@ -336,5 +353,14 @@ public class AspectJElementHierarchy implements IHierarchy {
protected void cache(String handle, ProgramElement pe) {
handleMap.put(handle,pe);
}
+
+ public void flushTypeMap() {
+ typeMap.clear();
+
+ }
+
+ public void flushHandleMap() {
+ handleMap.clear();
+ }
}
diff --git a/asm/src/org/aspectj/asm/internal/ProgramElement.java b/asm/src/org/aspectj/asm/internal/ProgramElement.java
index 3cff3287d..913a1cebc 100644
--- a/asm/src/org/aspectj/asm/internal/ProgramElement.java
+++ b/asm/src/org/aspectj/asm/internal/ProgramElement.java
@@ -8,16 +8,22 @@
*
* Contributors:
* Mik Kersten initial implementation
+ * Andy Clement Extensions for better IDE representation
* ******************************************************************/
package org.aspectj.asm.internal;
-import java.io.*;
-import java.util.*;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
-import org.aspectj.asm.*;
-import org.aspectj.bridge.*;
+import org.aspectj.asm.AsmManager;
+import org.aspectj.asm.HierarchyWalker;
+import org.aspectj.asm.IProgramElement;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
/**
@@ -55,6 +61,8 @@ public class ProgramElement implements IProgramElement {
private List parameterTypes = null;
private String details = null;
+
+ private ExtraInformation info;
/**
* Used during de-externalization.
@@ -126,6 +134,10 @@ public class ProgramElement implements IProgramElement {
public Accessibility getAccessibility() {
return accessibility;
}
+
+ public void setAccessibility(Accessibility a) {
+ accessibility=a;
+ }
public String getDeclaringType() {
return declaringType;
@@ -388,6 +400,9 @@ public class ProgramElement implements IProgramElement {
return sb.toString();
}
+
+ public static boolean shortITDNames = true;
+
/**
* TODO: move the "parent != null"==>injar heuristic to more explicit
*/
@@ -396,13 +411,20 @@ public class ProgramElement implements IProgramElement {
if (kind == Kind.CODE || kind == Kind.INITIALIZER) {
label = parent.getParent().getName() + ": ";
} else if (kind.isInterTypeMember()) {
- int dotIndex = name.indexOf('.');
- if (dotIndex != -1) {
- return parent.getName() + ": " + toLabelString().substring(dotIndex+1);
+ if (shortITDNames) {
+ // if (name.indexOf('.')!=-1) return toLabelString().substring(name.indexOf('.')+1);
+ label="";
} else {
+ int dotIndex = name.indexOf('.');
+ if (dotIndex != -1) {
+ return parent.getName() + ": " + toLabelString().substring(dotIndex+1);
+ } else {
label = parent.getName() + '.';
+ }
}
- } else if (kind == Kind.CLASS || kind == Kind.ASPECT) {
+ } else if (kind == Kind.CLASS || kind == Kind.ASPECT || kind == Kind.INTERFACE) {
+ label = "";
+ } else if (kind.equals(Kind.DECLARE_PARENTS)) {
label = "";
} else {
if (parent != null) {
@@ -487,5 +509,15 @@ public class ProgramElement implements IProgramElement {
hierarchy.cache(handle,this);
}
}
+
+ public void setExtraInfo(ExtraInformation info) {
+ this.info = info;
+
+ }
+
+ public ExtraInformation getExtraInfo() {
+ return info;
+ }
+
}
diff --git a/asm/src/org/aspectj/asm/internal/Relationship.java b/asm/src/org/aspectj/asm/internal/Relationship.java
index 68ee50e3f..c47fb159e 100644
--- a/asm/src/org/aspectj/asm/internal/Relationship.java
+++ b/asm/src/org/aspectj/asm/internal/Relationship.java
@@ -8,6 +8,7 @@
*
* Contributors:
* Mik Kersten initial implementation
+ * Andy Clement Extensions for better IDE representation
* ******************************************************************/
@@ -15,7 +16,6 @@ package org.aspectj.asm.internal;
import java.util.List;
-//import org.aspectj.asm.*;
import org.aspectj.asm.IRelationship;
//import org.aspectj.asm.IRelationship.Kind;
@@ -29,17 +29,20 @@ public class Relationship implements IRelationship {
private Kind kind;
private String sourceHandle;
private List targets;
+ private boolean hasRuntimeTest;
public Relationship(
String name,
Kind kind,
String sourceHandle,
- List targets) {
+ List targets,
+ boolean runtimeTest) {
this.name = name;
this.kind = kind;
this.sourceHandle = sourceHandle;
this.targets = targets;
+ this.hasRuntimeTest = runtimeTest;
}
public String getName() {
@@ -61,5 +64,15 @@ public class Relationship implements IRelationship {
public List getTargets() {
return targets;
}
+
+ public boolean addTarget(String handle) {
+ if (targets.contains(handle)) return false;
+ targets.add(handle);
+ return true;
+ }
+
+ public boolean hasRuntimeTest() {
+ return hasRuntimeTest;
+ }
}
diff --git a/asm/src/org/aspectj/asm/internal/RelationshipMap.java b/asm/src/org/aspectj/asm/internal/RelationshipMap.java
index ce05fd5c6..b70887af6 100644
--- a/asm/src/org/aspectj/asm/internal/RelationshipMap.java
+++ b/asm/src/org/aspectj/asm/internal/RelationshipMap.java
@@ -15,6 +15,7 @@ package org.aspectj.asm.internal;
import java.util.*;
import org.aspectj.asm.*;
+import org.aspectj.asm.IRelationship.Kind;
/**
* TODO: add a remove, and a clear all
@@ -24,12 +25,20 @@ import org.aspectj.asm.*;
*/
public class RelationshipMap extends HashMap implements IRelationshipMap {
- private IHierarchy hierarchy;
+ // As this gets serialized, make the hierarchy transient and
+ // settable
+ private transient IHierarchy hierarchy;
+
+ public RelationshipMap() { }
public RelationshipMap(IHierarchy hierarchy) {
this.hierarchy = hierarchy;
}
+ public void setHierarchy(IHierarchy hierarchy) {
+ this.hierarchy = hierarchy;
+ }
+
public List get(String handle) {
List relationships = (List)super.get(handle);
if (relationships == null) {
@@ -43,48 +52,67 @@ public class RelationshipMap extends HashMap implements IRelationshipMap {
return get(source.getHandleIdentifier());
}
- public IRelationship get(String source, IRelationship.Kind kind, String relationshipName) {
+ public IRelationship get(String source, IRelationship.Kind kind,
+ String relationshipName,boolean runtimeTest,boolean createIfMissing) {
List relationships = get(source);
if (relationships == null) {
+ if (!createIfMissing) return null;
relationships = new ArrayList();
- IRelationship rel = new Relationship(relationshipName, kind, source, new ArrayList());
+ IRelationship rel = new Relationship(relationshipName, kind, source, new ArrayList(),runtimeTest);
relationships.add(rel);
super.put(source, relationships);
return rel;
} else {
for (Iterator it = relationships.iterator(); it.hasNext(); ) {
IRelationship curr = (IRelationship)it.next();
- if (curr.getKind() == kind && curr.getName().equals(relationshipName)) {
+ if (curr.getKind() == kind &&
+ curr.getName().equals(relationshipName) &&
+ curr.hasRuntimeTest() == runtimeTest) {
return curr;
}
}
+ if (createIfMissing) {
+ // At this point we did find some relationships for 'source' but not one that looks like what we are
+ // after (either the kind or the name or the dynamictests setting don't match)
+ IRelationship rel = new Relationship(relationshipName, kind, source, new ArrayList(),runtimeTest);
+ relationships.add(rel);
+ return rel;
+ }
}
return null;
}
- public IRelationship get(IProgramElement source, IRelationship.Kind kind, String relationshipName) {
- return get(source.getHandleIdentifier(), kind, relationshipName);
+ public IRelationship get(IProgramElement source, IRelationship.Kind kind, String relationshipName, boolean runtimeTest,boolean createIfMissing) {
+ return get(source.getHandleIdentifier(), kind, relationshipName,runtimeTest,createIfMissing);
}
- public void remove(String source, IRelationship relationship) {
+ public IRelationship get(IProgramElement source, Kind kind, String relationshipName) {
+ return get(source,kind,relationshipName,false,true);
+ }
+
+ public boolean remove(String source, IRelationship relationship) {
List list = (List)super.get(source);
if (list != null) {
- boolean matched = false;
- for (Iterator it = list.iterator(); it.hasNext(); ) {
- IRelationship curr = (IRelationship)it.next();
- if (curr.getName().equals(relationship.getName())) {
- curr.getTargets().addAll(relationship.getTargets());
- matched = true;
- }
- }
- if (!matched) list.remove(relationship);
+ return list.remove(relationship);
+// boolean matched = false;
+// for (Iterator it = list.iterator(); it.hasNext(); ) {
+// IRelationship curr = (IRelationship)it.next();
+// if (curr.getName().equals(relationship.getName())) {
+// curr.getTargets().addAll(relationship.getTargets());
+// matched = true;
+// }
+// }
+// if (!matched) list.remove(relationship);
}
+ return false;
}
public void removeAll(String source) {
super.remove(source);
}
+ public Object put(Object o, Object p) {throw new RuntimeException("Fuck off!");
+ }
public void put(String source, IRelationship relationship) {
System.err.println(">> for: " + source + ", put::" + relationship);
@@ -103,7 +131,11 @@ public class RelationshipMap extends HashMap implements IRelationshipMap {
matched = true;
}
}
- if (matched) list.add(relationship);
+ if (matched) {
+ // bug?
+ System.err.println("matched = true");
+ }
+ if (matched) list.add(relationship); // Is this a bug, will it give us double entries?
}
}
@@ -115,4 +147,9 @@ public class RelationshipMap extends HashMap implements IRelationshipMap {
super.clear();
}
+ public Set getEntries() {
+ return keySet();
+ }
+
+
}