package grafos; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import java.util.Collections; import java.util.LinkedList; import java.util.List; public class Visitador extends VoidVisitorAdapter { //********************************************************/ //********************** Atributos ***********************/ //********************************************************/ private List prevNode; //********************************************************/ //*********************** Metodos ************************/ //********************************************************/ // Visitador de métodos // Este visitador añade el nodo final al CFG @Override public void visit(MethodDeclaration methodDeclaration, CFG graph) { prevNode = Collections.singletonList(graph.beginNode()); // Visitamos el método super.visit(methodDeclaration, graph); // Añadimos el nodo final al CFG Node end = graph.endNode(); for (Node n : prevNode) if (n != end) graph.connect(n, end); } @Override public void visit(IfStmt n, CFG graph) { Node ifStart = n.getCondition(); graph.addNode(ifStart); graph.connect(prevNode, ifStart); // TODO: shortcut conditions (||, &&) prevNode = Collections.singletonList(ifStart); List prevNodeBegin = prevNode; n.getThenStmt().accept(this, graph); List newPrev = new LinkedList<>(); if (prevNode == prevNodeBegin) newPrev.add(ifStart); else newPrev.addAll(prevNode); prevNode = Collections.singletonList(ifStart); if (n.getElseStmt().isPresent()) { n.getElseStmt().get().accept(this, graph); if (prevNode == prevNodeBegin) newPrev.add(ifStart); else newPrev.addAll(prevNode); } else { newPrev.add(ifStart); } prevNode = newPrev; } @Override public void visit(WhileStmt n, CFG graph) { Node whileStart = n.getCondition(); graph.addNode(whileStart); graph.connect(prevNode, whileStart); // TODO: shortcut conditions (||, &&) prevNode = Collections.singletonList(whileStart); n.getBody().accept(this, graph); graph.connect(prevNode, whileStart); prevNode = Collections.singletonList(whileStart); } @Override public void visit(DoStmt n, CFG graph) { prevNode = new LinkedList<>(prevNode); prevNode.add(n.getCondition()); n.getBody().accept(this, graph); graph.addNode(n.getCondition()); graph.connect(prevNode, n.getCondition()); prevNode = Collections.singletonList(n.getCondition()); } @Override public void visit(ForStmt n, CFG graph) { // Initialization expressions if (n.getInitialization() != null) { for (Expression e : n.getInitialization()) { graph.addNode(e); graph.connect(prevNode, e); prevNode = Collections.singletonList(e); } } // Comparison expression // TODO: shortcut conditions (||, &&) if (n.getCompare().isPresent()) { graph.addNode(n.getCompare().get()); graph.connect(prevNode, n.getCompare().get()); prevNode = Collections.singletonList(n.getCompare().get()); } // Loop body n.getBody().accept(this, graph); // Update expressions if (n.getUpdate() != null) { for (Expression e : n.getUpdate()) { graph.addNode(e); graph.connect(prevNode, e); prevNode = Collections.singletonList(e); } } // Connect to comparison expression if (n.getCompare().isPresent()) graph.connect(prevNode, n.getCompare().get()); else { // TODO: connect last update / end of loop with first element of loop body } // Set comparison as last possible statement if (n.getCompare().isPresent()) prevNode = Collections.singletonList(n.getCompare().get()); else // There is no comparison, can't exit the loop TODO implement break and continue as way to exit prevNode = Collections.emptyList(); } // Visitador de expresiones // Cada expresión encontrada genera un nodo en el CFG @Override public void visit(ExpressionStmt es, CFG graph) { graph.addNode(es); graph.connect(prevNode, es); prevNode = Collections.singletonList((Node) es); // Seguimos visitando... super.visit(es, graph); } }