package tfm.graphs; import com.github.javaparser.ast.body.MethodDeclaration; import tfm.arcs.Arc; import tfm.arcs.pdg.ControlDependencyArc; import tfm.arcs.pdg.DataDependencyArc; import tfm.nodes.GraphNode; import tfm.slicing.Slice; import tfm.slicing.SlicingCriterion; import tfm.utils.NodeNotFoundException; import java.util.Optional; /** * The Program Dependence Graph represents the statements of a method in * a graph, connecting statements according to their {@link ControlDependencyArc control} * and {@link DataDependencyArc data} relationships. You can build one manually or use * the {@link PDGBuilder PDGBuilder}. * The variations of the PDG are represented as child types. */ public class PDG extends GraphWithRootNode implements Sliceable { private boolean built = false; private CFG cfg; public PDG() { this(new CFG()); } public PDG(CFG cfg) { super(); this.cfg = cfg; } public void addControlDependencyArc(GraphNode from, GraphNode to) { this.addEdge(from, to, new ControlDependencyArc()); } public void addDataDependencyArc(GraphNode from, GraphNode to, String variable) { this.addEdge(from, to, new DataDependencyArc(variable)); } @Override public Slice slice(SlicingCriterion slicingCriterion) { Optional> node = slicingCriterion.findNode(this); if (!node.isPresent()) throw new NodeNotFoundException(slicingCriterion); Slice slice = new Slice(); getSliceNodes(slice, node.get()); return slice; } protected void getSliceNodes(Slice slice, GraphNode node) { slice.add(node); for (Arc arc : incomingEdgesOf(node)) { GraphNode from = getEdgeSource(arc); if (slice.contains(from)) continue; getSliceNodes(slice, from); } } public CFG getCfg() { return cfg; } @Override public void build(MethodDeclaration method) { new PDGBuilder(this).createFrom(method); built = true; } @Override public boolean isBuilt() { return built; } }