aspect DependencyEdges { abstract class DependencyEdge { protected abstract boolean isStart(CFGNode node); protected abstract boolean isTarget(CFGNode start, CFGNode end); public abstract SmallSet collect(CFGNode start); } abstract class BackwardEdge extends DependencyEdge { public abstract boolean terminates(CFGNode start, CFGNode end); public SmallSet collect(CFGNode start) { if(!isStart(start)) return SmallSet.empty(); return start.collect(this, start); } } abstract class IrreflexiveBackwardEdge extends BackwardEdge { public SmallSet collect(CFGNode start) { if(!isStart(start)) return SmallSet.empty(); SmallSet res = SmallSet.empty(); for(CFGNode p : (SmallSet)start.pred()) res = res.union(p.collect(this, start)); return res; } } syn lazy SmallSet CFGNode.collect(BackwardEdge be, CFGNode start) circular [SmallSet. empty()] { SmallSet res = be.isTarget(start, this) ? SmallSet.singleton((CFGNode)this) : SmallSet.empty(); if(be.terminates(start, this)) return res; for(CFGNode p : pred()) res = res.union(p.collect(be, start)); return res; } abstract class ForwardEdge extends DependencyEdge { public abstract boolean terminates(CFGNode start, CFGNode end); public SmallSet collect(CFGNode start) { if(!isStart(start)) return SmallSet.empty(); return start.collect(this, start); } } abstract class IrreflexiveForwardEdge extends ForwardEdge { public SmallSet collect(CFGNode start) { if(!isStart(start)) return SmallSet.empty(); SmallSet res = SmallSet.empty(); for(CFGNode p : (SmallSet)start.succ()) res = res.union(p.collect(this, start)); return res; } } syn lazy SmallSet CFGNode.collect(ForwardEdge fe, CFGNode start) circular [SmallSet. empty()] { SmallSet res = fe.isTarget(start, this) ? SmallSet.singleton((CFGNode)this) : SmallSet.empty(); if(fe.terminates(start, this)) return res; for(CFGNode p : succ()) res = res.union(p.collect(fe, start)); return res; } class PreservationStrategy { private DependencyEdge edge; public PreservationStrategy(DependencyEdge edge) { this.edge = edge; } public DependencyEdge getEdge() { return edge; } public boolean preserve(CFGNode n) { return true; } public boolean reflect(CFGNode n) { return true; } } protected IdentityHashMap> ASTNode.dependencies = null; public IdentityHashMap> CFGNode.getDependencies() { if(dependencies == null) dependencies = new IdentityHashMap>(); return dependencies; } public void ASTNode.lockDependencies(DependencyEdge... edges) { for(int i=0;i old_edges = getDependencies().get(e); if(old_edges != null) { SmallSet new_edges = e.collect(this); if(r.preserve(this) && !old_edges.subsetOf(new_edges)) throw new RefactoringException("couldn't preserve edge: "+e); if(r.reflect(this) && !new_edges.subsetOf(old_edges)) throw new RefactoringException("couldn't reflect edge: "+e); } } super.unlockDependencies(r); } }