Loading src/main/java/tfm/programs/pdg/Example1.java +29 −10 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ package tfm.programs.pdg; import tfm.utils.Logger; import java.util.Arrays; public class Example1 { public static void main(String[] args) { Loading @@ -12,8 +14,10 @@ public class Example1 { while (x < y) { y = x; while(y < x) { for(int i : Arrays.asList(1, 2, 3, 4,5 )) { y += x; if (x > y) continue; x = y; // while (x > 1) { Loading @@ -31,15 +35,30 @@ public class Example1 { y *= x; } int e = (Integer) x; switch (x) { case 1: e = 2; break; case 2: e = 3; } // int e = (Integer) x; // // switch (x) { // case 1: // e = 2; // // while (1 < 4) { // y = 2; // // if (4 < 1) { // break; // } // } // // e = 5; // // break; // case 2: // e = 3; // case 3: // e = 4; // break; // default: // } Logger.log(y); } Loading src/main/java/tfm/utils/Utils.java +24 −0 Original line number Diff line number Diff line Loading @@ -2,8 +2,13 @@ package tfm.utils; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.stmt.BlockStmt; import com.github.javaparser.ast.stmt.EmptyStmt; import com.github.javaparser.ast.stmt.Statement; import java.util.Collection; import java.util.Collections; import java.util.function.Predicate; public class Utils { Loading @@ -13,4 +18,23 @@ public class Utils { return new BlockStmt(new NodeList<>(statement)); } public static boolean isLoop(Statement statement) { return statement.isWhileStmt() || statement.isDoStmt() || statement.isForStmt() || statement.isForEachStmt(); } public static Statement findFirstAncestorStatementFrom(Statement statement, Predicate<Statement> predicate) { if (predicate.test(statement)) { return statement; } if (!statement.getParentNode().isPresent()) { return new EmptyStmt(); } return findFirstAncestorStatementFrom((Statement) statement.getParentNode().get(), predicate); } } src/main/java/tfm/visitors/CFGVisitor.java +50 −23 Original line number Diff line number Diff line package tfm.visitors; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.GenericVisitor; import com.github.javaparser.ast.visitor.VoidVisitor; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import sun.rmi.runtime.Log; import tfm.graphs.CFGGraph; import tfm.nodes.CFGNode; import tfm.utils.Logger; import tfm.utils.Utils; import java.util.*; import java.util.stream.Collectors; public class CFGVisitor extends VoidVisitorAdapter<Void> { private CFGGraph graph; private Queue<CFGNode> lastParentNodes; private List<CFGNode> bodyBreaks; public CFGVisitor(CFGGraph graph) { this.graph = graph; Loading @@ -31,6 +25,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { Collections.singletonList(graph.getRootNode()) ) ); this.bodyBreaks = new ArrayList<>(); } @Override Loading Loading @@ -95,6 +91,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { } lastParentNodes.add(whileCondition); lastParentNodes.addAll(bodyBreaks); bodyBreaks.clear(); } @Override Loading @@ -116,6 +114,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { } lastParentNodes.add(doWhileNode); lastParentNodes.addAll(bodyBreaks); bodyBreaks.clear(); } @Override Loading Loading @@ -150,6 +150,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { } lastParentNodes.add(forNode); lastParentNodes.addAll(bodyBreaks); bodyBreaks.clear(); } @Override Loading @@ -168,6 +170,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { } lastParentNodes.add(foreachNode); lastParentNodes.addAll(bodyBreaks); bodyBreaks.clear(); } @Override Loading @@ -179,38 +183,59 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { lastParentNodes.add(switchNode); List<CFGNode> lastEntryParents = new ArrayList<>(); // List<CFGNode> lastEntryParents = new ArrayList<>(); // // switchStmt.getEntries().forEach(entry -> { // Optional<BreakStmt> entryBreak = entry.findFirst(BreakStmt.class, breakStmt -> { // Optional<Node> parent = breakStmt.getParentNode(); // // return parent.isPresent() && parent.get() .equals(entry); // }); // // new BlockStmt(entry.getStatements()).accept(this, arg); // // if (entryBreak.isPresent()) { // while (!lastParentNodes.isEmpty()) { // lastEntryParents.add(lastParentNodes.poll()); // } // } // // lastParentNodes.add(switchNode); // }); // // lastParentNodes.clear(); // lastParentNodes.addAll(lastEntryParents); switchStmt.getEntries().forEach(entry -> { Optional<BreakStmt> entryBreak = entry.findFirst(BreakStmt.class, breakStmt -> { Optional<Node> parent = breakStmt.getParentNode(); List<CFGNode> allEntryBreaks = new ArrayList<>(); return parent.isPresent() && parent.get() .equals(entry); }); switchStmt.getEntries().forEach(switchEntryStmt -> { switchEntryStmt.getStatements().accept(this, null); new BlockStmt(entry.getStatements()).accept(this, arg); if (!bodyBreaks.isEmpty()) { // means it has no break allEntryBreaks.addAll(bodyBreaks); // save breaks of entry if (entryBreak.isPresent()) { while (!lastParentNodes.isEmpty()) { lastEntryParents.add(lastParentNodes.poll()); } } lastParentNodes.clear(); lastParentNodes.add(switchNode); // Set switch as the only parent lastParentNodes.add(switchNode); bodyBreaks.clear(); // Clear breaks } }); lastParentNodes.clear(); lastParentNodes.addAll(lastEntryParents); lastParentNodes.addAll(allEntryBreaks); } @Override public void visit(BreakStmt breakStmt, Void arg) { bodyBreaks.addAll(lastParentNodes); } @Override public void visit(ContinueStmt continueStmt, Void arg) { Statement continuableStatement = Utils.findFirstAncestorStatementFrom(continueStmt, Utils::isLoop); CFGNode continuableNode = graph.findNodeByStatement(continuableStatement).get(); lastParentNodes.forEach(parentNode -> graph.addControlFlowEdge(parentNode, continuableNode)); } @Override Loading @@ -233,4 +258,6 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { return node; } } Loading
src/main/java/tfm/programs/pdg/Example1.java +29 −10 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ package tfm.programs.pdg; import tfm.utils.Logger; import java.util.Arrays; public class Example1 { public static void main(String[] args) { Loading @@ -12,8 +14,10 @@ public class Example1 { while (x < y) { y = x; while(y < x) { for(int i : Arrays.asList(1, 2, 3, 4,5 )) { y += x; if (x > y) continue; x = y; // while (x > 1) { Loading @@ -31,15 +35,30 @@ public class Example1 { y *= x; } int e = (Integer) x; switch (x) { case 1: e = 2; break; case 2: e = 3; } // int e = (Integer) x; // // switch (x) { // case 1: // e = 2; // // while (1 < 4) { // y = 2; // // if (4 < 1) { // break; // } // } // // e = 5; // // break; // case 2: // e = 3; // case 3: // e = 4; // break; // default: // } Logger.log(y); } Loading
src/main/java/tfm/utils/Utils.java +24 −0 Original line number Diff line number Diff line Loading @@ -2,8 +2,13 @@ package tfm.utils; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.stmt.BlockStmt; import com.github.javaparser.ast.stmt.EmptyStmt; import com.github.javaparser.ast.stmt.Statement; import java.util.Collection; import java.util.Collections; import java.util.function.Predicate; public class Utils { Loading @@ -13,4 +18,23 @@ public class Utils { return new BlockStmt(new NodeList<>(statement)); } public static boolean isLoop(Statement statement) { return statement.isWhileStmt() || statement.isDoStmt() || statement.isForStmt() || statement.isForEachStmt(); } public static Statement findFirstAncestorStatementFrom(Statement statement, Predicate<Statement> predicate) { if (predicate.test(statement)) { return statement; } if (!statement.getParentNode().isPresent()) { return new EmptyStmt(); } return findFirstAncestorStatementFrom((Statement) statement.getParentNode().get(), predicate); } }
src/main/java/tfm/visitors/CFGVisitor.java +50 −23 Original line number Diff line number Diff line package tfm.visitors; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.GenericVisitor; import com.github.javaparser.ast.visitor.VoidVisitor; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import sun.rmi.runtime.Log; import tfm.graphs.CFGGraph; import tfm.nodes.CFGNode; import tfm.utils.Logger; import tfm.utils.Utils; import java.util.*; import java.util.stream.Collectors; public class CFGVisitor extends VoidVisitorAdapter<Void> { private CFGGraph graph; private Queue<CFGNode> lastParentNodes; private List<CFGNode> bodyBreaks; public CFGVisitor(CFGGraph graph) { this.graph = graph; Loading @@ -31,6 +25,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { Collections.singletonList(graph.getRootNode()) ) ); this.bodyBreaks = new ArrayList<>(); } @Override Loading Loading @@ -95,6 +91,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { } lastParentNodes.add(whileCondition); lastParentNodes.addAll(bodyBreaks); bodyBreaks.clear(); } @Override Loading @@ -116,6 +114,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { } lastParentNodes.add(doWhileNode); lastParentNodes.addAll(bodyBreaks); bodyBreaks.clear(); } @Override Loading Loading @@ -150,6 +150,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { } lastParentNodes.add(forNode); lastParentNodes.addAll(bodyBreaks); bodyBreaks.clear(); } @Override Loading @@ -168,6 +170,8 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { } lastParentNodes.add(foreachNode); lastParentNodes.addAll(bodyBreaks); bodyBreaks.clear(); } @Override Loading @@ -179,38 +183,59 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { lastParentNodes.add(switchNode); List<CFGNode> lastEntryParents = new ArrayList<>(); // List<CFGNode> lastEntryParents = new ArrayList<>(); // // switchStmt.getEntries().forEach(entry -> { // Optional<BreakStmt> entryBreak = entry.findFirst(BreakStmt.class, breakStmt -> { // Optional<Node> parent = breakStmt.getParentNode(); // // return parent.isPresent() && parent.get() .equals(entry); // }); // // new BlockStmt(entry.getStatements()).accept(this, arg); // // if (entryBreak.isPresent()) { // while (!lastParentNodes.isEmpty()) { // lastEntryParents.add(lastParentNodes.poll()); // } // } // // lastParentNodes.add(switchNode); // }); // // lastParentNodes.clear(); // lastParentNodes.addAll(lastEntryParents); switchStmt.getEntries().forEach(entry -> { Optional<BreakStmt> entryBreak = entry.findFirst(BreakStmt.class, breakStmt -> { Optional<Node> parent = breakStmt.getParentNode(); List<CFGNode> allEntryBreaks = new ArrayList<>(); return parent.isPresent() && parent.get() .equals(entry); }); switchStmt.getEntries().forEach(switchEntryStmt -> { switchEntryStmt.getStatements().accept(this, null); new BlockStmt(entry.getStatements()).accept(this, arg); if (!bodyBreaks.isEmpty()) { // means it has no break allEntryBreaks.addAll(bodyBreaks); // save breaks of entry if (entryBreak.isPresent()) { while (!lastParentNodes.isEmpty()) { lastEntryParents.add(lastParentNodes.poll()); } } lastParentNodes.clear(); lastParentNodes.add(switchNode); // Set switch as the only parent lastParentNodes.add(switchNode); bodyBreaks.clear(); // Clear breaks } }); lastParentNodes.clear(); lastParentNodes.addAll(lastEntryParents); lastParentNodes.addAll(allEntryBreaks); } @Override public void visit(BreakStmt breakStmt, Void arg) { bodyBreaks.addAll(lastParentNodes); } @Override public void visit(ContinueStmt continueStmt, Void arg) { Statement continuableStatement = Utils.findFirstAncestorStatementFrom(continueStmt, Utils::isLoop); CFGNode continuableNode = graph.findNodeByStatement(continuableStatement).get(); lastParentNodes.forEach(parentNode -> graph.addControlFlowEdge(parentNode, continuableNode)); } @Override Loading @@ -233,4 +258,6 @@ public class CFGVisitor extends VoidVisitorAdapter<Void> { return node; } }