From 7c1d9eaafc70875e23a7e00a1ec42b92867c41d7 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Wed, 3 Apr 2024 23:43:29 +0200 Subject: [PATCH 01/32] Update spoon pom to current version --- spoon-control-flow/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoon-control-flow/pom.xml b/spoon-control-flow/pom.xml index a705f656dbc..27a4b33dd16 100644 --- a/spoon-control-flow/pom.xml +++ b/spoon-control-flow/pom.xml @@ -18,7 +18,7 @@ fr.inria.gforge.spoon spoon-pom - 1.0 + 10.4.2 ../spoon-pom From 4c57655cd1c4ac3fd18f8fd335cd682a3c3e7f3e Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Thu, 4 Apr 2024 21:14:18 +0200 Subject: [PATCH 02/32] Use Launcher in MetaFactory --- .../inria/controlflow/SpoonMetaFactory.java | 60 +++---------------- 1 file changed, 8 insertions(+), 52 deletions(-) diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/SpoonMetaFactory.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/SpoonMetaFactory.java index 6b42e585ae8..bd5c5eec53f 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/SpoonMetaFactory.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/SpoonMetaFactory.java @@ -22,62 +22,18 @@ package fr.inria.controlflow; -//import fr.inria.diversify.util.Log; - +import spoon.Launcher; import spoon.reflect.factory.Factory; -import spoon.reflect.factory.FactoryImpl; -import spoon.support.DefaultCoreFactory; -import spoon.support.StandardEnvironment; -import spoon.support.compiler.jdt.JDTBasedSpoonCompiler; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -/** - * Created by marodrig on 16/06/2014. - */ public class SpoonMetaFactory { - public Factory buildNewFactory(String srcDirectory, int javaVersion) throws ClassNotFoundException, IllegalAccessException, InstantiationException { - ArrayList a = new ArrayList(); - a.add(srcDirectory); - return buildNewFactory(a, javaVersion); - } - - public Factory buildNewFactory(Collection srcDirectory, - int javaVersion) throws - ClassNotFoundException, IllegalAccessException, InstantiationException { - //String srcDirectory = DiversifyProperties.getProperty("project") + "/" + DiversifyProperties.getProperty("src"); - - StandardEnvironment env = new StandardEnvironment(); - env.setComplianceLevel(javaVersion); - env.setVerbose(true); - env.setDebug(true); + public Factory buildNewFactory(String sourceDirectory, + int javaVersion) { + Launcher launcher = new Launcher(); + launcher.getEnvironment().setComplianceLevel(javaVersion); + launcher.addInputResource(sourceDirectory); + launcher.getModelBuilder().build(); - DefaultCoreFactory f = new DefaultCoreFactory(); - - Factory factory = new FactoryImpl(f, env); - - JDTBasedSpoonCompiler compiler = new JDTBasedSpoonCompiler(factory); - - for (String s : srcDirectory) { - for (String dir : s.split(System.getProperty("path.separator"))) { - //Log.debug("add {} to classpath", dir); - File dirFile = new File(dir); - if (dirFile.isDirectory()) { - compiler.addInputSource(dirFile); - } - } - } - try { - compiler.build(); - } catch (Exception e) { - throw new RuntimeException(e); - } - - return factory; + return launcher.getFactory(); } - - } From 61ef636e4a360a0a14ead9cc89a0102ba078b3a1 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Thu, 4 Apr 2024 22:51:25 +0200 Subject: [PATCH 03/32] Clean up ForwardFlowBuilderVisitorTest and ControlFlowArithmetic --- .../ForwardFlowBuilderVisitorTest.java | 94 +++---------------- .../control-flow/ControlFlowArithmetic.java | 38 ++++---- 2 files changed, 31 insertions(+), 101 deletions(-) diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java index 2ddc71abbd1..32ffe330a33 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java @@ -30,25 +30,20 @@ import spoon.reflect.factory.Factory; import spoon.support.QueueProcessingManager; -import java.io.PrintWriter; import java.net.URISyntaxException; import static fr.inria.controlflow.BranchKind.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -/** - * Created by marodrig on 14/10/2015. - */ public class ForwardFlowBuilderVisitorTest { - public static ControlFlowGraph buildGraph(String folder, final String methodName, boolean simplify) - throws Exception { + public static ControlFlowGraph buildGraph(String folder, final String methodName, boolean simplify) { final ControlFlowBuilder visitor = new ControlFlowBuilder(); Factory factory = new SpoonMetaFactory().buildNewFactory(folder, 5); ProcessingManager pm = new QueueProcessingManager(factory); - pm.addProcessor(new AbstractProcessor() { + pm.addProcessor(new AbstractProcessor>() { @Override public void process(CtMethod element) { if (element.getSimpleName().equals(methodName)) { @@ -62,35 +57,19 @@ public void process(CtMethod element) { ControlFlowGraph graph = visitor.getResult(); if (simplify) graph.simplifyConvergenceNodes(); - System.out.println(graph.toGraphVisText()); - return graph; } public ControlFlowGraph testMethod(final String methodName, boolean simplify, - Integer branchCount, Integer stmntCount, Integer totalCount) throws Exception { + Integer branchCount, Integer statementCount, Integer totalCount) throws Exception { ControlFlowGraph graph = buildGraph( this.getClass().getResource("/control-flow").toURI().getPath(), methodName, simplify); - - PrintWriter out = new PrintWriter("target/graph.dot"); - out.println(graph.toGraphVisText()); - out.close(); - if (branchCount != null) assertEquals((int) branchCount, graph.branchCount()); - if (stmntCount != null) assertEquals((int) stmntCount, graph.statementCount()); + if (statementCount != null) assertEquals((int) statementCount, graph.statementCount()); if (totalCount != null) assertEquals((int) totalCount, graph.vertexSet().size()); - - -/* - graph.simplifyConvergenceNodes(); - PrintWriter out2 = new PrintWriter("C:\\MarcelStuff\\DATA\\graphsimplified.dot"); - out2.println(graph.toGraphVisText()); - out2.close();*/ return graph; - - } @@ -106,37 +85,30 @@ public ControlFlowGraph testMethod(final String methodName, boolean simplify, private void testEdges(ControlFlowGraph graph, Integer edgesBranchesStatement, Integer edgesBranchesBranches, Integer edgesStatementStatement, Integer totalEdges) { - int bs, bb, ss; - bs = bb = ss = 0; + int branchToStatementCount, branchToBranchCount, statementToStatementCount; + branchToStatementCount = branchToBranchCount = statementToStatementCount = 0; for (ControlFlowEdge e : graph.edgeSet()) { - if (e.getSourceNode().getKind() == BRANCH && e.getTargetNode().getKind() == STATEMENT) bs++; - else if (e.getSourceNode().getKind() == BRANCH && e.getTargetNode().getKind() == BRANCH) bb++; - else if (e.getSourceNode().getKind() == STATEMENT && e.getTargetNode().getKind() == STATEMENT) ss++; + if (e.getSourceNode().getKind() == BRANCH && e.getTargetNode().getKind() == STATEMENT) branchToStatementCount++; + else if (e.getSourceNode().getKind() == BRANCH && e.getTargetNode().getKind() == BRANCH) branchToBranchCount++; + else if (e.getSourceNode().getKind() == STATEMENT && e.getTargetNode().getKind() == STATEMENT) statementToStatementCount++; } if (edgesBranchesStatement != null) { - assertEquals((int) edgesBranchesStatement, bs); + assertEquals((int) edgesBranchesStatement, branchToStatementCount); } if (edgesBranchesBranches != null) { - assertEquals((int) edgesBranchesBranches, bb); + assertEquals((int) edgesBranchesBranches, branchToBranchCount); } if (edgesStatementStatement != null) { - assertEquals((int) edgesStatementStatement, ss); + assertEquals((int) edgesStatementStatement, statementToStatementCount); } if (totalEdges != null) assertEquals((int) totalEdges, graph.edgeSet().size()); } - /* - @Ignore("") - @Test - public void testBreakComplex() throws Exception { - testMethod("continueAndBreak", true, 6,22,39); - }*/ - @Test public void testBreakSimpleLabeled() throws Exception { testMethod("simpleBreakLabeled", true, 3, 12, 25); @@ -145,7 +117,6 @@ public void testBreakSimpleLabeled() throws Exception { @Test public void testBreakSimple() throws Exception { testMethod("simpleBreak", true, 3, 12, 25); -// fail(); } @@ -176,7 +147,6 @@ public void testSwitchFallThrough() throws Exception { @Test public void testSimple() throws Exception { ControlFlowGraph graph = testMethod("simple", false, 0, 2, 6); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 0, 0, 1, 5); } @@ -184,152 +154,115 @@ public void testSimple() throws Exception { @Test public void testMixed() throws Exception { - //int branchCount, int stmntCount, int totalCount ControlFlowGraph graph = testMethod("mixed", false, 2, 5, 17); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 0, 0, 0, null); } @Test public void testMixedSimplified() throws Exception { ControlFlowGraph graph = testMethod("mixed", true, 2, 5, 15); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 2, 0, 0, null); } @Test public void testCtFor() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctFor", true, 1, 4, 11); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 0, null); } @Test public void testCtForBlock() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctForBlock", true, 1, 5, 12); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 1, null); } @Test public void testIfThenBlock() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ifThenBlock", true, 1, 3, 10); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 1, null); } @Test public void testIfThenElse() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ifThenElse", true, 1, 3, 12); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 0, 0, 0, null); } @Test public void testIfThen() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ifThen", true, 1, 2, 9); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 0, null); } @Test public void testCtForEachBlock() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctForEachBlock", true, 1, 5, 12); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 2, null); } @Test public void testCtForEach() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctForEach", true, 1, 4, 11); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 1, null); } @Test public void testCtWhileBlock() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctWhileBlock", false, 1, 5, 13); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 0, 0, 2, null); } @Test public void testCtWhileBlockSimplify() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctWhileBlock", true, 1, 5, 12); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 2, null); } @Test public void testCtWhile() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctWhile", true, 1, 4, 11); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 1, null); } @Test public void testCtDoWhileBlock() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctDoWhileBlock", false, 1, 5, 14); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 0, 0, 2, null); } @Test public void testCtDoWhileBlockSimplify() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctDoWhileBlock", true, 1, 5, 12); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 2, null); } @Test public void testCtDoWhile() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("ctDoWhile", false, 1, 4, 13); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 0, 0, 1, null); } @Test public void testConditional() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("conditional", false, 1, 3, 9); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 2, 0, 0, null); } @Test public void testNestedConditional() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("nestedConditional", false, 2, 5, 13); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 3, 1, 0, null); } @Test public void testNestedIf() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("nestedIfs", false, 3, 6, null); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 0, 0, 2, null); } @Test public void testInvocation() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("invocation", true, 1, 2, null); - //Branches-Statement Branches-Branches sStatement-Statement total testEdges(graph, 1, 0, 0, null); } @@ -359,12 +292,9 @@ public void process(CtConstructor element) { @Test public void testtestCase() throws Exception { - //branchCount, stmntCount, totalCount ControlFlowGraph graph = testMethod("complex1", true, null, null, null); graph.simplifyBlockNodes(); System.out.println(graph.toGraphVisText()); - //Branches-Statement Branches-Branches sStatement-Statement total - //testEdges(graph, 2, 0, 2, null); } diff --git a/spoon-control-flow/src/test/resources/control-flow/ControlFlowArithmetic.java b/spoon-control-flow/src/test/resources/control-flow/ControlFlowArithmetic.java index 776f57bb71b..135bd41013b 100644 --- a/spoon-control-flow/src/test/resources/control-flow/ControlFlowArithmetic.java +++ b/spoon-control-flow/src/test/resources/control-flow/ControlFlowArithmetic.java @@ -33,7 +33,7 @@ public class ControlFlowArithmetic { /** - * A simple break to example + * A simple labeled continue example * * @return */ @@ -51,7 +51,7 @@ public int simpleContinueTo() { return i; } - //several constructions one after the other + // Several constructs one after the other public int mixed(int a, int b) { if (b % 2 == 0) { return a + b; @@ -62,7 +62,7 @@ public int mixed(int a, int b) { return a + b * 2; } - //several constructions one after the other + // Method invocation public int invocation(int a, int b) { if (b % 2 == 0) { return nestedIfs(a, b); @@ -71,7 +71,7 @@ public int invocation(int a, int b) { } /** - * Simple example of break + * Simple example of a labeled break * * @param args */ @@ -129,7 +129,7 @@ public boolean simpleBreak(String[] args) { } - //complex case of continue and breaks. + // Complex case of continue and breaks. public void continueAndBreak() { factorize_loop: while (true) { @@ -167,7 +167,7 @@ public void continueAndBreak() { } } - //Some nested ifs some not returning + // Some nested ifs some not returning public int nestedIfSomeNotReturning(int a, int b) { if (a > 0) { if (b > 0) return a * b; @@ -181,7 +181,7 @@ public int nestedIfSomeNotReturning(int a, int b) { return b; } - //Some nested ifs + // Some nested ifs that all have a return statement public int nestedIfAllReturning(int a, int b) { if (a > 0) { if (b > 0) return a * b; @@ -197,7 +197,7 @@ public int nestedIfAllReturning(int a, int b) { //return 0; } - //Some nested ifs + // Some nested ifs public int nestedIfs(int a, int b) { if (a > 0) { if (b > 0) return a * b; @@ -214,12 +214,12 @@ public int nestedIfs(int a, int b) { public void dontReturn(int a) { if (a > 0) System.out.print("otra cosa"); - else System.out.print("A < 0!"); + else System.out.print("A <= 0!"); } public void returnVoid(int a) { if (a > 0) return; - else System.out.print("A < 0!"); + else System.out.print("A <= 0!"); } public int nestedConditional(int a) { @@ -302,13 +302,13 @@ public int ctForEachBlock(List a) { return b; } - //A For to test the control flow in a for + // A For without a block to test the control flow in a for public int ctFor(int a, int b) { for (int i = 0; i < a; i++) b += a * b; return b; } - //A For to test the control flow in a for + // A For with a block to test the control flow in a for public int ctForBlock(int a, int b) { for (int i = 0; i < a; i++) { int k = i * i; @@ -317,13 +317,13 @@ public int ctForBlock(int a, int b) { return b; } - //Yet another dummy procedure to test some logic branches + // Yet another dummy procedure to test some logic branches public int ifThen(int a, int b) { if (b % 2 == 0) return a - b; return 0; } - //Yet another dummy procedure to test some logic branches + // Yet another dummy procedure to test some logic branches public int ifThenElse(int a, int b) { if (b % 2 == 0) return a - b; else b = b + a; @@ -331,7 +331,7 @@ public int ifThenElse(int a, int b) { } - //Yet another dummy procedure to test some logic branches + // Yet another dummy procedure to test some logic branches public int ifThenBlock(int a, int b) { if (b % 2 == 0) { a += b * b; @@ -340,7 +340,7 @@ public int ifThenBlock(int a, int b) { return 0; } - //Yet another dummy procedure to test some logic branches + // Yet another dummy procedure to test some logic branches public int ifThenElseBlock(int a, int b) { if (b % 2 == 0) { a += b * b; @@ -377,7 +377,7 @@ public int lastCaseFallThrough(int a) { return b; } - //All lines will be tested in this method + // All lines will be tested in this method public int simple(int a) { a = a + a / 2; return 10 * a; @@ -417,7 +417,7 @@ public int testCase1(boolean armed, double inputs1, double inputs2, double THRES return a; } - boolean m3() { + boolean method3() { return true; } @@ -429,7 +429,7 @@ public void complex1(double phase, double source, double target, double baseIncr phase -= 1.0; baseIncrement = method1(); } - } else if ((i == 0) && ((starved) || (!(m3())))) { + } else if ((i == 0) && ((starved) || (!(method3())))) { source = target = current; phase = 0.0; baseIncrement = method1(); From 45fc7e64ed011d8ee310a42aa77dcf1da9708df1 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 12:29:08 +0200 Subject: [PATCH 04/32] Remove unnecessary comments and raw types --- .../controlflow/AllBranchesReturnTest.java | 89 +------------------ 1 file changed, 3 insertions(+), 86 deletions(-) diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/AllBranchesReturnTest.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/AllBranchesReturnTest.java index ef1ea725f6b..2845c220d8f 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/AllBranchesReturnTest.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/AllBranchesReturnTest.java @@ -33,92 +33,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -/** - * Created by marodrig on 04/01/2016. - */ public class AllBranchesReturnTest { -/* - private ModifierKind getInvocationMethodVisibility(CtInvocation inv) { - if (inv.getExecutable().getDeclaration() != null && - inv.getExecutable().getDeclaration() instanceof CtMethodImpl) - return (inv.getExecutable().getDeclaration()).getVisibility(); - return null; - } - - @Test - public void testSegment2() throws Exception { - final Factory factory = new SpoonMetaFactory().buildNewFactory( - "C:\\MarcelStuff\\DATA\\DIVERSE\\input_programs\\MATH_3_2\\src\\main\\java", 7); - // "C:\\MarcelStuff\\DATA\\DIVERSE\\input_programs\\easymock-light-3.2\\src\\main\\javaz", 7); - ProcessingManager pm = new QueueProcessingManager(factory); - - - AbstractProcessor p = new AbstractProcessor() { - @Override - public void process(CtMethod ctMethod) { - List fors = ctMethod.getElements(new TypeFilter(CtFor.class)); - if (ctMethod.getBody() == null || ctMethod.getBody().getStatements() == null) return; - - int size = ctMethod.getBody().getStatements().size(); - - if (size > 6 || fors.size() < 1 || !hasInterfaceVariables(ctMethod) ) return; - - printMethod(ctMethod); - - } - }; - - pm.addProcessor(p); - pm.process(); - } - - private boolean hasInterfaceVariables(CtMethod ctMethod) { - List vars = - ctMethod.getElements(new TypeFilter(CtVariableAccess.class)); - for ( CtVariableAccess a : vars ) { - try { - if (!a.getVariable().getDeclaration().getModifiers().contains(ModifierKind.FINAL) && - a.getVariable().getType().isInterface()) return true; - } catch (Exception e) { - System.out.print("."); - } - } - return false; - } - - private void printMethod(CtMethod ctMethod) { - System.out.println(ctMethod.getPosition().toString()); - System.out.println(ctMethod); - //System.out.println(invName); - System.out.println("+++++++++++++++++++++++++++++++++++++"); - - } - - private void printStaticInvocations(CtMethodImpl ctMethod) { - List invs = ctMethod.getElements(new TypeFilter(CtInvocation.class)); - boolean staticInv = true; - boolean abstractVarAccess = false; - String invName = ""; - for (CtInvocation inv : invs) { - ModifierKind mk = getInvocationMethodVisibility(inv); - if (inv.getExecutable().isStatic() && - (mk == ModifierKind.PRIVATE || mk == ModifierKind.PROTECTED)) { - invName = inv.toString(); - staticInv = true; - break; - } - } - if( staticInv) { - System.out.println(ctMethod.getPosition().toString()); - System.out.println(ctMethod); - System.out.println(invName); - System.out.println("+++++++++++++++++++++++++++++++++++++"); - } - }*/ - public void testSegment(AbstractProcessor processor) throws Exception { - //ControlFlowGraph graph = buildGraph(this.getClass().getResource("/control-flow").toURI().getPath(), - // "nestedIfSomeNotReturning", false); + public void testSegment(AbstractProcessor processor) throws Exception { Factory factory = new SpoonMetaFactory().buildNewFactory( this.getClass().getResource("/control-flow").toURI().getPath(), 7); @@ -132,7 +49,7 @@ public void nestedIfSomeNotReturning() throws Exception { testSegment(new AbstractProcessor() { @Override public void process(CtIf element) { - CtMethod m = element.getParent().getParent(CtMethod.class); + CtMethod m = element.getParent().getParent(CtMethod.class); if (m != null && m.getSimpleName().equals("nestedIfSomeNotReturning")) if (element.getCondition().toString().contains("b < 1")) { AllBranchesReturn alg = new AllBranchesReturn(); @@ -147,7 +64,7 @@ public void testNestedIfAllReturning() throws Exception { testSegment(new AbstractProcessor() { @Override public void process(CtIf element) { - CtMethod m = element.getParent().getParent(CtMethod.class); + CtMethod m = element.getParent().getParent(CtMethod.class); if (m != null && m.getSimpleName().equals("nestedIfAllReturning")) if (element.getCondition().toString().contains("a > 0")) { AllBranchesReturn alg = new AllBranchesReturn(); From 8baab3fe82e994f0ff48d276523a9c223bf055de Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 12:33:50 +0200 Subject: [PATCH 05/32] Properly format javadoc, remove unnecessary throw --- .../inria/controlflow/ControlFlowGraphTests.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java index 1ed0fa866bc..682d154548a 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java @@ -36,13 +36,11 @@ /** * Control flow graph tests - * - * Created by marodrig on 14/10/2015. */ public class ControlFlowGraphTests { @Test - public void testFindNodeNotFound() throws NotFoundException{ + public void testFindNodeNotFound() { assertThrows(NotFoundException.class, () -> { ControlFlowGraph graph = new ControlFlowGraph(); CtStatement s = new CtIfImpl(); @@ -67,16 +65,20 @@ public void testFindNode() throws NotFoundException { /** * Build this graph (* means fictitious nodes) + *
 	 *     X1 -X2 - O1
 	 *     |    |   |
 	 *     \ __*1 _/
 	 *          |
 	 *          O2
