diff options
author | aclement <aclement> | 2004-08-03 12:31:29 +0000 |
---|---|---|
committer | aclement <aclement> | 2004-08-03 12:31:29 +0000 |
commit | 2982b4cc622a2a95429b16f0aa3c55b7e20d798a (patch) | |
tree | a1453e59e3356d36b7bacaf272298f91f6fa1407 /asm | |
parent | fe049bdf23ae91b938e64fc2106aebf72be34e3b (diff) | |
download | aspectj-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.java | 486 | ||||
-rw-r--r-- | asm/src/org/aspectj/asm/IHierarchy.java | 5 | ||||
-rw-r--r-- | asm/src/org/aspectj/asm/IProgramElement.java | 17 | ||||
-rw-r--r-- | asm/src/org/aspectj/asm/IRelationship.java | 24 | ||||
-rw-r--r-- | asm/src/org/aspectj/asm/IRelationshipMap.java | 21 | ||||
-rw-r--r-- | asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java | 28 | ||||
-rw-r--r-- | asm/src/org/aspectj/asm/internal/ProgramElement.java | 48 | ||||
-rw-r--r-- | asm/src/org/aspectj/asm/internal/Relationship.java | 17 | ||||
-rw-r--r-- | asm/src/org/aspectj/asm/internal/RelationshipMap.java | 71 |
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(); + } + + } |