+	 *     
* * Simplify onto this + *
 	 *     X1 -X2 - O1
 	 *     |    |   |
 	 *     \__ O2 __/
+	 *     
*/ @Test public void testSimplify() { @@ -107,6 +109,7 @@ public void testSimplify() { /** * Build this graph (* means fictitious nodes) + *
 	 *     X1 -X2 - O1
 	 *     |    |   |
 	 *     \ __*1 _/
@@ -114,11 +117,14 @@ public void testSimplify() {
 	 *         *2
 	 *          |
 	 *          O2
-	 *
+	 *    
+ *

* Simplify onto this + *

 	 *     X1 -X2 - O1
 	 *     |    |   |
 	 *     \__ O2 __/
+	 *     
*/ @Test public void testSimplify2() { From f8c8edd3a49ff5b50f44c6504d27fa284f61e6ea Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 12:34:48 +0200 Subject: [PATCH 06/32] Remove unnecessary print of cfg --- .../src/test/java/fr/inria/controlflow/ExceptionFlowTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java index 18dbcc678db..6e044b9feb9 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java @@ -516,7 +516,6 @@ public void testFinalizerReturnStatementWithSimplifyingOption() { builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy(options)); builder.build(method); ControlFlowGraph cfg = builder.getResult(); - System.out.println(cfg.toGraphVisText()); ControlFlowNode ret = findNodeByString(cfg, "return"); ControlFlowNode a = findNodeByString(cfg, "a()"); From 283fc658317d61f0e170a6ac3a7af8c37bd45452 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 12:39:14 +0200 Subject: [PATCH 07/32] Better formatting for javadoc --- .../main/java/fr/inria/controlflow/AllBranchesReturn.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java index 4d84acf5123..6c10f76b15e 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java @@ -30,23 +30,19 @@ /** * An algorithm that takes a CtElement, builds a graph for it and checks that all branches return * something or that there is no branch returns anything - * - * Created by marodrig on 04/01/2016. */ public class AllBranchesReturn { /** * Finds if all branches returns * - * @param element starting point + * @param element starting point * @return True if all branches return or none return */ public boolean execute(CtElement element) { ControlFlowBuilder builder = new ControlFlowBuilder(); ControlFlowGraph graph = builder.build(element); graph.simplify(); - //System.out.println(graph.toGraphVisText()); - //System.out.println(graph.toGraphVisText()); List exits = graph.findNodesOfKind(BranchKind.EXIT); From da7554c888542d902d99cb254166576124d78f44 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 12:44:14 +0200 Subject: [PATCH 08/32] Rename BranchKind to NodeKind, add better JavaDoc --- .../inria/controlflow/AllBranchesReturn.java | 2 +- .../inria/controlflow/ControlFlowBuilder.java | 74 +++++++++---------- .../inria/controlflow/ControlFlowGraph.java | 22 +++--- .../fr/inria/controlflow/ControlFlowNode.java | 8 +- .../controlflow/GraphVisPrettyPrinter.java | 10 +-- .../NaiveExceptionControlFlowStrategy.java | 18 ++--- .../{BranchKind.java => NodeKind.java} | 54 +++++++++++--- .../inria/dataflow/InitializedVariables.java | 8 +- .../controlflow/ControlFlowGraphTests.java | 2 +- .../inria/controlflow/ExceptionFlowTests.java | 4 +- .../ForwardFlowBuilderVisitorTest.java | 3 +- .../dataflow/InitializedVariablesTest.java | 2 +- 12 files changed, 119 insertions(+), 88 deletions(-) rename spoon-control-flow/src/main/java/fr/inria/controlflow/{BranchKind.java => NodeKind.java} (61%) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java index 6c10f76b15e..e31f7c85ade 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java @@ -45,7 +45,7 @@ public boolean execute(CtElement element) { graph.simplify(); - List exits = graph.findNodesOfKind(BranchKind.EXIT); + List exits = graph.findNodesOfKind(NodeKind.EXIT); int returnCount = 0; int incomingCount = -1; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java index fbf881d0215..5db58dba159 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java @@ -127,9 +127,9 @@ public class ControlFlowBuilder extends CtAbstractVisitor { ControlFlowGraph result = new ControlFlowGraph(ControlFlowEdge.class); - ControlFlowNode exitNode = new ControlFlowNode(null, result, BranchKind.EXIT); + ControlFlowNode exitNode = new ControlFlowNode(null, result, NodeKind.EXIT); - ControlFlowNode beginNode = new ControlFlowNode(null, result, BranchKind.BEGIN); + ControlFlowNode beginNode = new ControlFlowNode(null, result, NodeKind.BEGIN); ControlFlowNode lastNode = beginNode; @@ -196,15 +196,15 @@ public ControlFlowGraph build(CtElement s) { } private void visitConditional(CtElement parent, CtConditional conditional) { - ControlFlowNode branch = new ControlFlowNode(parent, result, BranchKind.BRANCH); + ControlFlowNode branch = new ControlFlowNode(parent, result, NodeKind.BRANCH); tryAddEdge(lastNode, branch); - ControlFlowNode convergenceNode = new ControlFlowNode(null, result, BranchKind.CONVERGE); + ControlFlowNode convergenceNode = new ControlFlowNode(null, result, NodeKind.CONVERGE); lastNode = branch; if (conditional.getThenExpression() instanceof CtConditional) { visitConditional(conditional, (CtConditional) conditional.getThenExpression()); } else { - lastNode = new ControlFlowNode(conditional.getThenExpression(), result, BranchKind.STATEMENT); + lastNode = new ControlFlowNode(conditional.getThenExpression(), result, NodeKind.STATEMENT); tryAddEdge(branch, lastNode); } tryAddEdge(lastNode, convergenceNode); @@ -213,7 +213,7 @@ private void visitConditional(CtElement parent, CtConditional conditional) { if (conditional.getElseExpression() instanceof CtConditional) { visitConditional(conditional, (CtConditional) conditional.getElseExpression()); } else { - lastNode = new ControlFlowNode(conditional.getElseExpression(), result, BranchKind.STATEMENT); + lastNode = new ControlFlowNode(conditional.getElseExpression(), result, NodeKind.STATEMENT); tryAddEdge(branch, lastNode); } tryAddEdge(lastNode, convergenceNode); @@ -273,7 +273,7 @@ public static ControlFlowNode firstNode(ControlFlowGraph g, CtElement statement) } - private void defaultAction(BranchKind kind, CtStatement st) { + private void defaultAction(NodeKind kind, CtStatement st) { ControlFlowNode n = new ControlFlowNode(st, result, kind); tryAddEdge(lastNode, n); lastNode = n; @@ -311,7 +311,7 @@ private void tryAddEdge(ControlFlowNode source, ControlFlowNode target) { * @param breakDance indicates that the edge is a jump out of the block */ private void tryAddEdge(ControlFlowNode source, ControlFlowNode target, boolean isLooping, boolean breakDance) { - if (source != null && source.getKind() != BranchKind.CATCH && source.getStatement() != null && exceptionControlFlowStrategy != null) { + if (source != null && source.getKind() != NodeKind.CATCH && source.getStatement() != null && exceptionControlFlowStrategy != null) { exceptionControlFlowStrategy.handleStatement(this, source); } @@ -370,7 +370,7 @@ public void visitCtArrayTypeReference(CtArrayTypeReference reference) { @Override public void visitCtAssert(CtAssert asserted) { - defaultAction(BranchKind.STATEMENT, asserted); + defaultAction(NodeKind.STATEMENT, asserted); } @Override @@ -381,7 +381,7 @@ public void visitCtAssignment(CtAssignment assignement) { if (assignement.getAssignment() instanceof CtConditional) { visitConditional(assignement, (CtConditional) assignement.getAssignment()); } else { - defaultAction(BranchKind.STATEMENT, assignement); + defaultAction(NodeKind.STATEMENT, assignement); } } @@ -391,7 +391,7 @@ public void visitCtBinaryOperator(CtBinaryOperator operator) { } private void travelStatementList(List statements) { - ControlFlowNode begin = new ControlFlowNode(null, result, BranchKind.BLOCK_BEGIN); + ControlFlowNode begin = new ControlFlowNode(null, result, NodeKind.BLOCK_BEGIN); tryAddEdge(lastNode, begin); lastNode = begin; for (CtStatement s : statements) { @@ -399,7 +399,7 @@ private void travelStatementList(List statements) { s.accept(this); // <- This should modify last node //tryAddEdge(before, lastNode); //Probably the link is already added } - ControlFlowNode end = new ControlFlowNode(null, result, BranchKind.BLOCK_END); + ControlFlowNode end = new ControlFlowNode(null, result, NodeKind.BLOCK_END); tryAddEdge(lastNode, end); lastNode = end; } @@ -418,11 +418,11 @@ public void visitCtBreak(CtBreak breakStatement) { to = null; } if (to != null) { - defaultAction(BranchKind.STATEMENT, breakStatement); + defaultAction(NodeKind.STATEMENT, breakStatement); tryAddEdge(lastNode, to, true, false); } else if (!breakingBad.empty()) { //Jump to the last guy who said I can jump to... - defaultAction(BranchKind.STATEMENT, breakStatement); + defaultAction(NodeKind.STATEMENT, breakStatement); tryAddEdge(lastNode, breakingBad.peek(), false, true); } } @@ -434,7 +434,7 @@ public void visitCtCatch(CtCatch catchBlock) { @Override public void visitCtClass(CtClass ctClass) { - defaultAction(BranchKind.STATEMENT, ctClass); + defaultAction(NodeKind.STATEMENT, ctClass); } @Override @@ -456,7 +456,7 @@ public void visitCtContinue(CtContinue continueStatement) { to = continueBad.peek(); } if (to != null) { - defaultAction(BranchKind.STATEMENT, continueStatement); + defaultAction(NodeKind.STATEMENT, continueStatement); tryAddEdge(lastNode, to, true, false); } } @@ -465,15 +465,15 @@ public void visitCtContinue(CtContinue continueStatement) { public void visitCtDo(CtDo doLoop) { registerStatementLabel(doLoop); - ControlFlowNode convergenceNode = new ControlFlowNode(null, result, BranchKind.CONVERGE); + ControlFlowNode convergenceNode = new ControlFlowNode(null, result, NodeKind.CONVERGE); continueBad.push(convergenceNode); //to break out of the do loop - ControlFlowNode convergenceNodeOut = new ControlFlowNode(null, result, BranchKind.CONVERGE); + ControlFlowNode convergenceNodeOut = new ControlFlowNode(null, result, NodeKind.CONVERGE); breakingBad.push(convergenceNodeOut); tryAddEdge(lastNode, convergenceNode); - ControlFlowNode branch = new ControlFlowNode(doLoop.getLoopingExpression(), result, BranchKind.BRANCH); + ControlFlowNode branch = new ControlFlowNode(doLoop.getLoopingExpression(), result, NodeKind.BRANCH); tryAddEdge(branch, convergenceNode, true, false); tryAddEdge(branch, convergenceNodeOut); @@ -536,11 +536,11 @@ public void visitCtFor(CtFor forLoop) { } } - ControlFlowNode convergence = new ControlFlowNode(forLoop.getExpression(), result, BranchKind.CONVERGE); + ControlFlowNode convergence = new ControlFlowNode(forLoop.getExpression(), result, NodeKind.CONVERGE); breakingBad.push(convergence); //Next the branch - ControlFlowNode branch = new ControlFlowNode(forLoop.getExpression(), result, BranchKind.BRANCH); + ControlFlowNode branch = new ControlFlowNode(forLoop.getExpression(), result, NodeKind.BRANCH); tryAddEdge(lastNode, branch); //Node continue statements can continue to @@ -577,14 +577,14 @@ public void visitCtFor(CtFor forLoop) { public void visitCtForEach(CtForEach foreach) { registerStatementLabel(foreach); - ControlFlowNode convergence = new ControlFlowNode(null, result, BranchKind.CONVERGE); + ControlFlowNode convergence = new ControlFlowNode(null, result, NodeKind.CONVERGE); breakingBad.push(convergence); - ControlFlowNode init = new ControlFlowNode(foreach.getVariable(), result, BranchKind.STATEMENT); + ControlFlowNode init = new ControlFlowNode(foreach.getVariable(), result, NodeKind.STATEMENT); tryAddEdge(lastNode, init); lastNode = init; - ControlFlowNode branch = new ControlFlowNode(foreach.getExpression(), result, BranchKind.BRANCH); + ControlFlowNode branch = new ControlFlowNode(foreach.getExpression(), result, NodeKind.BRANCH); continueBad.push(branch); tryAddEdge(lastNode, branch); @@ -606,10 +606,10 @@ public void visitCtForEach(CtForEach foreach) { public void visitCtIf(CtIf ifElement) { registerStatementLabel(ifElement); - ControlFlowNode branch = new ControlFlowNode(ifElement.getCondition(), result, BranchKind.BRANCH); + ControlFlowNode branch = new ControlFlowNode(ifElement.getCondition(), result, NodeKind.BRANCH); tryAddEdge(lastNode, branch); - ControlFlowNode convergenceNode = new ControlFlowNode(null, result, BranchKind.CONVERGE); + ControlFlowNode convergenceNode = new ControlFlowNode(null, result, NodeKind.CONVERGE); if (ifElement.getThenStatement() != null) { lastNode = branch; ifElement.getThenStatement().accept(this); @@ -634,7 +634,7 @@ public void visitCtInterface(CtInterface intrface) { @Override public void visitCtInvocation(CtInvocation invocation) { registerStatementLabel(invocation); - defaultAction(BranchKind.STATEMENT, invocation); + defaultAction(NodeKind.STATEMENT, invocation); } @Override @@ -653,7 +653,7 @@ public void visitCtLocalVariable(CtLocalVariable localVariable) { if (localVariable.getDefaultExpression() instanceof CtConditional) { visitConditional(localVariable, (CtConditional) localVariable.getDefaultExpression()); } else { - defaultAction(BranchKind.STATEMENT, localVariable); + defaultAction(NodeKind.STATEMENT, localVariable); } } @@ -710,7 +710,7 @@ public > void visitCtExecutableReferenceExpression( @Override public void visitCtOperatorAssignment(CtOperatorAssignment assignment) { registerStatementLabel(assignment); - defaultAction(BranchKind.STATEMENT, assignment); + defaultAction(NodeKind.STATEMENT, assignment); } @Override @@ -736,7 +736,7 @@ public void visitCtParameterReference(CtParameterReference reference) { @Override public void visitCtReturn(CtReturn returnStatement) { registerStatementLabel(returnStatement); - ControlFlowNode n = new ControlFlowNode(returnStatement, result, BranchKind.STATEMENT); + ControlFlowNode n = new ControlFlowNode(returnStatement, result, NodeKind.STATEMENT); tryAddEdge(lastNode, n); tryAddEdge(n, exitNode); lastNode = null; //Special case in which this node does not connect with the next, because is a return @@ -750,7 +750,7 @@ public void visitCtStatementList(CtStatementList statements) { @Override public void visitCtCase(CtCase caseStatement) { registerStatementLabel(caseStatement); - ControlFlowNode caseNode = new ControlFlowNode(caseStatement.getCaseExpression(), result, BranchKind.STATEMENT); + ControlFlowNode caseNode = new ControlFlowNode(caseStatement.getCaseExpression(), result, NodeKind.STATEMENT); tryAddEdge(lastNode, caseNode); lastNode = caseNode; travelStatementList(caseStatement.getStatements()); @@ -760,11 +760,11 @@ public void visitCtCase(CtCase caseStatement) { public void visitCtSwitch(CtSwitch switchStatement) { registerStatementLabel(switchStatement); //Push the condition - ControlFlowNode switchNode = new ControlFlowNode(switchStatement.getSelector(), result, BranchKind.BRANCH); + ControlFlowNode switchNode = new ControlFlowNode(switchStatement.getSelector(), result, NodeKind.BRANCH); tryAddEdge(lastNode, switchNode); //Create a convergence node for all the branches to converge after this - ControlFlowNode convergenceNode = new ControlFlowNode(null, result, BranchKind.CONVERGE); + ControlFlowNode convergenceNode = new ControlFlowNode(null, result, NodeKind.CONVERGE); //Push the convergence node so all non labeled breaks jumps there breakingBad.push(convergenceNode); @@ -773,7 +773,7 @@ public void visitCtSwitch(CtSwitch switchStatement) { //Visit Case registerStatementLabel(caseStatement); - ControlFlowNode cn = new ControlFlowNode(caseStatement.getCaseExpression(), result, BranchKind.STATEMENT); + ControlFlowNode cn = new ControlFlowNode(caseStatement.getCaseExpression(), result, NodeKind.STATEMENT); tryAddEdge(lastNode, cn); if (lastNode != switchNode) { tryAddEdge(switchNode, cn); @@ -852,7 +852,7 @@ public void visitCtTypeAccess(CtTypeAccess typeAccess) { @Override public void visitCtUnaryOperator(CtUnaryOperator operator) { - defaultAction(BranchKind.STATEMENT, operator); + defaultAction(NodeKind.STATEMENT, operator); } @Override @@ -869,10 +869,10 @@ public void visitCtVariableWrite(CtVariableWrite variableWrite) { public void visitCtWhile(CtWhile whileLoop) { registerStatementLabel(whileLoop); - ControlFlowNode convergenceNode = new ControlFlowNode(null, result, BranchKind.CONVERGE); + ControlFlowNode convergenceNode = new ControlFlowNode(null, result, NodeKind.CONVERGE); breakingBad.push(convergenceNode); - ControlFlowNode branch = new ControlFlowNode(whileLoop.getLoopingExpression(), result, BranchKind.BRANCH); + ControlFlowNode branch = new ControlFlowNode(whileLoop.getLoopingExpression(), result, NodeKind.BRANCH); continueBad.push(branch); tryAddEdge(lastNode, branch); diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java index ad3fb5b2c5b..6d8b04395d5 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java @@ -48,7 +48,7 @@ public ControlFlowGraph() { super(ControlFlowEdge.class); } - private int countNodes(BranchKind kind) { + private int countNodes(NodeKind kind) { int result = 0; for (ControlFlowNode v : vertexSet()) { if (v.getKind().equals(kind)) { @@ -100,7 +100,7 @@ public ControlFlowNode findNodeById(int id) { * @param kind of node to find * @return list of nodes */ - public List findNodesOfKind(BranchKind kind) { + public List findNodesOfKind(NodeKind kind) { ArrayList result = new ArrayList(); for (ControlFlowNode n : vertexSet()) { if (n.getKind().equals(kind)) { @@ -125,17 +125,17 @@ public ControlFlowEdge addEdge(ControlFlowNode source, ControlFlowNode target) { * Returns all statements */ public List statements() { - return findNodesOfKind(BranchKind.STATEMENT); + return findNodesOfKind(NodeKind.STATEMENT); } /** * Returns all branches */ public List branches() { - return findNodesOfKind(BranchKind.BRANCH); + return findNodesOfKind(NodeKind.BRANCH); } - private void simplify(BranchKind kind) { + private void simplify(NodeKind kind) { try { List convergence = findNodesOfKind(kind); for (ControlFlowNode n : convergence) { @@ -169,8 +169,8 @@ private void simplify(BranchKind kind) { * Removes all blocks */ public void simplifyBlockNodes() { - simplify(BranchKind.BLOCK_BEGIN); - simplify(BranchKind.BLOCK_END); + simplify(NodeKind.BLOCK_BEGIN); + simplify(NodeKind.BLOCK_END); } /** @@ -185,17 +185,17 @@ public void simplify() { * Removes all convergence nodes */ public void simplifyConvergenceNodes() { - simplify(BranchKind.CONVERGE); + simplify(NodeKind.CONVERGE); } //public void public int branchCount() { - return countNodes(BranchKind.BRANCH); + return countNodes(NodeKind.BRANCH); } public int statementCount() { - return countNodes(BranchKind.STATEMENT); + return countNodes(NodeKind.STATEMENT); } public void setName(String name) { @@ -208,7 +208,7 @@ public String getName() { public ControlFlowNode getExitNode() { if (exitNode == null) { - exitNode = findNodesOfKind(BranchKind.EXIT).get(0); + exitNode = findNodesOfKind(NodeKind.EXIT).get(0); } return exitNode; } diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java index e189cb3315a..db15e54bbf8 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java @@ -42,15 +42,15 @@ public class ControlFlowNode { */ ControlFlowGraph parent; - public BranchKind getKind() { + public NodeKind getKind() { return kind; } - public void setKind(BranchKind kind) { + public void setKind(NodeKind kind) { this.kind = kind; } - private BranchKind kind; + private NodeKind kind; /** * Statement that is going to be pointed to by this node @@ -69,7 +69,7 @@ public void setKind(BranchKind kind) { */ TransferFunctionVisitor visitor; - public ControlFlowNode(CtElement statement, ControlFlowGraph parent, BranchKind kind) { + public ControlFlowNode(CtElement statement, ControlFlowGraph parent, NodeKind kind) { this.kind = kind; this.parent = parent; this.statement = statement; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java index 08cab971373..e42ac9d065a 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java @@ -65,15 +65,15 @@ public String print() { private String printNode(int i, ControlFlowNode n, StringBuilder sb) { String labelStr = " [shape=rectangle, label=\""; - if (n.getKind() == BranchKind.BRANCH) { + if (n.getKind() == NodeKind.BRANCH) { labelStr = " [shape=diamond, label=\""; - } else if (n.getKind() == BranchKind.BEGIN) { + } else if (n.getKind() == NodeKind.BEGIN) { labelStr = " [shape=Mdiamond, label=\""; - } else if (n.getKind() == BranchKind.BLOCK_BEGIN || n.getKind() == BranchKind.BLOCK_END) { + } else if (n.getKind() == NodeKind.BLOCK_BEGIN || n.getKind() == NodeKind.BLOCK_END) { labelStr = " [shape=rectangle, style=filled, fillcolor=gray, label=\""; - } else if (n.getKind() == BranchKind.EXIT) { + } else if (n.getKind() == NodeKind.EXIT) { labelStr = " [shape=doublecircle, label=\""; - } else if (n.getKind() == BranchKind.CONVERGE) { + } else if (n.getKind() == NodeKind.CONVERGE) { labelStr = " [shape=point label=\""; } diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java index 09ec4bc2962..da129ad696b 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java @@ -120,17 +120,17 @@ public void handleTryStatement(ControlFlowBuilder builder, CtTry tryBlock) { ControlFlowNode lastNode = builder.getLastNode(); List catchNodes = new ArrayList<>(); - ControlFlowNode tryNode = new ControlFlowNode(null, graph, BranchKind.TRY); - ControlFlowNode convergeNode = new ControlFlowNode(null, graph, BranchKind.CONVERGE); + ControlFlowNode tryNode = new ControlFlowNode(null, graph, NodeKind.TRY); + ControlFlowNode convergeNode = new ControlFlowNode(null, graph, NodeKind.CONVERGE); for (CtCatch catchBlock : tryBlock.getCatchers()) { - catchNodes.add(new ControlFlowNode(catchBlock.getParameter(), graph, BranchKind.CATCH)); + catchNodes.add(new ControlFlowNode(catchBlock.getParameter(), graph, NodeKind.CATCH)); } ControlFlowNode finallyNode = null; if (tryBlock.getFinalizer() != null) { - finallyNode = new ControlFlowNode(null, graph, BranchKind.FINALLY); + finallyNode = new ControlFlowNode(null, graph, NodeKind.FINALLY); } graph.addEdge(lastNode, tryNode); @@ -182,7 +182,7 @@ public void handleThrowStatement(ControlFlowBuilder builder, CtThrow throwStatem // in postProcess() we will remove the successor for the successful execution. ControlFlowGraph graph = builder.getResult(); - ControlFlowNode throwNode = new ControlFlowNode(throwStatement, graph, BranchKind.STATEMENT); + ControlFlowNode throwNode = new ControlFlowNode(throwStatement, graph, NodeKind.STATEMENT); graph.addEdge(builder.getLastNode(), throwNode); builder.setLastNode(throwNode); } @@ -228,12 +228,12 @@ public void postProcess(ControlFlowGraph graph) { * @param graph Graph to process */ private void removeNonCatchSuccessorsFromThrowStatements(ControlFlowGraph graph) { - graph.findNodesOfKind(BranchKind.STATEMENT).forEach(node -> { + graph.findNodesOfKind(NodeKind.STATEMENT).forEach(node -> { if (!(node.getStatement() instanceof CtThrow)) { return; } - node.next().stream().filter(x -> x.getKind() != BranchKind.CATCH).forEach(nextNode -> { + node.next().stream().filter(x -> x.getKind() != NodeKind.CATCH).forEach(nextNode -> { graph.removeEdge(node, nextNode); removePathWhileUnreachable(nextNode); }); @@ -246,11 +246,11 @@ private void removeNonCatchSuccessorsFromThrowStatements(ControlFlowGraph graph) * @param graph Graph to process */ private void removeUnreachableCatchNodes(ControlFlowGraph graph) { - nodesWithoutPredecessors(graph).stream().filter(node -> node.getKind() == BranchKind.CATCH).forEach(this::removePathWhileUnreachable); + nodesWithoutPredecessors(graph).stream().filter(node -> node.getKind() == NodeKind.CATCH).forEach(this::removePathWhileUnreachable); } private void removeUnreachableFinalizerNodeBlockEndPredecessors(ControlFlowGraph graph) { - graph.findNodesOfKind(BranchKind.FINALLY).forEach(node -> { + graph.findNodesOfKind(NodeKind.FINALLY).forEach(node -> { node.prev().stream().filter(prevNode -> prevNode.prev().size() == 0).forEach(graph::removeVertex); }); } diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/BranchKind.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/NodeKind.java similarity index 61% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/BranchKind.java rename to spoon-control-flow/src/main/java/fr/inria/controlflow/NodeKind.java index e406a0630f0..6d2abbf790c 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/BranchKind.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/NodeKind.java @@ -22,17 +22,47 @@ package fr.inria.controlflow; /** - * Branching for a node + * The kind of a {@link ControlFlowNode} */ -public enum BranchKind { - TRY, // Represents the start of a try block - CATCH, // Represents the start of a catch block - FINALLY, // Represents the start of a finally block - BRANCH, // Represents a branch - STATEMENT, // Represents an statement - BLOCK_BEGIN, // Represents the begining of a block - BLOCK_END, // Represents the end of a block - CONVERGE, // The exit node of all branches. Depending on the analysis it may be convenient to leave them - EXIT, // EXIT node is where all return statements points to - BEGIN // BEGIN node is where all begins +public enum NodeKind { + /** + * Represents the start of a try block + */ + TRY, + /** + * Represents the start of a catch block + */ + CATCH, + /** + * Represents the start of a finally block + */ + FINALLY, + /** + * Represents a branch + */ + BRANCH, + /** + * Represents an statement + */ + STATEMENT, + /** + * Represents the beginning of a block + */ + BLOCK_BEGIN, + /** + * Represents the end of a block + */ + BLOCK_END, + /** + * The exit node of all branches. Depending on the analysis it may be convenient to leave them + */ + CONVERGE, + /** + * The node, where all return statements point to + */ + EXIT, + /** + * Entry point for the control flow graph + */ + BEGIN } diff --git a/spoon-control-flow/src/main/java/fr/inria/dataflow/InitializedVariables.java b/spoon-control-flow/src/main/java/fr/inria/dataflow/InitializedVariables.java index da16864ab53..2e3a873a5de 100644 --- a/spoon-control-flow/src/main/java/fr/inria/dataflow/InitializedVariables.java +++ b/spoon-control-flow/src/main/java/fr/inria/dataflow/InitializedVariables.java @@ -21,7 +21,7 @@ */ package fr.inria.dataflow; -import fr.inria.controlflow.BranchKind; +import fr.inria.controlflow.NodeKind; import fr.inria.controlflow.ControlFlowEdge; import fr.inria.controlflow.ControlFlowNode; import spoon.reflect.code.CtArrayAccess; @@ -80,9 +80,9 @@ public void run(ControlFlowNode node) { HashMap factors = new HashMap<>(); if (node.getParent() != null) { - if (node.getParent().findNodesOfKind(BranchKind.BLOCK_END).size() > 0 - || node.getParent().findNodesOfKind(BranchKind.BLOCK_BEGIN).size() > 0 - || node.getParent().findNodesOfKind(BranchKind.CONVERGE).size() > 0) { + if (node.getParent().findNodesOfKind(NodeKind.BLOCK_END).size() > 0 + || node.getParent().findNodesOfKind(NodeKind.BLOCK_BEGIN).size() > 0 + || node.getParent().findNodesOfKind(NodeKind.CONVERGE).size() > 0) { throw new RuntimeException("Invalid node types. Simplify the graph with the simplify() method."); } } diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java index 682d154548a..1fff63c4196 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java @@ -27,7 +27,7 @@ import spoon.reflect.code.CtStatement; import spoon.reflect.declaration.CtElement; import spoon.support.reflect.code.CtIfImpl; -import static fr.inria.controlflow.BranchKind.*; +import static fr.inria.controlflow.NodeKind.*; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java index 6e044b9feb9..3bb0ff2f0d3 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java @@ -565,7 +565,7 @@ private List> paths(List> prior) { for (List path : prior) { ControlFlowNode lastNode = path.get(path.size() - 1); - if (lastNode.getKind() == BranchKind.EXIT) { + if (lastNode.getKind() == NodeKind.EXIT) { result.add(new ArrayList<>(path)); } else { for (ControlFlowNode nextNode : lastNode.next()) { @@ -591,7 +591,7 @@ private List> paths(List> prior) { * @return True if path contains a catch block node, false otherwise */ private boolean containsCatchBlockNode(List nodes) { - return nodes.stream().anyMatch(node -> node.getKind() == BranchKind.CATCH); + return nodes.stream().anyMatch(node -> node.getKind() == NodeKind.CATCH); } /** diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java index 32ffe330a33..36015334110 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java @@ -32,7 +32,8 @@ import java.net.URISyntaxException; -import static fr.inria.controlflow.BranchKind.*; +import static fr.inria.controlflow.NodeKind.BRANCH; +import static fr.inria.controlflow.NodeKind.STATEMENT; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; diff --git a/spoon-control-flow/src/test/java/fr/inria/dataflow/InitializedVariablesTest.java b/spoon-control-flow/src/test/java/fr/inria/dataflow/InitializedVariablesTest.java index acfb0011030..73920f25811 100644 --- a/spoon-control-flow/src/test/java/fr/inria/dataflow/InitializedVariablesTest.java +++ b/spoon-control-flow/src/test/java/fr/inria/dataflow/InitializedVariablesTest.java @@ -41,7 +41,7 @@ public void testRunSimple() throws Exception { this.getClass().getResource("/initialized").toURI().getPath(), "simpleflow", true); InitializedVariables vars = new InitializedVariables(); graph.simplify(); - ControlFlowNode n = graph.findNodesOfKind(BranchKind.EXIT).get(0); + ControlFlowNode n = graph.findNodesOfKind(NodeKind.EXIT).get(0); vars.run(n); for (CtVariableReference v : vars.getInitialized()) { From fa0df40c89e0f7b36788fe62aab8a67ad50ba2e1 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 12:54:11 +0200 Subject: [PATCH 09/32] Remove dependency provided by spoon-pom --- spoon-control-flow/pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/spoon-control-flow/pom.xml b/spoon-control-flow/pom.xml index 27a4b33dd16..1fad46e4abd 100644 --- a/spoon-control-flow/pom.xml +++ b/spoon-control-flow/pom.xml @@ -83,13 +83,6 @@ jgrapht-core 0.9.2 - - - junit - junit - 4.13.2 - test - From 49dd4e014a2366a282ef9da1da467f2a694a2026 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 13:17:11 +0200 Subject: [PATCH 10/32] Clean up ControlFlowBuilder remove unnecessary Overrides Replace Raw types --- .../inria/controlflow/ControlFlowBuilder.java | 453 ++---------------- 1 file changed, 32 insertions(+), 421 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java index 5db58dba159..8ee519720f0 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java @@ -21,124 +21,57 @@ */ package fr.inria.controlflow; -import spoon.reflect.code.CtAnnotationFieldAccess; -import spoon.reflect.code.CtArrayRead; -import spoon.reflect.code.CtArrayWrite; import spoon.reflect.code.CtAssert; import spoon.reflect.code.CtAssignment; -import spoon.reflect.code.CtBinaryOperator; import spoon.reflect.code.CtBlock; import spoon.reflect.code.CtBreak; import spoon.reflect.code.CtCase; -import spoon.reflect.code.CtCatch; -import spoon.reflect.code.CtCatchVariable; -import spoon.reflect.code.CtCodeSnippetExpression; -import spoon.reflect.code.CtCodeSnippetStatement; -import spoon.reflect.code.CtComment; import spoon.reflect.code.CtConditional; -import spoon.reflect.code.CtConstructorCall; import spoon.reflect.code.CtContinue; import spoon.reflect.code.CtDo; -import spoon.reflect.code.CtExecutableReferenceExpression; -import spoon.reflect.code.CtExpression; -import spoon.reflect.code.CtFieldRead; -import spoon.reflect.code.CtFieldWrite; import spoon.reflect.code.CtFor; import spoon.reflect.code.CtForEach; import spoon.reflect.code.CtIf; import spoon.reflect.code.CtInvocation; -import spoon.reflect.code.CtJavaDoc; -import spoon.reflect.code.CtJavaDocTag; -import spoon.reflect.code.CtLambda; -import spoon.reflect.code.CtLiteral; import spoon.reflect.code.CtLocalVariable; -import spoon.reflect.code.CtNewArray; -import spoon.reflect.code.CtNewClass; import spoon.reflect.code.CtOperatorAssignment; import spoon.reflect.code.CtReturn; import spoon.reflect.code.CtStatement; -import spoon.reflect.code.CtStatementList; -import spoon.reflect.code.CtSuperAccess; import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSwitchExpression; -import spoon.reflect.code.CtSynchronized; -import spoon.reflect.code.CtTextBlock; -import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; -import spoon.reflect.code.CtTryWithResource; -import spoon.reflect.code.CtTypeAccess; -import spoon.reflect.code.CtTypePattern; import spoon.reflect.code.CtUnaryOperator; -import spoon.reflect.code.CtVariableRead; -import spoon.reflect.code.CtVariableWrite; import spoon.reflect.code.CtWhile; -import spoon.reflect.code.CtYieldStatement; -import spoon.reflect.declaration.CtAnnotation; -import spoon.reflect.declaration.CtAnnotationMethod; -import spoon.reflect.declaration.CtAnnotationType; -import spoon.reflect.declaration.CtAnonymousExecutable; import spoon.reflect.declaration.CtClass; -import spoon.reflect.declaration.CtCompilationUnit; -import spoon.reflect.declaration.CtConstructor; import spoon.reflect.declaration.CtElement; -import spoon.reflect.declaration.CtEnum; -import spoon.reflect.declaration.CtEnumValue; -import spoon.reflect.declaration.CtField; -import spoon.reflect.declaration.CtImport; -import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; -import spoon.reflect.declaration.CtModule; -import spoon.reflect.declaration.CtModuleRequirement; -import spoon.reflect.declaration.CtPackage; -import spoon.reflect.declaration.CtPackageDeclaration; -import spoon.reflect.declaration.CtPackageExport; -import spoon.reflect.declaration.CtParameter; -import spoon.reflect.declaration.CtProvidedService; -import spoon.reflect.declaration.CtTypeParameter; -import spoon.reflect.declaration.CtUsedService; -import spoon.reflect.reference.CtArrayTypeReference; -import spoon.reflect.reference.CtCatchVariableReference; -import spoon.reflect.reference.CtExecutableReference; -import spoon.reflect.reference.CtFieldReference; -import spoon.reflect.reference.CtIntersectionTypeReference; -import spoon.reflect.reference.CtLocalVariableReference; -import spoon.reflect.reference.CtModuleReference; -import spoon.reflect.reference.CtPackageReference; -import spoon.reflect.reference.CtParameterReference; -import spoon.reflect.reference.CtTypeMemberWildcardImportReference; -import spoon.reflect.reference.CtTypeParameterReference; -import spoon.reflect.reference.CtTypeReference; -import spoon.reflect.reference.CtUnboundVariableReference; -import spoon.reflect.reference.CtWildcardReference; import spoon.reflect.visitor.CtAbstractVisitor; -import java.lang.annotation.Annotation; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.HashMap; import java.util.List; -import java.util.Stack; /** * Builds the control graph for a given snippet of code - * - * Created by marodrig on 13/10/2015. */ public class ControlFlowBuilder extends CtAbstractVisitor { - ControlFlowGraph result = new ControlFlowGraph(ControlFlowEdge.class); + private final ControlFlowGraph result = new ControlFlowGraph(ControlFlowEdge.class); ControlFlowNode exitNode = new ControlFlowNode(null, result, NodeKind.EXIT); ControlFlowNode beginNode = new ControlFlowNode(null, result, NodeKind.BEGIN); - ControlFlowNode lastNode = beginNode; + private ControlFlowNode lastNode = beginNode; HashMap labeledStatement = new HashMap<>(); //This stack pushes all the nodes to wich a break statement may jump to. - Stack breakingBad = new Stack<>(); + Deque breakingBad = new ArrayDeque<>(); //This stack pushes all the nodes to wich a continue statement may jump to. - Stack continueBad = new Stack<>(); + Deque continueBad = new ArrayDeque<>(); /** * Strategy for modeling exception control flow, if any. @@ -179,7 +112,7 @@ public ControlFlowGraph getResult() { } /** - * Build the control graph + * Build the control graph for the given element * * @param s starting point * @return control flow graph @@ -195,14 +128,14 @@ public ControlFlowGraph build(CtElement s) { return result; } - private void visitConditional(CtElement parent, CtConditional conditional) { + private void visitConditional(CtElement parent, CtConditional conditional) { ControlFlowNode branch = new ControlFlowNode(parent, result, NodeKind.BRANCH); tryAddEdge(lastNode, branch); ControlFlowNode convergenceNode = new ControlFlowNode(null, result, NodeKind.CONVERGE); lastNode = branch; - if (conditional.getThenExpression() instanceof CtConditional) { - visitConditional(conditional, (CtConditional) conditional.getThenExpression()); + if (conditional.getThenExpression() instanceof CtConditional conditionalThen) { + visitConditional(conditional, conditionalThen); } else { lastNode = new ControlFlowNode(conditional.getThenExpression(), result, NodeKind.STATEMENT); tryAddEdge(branch, lastNode); @@ -210,8 +143,8 @@ private void visitConditional(CtElement parent, CtConditional conditional) { tryAddEdge(lastNode, convergenceNode); lastNode = branch; - if (conditional.getElseExpression() instanceof CtConditional) { - visitConditional(conditional, (CtConditional) conditional.getElseExpression()); + if (conditional.getElseExpression() instanceof CtConditional conditionalElse) { + visitConditional(conditional, conditionalElse); } else { lastNode = new ControlFlowNode(conditional.getElseExpression(), result, NodeKind.STATEMENT); tryAddEdge(branch, lastNode); @@ -221,9 +154,9 @@ private void visitConditional(CtElement parent, CtConditional conditional) { } /** - * Returns the first graph node representing the statement s construction. - * - * Usually an statement is represented by many blocks and branches. + * Returns the first graph node representing the statement's construction. + *

+ * Usually a statement is represented by many blocks and branches. * This method returns the first of those blocks/branches. * * @param g Graph in which the bloc is to be found @@ -237,9 +170,8 @@ public static ControlFlowNode firstNode(ControlFlowGraph g, CtElement statement) throw new NotFoundException("statement null"); } - if (statement instanceof CtFor) { - CtFor ctFor = (CtFor) statement; - if (ctFor.getForInit().size() > 0) { + if (statement instanceof CtFor ctFor) { + if (!ctFor.getForInit().isEmpty()) { return g.findNode(ctFor.getForInit().get(0)); } else { return g.findNode(ctFor.getExpression()); @@ -261,12 +193,12 @@ public static ControlFlowNode firstNode(ControlFlowGraph g, CtElement statement) throw new NotFoundException("cannot find initial node of do while loop"); } return n1; - } else if (statement instanceof CtIf) { - return g.findNode(((CtIf) statement).getCondition()); - } else if (statement instanceof CtSwitch) { - return g.findNode(((CtSwitch) statement).getSelector()); - } else if (statement instanceof CtBlock) { - return g.findNode(((CtBlock) statement).getStatement(0)); + } else if (statement instanceof CtIf ifStatement) { + return g.findNode(ifStatement.getCondition()); + } else if (statement instanceof CtSwitch switchStatement) { + return g.findNode(switchStatement.getSelector()); + } else if (statement instanceof CtBlock blockStatement) { + return g.findNode(blockStatement.getStatement(0)); } else { return g.findNode(statement); } @@ -281,7 +213,6 @@ private void defaultAction(NodeKind kind, CtStatement st) { /** * Register the label of the statement - * */ private void registerStatementLabel(CtStatement st) { if (st.getLabel() == null || st.getLabel().isEmpty()) { @@ -319,55 +250,14 @@ private void tryAddEdge(ControlFlowNode source, ControlFlowNode target, boolean boolean isContinue = source != null && source.getStatement() instanceof CtContinue; if (source != null && target != null - && !result.containsEdge(source, target) - && (isLooping || breakDance || !(isBreak || isContinue))) { + && !result.containsEdge(source, target) + && (isLooping || breakDance || !(isBreak || isContinue))) { ControlFlowEdge e = result.addEdge(source, target); e.setBackEdge(isLooping); } } - - @Override - public void visitCtAnnotation(CtAnnotation annotation) { - - } - - @Override - public void visitCtCodeSnippetExpression(CtCodeSnippetExpression expression) { - - } - - @Override - public void visitCtCodeSnippetStatement(CtCodeSnippetStatement statement) { - - } - - @Override - public void visitCtAnnotationType(CtAnnotationType annotationType) { - - } - - @Override - public void visitCtAnonymousExecutable(CtAnonymousExecutable anonymousExec) { - - } - - @Override - public void visitCtArrayRead(CtArrayRead arrayRead) { - - } - - @Override - public void visitCtArrayWrite(CtArrayWrite arrayWrite) { - - } - - @Override - public void visitCtArrayTypeReference(CtArrayTypeReference reference) { - - } - @Override public void visitCtAssert(CtAssert asserted) { defaultAction(NodeKind.STATEMENT, asserted); @@ -378,18 +268,13 @@ public void visitCtAssignment(CtAssignment assignement) { registerStatementLabel(assignement); - if (assignement.getAssignment() instanceof CtConditional) { - visitConditional(assignement, (CtConditional) assignement.getAssignment()); + if (assignement.getAssignment() instanceof CtConditional conditionalAssignment) { + visitConditional(assignement, conditionalAssignment); } else { defaultAction(NodeKind.STATEMENT, assignement); } } - @Override - public void visitCtBinaryOperator(CtBinaryOperator operator) { - - } - private void travelStatementList(List statements) { ControlFlowNode begin = new ControlFlowNode(null, result, NodeKind.BLOCK_BEGIN); tryAddEdge(lastNode, begin); @@ -420,28 +305,18 @@ public void visitCtBreak(CtBreak breakStatement) { if (to != null) { defaultAction(NodeKind.STATEMENT, breakStatement); tryAddEdge(lastNode, to, true, false); - } else if (!breakingBad.empty()) { + } else if (!breakingBad.isEmpty()) { //Jump to the last guy who said I can jump to... defaultAction(NodeKind.STATEMENT, breakStatement); tryAddEdge(lastNode, breakingBad.peek(), false, true); } } - @Override - public void visitCtCatch(CtCatch catchBlock) { - - } - @Override public void visitCtClass(CtClass ctClass) { defaultAction(NodeKind.STATEMENT, ctClass); } - @Override - public void visitCtConditional(CtConditional conditional) { - - } - @Override public void visitCtConstructor(CtConstructor constructor) { constructor.getBody().accept(this); @@ -488,41 +363,6 @@ public void visitCtDo(CtDo doLoop) { continueBad.pop(); } - @Override - public > void visitCtEnum(CtEnum ctEnum) { - - } - - @Override - public void visitCtExecutableReference(CtExecutableReference reference) { - - } - - @Override - public void visitCtField(CtField f) { - - } - - @Override - public void visitCtEnumValue(CtEnumValue enumValue) { - - } - - @Override - public void visitCtThisAccess(CtThisAccess thisAccess) { - - } - - @Override - public void visitCtFieldReference(CtFieldReference reference) { - - } - - @Override - public void visitCtUnboundVariableReference(CtUnboundVariableReference reference) { - - } - @Override public void visitCtFor(CtFor forLoop) { registerStatementLabel(forLoop); @@ -531,7 +371,7 @@ public void visitCtFor(CtFor forLoop) { if (forLoop.getForInit() != null) { if (forLoop.getForInit().size() > 1) { travelStatementList(forLoop.getForInit()); - } else if (forLoop.getForInit().size() > 0) { + } else if (!forLoop.getForInit().isEmpty()) { forLoop.getForInit().get(0).accept(this); } } @@ -556,7 +396,7 @@ public void visitCtFor(CtFor forLoop) { if (forLoop.getForUpdate() != null) { if (forLoop.getForUpdate().size() > 1) { travelStatementList(forLoop.getForUpdate()); - } else if (forLoop.getForUpdate().size() > 0) { + } else if (!forLoop.getForUpdate().isEmpty()) { forLoop.getForUpdate().get(0).accept(this); } } @@ -626,113 +466,33 @@ public void visitCtIf(CtIf ifElement) { lastNode = convergenceNode; } - @Override - public void visitCtInterface(CtInterface intrface) { - - } - @Override public void visitCtInvocation(CtInvocation invocation) { registerStatementLabel(invocation); defaultAction(NodeKind.STATEMENT, invocation); } - @Override - public void visitCtLiteral(CtLiteral literal) { - - } - - @Override - public void visitCtTextBlock(CtTextBlock literal) { - - } - @Override public void visitCtLocalVariable(CtLocalVariable localVariable) { registerStatementLabel(localVariable); - if (localVariable.getDefaultExpression() instanceof CtConditional) { - visitConditional(localVariable, (CtConditional) localVariable.getDefaultExpression()); + if (localVariable.getDefaultExpression() instanceof CtConditional conditionalDefaultExpression) { + visitConditional(localVariable, conditionalDefaultExpression); } else { defaultAction(NodeKind.STATEMENT, localVariable); } } - @Override - public void visitCtLocalVariableReference(CtLocalVariableReference reference) { - - } - - @Override - public void visitCtCatchVariable(CtCatchVariable ctCatchVariable) { - - } - - @Override - public void visitCtCatchVariableReference(CtCatchVariableReference ctCatchVariableReference) { - - } - @Override public void visitCtMethod(CtMethod m) { m.getBody().accept(this); } - @Override - public void visitCtAnnotationMethod(CtAnnotationMethod annotationMethod) { - - } - - @Override - public void visitCtNewArray(CtNewArray newArray) { - - } - - @Override - public void visitCtConstructorCall(CtConstructorCall ctConstructorCall) { - - } - - @Override - public void visitCtNewClass(CtNewClass newClass) { - - } - - @Override - public void visitCtLambda(CtLambda lambda) { - - } - - @Override - public > void visitCtExecutableReferenceExpression(CtExecutableReferenceExpression expression) { - - } - @Override public void visitCtOperatorAssignment(CtOperatorAssignment assignment) { registerStatementLabel(assignment); defaultAction(NodeKind.STATEMENT, assignment); } - @Override - public void visitCtPackage(CtPackage ctPackage) { - - } - - @Override - public void visitCtPackageReference(CtPackageReference reference) { - - } - - @Override - public void visitCtParameter(CtParameter parameter) { - - } - - @Override - public void visitCtParameterReference(CtParameterReference reference) { - - } - @Override public void visitCtReturn(CtReturn returnStatement) { registerStatementLabel(returnStatement); @@ -742,11 +502,6 @@ public void visitCtReturn(CtReturn returnStatement) { lastNode = null; //Special case in which this node does not connect with the next, because is a return } - @Override - public void visitCtStatementList(CtStatementList statements) { - - } - @Override public void visitCtCase(CtCase caseStatement) { registerStatementLabel(caseStatement); @@ -796,11 +551,6 @@ public void visitCtSwitchExpression(CtSwitchExpression switchExpres //TODO: missing, implementation needed } - @Override - public void visitCtSynchronized(CtSynchronized synchro) { - - } - @Override public void visitCtThrow(CtThrow throwStatement) { if (exceptionControlFlowStrategy != null) { @@ -815,56 +565,11 @@ public void visitCtTry(CtTry tryBlock) { } } - @Override - public void visitCtTryWithResource(CtTryWithResource ctTryWithResource) { - - } - - @Override - public void visitCtTypeParameter(CtTypeParameter typeParameter) { - - } - - @Override - public void visitCtTypeParameterReference(CtTypeParameterReference ref) { - - } - - @Override - public void visitCtWildcardReference(CtWildcardReference wildcardReference) { - - } - - @Override - public void visitCtIntersectionTypeReference(CtIntersectionTypeReference reference) { - - } - - @Override - public void visitCtTypeReference(CtTypeReference reference) { - - } - - @Override - public void visitCtTypeAccess(CtTypeAccess typeAccess) { - - } - @Override public void visitCtUnaryOperator(CtUnaryOperator operator) { defaultAction(NodeKind.STATEMENT, operator); } - @Override - public void visitCtVariableRead(CtVariableRead variableRead) { - - } - - @Override - public void visitCtVariableWrite(CtVariableWrite variableWrite) { - - } - @Override public void visitCtWhile(CtWhile whileLoop) { registerStatementLabel(whileLoop); @@ -888,98 +593,4 @@ public void visitCtWhile(CtWhile whileLoop) { continueBad.pop(); } - @Override - public void visitCtAnnotationFieldAccess(CtAnnotationFieldAccess annotationFieldAccess) { - - } - - @Override - public void visitCtFieldRead(CtFieldRead fieldRead) { - - } - - @Override - public void visitCtFieldWrite(CtFieldWrite fieldWrite) { - - } - - @Override - public void visitCtSuperAccess(CtSuperAccess f) { - - } - - @Override - public void visitCtComment(CtComment comment) { - - } - - @Override - public void visitCtJavaDoc(CtJavaDoc comment) { - - } - - @Override - public void visitCtJavaDocTag(CtJavaDocTag docTag) { - - } - - @Override - public void visitCtImport(CtImport ctImport) { - - } - - @Override - public void visitCtModule(CtModule module) { - - } - - @Override - public void visitCtModuleReference(CtModuleReference moduleReference) { - - } - - @Override - public void visitCtPackageExport(CtPackageExport moduleExport) { - - } - - @Override - public void visitCtModuleRequirement(CtModuleRequirement moduleRequirement) { - - } - - @Override - public void visitCtProvidedService(CtProvidedService moduleProvidedService) { - - } - - @Override - public void visitCtUsedService(CtUsedService usedService) { - - } - - @Override - public void visitCtCompilationUnit(CtCompilationUnit compilationUnit) { - - } - - @Override - public void visitCtPackageDeclaration(CtPackageDeclaration packageDeclaration) { - - } - - @Override - public void visitCtTypeMemberWildcardImportReference(CtTypeMemberWildcardImportReference wildcardReference) { - - } - - @Override - public void visitCtYieldStatement(CtYieldStatement ctYieldStatement) { - - } - - @Override - public void visitCtTypePattern(CtTypePattern pattern) { - - } } From 7e13d1697cb518b48280ea5891c79887905b368d Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 13:28:01 +0200 Subject: [PATCH 11/32] Clean up control flow graph elements --- .../fr/inria/controlflow/ControlFlowEdge.java | 7 ++----- .../inria/controlflow/ControlFlowGraph.java | 21 ++++++++++++------- .../fr/inria/controlflow/ControlFlowNode.java | 12 +++++------ 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowEdge.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowEdge.java index 85864edbf27..eea3c4dae98 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowEdge.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowEdge.java @@ -23,9 +23,6 @@ import org.jgrapht.graph.DefaultEdge; -/** - * Created by marodrig on 13/10/2015. - */ public class ControlFlowEdge extends DefaultEdge { /** @@ -37,8 +34,8 @@ public boolean isBackEdge() { return isBackEdge; } - public void setBackEdge(boolean isLooopingEdge) { - this.isBackEdge = isLooopingEdge; + public void setBackEdge(boolean isBackEdge) { + this.isBackEdge = isBackEdge; } public ControlFlowNode getTargetNode() { diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java index 6d8b04395d5..9f86a4fb351 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java @@ -29,7 +29,7 @@ import java.util.Set; /** - * Created by marodrig on 13/10/2015. + * Representation of a Control Flow Graph */ public class ControlFlowGraph extends DefaultDirectedGraph { @@ -67,7 +67,8 @@ public String toGraphVisText() { * Find the node holding and element * * @param e node to find - * @return + * @return the node if found + * @throws NotFoundException if no such node could be found */ public ControlFlowNode findNode(CtElement e) throws NotFoundException { if (e != null) { @@ -83,7 +84,7 @@ public ControlFlowNode findNode(CtElement e) throws NotFoundException { /** * Find nodes by a given id * @param id of the node to find - * @return + * @return the node if found or {@code null} if no such node exists */ public ControlFlowNode findNodeById(int id) { for (ControlFlowNode n : vertexSet()) { @@ -98,10 +99,10 @@ public ControlFlowNode findNodeById(int id) { * Find all nodes of a given kind * * @param kind of node to find - * @return list of nodes + * @return a list of all the nodes of the given kind */ public List findNodesOfKind(NodeKind kind) { - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); for (ControlFlowNode n : vertexSet()) { if (n.getKind().equals(kind)) { result.add(n); @@ -110,6 +111,12 @@ public List findNodesOfKind(NodeKind kind) { return result; } + /** + * Add an edge to this graph + * @param source The node the edge originates from + * @param target The node the edge ends at + * @return the inserted edge + */ @Override public ControlFlowEdge addEdge(ControlFlowNode source, ControlFlowNode target) { if (!containsVertex(source)) { @@ -122,14 +129,14 @@ public ControlFlowEdge addEdge(ControlFlowNode source, ControlFlowNode target) { } /** - * Returns all statements + * {@return all statements} */ public List statements() { return findNodesOfKind(NodeKind.STATEMENT); } /** - * Returns all branches + * {@return all branches} */ public List branches() { return findNodesOfKind(NodeKind.BRANCH); diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java index db15e54bbf8..8d34e78b5d6 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java @@ -28,14 +28,12 @@ /** * A node of the control flow - * - * Created by marodrig on 13/10/2015. */ public class ControlFlowNode { public static int count = 0; - private int id; + private final int id; /** * Çontrol flow graph containing this node @@ -55,11 +53,11 @@ public void setKind(NodeKind kind) { /** * Statement that is going to be pointed to by this node */ - CtElement statement; + private CtElement statement; - List input; + private List input; - List output; + private List output; //An object you can tag to the node Object tag; @@ -188,7 +186,7 @@ public void setTag(Object tag) { @Override public String toString() { if (statement != null) { - return id + " - " + statement.toString(); + return id + " - " + statement; } else { return kind + "_" + id; } From 229e618836a19db9db621a132a6c51cd12d37edc Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 13:31:19 +0200 Subject: [PATCH 12/32] Replace else if construct with switch --- .../controlflow/GraphVisPrettyPrinter.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java index e42ac9d065a..9e0689421aa 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java @@ -24,8 +24,6 @@ import java.util.HashMap; /** * Prints the control flow in .Dot for GraphVis to visualize - * - * Created by marodrig on 14/10/2015. */ public class GraphVisPrettyPrinter { @@ -37,7 +35,6 @@ public GraphVisPrettyPrinter(ControlFlowGraph graph) { public String print() { StringBuilder sb = new StringBuilder("digraph ").append(graph.getName()).append(" { \n"); - //sb.append("exit [shape=doublecircle];\n"); sb.append("node [fontsize = 8];\n"); @@ -64,20 +61,16 @@ public String print() { private String printNode(int i, ControlFlowNode n, StringBuilder sb) { - String labelStr = " [shape=rectangle, label=\""; - if (n.getKind() == NodeKind.BRANCH) { - labelStr = " [shape=diamond, label=\""; - } else if (n.getKind() == NodeKind.BEGIN) { - labelStr = " [shape=Mdiamond, label=\""; - } else if (n.getKind() == NodeKind.BLOCK_BEGIN || n.getKind() == NodeKind.BLOCK_END) { - labelStr = " [shape=rectangle, style=filled, fillcolor=gray, label=\""; - } else if (n.getKind() == NodeKind.EXIT) { - labelStr = " [shape=doublecircle, label=\""; - } else if (n.getKind() == NodeKind.CONVERGE) { - labelStr = " [shape=point label=\""; - } + String labelString = switch (n.getKind()) { + case BRANCH -> " [shape=diamond, label=\""; + case BEGIN -> " [shape=Mdiamond, label=\""; + case BLOCK_BEGIN, BLOCK_END -> " [shape=rectangle, style=filled, fillcolor=gray, label=\""; + case EXIT -> " [shape=doublecircle, label=\""; + case CONVERGE -> " [shape=point label=\""; + default -> " [shape=rectangle, label=\""; + }; - sb.append(i).append(labelStr).append(n.toString().replace("\"", "quot ")).append(" \"]").append(";\n"); + sb.append(i).append(labelString).append(n.toString().replace("\"", "quot ")).append(" \"]").append(";\n"); return sb.toString(); } From 0af0a32e1d26a7ebb1feabae8454a704a0901b1e Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 13:33:55 +0200 Subject: [PATCH 13/32] Properly render javadoc --- .../NaiveExceptionControlFlowStrategy.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java index da129ad696b..7c7445e1586 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java @@ -37,13 +37,14 @@ /** * A naive over-approximating model of exception control flow with limited support for finalizers. - * + *

* The model uses the following assumptions: - * - * 1) Any statement can potentially throw any exception. - * 2) All exceptions thrown inside a try block are caught by the catchers immediately associated with the block. - * - * Support for finalizers is limited by the lack of modeling for the semantics of return statements in regards to + *

    + *
  1. Any statement can potentially throw any exception.
  2. + *
  3. All exceptions thrown inside a try block are caught by the catchers immediately associated with the block.
  4. + *
+ * Support for finalizers is limited by the lack of modeling for the semantics of return statements in regard to * executing finalizers before actually returning. Because of this limitation, by default the implementation will * refuse to model the flow of a try-(catch-)finally construct that contains return statements. An option is * available to allow the model to produce a partially incorrect graph where return statements jump directly to the @@ -56,9 +57,9 @@ public class NaiveExceptionControlFlowStrategy implements ExceptionControlFlowSt public enum Options { /** * Add paths between the end of an empty try {} block and its catchers. - * + *

* Default: disabled. - * + *

* This option exists because expressions of the form "try { } catch(Exception e) { foo(); }" (i.e empty try * blocks) are legal in Java, despite the statement "foo()" trivially being unreachable. In some use cases, * excluding such unreachable statements from the control flow graph may be desirable, while in other cases the @@ -71,9 +72,9 @@ public enum Options { /** * Model (incorrectly) return statements as jumping directly to the exit node without executing any "in-scope" * finalizers. - * + *

* Default: disabled. - * + *

* This option exists to provide a limited form of support for return statements in try-(catch-)finally * constructs despite the lack of complete modeling for the semantics of return statements when finalizers are * present. Depending on the use case, the incorrect aspects of the produced graph may be an acceptable @@ -145,7 +146,7 @@ public void handleTryStatement(ControlFlowBuilder builder, CtTry tryBlock) { graph.addEdge(builder.getLastNode(), finallyNode != null ? finallyNode : convergeNode); for (ControlFlowNode catchNode : catchNodes) { - if (tryBlock.getBody().getStatements().size() == 0 && instanceOptions.contains(Options.AddPathsForEmptyTryBlocks)) { + if (tryBlock.getBody().getStatements().isEmpty() && instanceOptions.contains(Options.AddPathsForEmptyTryBlocks)) { graph.addEdge(tryNode.next().get(0).next().get(0), catchNode); } @@ -251,7 +252,7 @@ private void removeUnreachableCatchNodes(ControlFlowGraph graph) { private void removeUnreachableFinalizerNodeBlockEndPredecessors(ControlFlowGraph graph) { graph.findNodesOfKind(NodeKind.FINALLY).forEach(node -> { - node.prev().stream().filter(prevNode -> prevNode.prev().size() == 0).forEach(graph::removeVertex); + node.prev().stream().filter(prevNode -> prevNode.prev().isEmpty()).forEach(graph::removeVertex); }); } @@ -275,13 +276,13 @@ private void removePathWhileUnreachable(ControlFlowNode start) { * Find all nodes that have an empty set of predecessors. * * @param graph Graph to search - * @return Set of nodes lacking predecessors + * @return The list of nodes lacking predecessors */ private List nodesWithoutPredecessors(ControlFlowGraph graph) { List result = new ArrayList<>(); for (ControlFlowNode node : graph.vertexSet()) { - if (node.prev().size() == 0) { + if (node.prev().isEmpty()) { result.add(node); } } From e3f413a43b44ce6b94c1a6346abc72b9c73067f3 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 13:34:43 +0200 Subject: [PATCH 14/32] Remove creation date --- .../src/main/java/fr/inria/controlflow/NotFoundException.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/NotFoundException.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/NotFoundException.java index 912ca98350e..c8e0368ab03 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/NotFoundException.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/NotFoundException.java @@ -21,9 +21,6 @@ */ package fr.inria.controlflow; -/** - * Created by marodrig on 09/11/2015. - */ public class NotFoundException extends Exception { public NotFoundException(String found) { super(found); From d1d6a8bae6af192a8711a42d389a5c103900f956 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 13:37:33 +0200 Subject: [PATCH 15/32] Remove creation date and unnecessary type parameters --- .../fr/inria/controlflow/TransferFunctionVisitor.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java index deb4dd99f6e..1623dd100ac 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java @@ -31,10 +31,8 @@ /** * Parent for all transfer function visitors. - * + *

* These visitors are meant to be the transfer functions of control flow nodes. - * - * Created by marodrig on 13/10/2015. */ public abstract class TransferFunctionVisitor implements CtVisitor { @@ -61,13 +59,13 @@ public void setControlGraph(DirectedGraph controlGraph */ public List getOutput() { if (output == null) { - output = new ArrayList(); + output = new ArrayList<>(); } return output; } public List transfer(CtElement statement) { - output = new ArrayList(); + output = new ArrayList<>(); statement.accept(this); return output; } From efdc0dab8a8392d4eacd88d128171843455bc9c3 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 13:38:12 +0200 Subject: [PATCH 16/32] Clean up value --- .../src/main/java/fr/inria/controlflow/Value.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/Value.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/Value.java index 1f1d1f69c4f..ded58377100 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/Value.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/Value.java @@ -25,24 +25,22 @@ /** * Value traveling the data-flow - * - * Created by marodrig on 13/10/2015. */ public class Value { - public CtVariable getVariable() { + public CtVariable getVariable() { return variable; } - public void setVariable(CtVariable variable) { + public void setVariable(CtVariable variable) { this.variable = variable; } /** * Variable holding this value */ - CtVariable variable; + private CtVariable variable; } From 237de0c85a0af20676e368b1d6c3fdde895b6e2a Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 13:56:18 +0200 Subject: [PATCH 17/32] Remove unnecessary type arguments --- .../src/main/java/fr/inria/controlflow/ControlFlowNode.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java index 8d34e78b5d6..f125b056762 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java @@ -111,7 +111,7 @@ public int getId() { * Obtains the siblings of a control node. Siblings are the nodes in parallel branches */ public List siblings() { - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); for (ControlFlowNode n : prev()) { for (ControlFlowNode nn : n.next()) { if (!nn.equals(this)) { @@ -126,7 +126,7 @@ public List siblings() { * List of nodes that can be executed just after this one */ public List next() { - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); for (ControlFlowEdge e : parent.outgoingEdgesOf(this)) { result.add(e.getTargetNode()); } @@ -137,7 +137,7 @@ public List next() { * List of nodes that could be executed just before this one */ public List prev() { - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); for (ControlFlowEdge e : parent.incomingEdgesOf(this)) { result.add(e.getSourceNode()); } From fb7148fb4f2fb9f7fcaf686bb26c8339243f0256 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 13:58:07 +0200 Subject: [PATCH 18/32] Update jgrapht version --- spoon-control-flow/pom.xml | 2 +- .../fr/inria/controlflow/TransferFunctionVisitor.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spoon-control-flow/pom.xml b/spoon-control-flow/pom.xml index 1fad46e4abd..2f9d3f66df6 100644 --- a/spoon-control-flow/pom.xml +++ b/spoon-control-flow/pom.xml @@ -81,7 +81,7 @@ org.jgrapht jgrapht-core - 0.9.2 + 1.5.2 diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java index 1623dd100ac..449e58b2cbe 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java @@ -21,7 +21,7 @@ */ package fr.inria.controlflow; -import org.jgrapht.DirectedGraph; +import org.jgrapht.Graph; import spoon.reflect.code.CtStatement; import spoon.reflect.declaration.CtElement; import spoon.reflect.visitor.CtVisitor; @@ -39,18 +39,18 @@ public abstract class TransferFunctionVisitor implements CtVisitor { /** * Control graph over the data flow is being exists */ - DirectedGraph controlGraph; + Graph controlGraph; /** * Outputs of the statement calling the transfer. */ protected List output; - public DirectedGraph getControlGraph() { + public Graph getControlGraph() { return controlGraph; } - public void setControlGraph(DirectedGraph controlGraph) { + public void setControlGraph(Graph controlGraph) { this.controlGraph = controlGraph; } From bb9bd6c568cf8bddfeef8c05a6c850e9cc5a531d Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 14:05:18 +0200 Subject: [PATCH 19/32] Clean up pom xml. Version now follows spoon --- spoon-control-flow/pom.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/spoon-control-flow/pom.xml b/spoon-control-flow/pom.xml index 2f9d3f66df6..f7b7e445f09 100644 --- a/spoon-control-flow/pom.xml +++ b/spoon-control-flow/pom.xml @@ -3,14 +3,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - fr.inria.gforge.spoon spoon-control-flow - 0.0.2-SNAPSHOT + 11.0.1-SNAPSHOT The MIT license - http://www.opensource.org/licenses/mit-license.php + https://www.opensource.org/licenses/mit-license.php repo @@ -18,7 +17,7 @@ fr.inria.gforge.spoon spoon-pom - 10.4.2 + 11.0.1-SNAPSHOT ../spoon-pom @@ -75,7 +74,7 @@ fr.inria.gforge.spoon spoon-core - 11.0.0 + ${project.version} From b9c24aa7c6109a93e2868e2cc3e2caedaabb5348 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 14:31:19 +0200 Subject: [PATCH 20/32] Remove never-used TransferFunctionVisitor and Value (dataflow) from control-flow --- .../fr/inria/controlflow/ControlFlowNode.java | 44 ----------- .../controlflow/TransferFunctionVisitor.java | 74 ------------------- .../main/java/fr/inria/controlflow/Value.java | 46 ------------ 3 files changed, 164 deletions(-) delete mode 100644 spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java delete mode 100644 spoon-control-flow/src/main/java/fr/inria/controlflow/Value.java diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java index f125b056762..6cfe5dea94a 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java @@ -55,18 +55,9 @@ public void setKind(NodeKind kind) { */ private CtElement statement; - private List input; - - private List output; - //An object you can tag to the node Object tag; - /** - * Visitor containing the transfer functions for each node - */ - TransferFunctionVisitor visitor; - public ControlFlowNode(CtElement statement, ControlFlowGraph parent, NodeKind kind) { this.kind = kind; this.parent = parent; @@ -83,26 +74,6 @@ public ControlFlowNode(CtElement statement, ControlFlowGraph parent) { id = count; } - /** - * Performs the transfer using a given visitor - */ - public void transfer(TransferFunctionVisitor visitor) { - this.visitor = visitor; - transfer(); - } - - /** - * Perform the transfer function - */ - public void transfer() { - if (statement != null && visitor != null) { - output = visitor.transfer(statement); - } else { - throw new RuntimeException("Unable to perform the transfer function. Statement or visitor are null."); - } - - } - public int getId() { return id; } @@ -144,13 +115,6 @@ public List prev() { return result; } - public List getOutput() { - if (output == null) { - transfer(); - } - return output; - } - public CtElement getStatement() { return statement; } @@ -159,14 +123,6 @@ public void setStatement(CtElement statement) { this.statement = statement; } - public List getInput() { - return input; - } - - public void setInput(List input) { - this.input = input; - } - public ControlFlowGraph getParent() { return parent; } diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java deleted file mode 100644 index 449e58b2cbe..00000000000 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/TransferFunctionVisitor.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * The MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package fr.inria.controlflow; - -import org.jgrapht.Graph; -import spoon.reflect.code.CtStatement; -import spoon.reflect.declaration.CtElement; -import spoon.reflect.visitor.CtVisitor; - -import java.util.ArrayList; -import java.util.List; - -/** - * Parent for all transfer function visitors. - *

- * These visitors are meant to be the transfer functions of control flow nodes. - */ -public abstract class TransferFunctionVisitor implements CtVisitor { - - /** - * Control graph over the data flow is being exists - */ - Graph controlGraph; - - /** - * Outputs of the statement calling the transfer. - */ - protected List output; - - public Graph getControlGraph() { - return controlGraph; - } - - public void setControlGraph(Graph controlGraph) { - this.controlGraph = controlGraph; - } - - /** - * Output of the last node that called the transfer function - */ - public List getOutput() { - if (output == null) { - output = new ArrayList<>(); - } - return output; - } - - public List transfer(CtElement statement) { - output = new ArrayList<>(); - statement.accept(this); - return output; - } - - -} diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/Value.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/Value.java deleted file mode 100644 index ded58377100..00000000000 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/Value.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * The MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package fr.inria.controlflow; - -import spoon.reflect.declaration.CtVariable; - -/** - * Value traveling the data-flow - */ -public class Value { - - - public CtVariable getVariable() { - return variable; - } - - public void setVariable(CtVariable variable) { - this.variable = variable; - } - - /** - * Variable holding this value - */ - private CtVariable variable; - - -} From 78d242d8cb67f650b6a7fb6c0bd80d0df4bc1763 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 15:39:24 +0200 Subject: [PATCH 21/32] Remove uselessAssignmentAnalysis as it was completely broken --- .../dataflow/UselessAssignmentAnalysis.java | 106 ------------------ .../inria/dataflow/UselessAssignmentTest.java | 37 ------ 2 files changed, 143 deletions(-) delete mode 100644 spoon-control-flow/src/main/java/fr/inria/dataflow/UselessAssignmentAnalysis.java delete mode 100644 spoon-control-flow/src/test/java/fr/inria/dataflow/UselessAssignmentTest.java diff --git a/spoon-control-flow/src/main/java/fr/inria/dataflow/UselessAssignmentAnalysis.java b/spoon-control-flow/src/main/java/fr/inria/dataflow/UselessAssignmentAnalysis.java deleted file mode 100644 index 79934a30b49..00000000000 --- a/spoon-control-flow/src/main/java/fr/inria/dataflow/UselessAssignmentAnalysis.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * The MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package fr.inria.dataflow; - -import fr.inria.controlflow.ControlFlowBuilder; -import fr.inria.controlflow.ControlFlowEdge; -import fr.inria.controlflow.ControlFlowGraph; -import fr.inria.controlflow.ControlFlowNode; -import fr.inria.controlflow.NotFoundException; -import spoon.reflect.code.CtAssignment; -import spoon.reflect.code.CtExpression; -import spoon.reflect.code.CtVariableAccess; -import spoon.reflect.declaration.CtElement; -import spoon.reflect.declaration.CtVariable; -import spoon.reflect.visitor.filter.TypeFilter; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Find useless assignments. A useless assignment is the one assigning to a dead variable. - * (https://en.wikipedia.org/wiki/Live_variable_analysis) - *

- * Return the list of useless assignments - *

- * Created by marodrig on 03/02/2016. - */ -public class UselessAssignmentAnalysis { - - Set useless; - - /** - * The method calculates the control flow for 'container' and then returns the useless assignments - * - * @param container to run - * @throws NotFoundException if element 'begin' does not belong to 'container' - */ - public void run(CtElement container) throws NotFoundException { - ControlFlowGraph graph = new ControlFlowBuilder().build(container); - run(graph); - } - - /** - * The method calculates the control flow for 'container' and then returns the useless assignments - * - * @param graph to be processed - */ - public void run(ControlFlowGraph graph) { - //This is a backward analysis. So start from the end - ControlFlowNode exitNode = graph.getExitNode(); - useless = new HashSet<>(); - doRun(exitNode, graph); - } - - public void doRun(ControlFlowNode n, ControlFlowGraph graph) { - for (ControlFlowEdge e : graph.incomingEdgesOf(n)) { - - HashSet kill = new HashSet<>(); - HashSet gen = new HashSet<>(); - - if (n.getStatement() instanceof CtAssignment) { - CtExpression left = ((CtAssignment) n.getStatement()).getAssigned(); - CtExpression right = ((CtAssignment) n.getStatement()).getAssigned(); - if (right instanceof CtVariableAccess) { - kill.add(((CtVariableAccess) right).getVariable().getDeclaration()); - //else if ( ex instanceof CtArrayAccess) kill.add(((CtArrayAccess)ex).getTarget()); - } else { - throw new UnsupportedOperationException(); - } - - gen.retainAll(getVariableAccess(right)); - - } else { - gen.retainAll(getVariableAccess(n.getStatement())); - } - - - doRun(e.getSourceNode(), graph); - } - } - - private List getVariableAccess(CtElement statement) { - return statement.getElements(new TypeFilter(CtVariableAccess.class)); - } - -} diff --git a/spoon-control-flow/src/test/java/fr/inria/dataflow/UselessAssignmentTest.java b/spoon-control-flow/src/test/java/fr/inria/dataflow/UselessAssignmentTest.java deleted file mode 100644 index 9b7d43c2c66..00000000000 --- a/spoon-control-flow/src/test/java/fr/inria/dataflow/UselessAssignmentTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * The MIT License - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package fr.inria.dataflow; - -import org.junit.jupiter.api.Test; - -/** - * Created by marodrig on 03/02/2016. - */ -public class UselessAssignmentTest { - - @Test - public void testLiveness() { - - } - -} From c204bfdcfdac0cf0a75bdaa4b8de6022f768d619 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 15:40:06 +0200 Subject: [PATCH 22/32] Clean up InitializedVariables analysis and move it to control flow --- .../InitializedVariables.java | 110 ++++++++---------- .../InitializedVariablesTest.java | 6 +- 2 files changed, 54 insertions(+), 62 deletions(-) rename spoon-control-flow/src/main/java/fr/inria/{dataflow => controlflow}/InitializedVariables.java (58%) rename spoon-control-flow/src/test/java/fr/inria/{dataflow => controlflow}/InitializedVariablesTest.java (97%) diff --git a/spoon-control-flow/src/main/java/fr/inria/dataflow/InitializedVariables.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java similarity index 58% rename from spoon-control-flow/src/main/java/fr/inria/dataflow/InitializedVariables.java rename to spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java index 2e3a873a5de..c42bb20df43 100644 --- a/spoon-control-flow/src/main/java/fr/inria/dataflow/InitializedVariables.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Permission is hereby granted, free of charge, to any person obtaining a copy + * Permission is hereby granted, free of charge, to any person obtaining access copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell @@ -19,11 +19,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.dataflow; +package fr.inria.controlflow; -import fr.inria.controlflow.NodeKind; import fr.inria.controlflow.ControlFlowEdge; import fr.inria.controlflow.ControlFlowNode; +import fr.inria.controlflow.NodeKind; import spoon.reflect.code.CtArrayAccess; import spoon.reflect.code.CtAssignment; import spoon.reflect.code.CtExpression; @@ -37,12 +37,10 @@ import java.util.Set; /** - * Find initialized variables in a control flow graph. - *

+ * Find initialized variables in access control flow graph. + * * The algorithms trust that the code from which the graph was created was successfully compiled. That's why * not only assigned variables are considered initialized, but also used variables. - *

- * Created by marodrig on 13/11/2015. */ public class InitializedVariables { @@ -62,27 +60,26 @@ public void setIncludeDefinedInNode(boolean includeDefinedInNode) { */ private boolean includeDefinedInNode = false; - private class InitFactors { - //DO NOT INITIALIZE!!!!! Initial Null value needed by the algorithm - Set defined = null; - //Initialize this one - Set used = new HashSet<>(); + private record InitFactors(Set> defined, Set> used) { + InitFactors() { + this(new HashSet<>(), new HashSet<>()); + } } - public Set getInitialized() { + public Set> getInitialized() { return initialized; } - Set initialized = new HashSet<>(); + Set> initialized = new HashSet<>(); public void run(ControlFlowNode node) { //Already calculated factors HashMap factors = new HashMap<>(); if (node.getParent() != null) { - if (node.getParent().findNodesOfKind(NodeKind.BLOCK_END).size() > 0 - || node.getParent().findNodesOfKind(NodeKind.BLOCK_BEGIN).size() > 0 - || node.getParent().findNodesOfKind(NodeKind.CONVERGE).size() > 0) { + if (!node.getParent().findNodesOfKind(NodeKind.BLOCK_END).isEmpty() + || !node.getParent().findNodesOfKind(NodeKind.BLOCK_BEGIN).isEmpty() + || !node.getParent().findNodesOfKind(NodeKind.CONVERGE).isEmpty()) { throw new RuntimeException("Invalid node types. Simplify the graph with the simplify() method."); } } @@ -92,24 +89,23 @@ public void run(ControlFlowNode node) { initialized.addAll(fp.used); } - private Set defined(ControlFlowNode n) { + private Set> defined(ControlFlowNode n) { //Obtain the variables defined in this node - HashSet def = new HashSet<>(); + HashSet> def = new HashSet<>(); if (n.getStatement() != null) { - if (n.getStatement() instanceof CtLocalVariable) { - CtLocalVariable lv = ((CtLocalVariable) n.getStatement()); - if (lv.getDefaultExpression() != null) { - def.add(lv.getReference()); + if (n.getStatement() instanceof CtLocalVariable localVariable) { + if (localVariable.getDefaultExpression() != null) { + def.add(localVariable.getReference()); } - } else if (n.getStatement() instanceof CtAssignment) { - CtExpression e = ((CtAssignment) n.getStatement()).getAssigned(); - if (e instanceof CtVariableAccess) { - def.add(((CtVariableAccess) e).getVariable()); - } else if (e instanceof CtArrayAccess) { - CtExpression exp = ((CtArrayAccess) e).getTarget(); - if (exp instanceof CtVariableAccess) { - CtVariableReference a = ((CtVariableAccess) exp).getVariable(); - def.add(a); + } else if (n.getStatement() instanceof CtAssignment assignment) { + CtExpression assignedExpression = assignment.getAssigned(); + if (assignedExpression instanceof CtVariableAccess variableAccess) { + def.add(variableAccess.getVariable()); + } else if (assignedExpression instanceof CtArrayAccess arrayAccess) { + CtExpression arrayExpression = arrayAccess.getTarget(); + if (arrayExpression instanceof CtVariableAccess variableAccess) { + CtVariableReference array = variableAccess.getVariable(); + def.add(array); } else { System.out.println("Could not obtain variable from expression"); } @@ -119,25 +115,25 @@ private Set defined(ControlFlowNode n) { return def; } - private Set used(ControlFlowNode n) { + private Set> used(ControlFlowNode n) { if (n.getStatement() == null) { return new HashSet<>(); } //Obtain variables used in this node - HashSet used = new HashSet<>(); - for (CtVariableAccess a: n.getStatement().getElements(new TypeFilter(CtVariableAccess.class))) { - used.add(a.getVariable()); + HashSet> used = new HashSet<>(); + for (CtVariableAccess access : n.getStatement().getElements(new TypeFilter<>(CtVariableAccess.class))) { + used.add(access.getVariable()); } return used; } /** - * Finds the initialized variables at a given point in the control flow + * Finds the initialized variables at access given point in the control flow * * @param n Node to find initialized variables * @param factors already calculated factors for all nodes - * @param includeDefinedInNode - * @return + * @param includeDefinedInNode Whether to include initializations and usages in the node n + * @return An init factors object holding initialized and used variables for the given node */ private InitFactors initialized(ControlFlowNode n, HashMap factors, boolean includeDefinedInNode) { //+ -> Union @@ -151,44 +147,40 @@ private InitFactors initialized(ControlFlowNode n, HashMap defN = includeDefinedInNode ? defined(n) : new HashSet(); + Set> defN = includeDefinedInNode ? defined(n) : new HashSet<>(); //[Used_n - Def_n] - Set usedN = includeDefinedInNode ? used(n) : new HashSet(); + Set> usedN = includeDefinedInNode ? used(n) : new HashSet<>(); usedN.removeAll(defN); InitFactors result = new InitFactors(); - for (ControlFlowEdge e : n.getParent().incomingEdgesOf(n)) { - if (e.isBackEdge()) { + boolean initialEdge = true; + for (ControlFlowEdge edge : n.getParent().incomingEdgesOf(n)) { + if (edge.isBackEdge()) { continue; } - ControlFlowNode p = e.getSourceNode(); + ControlFlowNode previous = edge.getSourceNode(); depth++; - InitFactors fp; - if (factors.containsKey(p)) { - fp = factors.get(p); + InitFactors previousFactors; + if (factors.containsKey(previous)) { + previousFactors = factors.get(previous); } else { - fp = initialized(p, factors, true); + previousFactors = initialized(previous, factors, true); } depth--; //[Def_P for each P ] - if (result.defined == null) { - result.defined = new HashSet<>(); - result.defined.addAll(fp.defined); + if (initialEdge) { + initialEdge = false; + result.defined.addAll(previousFactors.defined); } else { - result.defined.retainAll(fp.defined); + result.defined.retainAll(previousFactors.defined); } - fp.used.removeAll(fp.defined); - result.used.addAll(fp.used); + result.used.addAll(previousFactors.used); } - if (result.defined == null) { - result.defined = defN; - } else { - result.defined.addAll(defN); - } + result.defined.addAll(defN); result.used.addAll(usedN); result.used.removeAll(result.defined); diff --git a/spoon-control-flow/src/test/java/fr/inria/dataflow/InitializedVariablesTest.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java similarity index 97% rename from spoon-control-flow/src/test/java/fr/inria/dataflow/InitializedVariablesTest.java rename to spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java index 73920f25811..3cce1d116de 100644 --- a/spoon-control-flow/src/test/java/fr/inria/dataflow/InitializedVariablesTest.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java @@ -20,7 +20,7 @@ * THE SOFTWARE. */ -package fr.inria.dataflow; +package fr.inria.controlflow; import fr.inria.controlflow.*; import org.junit.jupiter.api.Disabled; @@ -41,10 +41,10 @@ public void testRunSimple() throws Exception { this.getClass().getResource("/initialized").toURI().getPath(), "simpleflow", true); InitializedVariables vars = new InitializedVariables(); graph.simplify(); - ControlFlowNode n = graph.findNodesOfKind(NodeKind.EXIT).get(0); + ControlFlowNode n = graph.findNodesOfKind(NodeKind.EXIT).getFirst(); vars.run(n); - for (CtVariableReference v : vars.getInitialized()) { + for (CtVariableReference v : vars.getInitialized()) { assertFalse(v.getSimpleName().contains("notInitialized")); } assertEquals(vars.getInitialized().size(), 6); From 708b7a62c4f1d741bbe235073508aabf93413e96 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 15:40:23 +0200 Subject: [PATCH 23/32] Remove unused and unimplemented visitors --- .../dataflow/ControlFlowVisitorBackwards.java | 72 ------------------- .../dataflow/ControlFlowVisitorForward.java | 72 ------------------- 2 files changed, 144 deletions(-) delete mode 100644 spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitorBackwards.java delete mode 100644 spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitorForward.java diff --git a/spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitorBackwards.java b/spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitorBackwards.java deleted file mode 100644 index 75b260e4867..00000000000 --- a/spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitorBackwards.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * The MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package fr.inria.dataflow; - -/** - * Created by marodrig on 12/11/2015. - */ -public abstract class ControlFlowVisitorBackwards extends AbstractControlFlowVisitor { - - - /** - * Runs the graph backwards starting from a node visiting all nodes until - * it reach the begin or some node signals an stop - * - * @param statementNode Statement node to stop - */ - /* - public void run(ControlFlowNode statementNode) throws InvalidArgumentException { - - Set visited = new HashSet<>(); - Stack stack = new Stack<>(); - - if (statementNode.getParent() == null) { - throw new InvalidArgumentException(new String[]{"The node has no parent"}); - } - ControlFlowGraph graph = statementNode.getParent(); - - stack.push(graph.findNodesOfKind(BranchKind.BEGIN).get(0)); - do { - ControlFlowNode n = stack.pop(); - - //Don't do anything on the begin node - if (n.getKind().equals(BranchKind.BEGIN)) continue; - - //Skip this node if we have already visited - if (visited.contains(n)) continue; - else visited.add(n); - - if ( visit(n) ) return; - - //Visit backwards - for (ControlFlowEdge e : graph.incomingEdgesOf(n)) { - n = e.getSourceNode(); - stack.push(n); - } - } while (!stack.empty()); - } - - public void doRun(ControlFlowNode n, Set visited) { - - }*/ - -} diff --git a/spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitorForward.java b/spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitorForward.java deleted file mode 100644 index 7dbb3aebf15..00000000000 --- a/spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitorForward.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * The MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package fr.inria.dataflow; - -import fr.inria.controlflow.ControlFlowNode; - -/** - * Created by marodrig on 12/11/2015. - */ -public abstract class ControlFlowVisitorForward extends AbstractControlFlowVisitor { - - /** - * Runs the graph backwards starting from a node visiting all nodes until - * it reach the node pased as parameters or some node signals an stop - * - * @param statementNode Statement node to stop - */ - public void run(ControlFlowNode statementNode) { - - /* - Set visited = new HashSet<>(); - Stack stack = new Stack<>(); - - if (statementNode.getParent() == null) { - throw new InvalidArgumentException(new String[]{"The node has no parent"}); - } - ControlFlowGraph graph = statementNode.getParent(); - - stack.push(graph.findNodesOfKind(BranchKind.BEGIN).get(0)); - do { - ControlFlowNode n = stack.pop(); - - //Finished when we arrive at the node - //and the stack is empty - if (n.equals(statementNode) && stack.empty()) return; - - //Skip this node if we have already visited - if (n.getKind().equals(BranchKind.BEGIN)) continue; - if (visited.contains(n)) continue; - else visited.add(n); - - //Visit the node - - //Visit forward - for (ControlFlowEdge e : graph.outgoingEdgesOf(n)) { - n = e.getTargetNode(); - if (n.equals(statementNode)) return ; - stack.push(n); - } - } while (!stack.empty());*/ - } - -} From 96ca648a010bb7e832fca6e645e8126084237e59 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 15:40:40 +0200 Subject: [PATCH 24/32] Move visitors to control flow package --- .../AbstractControlFlowVisitor.java | 28 +++++++------------ .../ControlFlowVisitor.java | 7 +---- 2 files changed, 11 insertions(+), 24 deletions(-) rename spoon-control-flow/src/main/java/fr/inria/{dataflow => controlflow}/AbstractControlFlowVisitor.java (78%) rename spoon-control-flow/src/main/java/fr/inria/{dataflow => controlflow}/ControlFlowVisitor.java (95%) diff --git a/spoon-control-flow/src/main/java/fr/inria/dataflow/AbstractControlFlowVisitor.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java similarity index 78% rename from spoon-control-flow/src/main/java/fr/inria/dataflow/AbstractControlFlowVisitor.java rename to spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java index be2578d1577..f8438641ca9 100644 --- a/spoon-control-flow/src/main/java/fr/inria/dataflow/AbstractControlFlowVisitor.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java @@ -19,31 +19,23 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.dataflow; +package fr.inria.controlflow; import fr.inria.controlflow.ControlFlowNode; +import fr.inria.controlflow.ControlFlowVisitor; -/** - * Created by marodrig on 13/11/2015. - */ public abstract class AbstractControlFlowVisitor implements ControlFlowVisitor { protected boolean visit(ControlFlowNode n) { //Visit the node - switch (n.getKind()) { - case BEGIN: - return visitBegin(n); - case BLOCK_BEGIN: - return visitBlockBegin(n); - case BLOCK_END: - return visitBlockEnd(n); - case BRANCH: - return visitBranch(n); - case STATEMENT: - return visitStatement(n); - default: - return false; - } + return switch (n.getKind()) { + case BEGIN -> visitBegin(n); + case BLOCK_BEGIN -> visitBlockBegin(n); + case BLOCK_END -> visitBlockEnd(n); + case BRANCH -> visitBranch(n); + case STATEMENT -> visitStatement(n); + default -> false; + }; } } diff --git a/spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitor.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowVisitor.java similarity index 95% rename from spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitor.java rename to spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowVisitor.java index eac6dc956d0..79a452ff9b2 100644 --- a/spoon-control-flow/src/main/java/fr/inria/dataflow/ControlFlowVisitor.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowVisitor.java @@ -19,13 +19,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.dataflow; +package fr.inria.controlflow; -import fr.inria.controlflow.ControlFlowNode; - -/** - * Created by marodrig on 12/11/2015. - */ public interface ControlFlowVisitor { /** From 84e7fd9a246348295f34565983ceb8c1cce25f6e Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 15:41:34 +0200 Subject: [PATCH 25/32] =?UTF-8?q?supprimer=20l'accent=20fran=C3=A7ais?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/fr/inria/controlflow/ControlFlowNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java index 6cfe5dea94a..5b9f8e51d00 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java @@ -36,7 +36,7 @@ public class ControlFlowNode { private final int id; /** - * Çontrol flow graph containing this node + * Control flow graph containing this node */ ControlFlowGraph parent; From 12b8c4e4acb9df4a178b146def4d4a728f261ee1 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 15:46:12 +0200 Subject: [PATCH 26/32] Remove unnecessary imports --- .../java/fr/inria/controlflow/AbstractControlFlowVisitor.java | 3 --- .../main/java/fr/inria/controlflow/InitializedVariables.java | 3 --- 2 files changed, 6 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java index f8438641ca9..f7825152ffc 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java @@ -21,9 +21,6 @@ */ package fr.inria.controlflow; -import fr.inria.controlflow.ControlFlowNode; -import fr.inria.controlflow.ControlFlowVisitor; - public abstract class AbstractControlFlowVisitor implements ControlFlowVisitor { protected boolean visit(ControlFlowNode n) { diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java index c42bb20df43..c33864d21bd 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java @@ -21,9 +21,6 @@ */ package fr.inria.controlflow; -import fr.inria.controlflow.ControlFlowEdge; -import fr.inria.controlflow.ControlFlowNode; -import fr.inria.controlflow.NodeKind; import spoon.reflect.code.CtArrayAccess; import spoon.reflect.code.CtAssignment; import spoon.reflect.code.CtExpression; From b48721c48988a33d4531a550f231bd01f6fba45c Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 15:53:41 +0200 Subject: [PATCH 27/32] Use multiline strings --- .../inria/controlflow/ExceptionFlowTests.java | 420 +++++++++--------- 1 file changed, 222 insertions(+), 198 deletions(-) diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java index 3bb0ff2f0d3..5066232e866 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java @@ -18,18 +18,20 @@ public void testBasicSingle() { // contract: NaiveExceptionControlFlowStrategy should result in every statement parented by a try // block having a path to the corresponding catch block. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " try {\n" + - " a();\n" + - " b();\n" + - " c();\n" + - " } catch (Exception e) {\n" + - " bang();\n" + - " }\n" + - " x();\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + try { + a(); + b(); + c(); + } catch (Exception e) { + bang(); + } + x(); + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); @@ -62,21 +64,23 @@ public void testBasicDouble() { // contract: NaiveExceptionControlFlowStrategy should result in every statement parented by a try // block having a path to the corresponding catch block. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " try {\n" + - " a();\n" + - " } catch (Exception e) {\n" + - " bang();\n" + - " }\n" + - " x();\n" + - " try {\n" + - " b();\n" + - " } catch (Exception e) {\n" + - " boom();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + try { + a(); + } catch (Exception e) { + bang(); + } + x(); + try { + b(); + } catch (Exception e) { + boom(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); @@ -108,21 +112,23 @@ public void testBasicNested() { // contract: NaiveExceptionControlFlowStrategy should result in every statement parented by a try // block having a path to the corresponding catch block. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " try {\n" + - " a();\n" + - " try {\n" + - " b();\n" + - " } catch (Exception e2) {\n" + - " boom();\n" + - " }\n" + - " c();\n" + - " } catch (Exception e1) {\n" + - " bang();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + try { + a(); + try { + b(); + } catch (Exception e2) { + boom(); + } + c(); + } catch (Exception e1) { + bang(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); @@ -155,20 +161,22 @@ public void testMultipleCatchers() { // flow is guaranteed to enter a try block equipped with multiple catchers, or 2) parented // by a try block equipped with multiple catchers, to have a path to every catcher. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " top();\n" + - " try {\n" + - " a();\n" + - " }\n" + - " catch (IOException e) {\n" + - " b();\n" + - " }\n" + - " catch (RuntimeException e) {\n" + - " c();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + top(); + try { + a(); + } + catch (IOException e) { + b(); + } + catch (RuntimeException e) { + c(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); @@ -200,20 +208,22 @@ public void testThrowStatement() { // catcher while having no other paths, meaning unreachable post-throw statements should never // make it into the graph. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " try {\n" + - " throw new RuntimeException();\n" + - " unreachable();\n" + - " }\n" + - " catch (RuntimeException e) {\n" + - " boom();\n" + - " }\n" + - " catch (Exception e) {\n" + - " bang();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + try { + throw new RuntimeException(); + unreachable(); + } + catch (RuntimeException e) { + boom(); + } + catch (Exception e) { + bang(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); @@ -238,15 +248,17 @@ public void testAddPathsForEmptyTryBlocksDisabled() { // any of its catchers, preventing unreachable statements in catch blocks from appearing in // the CFG. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " try {\n" + - " }\n" + - " catch (Exception e) {\n" + - " bang();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + try { + } + catch (Exception e) { + bang(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); @@ -262,15 +274,17 @@ public void testAddPathsForEmptyTryBlocksEnabled() { // an empty try block to each of its catchers, causing unreachable statements in catch blocks to // be included in the CFG. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " try {\n" + - " }\n" + - " catch (Exception e) {\n" + - " bang();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + try { + } + catch (Exception e) { + bang(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); EnumSet options = EnumSet.of(NaiveExceptionControlFlowStrategy.Options.AddPathsForEmptyTryBlocks); @@ -287,26 +301,28 @@ public void testFinalizerReturnStatementInTryBlockRejected() { // contract: NaiveExceptionControlFlowStrategy should reject a try-catch construct if it is equipped with a // finalizer and return statements are used anywhere in the construct - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " top();\n" + - " try {\n" + - " return;\n" + - " }\n" + - " catch (Exception e) {\n" + - " b();\n" + - " }\n" + - " finally {\n" + - " c();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + top(); + try { + return; + } + catch (Exception e) { + b(); + } + finally { + c(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); builder.build(method); }); - } + } @Test public void testFinalizerReturnStatementInCatchBlockRejected() { @@ -314,60 +330,60 @@ public void testFinalizerReturnStatementInCatchBlockRejected() { // contract: NaiveExceptionControlFlowStrategy should reject a try-catch construct if it is equipped with a // finalizer and return statements are used anywhere in the construct - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " top();\n" + - " try {\n" + - " a();\n" + - " }\n" + - " catch (Exception e) {\n" + - " if (random > 0.5f) {\n" + - " return;\n" + - " }\n" + - " }\n" + - " finally {\n" + - " c();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + top(); + try { + a(); + } + catch (Exception e) { + if (random > 0.5f) { + return; + } + } + finally { + c(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); builder.build(method); }); - } + } @Test public void testFinalizerReturnStatementInFinalizerBlockRejected() { // contract: NaiveExceptionControlFlowStrategy should reject a try-catch construct if it is equipped with a // finalizer and return statements are used anywhere in the construct - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " top();\n" + - " try {\n" + - " a();\n" + - " }\n" + - " catch (Exception e) {\n" + - " b();\n" + - " }\n" + - " finally {\n" + - " try {\n" + - " c();" + - " }\n" + - " catch (Exception e) {\n" + - " return;" + - " }\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + top(); + try { + a(); + } + catch (Exception e) { + b(); + } + finally { + try { + c(); } + catch (Exception e) { + return; } + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); - assertThrows(IllegalArgumentException.class, () -> { - builder.build(method); - }); - } + assertThrows(IllegalArgumentException.class, () -> builder.build(method)); + } @Test public void testFinalizer() { @@ -377,20 +393,22 @@ public void testFinalizer() { // block equipped with a finalizer, to unavoidably reach the finalizer block when no return // statements are used. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " top();\n" + - " try {\n" + - " a();\n" + - " }\n" + - " catch (Exception e) {\n" + - " b();\n" + - " }\n" + - " finally {\n" + - " c();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + top(); + try { + a(); + } + catch (Exception e) { + b(); + } + finally { + c(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); @@ -419,17 +437,19 @@ public void testCatchlessTry() { // block equipped with a finalizer, to unavoidably reach the finalizer block when no return // statements are used. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " top();\n" + - " try {\n" + - " a();\n" + - " }\n" + - " finally {\n" + - " b();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + top(); + try { + a(); + } + finally { + b(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); @@ -453,23 +473,25 @@ public void testMultipleCatchersWithFinalizer() { // or 2) parented by a try block equipped with multiple catchers and a finalizer, to unavoidably // reach the finalizer when no return statements are used. - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " top();\n" + - " try {\n" + - " a();\n" + - " }\n" + - " catch (IOException e) {\n" + - " b();\n" + - " }\n" + - " catch (RuntimeException e) {\n" + - " c();\n" + - " }\n" + - " finally {\n" + - " breathe();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + top(); + try { + a(); + } + catch (IOException e) { + b(); + } + catch (RuntimeException e) { + c(); + } + finally { + breathe(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); builder.setExceptionControlFlowStrategy(new NaiveExceptionControlFlowStrategy()); @@ -494,19 +516,21 @@ public void testFinalizerReturnStatementWithSimplifyingOption() { // contract: NaiveExceptionControlFlowStrategy should reject a try-catch construct if it is equipped with a // finalizer and return statements are used anywhere in the construct - CtMethod method = Launcher.parseClass("class A {\n" + - " void m() {\n" + - " try {\n" + - " return;\n" + - " }\n" + - " catch (Exception e) {\n" + - " a();\n" + - " }\n" + - " finally {\n" + - " b();\n" + - " }\n" + - " }\n" + - "}\n").getMethods().iterator().next(); + CtMethod method = Launcher.parseClass(""" + class A { + void m() { + try { + return; + } + catch (Exception e) { + a(); + } + finally { + b(); + } + } + } + """).getMethods().iterator().next(); ControlFlowBuilder builder = new ControlFlowBuilder(); From b458a6f4d7dff33006bccea22921f37bcb7acc5a Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 15:54:35 +0200 Subject: [PATCH 28/32] Small cleanup of InitializedVariablesTest --- .../controlflow/InitializedVariablesTest.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java index 3cce1d116de..561f34f2233 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java @@ -22,16 +22,13 @@ package fr.inria.controlflow; -import fr.inria.controlflow.*; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import spoon.reflect.reference.CtVariableReference; import java.util.HashSet; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.*; public class InitializedVariablesTest { @@ -97,7 +94,7 @@ public void testRunComplex2() throws Exception { vars.run(n); HashSet names = new HashSet<>(); - for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); + for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); assertEquals(vars.getInitialized().size(), 5); assertTrue(names.contains("pp")); @@ -119,10 +116,8 @@ public void testRunComplexSwitch() throws Exception { ControlFlowNode n = ControlFlowBuilder.firstNode(graph, graph.branches().get(3).getStatement().getParent()); vars.run(n); - //boolean cwk1r = false; - //boolean cwk3r = false; HashSet names = new HashSet<>(); - for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); + for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); assertEquals(vars.getInitialized().size(), 6); assertTrue(names.contains("a")); @@ -143,13 +138,11 @@ public void testIndex54_Bug() throws Exception { InitializedVariables vars = new InitializedVariables(); graph.simplify(); System.out.print(graph.toGraphVisText()); - ControlFlowNode n = ControlFlowBuilder.firstNode(graph, graph.branches().get(0).getStatement().getParent()); + ControlFlowNode n = ControlFlowBuilder.firstNode(graph, graph.branches().getFirst().getStatement().getParent()); vars.run(n); - //boolean cwk1r = false; - //boolean cwk3r = false; HashSet names = new HashSet<>(); - for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); + for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); assertEquals(vars.getInitialized().size(), 2); assertTrue(names.contains("eigenValues")); assertTrue(names.contains("e")); From 16b26e284a479d406f7d51d9318c969761b99c53 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 16:02:42 +0200 Subject: [PATCH 29/32] Various minor improvements --- .../inria/controlflow/ControlFlowBuilder.java | 20 +++++++++---------- .../controlflow/GraphVisPrettyPrinter.java | 5 ++--- .../controlflow/InitializedVariables.java | 3 --- .../NaiveExceptionControlFlowStrategy.java | 14 +++++-------- .../ForwardFlowBuilderVisitorTest.java | 2 +- .../controlflow/InitializedVariablesTest.java | 4 ++-- 6 files changed, 20 insertions(+), 28 deletions(-) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java index 8ee519720f0..ed3f5b1012d 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java @@ -60,18 +60,18 @@ public class ControlFlowBuilder extends CtAbstractVisitor { private final ControlFlowGraph result = new ControlFlowGraph(ControlFlowEdge.class); - ControlFlowNode exitNode = new ControlFlowNode(null, result, NodeKind.EXIT); + private final ControlFlowNode exitNode = new ControlFlowNode(null, result, NodeKind.EXIT); - ControlFlowNode beginNode = new ControlFlowNode(null, result, NodeKind.BEGIN); + private final ControlFlowNode beginNode = new ControlFlowNode(null, result, NodeKind.BEGIN); private ControlFlowNode lastNode = beginNode; - HashMap labeledStatement = new HashMap<>(); + private final HashMap labeledStatement = new HashMap<>(); //This stack pushes all the nodes to wich a break statement may jump to. - Deque breakingBad = new ArrayDeque<>(); + private final Deque breakingBad = new ArrayDeque<>(); //This stack pushes all the nodes to wich a continue statement may jump to. - Deque continueBad = new ArrayDeque<>(); + private final Deque continueBad = new ArrayDeque<>(); /** * Strategy for modeling exception control flow, if any. @@ -264,14 +264,14 @@ public void visitCtAssert(CtAssert asserted) { } @Override - public void visitCtAssignment(CtAssignment assignement) { + public void visitCtAssignment(CtAssignment assignment) { - registerStatementLabel(assignement); + registerStatementLabel(assignment); - if (assignement.getAssignment() instanceof CtConditional conditionalAssignment) { - visitConditional(assignement, conditionalAssignment); + if (assignment.getAssignment() instanceof CtConditional conditionalAssignment) { + visitConditional(assignment, conditionalAssignment); } else { - defaultAction(NodeKind.STATEMENT, assignement); + defaultAction(NodeKind.STATEMENT, assignment); } } diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java index 9e0689421aa..944a8c36c2a 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java @@ -39,7 +39,7 @@ public String print() { int i = 0; - HashMap nodeIds = new HashMap(); + HashMap nodeIds = new HashMap<>(); for (ControlFlowNode n : graph.vertexSet()) { printNode(++i, n, sb); nodeIds.put(n, i); @@ -60,7 +60,7 @@ public String print() { } - private String printNode(int i, ControlFlowNode n, StringBuilder sb) { + private void printNode(int i, ControlFlowNode n, StringBuilder sb) { String labelString = switch (n.getKind()) { case BRANCH -> " [shape=diamond, label=\""; case BEGIN -> " [shape=Mdiamond, label=\""; @@ -71,7 +71,6 @@ private String printNode(int i, ControlFlowNode n, StringBuilder sb) { }; sb.append(i).append(labelString).append(n.toString().replace("\"", "quot ")).append(" \"]").append(";\n"); - return sb.toString(); } } diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java index c33864d21bd..cdfcadd15d5 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java @@ -41,7 +41,6 @@ */ public class InitializedVariables { - private int depth = 0; //See the algorithm description in the adjoint pdf public boolean getIncludeDefinedInNode() { @@ -157,14 +156,12 @@ private InitFactors initialized(ControlFlowNode n, HashMap { - graph.addEdge(source, catchNode); - }); + catchNodes.forEach(catchNode -> graph.addEdge(source, catchNode)); } } @@ -251,9 +249,7 @@ private void removeUnreachableCatchNodes(ControlFlowGraph graph) { } private void removeUnreachableFinalizerNodeBlockEndPredecessors(ControlFlowGraph graph) { - graph.findNodesOfKind(NodeKind.FINALLY).forEach(node -> { - node.prev().stream().filter(prevNode -> prevNode.prev().isEmpty()).forEach(graph::removeVertex); - }); + graph.findNodesOfKind(NodeKind.FINALLY).forEach(node -> node.prev().stream().filter(prevNode -> prevNode.prev().isEmpty()).forEach(graph::removeVertex)); } /** @@ -263,7 +259,7 @@ private void removeUnreachableFinalizerNodeBlockEndPredecessors(ControlFlowGraph * @param start Starting node */ private void removePathWhileUnreachable(ControlFlowNode start) { - Deque nodesToRemove = new LinkedList(Collections.singletonList(start)); + Deque nodesToRemove = new LinkedList<>(Collections.singletonList(start)); while (!nodesToRemove.isEmpty()) { ControlFlowNode node = nodesToRemove.removeFirst(); @@ -293,10 +289,10 @@ private List nodesWithoutPredecessors(ControlFlowGraph graph) { /** * Stack of catch nodes that statements parented by a try block may jump to. */ - private Stack> catchNodeStack; + private final Stack> catchNodeStack; /** * Flag indicating whether paths should be added between an empty try {} block and its catchers. */ - private EnumSet instanceOptions; + private final EnumSet instanceOptions; } diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java index 36015334110..04edcc8b023 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java @@ -46,7 +46,7 @@ public static ControlFlowGraph buildGraph(String folder, final String methodName ProcessingManager pm = new QueueProcessingManager(factory); pm.addProcessor(new AbstractProcessor>() { @Override - public void process(CtMethod element) { + public void process(CtMethod element) { if (element.getSimpleName().equals(methodName)) { visitor.build(element); } diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java b/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java index 561f34f2233..52bab5334bc 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java +++ b/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java @@ -61,7 +61,7 @@ public void testRunComplex() throws Exception { vars.run(n); HashSet names = new HashSet<>(); - for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); + for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); assertEquals(vars.getInitialized().size(), 11); assertTrue(names.contains("wn4r")); @@ -165,7 +165,7 @@ public void testTwoConsecutiveLoops() throws Exception { //boolean cwk1r = false; //boolean cwk3r = false; HashSet names = new HashSet<>(); - for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); + for (CtVariableReference v : vars.getInitialized()) names.add(v.getSimpleName()); assertEquals(2, vars.getInitialized().size()); assertFalse(names.contains("i")); } From 4068d9b31730697920e087adb2c7422ea9719054 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 16:28:35 +0200 Subject: [PATCH 30/32] Move to better package name (analogous to spoon-javadoc) --- .../controlflow/AbstractControlFlowVisitor.java | 2 +- .../{fr/inria => spoon}/controlflow/AllBranchesReturn.java | 2 +- .../inria => spoon}/controlflow/ControlFlowBuilder.java | 2 +- .../{fr/inria => spoon}/controlflow/ControlFlowEdge.java | 2 +- .../{fr/inria => spoon}/controlflow/ControlFlowGraph.java | 2 +- .../{fr/inria => spoon}/controlflow/ControlFlowNode.java | 2 +- .../inria => spoon}/controlflow/ControlFlowVisitor.java | 2 +- .../controlflow/ExceptionControlFlowStrategy.java | 2 +- .../inria => spoon}/controlflow/GraphVisPrettyPrinter.java | 2 +- .../inria => spoon}/controlflow/InitializedVariables.java | 2 +- .../controlflow/NaiveExceptionControlFlowStrategy.java | 2 +- .../java/{fr/inria => spoon}/controlflow/NodeKind.java | 2 +- .../{fr/inria => spoon}/controlflow/NotFoundException.java | 2 +- .../inria => spoon}/controlflow/AllBranchesReturnTest.java | 2 +- .../inria => spoon}/controlflow/ControlFlowGraphTests.java | 7 ++++--- .../inria => spoon}/controlflow/ExceptionFlowTests.java | 2 +- .../controlflow/ForwardFlowBuilderVisitorTest.java | 6 +++--- .../controlflow/InitializedVariablesTest.java | 2 +- .../{fr/inria => spoon}/controlflow/SpoonMetaFactory.java | 2 +- 19 files changed, 24 insertions(+), 23 deletions(-) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/AbstractControlFlowVisitor.java (98%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/AllBranchesReturn.java (98%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/ControlFlowBuilder.java (99%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/ControlFlowEdge.java (98%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/ControlFlowGraph.java (99%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/ControlFlowNode.java (99%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/ControlFlowVisitor.java (98%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/ExceptionControlFlowStrategy.java (98%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/GraphVisPrettyPrinter.java (98%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/InitializedVariables.java (99%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/NaiveExceptionControlFlowStrategy.java (99%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/NodeKind.java (98%) rename spoon-control-flow/src/main/java/{fr/inria => spoon}/controlflow/NotFoundException.java (97%) rename spoon-control-flow/src/test/java/{fr/inria => spoon}/controlflow/AllBranchesReturnTest.java (98%) rename spoon-control-flow/src/test/java/{fr/inria => spoon}/controlflow/ControlFlowGraphTests.java (97%) rename spoon-control-flow/src/test/java/{fr/inria => spoon}/controlflow/ExceptionFlowTests.java (99%) rename spoon-control-flow/src/test/java/{fr/inria => spoon}/controlflow/ForwardFlowBuilderVisitorTest.java (98%) rename spoon-control-flow/src/test/java/{fr/inria => spoon}/controlflow/InitializedVariablesTest.java (99%) rename spoon-control-flow/src/test/java/{fr/inria => spoon}/controlflow/SpoonMetaFactory.java (98%) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java b/spoon-control-flow/src/main/java/spoon/controlflow/AbstractControlFlowVisitor.java similarity index 98% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java rename to spoon-control-flow/src/main/java/spoon/controlflow/AbstractControlFlowVisitor.java index f7825152ffc..c7b51375229 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/AbstractControlFlowVisitor.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/AbstractControlFlowVisitor.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; public abstract class AbstractControlFlowVisitor implements ControlFlowVisitor { diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java b/spoon-control-flow/src/main/java/spoon/controlflow/AllBranchesReturn.java similarity index 98% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java rename to spoon-control-flow/src/main/java/spoon/controlflow/AllBranchesReturn.java index e31f7c85ade..eeb493f4638 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/AllBranchesReturn.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/AllBranchesReturn.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import spoon.reflect.code.CtReturn; import spoon.reflect.declaration.CtElement; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowBuilder.java similarity index 99% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java rename to spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowBuilder.java index ed3f5b1012d..c692f71e6c6 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowBuilder.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import spoon.reflect.code.CtAssert; import spoon.reflect.code.CtAssignment; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowEdge.java b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowEdge.java similarity index 98% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowEdge.java rename to spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowEdge.java index eea3c4dae98..91d71f045aa 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowEdge.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowEdge.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import org.jgrapht.graph.DefaultEdge; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowGraph.java similarity index 99% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java rename to spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowGraph.java index 9f86a4fb351..e94d175f7da 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowGraph.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowGraph.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import org.jgrapht.graph.DefaultDirectedGraph; import spoon.reflect.declaration.CtElement; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowNode.java similarity index 99% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java rename to spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowNode.java index 5b9f8e51d00..29a8dca94f5 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowNode.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowNode.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import spoon.reflect.declaration.CtElement; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowVisitor.java b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowVisitor.java similarity index 98% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowVisitor.java rename to spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowVisitor.java index 79a452ff9b2..7cf55608f6f 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowVisitor.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/ControlFlowVisitor.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; public interface ControlFlowVisitor { diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ExceptionControlFlowStrategy.java b/spoon-control-flow/src/main/java/spoon/controlflow/ExceptionControlFlowStrategy.java similarity index 98% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/ExceptionControlFlowStrategy.java rename to spoon-control-flow/src/main/java/spoon/controlflow/ExceptionControlFlowStrategy.java index 035a7e0bca5..e8d292463ec 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ExceptionControlFlowStrategy.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/ExceptionControlFlowStrategy.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java b/spoon-control-flow/src/main/java/spoon/controlflow/GraphVisPrettyPrinter.java similarity index 98% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java rename to spoon-control-flow/src/main/java/spoon/controlflow/GraphVisPrettyPrinter.java index 944a8c36c2a..106c6d85588 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/GraphVisPrettyPrinter.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/GraphVisPrettyPrinter.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import java.util.HashMap; /** diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java b/spoon-control-flow/src/main/java/spoon/controlflow/InitializedVariables.java similarity index 99% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java rename to spoon-control-flow/src/main/java/spoon/controlflow/InitializedVariables.java index cdfcadd15d5..722224c983f 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/InitializedVariables.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/InitializedVariables.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import spoon.reflect.code.CtArrayAccess; import spoon.reflect.code.CtAssignment; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java b/spoon-control-flow/src/main/java/spoon/controlflow/NaiveExceptionControlFlowStrategy.java similarity index 99% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java rename to spoon-control-flow/src/main/java/spoon/controlflow/NaiveExceptionControlFlowStrategy.java index ef33b9ddb0c..61a7f14084c 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/NaiveExceptionControlFlowStrategy.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/NaiveExceptionControlFlowStrategy.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import spoon.reflect.code.CtCatch; import spoon.reflect.code.CtReturn; diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/NodeKind.java b/spoon-control-flow/src/main/java/spoon/controlflow/NodeKind.java similarity index 98% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/NodeKind.java rename to spoon-control-flow/src/main/java/spoon/controlflow/NodeKind.java index 6d2abbf790c..5825c929b25 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/NodeKind.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/NodeKind.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; /** * The kind of a {@link ControlFlowNode} diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/NotFoundException.java b/spoon-control-flow/src/main/java/spoon/controlflow/NotFoundException.java similarity index 97% rename from spoon-control-flow/src/main/java/fr/inria/controlflow/NotFoundException.java rename to spoon-control-flow/src/main/java/spoon/controlflow/NotFoundException.java index c8e0368ab03..92563842220 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/NotFoundException.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/NotFoundException.java @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; public class NotFoundException extends Exception { public NotFoundException(String found) { diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/AllBranchesReturnTest.java b/spoon-control-flow/src/test/java/spoon/controlflow/AllBranchesReturnTest.java similarity index 98% rename from spoon-control-flow/src/test/java/fr/inria/controlflow/AllBranchesReturnTest.java rename to spoon-control-flow/src/test/java/spoon/controlflow/AllBranchesReturnTest.java index 2845c220d8f..99624913f8b 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/AllBranchesReturnTest.java +++ b/spoon-control-flow/src/test/java/spoon/controlflow/AllBranchesReturnTest.java @@ -20,7 +20,7 @@ * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import org.junit.jupiter.api.Test; import spoon.processing.AbstractProcessor; diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java b/spoon-control-flow/src/test/java/spoon/controlflow/ControlFlowGraphTests.java similarity index 97% rename from spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java rename to spoon-control-flow/src/test/java/spoon/controlflow/ControlFlowGraphTests.java index 1fff63c4196..522cd8103d9 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ControlFlowGraphTests.java +++ b/spoon-control-flow/src/test/java/spoon/controlflow/ControlFlowGraphTests.java @@ -20,14 +20,15 @@ * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import spoon.Launcher; import spoon.reflect.code.CtStatement; import spoon.reflect.declaration.CtElement; import spoon.support.reflect.code.CtIfImpl; -import static fr.inria.controlflow.NodeKind.*; +import static spoon.controlflow.NodeKind.*; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -184,6 +185,6 @@ void issue4803() { ControlFlowBuilder builder = new ControlFlowBuilder(); Launcher launcher = new Launcher(); CtElement element = launcher.getFactory().createCodeSnippetStatement("while(true)").compile(); - assertDoesNotThrow(() -> builder.build(element)); + Assertions.assertDoesNotThrow(() -> builder.build(element)); } } diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java b/spoon-control-flow/src/test/java/spoon/controlflow/ExceptionFlowTests.java similarity index 99% rename from spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java rename to spoon-control-flow/src/test/java/spoon/controlflow/ExceptionFlowTests.java index 5066232e866..a75b50fb850 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ExceptionFlowTests.java +++ b/spoon-control-flow/src/test/java/spoon/controlflow/ExceptionFlowTests.java @@ -1,4 +1,4 @@ -package fr.inria.controlflow; +package spoon.controlflow; import java.util.*; import org.junit.jupiter.api.Test; diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java b/spoon-control-flow/src/test/java/spoon/controlflow/ForwardFlowBuilderVisitorTest.java similarity index 98% rename from spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java rename to spoon-control-flow/src/test/java/spoon/controlflow/ForwardFlowBuilderVisitorTest.java index 04edcc8b023..2fa8ba1a667 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/ForwardFlowBuilderVisitorTest.java +++ b/spoon-control-flow/src/test/java/spoon/controlflow/ForwardFlowBuilderVisitorTest.java @@ -20,7 +20,7 @@ * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import org.junit.jupiter.api.Test; import spoon.processing.AbstractProcessor; @@ -32,8 +32,8 @@ import java.net.URISyntaxException; -import static fr.inria.controlflow.NodeKind.BRANCH; -import static fr.inria.controlflow.NodeKind.STATEMENT; +import static spoon.controlflow.NodeKind.BRANCH; +import static spoon.controlflow.NodeKind.STATEMENT; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java b/spoon-control-flow/src/test/java/spoon/controlflow/InitializedVariablesTest.java similarity index 99% rename from spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java rename to spoon-control-flow/src/test/java/spoon/controlflow/InitializedVariablesTest.java index 52bab5334bc..6ba86f5d378 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/InitializedVariablesTest.java +++ b/spoon-control-flow/src/test/java/spoon/controlflow/InitializedVariablesTest.java @@ -20,7 +20,7 @@ * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; diff --git a/spoon-control-flow/src/test/java/fr/inria/controlflow/SpoonMetaFactory.java b/spoon-control-flow/src/test/java/spoon/controlflow/SpoonMetaFactory.java similarity index 98% rename from spoon-control-flow/src/test/java/fr/inria/controlflow/SpoonMetaFactory.java rename to spoon-control-flow/src/test/java/spoon/controlflow/SpoonMetaFactory.java index bd5c5eec53f..31dd0d225ff 100644 --- a/spoon-control-flow/src/test/java/fr/inria/controlflow/SpoonMetaFactory.java +++ b/spoon-control-flow/src/test/java/spoon/controlflow/SpoonMetaFactory.java @@ -20,7 +20,7 @@ * THE SOFTWARE. */ -package fr.inria.controlflow; +package spoon.controlflow; import spoon.Launcher; import spoon.reflect.factory.Factory; From c64b226e3b37c06a1a7282890aced41a1f20b142 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Fri, 5 Apr 2024 21:03:33 +0200 Subject: [PATCH 31/32] Update spoon version and correctly use java 17 --- .../test/java/spoon/controlflow/InitializedVariablesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spoon-control-flow/src/test/java/spoon/controlflow/InitializedVariablesTest.java b/spoon-control-flow/src/test/java/spoon/controlflow/InitializedVariablesTest.java index 6ba86f5d378..3e6d1b2cdbf 100644 --- a/spoon-control-flow/src/test/java/spoon/controlflow/InitializedVariablesTest.java +++ b/spoon-control-flow/src/test/java/spoon/controlflow/InitializedVariablesTest.java @@ -38,7 +38,7 @@ public void testRunSimple() throws Exception { this.getClass().getResource("/initialized").toURI().getPath(), "simpleflow", true); InitializedVariables vars = new InitializedVariables(); graph.simplify(); - ControlFlowNode n = graph.findNodesOfKind(NodeKind.EXIT).getFirst(); + ControlFlowNode n = graph.findNodesOfKind(NodeKind.EXIT).get(0); vars.run(n); for (CtVariableReference v : vars.getInitialized()) { @@ -138,7 +138,7 @@ public void testIndex54_Bug() throws Exception { InitializedVariables vars = new InitializedVariables(); graph.simplify(); System.out.print(graph.toGraphVisText()); - ControlFlowNode n = ControlFlowBuilder.firstNode(graph, graph.branches().getFirst().getStatement().getParent()); + ControlFlowNode n = ControlFlowBuilder.firstNode(graph, graph.branches().get(0).getStatement().getParent()); vars.run(n); HashSet names = new HashSet<>(); From 511c23c179022ad359a1c58265557d12e59808a6 Mon Sep 17 00:00:00 2001 From: Mr-Pine Date: Sat, 6 Apr 2024 12:34:00 +0200 Subject: [PATCH 32/32] Check and fix licenses --- .../src/main/java/spoon/controlflow/InitializedVariables.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoon-control-flow/src/main/java/spoon/controlflow/InitializedVariables.java b/spoon-control-flow/src/main/java/spoon/controlflow/InitializedVariables.java index 722224c983f..086721798aa 100644 --- a/spoon-control-flow/src/main/java/spoon/controlflow/InitializedVariables.java +++ b/spoon-control-flow/src/main/java/spoon/controlflow/InitializedVariables.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Permission is hereby granted, free of charge, to any person obtaining access copy + * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell