From edee0d4dc36318ad35c1b2ffd86eed60ab7c16d7 Mon Sep 17 00:00:00 2001 From: Patrick Viry Date: Fri, 27 May 2022 17:54:45 +0200 Subject: [PATCH] WIP --- .../java/dataflow/FindProgramPoint.java | 2 +- .../java/dataflow2/DataFlowGraph.java | 76 +++++++++++-------- .../java/dataflow2/ProgramPoint.java | 3 +- .../src/{ => sandbox}/FindProgramPoint.java | 5 +- sandbox/src/{ => sandbox}/Main.java | 52 +++++++------ 5 files changed, 78 insertions(+), 60 deletions(-) rename sandbox/src/{ => sandbox}/FindProgramPoint.java (97%) rename sandbox/src/{ => sandbox}/Main.java (85%) diff --git a/rewrite-java-11/src/test/kotlin/org/openrewrite/java/dataflow/FindProgramPoint.java b/rewrite-java-11/src/test/kotlin/org/openrewrite/java/dataflow/FindProgramPoint.java index 9210510bde58..3bd10363202c 100644 --- a/rewrite-java-11/src/test/kotlin/org/openrewrite/java/dataflow/FindProgramPoint.java +++ b/rewrite-java-11/src/test/kotlin/org/openrewrite/java/dataflow/FindProgramPoint.java @@ -33,7 +33,7 @@ public static void assertPrevious(J.CompilationUnit cu, String pp, String... pre List expectedPrevs = Arrays.asList(previous); Cursor c = FindProgramPoint.findProgramPoint(cu, pp); assert(c != null); - Collection prevs = DataFlowGraph.previous(c); + Collection prevs = DataFlowGraph.primitiveSources(c); assert(prevs != null); List actualPrevs = prevs.stream().map(prev -> print(prev)).collect(Collectors.toList()); diff --git a/rewrite-java/src/main/java/org/openrewrite/java/dataflow2/DataFlowGraph.java b/rewrite-java/src/main/java/org/openrewrite/java/dataflow2/DataFlowGraph.java index 540af4ba92c6..0089f1992bff 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/dataflow2/DataFlowGraph.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/dataflow2/DataFlowGraph.java @@ -26,8 +26,8 @@ public class DataFlowGraph { * @return The set of primitive program points (i.e., not containing other program points) * preceding given program point in the dataflow graph. */ - public static @NonNull Collection previous(Cursor programPoint) { - Collection pp = previousNonTerminal(programPoint); + public static @NonNull Collection primitiveSources(Cursor programPoint) { + Collection pp = sources(programPoint); return last(pp); } @@ -36,12 +36,12 @@ public class DataFlowGraph { * program point(s) inside that compound. Otherwise return the program point itself. */ public static @NonNull Collection last(Cursor cursor) { - Collection result = previousIn(cursor, ProgramPoint.EXIT); - System.out.print(" last(" + print(cursor) + ") = {"); - for(Cursor r : result) { - System.out.print(" <" + print(r) + ">"); - } - System.out.println(" }"); + Collection result = previousSourcesIn(cursor, ProgramPoint.EXIT); +// System.out.print(" last(" + print(cursor) + ") = {"); +// for(Cursor r : result) { +// System.out.print(" <" + print(r) + ">"); +// } +// System.out.println(" }"); return result; } @@ -58,7 +58,7 @@ public class DataFlowGraph { * @return The set of program points, possibly composite (i.e. containing other program points, such as * a while loop), preceding given program point in the dataflow graph. */ - public static @NonNull Collection previousNonTerminal(Cursor programPoint) { + public static @NonNull Collection sources(Cursor programPoint) { ProgramPoint current = (ProgramPoint) programPoint.getValue(); switch (current.getClass().getName().replaceAll("^org.openrewrite.java.tree.", "")) { @@ -74,15 +74,18 @@ public class DataFlowGraph { case "J$Binary": return Collections.singletonList(new Cursor(programPoint, ((J.Binary)current).getRight())); + case "J$Unary": + return Collections.singletonList(new Cursor(programPoint, + ((J.Unary)current).getExpression())); } // ... or it is the previous PP in the parent Cursor parentCursor = programPoint.dropParentUntil(t -> t instanceof J); - return previousIn(parentCursor, current); + return previousSourcesIn(parentCursor, current); } - public static @NonNull Collection previousIn(Cursor parentCursor, ProgramPoint current) { - if(parentCursor.getValue() instanceof JLeftPadded) return previousIn(parentCursor.getParent(), current); - if(parentCursor.getValue() instanceof JRightPadded) return previousIn(parentCursor.getParent(), current); + public static @NonNull Collection previousSourcesIn(Cursor parentCursor, ProgramPoint current) { + if(parentCursor.getValue() instanceof JLeftPadded) return previousSourcesIn(parentCursor.getParent(), current); + if(parentCursor.getValue() instanceof JRightPadded) return previousSourcesIn(parentCursor.getParent(), current); try { J parent = parentCursor.getValue(); switch (parent.getClass().getName().replaceAll("^org.openrewrite.java.tree.", "")) { @@ -146,14 +149,14 @@ public class DataFlowGraph { if(stmts.size() > 0) { return Collections.singletonList(new Cursor(parentCursor, stmts.get(stmts.size() - 1))); } else { - return DataFlowGraph.previous(parentCursor); + return DataFlowGraph.primitiveSources(parentCursor); } } else { int index = stmts.indexOf(p); if (index > 0) { return Collections.singletonList(new Cursor(parentCursor, stmts.get(index - 1))); } else if (index == 0) { - return DataFlowGraph.previous(parentCursor); + return DataFlowGraph.primitiveSources(parentCursor); } else { throw new IllegalStateException(); } @@ -167,16 +170,16 @@ public class DataFlowGraph { if (variables.size() > 0) { return Collections.singletonList(new Cursor(parentCursor, variables.get(variables.size() - 1))); } else { - return DataFlowGraph.previous(parentCursor); + return DataFlowGraph.primitiveSources(parentCursor); } } else if(p == ProgramPoint.ENTRY) { - return DataFlowGraph.previous(parentCursor); + return DataFlowGraph.primitiveSources(parentCursor); } else { int index = parent.getVariables().indexOf(p); if (index > 0) { return Collections.singletonList(new Cursor(parentCursor, variables.get(index - 1))); } else if (index == 0) { - return DataFlowGraph.previous(parentCursor); + return DataFlowGraph.primitiveSources(parentCursor); } else { throw new IllegalStateException(); } @@ -215,7 +218,7 @@ enum ForLoopPosition { if(init.size() > 0) { return Collections.singletonList(new Cursor(forLoopCursor, init.get(init.size()-1))); } else { - return DataFlowGraph.previous(forLoopCursor); + return DataFlowGraph.primitiveSources(forLoopCursor); } } throw new IllegalStateException(); @@ -256,7 +259,7 @@ enum ForLoopPosition { } else if(p == elsePart) { return Collections.singletonList(new Cursor(ifCursor, cond)); } else if(p == cond) { - return DataFlowGraph.previous(ifCursor); + return DataFlowGraph.primitiveSources(ifCursor); } throw new IllegalStateException(); } @@ -269,7 +272,7 @@ enum ForLoopPosition { if(p == ProgramPoint.EXIT) { return Collections.singletonList(new Cursor(ifElseCursor, body)); } else if(p == body) { - return DataFlowGraph.previous(ifElseCursor); + return DataFlowGraph.primitiveSources(ifElseCursor); } throw new IllegalStateException(); } @@ -292,7 +295,7 @@ enum ForLoopPosition { } else if(p == body) { return Collections.singletonList(new Cursor(whileCursor, cond)); } else if(p == cond) { - return DataFlowGraph.previous(whileCursor); + return DataFlowGraph.primitiveSources(whileCursor); } throw new UnsupportedOperationException("TODO"); @@ -312,12 +315,16 @@ enum ForLoopPosition { Statement body = forLoop.getBody(); List update = forLoop.getControl().getUpdate(); + if(p == ProgramPoint.EXIT) { Set result = new HashSet<>(); result.add(new Cursor(forLoopCursor, update)); result.add(new Cursor(forLoopCursor, cond)); return result; + } else if(p == ProgramPoint.ENTRY) { + return Collections.singletonList(new Cursor(forLoopCursor, cond)); + } else if(p == body) { return Collections.singletonList(new Cursor(forLoopCursor, cond)); @@ -334,7 +341,7 @@ enum ForLoopPosition { if (index > 0) { return Collections.singletonList(new Cursor(forLoopCursor, init.get(index - 1))); } else if (index == 0) { - return DataFlowGraph.previous(forLoopCursor); + return DataFlowGraph.primitiveSources(forLoopCursor); } index = update.indexOf(p); @@ -361,7 +368,7 @@ public static Collection previousInParentheses(Cursor parenthesesCursor, if(p == ProgramPoint.EXIT) { return Collections.singletonList(new Cursor(parenthesesCursor, tree)); } else if(p == tree) { - return DataFlowGraph.previous(parenthesesCursor); + return DataFlowGraph.primitiveSources(parenthesesCursor); } throw new IllegalStateException(); } @@ -373,7 +380,7 @@ public static Collection previousInControlParentheses(Cursor parentheses if(p == ProgramPoint.EXIT) { return Collections.singletonList(new Cursor(parenthesesCursor, tree)); } else if(p == tree) { - return DataFlowGraph.previous(parenthesesCursor); + return DataFlowGraph.primitiveSources(parenthesesCursor); } throw new IllegalStateException(); } @@ -386,12 +393,13 @@ public static Collection previousInNamedVariable(Cursor namedVariableCur if(p == ProgramPoint.EXIT) { return Collections.singletonList(namedVariableCursor); } else if(p == ProgramPoint.ENTRY) { - return DataFlowGraph.previousIn(namedVariableCursor.getParent(), namedVariableCursor.getValue()); + return DataFlowGraph.previousSourcesIn(namedVariableCursor.getParent(), namedVariableCursor.getValue()); } else if(p == name) { // it is an accident that 'name' is an expression, asking for its previous program point doesn't really make sense return Collections.emptyList(); } else if(p == initializer) { - return Collections.singletonList(new Cursor(namedVariableCursor, namedVariable.getInitializer())); + return previousSourcesIn(namedVariableCursor.getParent(), namedVariableCursor.getValue()); + //return Collections.singletonList(new Cursor(namedVariableCursor, namedVariable.getInitializer())); } throw new IllegalStateException(); } @@ -400,10 +408,12 @@ public static Collection previousInUnary(Cursor unaryCursor, ProgramPoin J.Unary unary = (J.Unary) unaryCursor.getValue(); Expression expr = unary.getExpression(); - if(p == ProgramPoint.EXIT) { - return Collections.singletonList(new Cursor(unaryCursor, expr)); + if(p == ProgramPoint.ENTRY) { + return previousSourcesIn(unaryCursor.getParent(), unaryCursor.getValue()); + } else if(p == ProgramPoint.EXIT) { + return Collections.singletonList(unaryCursor); } else if(p == unary.getExpression()) { - return DataFlowGraph.previous(unaryCursor); + return previousSourcesIn(unaryCursor, ProgramPoint.ENTRY); } throw new IllegalStateException(); } @@ -416,7 +426,7 @@ public static Collection previousInBinary(Cursor binaryCursor, ProgramPo J.Binary.Type op = binary.getOperator(); if(p == ProgramPoint.ENTRY) { - return previousIn(binaryCursor.getParent(), p); + return previousSourcesIn(binaryCursor.getParent(), binaryCursor.getValue()); } else if(p == ProgramPoint.EXIT) { return Collections.singletonList(binaryCursor); /* @@ -434,7 +444,7 @@ public static Collection previousInBinary(Cursor binaryCursor, ProgramPo return Collections.singletonList(new Cursor(binaryCursor, left)); } else if(p == left) { //return DataFlowGraph.previous(binaryCursor); - return previousIn(binaryCursor, ProgramPoint.ENTRY); + return previousSourcesIn(binaryCursor, ProgramPoint.ENTRY); } throw new IllegalStateException(); } @@ -446,7 +456,7 @@ public static Collection previousInAssignment(Cursor assignmentCursor, P if(p == ProgramPoint.EXIT) { return Collections.singletonList(new Cursor(assignmentCursor, a)); } else if(p == a) { - return DataFlowGraph.previous(assignmentCursor); + return DataFlowGraph.primitiveSources(assignmentCursor); } throw new IllegalStateException(); } diff --git a/rewrite-java/src/main/java/org/openrewrite/java/dataflow2/ProgramPoint.java b/rewrite-java/src/main/java/org/openrewrite/java/dataflow2/ProgramPoint.java index ee08f464e44d..14b0b503c92d 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/dataflow2/ProgramPoint.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/dataflow2/ProgramPoint.java @@ -2,7 +2,6 @@ import org.openrewrite.Cursor; import org.openrewrite.java.tree.J; -import org.openrewrite.java.tree.Statement; import java.util.Collection; @@ -16,7 +15,7 @@ public interface ProgramPoint { default Collection previous(Cursor c) { - return DataFlowGraph.previous(c); + return DataFlowGraph.primitiveSources(c); } default Collection next(Cursor c) { return DataFlowGraph.next(c); diff --git a/sandbox/src/FindProgramPoint.java b/sandbox/src/sandbox/FindProgramPoint.java similarity index 97% rename from sandbox/src/FindProgramPoint.java rename to sandbox/src/sandbox/FindProgramPoint.java index ed961eda68d4..6891e511e9eb 100644 --- a/sandbox/src/FindProgramPoint.java +++ b/sandbox/src/sandbox/FindProgramPoint.java @@ -1,4 +1,5 @@ -import org.assertj.core.api.AssertionsForClassTypes; +package sandbox; + import org.openrewrite.Cursor; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.dataflow2.DataFlowGraph; @@ -32,7 +33,7 @@ public static void assertPrevious(J.CompilationUnit cu, String pp, String... pre List expected = Arrays.asList(previous); Cursor c = FindProgramPoint.findProgramPoint(cu, pp); assertThat(c).withFailMessage("program point <" + pp + "> not found").isNotNull(); - Collection prevs = DataFlowGraph.previous(c); + Collection prevs = DataFlowGraph.primitiveSources(c); assertThat(c).withFailMessage("previous() returned null").isNotNull(); List actual = prevs.stream().map(prev -> print(prev)).collect(Collectors.toList()); diff --git a/sandbox/src/Main.java b/sandbox/src/sandbox/Main.java similarity index 85% rename from sandbox/src/Main.java rename to sandbox/src/sandbox/Main.java index 1b48ca7431da..8468ed260294 100644 --- a/sandbox/src/Main.java +++ b/sandbox/src/sandbox/Main.java @@ -1,3 +1,5 @@ +package sandbox; + import org.openrewrite.Cursor; import org.openrewrite.ExecutionContext; import org.openrewrite.InMemoryExecutionContext; @@ -15,6 +17,8 @@ public class Main { + public static boolean debug = false; + private static J.CompilationUnit parse(String src) { Java11Parser parser = new Java11Parser.Builder().build(); ExecutionContext ctx = new InMemoryExecutionContext(); @@ -76,9 +80,9 @@ public static void testForLoop() " void f() {} \n" + " void g() {} \n" + " void h() {} \n" + - " void m() { \n" + + " void method() { \n" + " a(); \n" + - " for(int i=0, j=1; i++<10 && j<10; i++, j++) { \n" + + " for(int i=0, j=1; 2<3; m++, n++) { \n" + " f(); g(); h(); \n" + " } \n" + " b(); \n" + @@ -88,23 +92,27 @@ public static void testForLoop() J.CompilationUnit cu = parse(source); - // new MyVisitor().visit(cu, null); + new PrintProgramPointsVisitor().visit(cu, null); FindProgramPoint.assertPrevious(cu,"a()"); FindProgramPoint.assertPrevious(cu,"int i=0, j=1", "a()"); FindProgramPoint.assertPrevious(cu,"i=0", "0"); FindProgramPoint.assertPrevious(cu,"0", "a()"); - FindProgramPoint.assertPrevious(cu,"j=1", "i=0"); - FindProgramPoint.assertPrevious(cu,"j++", "i++"); - FindProgramPoint.assertPrevious(cu,"i++", "{ f(); g(); h(); }"); - // "j++" instead of "i++, j++" since update is List, i.e. not a ProgramPoint - FindProgramPoint.assertPrevious(cu,"{ f(); g(); h(); }", "int i=0, j=1", "j++"); - // "j++" instead of "i++, j++" since update is List, i.e. not a ProgramPoint - FindProgramPoint.assertPrevious(cu,"f()","int i=0, j=1", "j++"); - FindProgramPoint.assertPrevious(cu,"g()", "f()"); + FindProgramPoint.assertPrevious(cu,"j=1", "1"); + FindProgramPoint.assertPrevious(cu,"1", "i=0"); + FindProgramPoint.assertPrevious(cu,"n++", "n"); + FindProgramPoint.assertPrevious(cu,"n", "m++"); + FindProgramPoint.assertPrevious(cu,"m++", "m"); + FindProgramPoint.assertPrevious(cu,"m", "h()"); FindProgramPoint.assertPrevious(cu,"h()", "g()"); - FindProgramPoint.assertPrevious(cu,"b()", - "for(int i=0, j=1; i<10 && j<10; i++, j++) { f(); g(); h(); }"); + FindProgramPoint.assertPrevious(cu,"g()", "f()"); + FindProgramPoint.assertPrevious(cu,"f()", "2<3"); + FindProgramPoint.assertPrevious(cu,"{ f(); g(); h(); }", "2<3"); + FindProgramPoint.assertPrevious(cu,"2<3", "3"); + FindProgramPoint.assertPrevious(cu,"3", "2"); + FindProgramPoint.assertPrevious(cu,"2", "j=1", "n++"); +// FindProgramPoint.assertPrevious(cu,"b()", +// "for(int i=0, j=1; i<10 && j<10; i++, j++) { f(); g(); h(); }"); } @@ -181,13 +189,13 @@ public static String print(Cursor c) @Override public Statement visitStatement(Statement statement, Object o) { System.out.println("statement = <" + print(getCursor()) + "> " + statement.getClass().getSimpleName()); - if (print(getCursor()).equals("int x = 1 + 2")) { + if (print(getCursor()).equals("0")) { System.out.println(); } - Collection pp = DataFlowGraph.previous(getCursor()); + Collection pp = DataFlowGraph.primitiveSources(getCursor()); if (pp == null) { System.out.println(" (prevs = null)"); - DataFlowGraph.previous(getCursor()); + DataFlowGraph.primitiveSources(getCursor()); } else { for (Cursor p : pp) { System.out.println(" prev = " + print(p)); @@ -210,13 +218,13 @@ public Expression visitExpression(Expression expr, Object o) { print(new Cursor(getCursor(), b.getRight())) ); } - if (print(getCursor()).equals("u")) { - System.out.println(); + if (print(getCursor()).equals("xxx")) { + Main.debug = true; } - Collection pp = DataFlowGraph.previous(getCursor()); + Collection pp = DataFlowGraph.primitiveSources(getCursor()); if (pp == null) { System.out.println(" (prevs = null)"); - DataFlowGraph.previous(getCursor()); + DataFlowGraph.primitiveSources(getCursor()); } else { for (Cursor p : pp) { System.out.println(" prev = " + print(p)); @@ -229,10 +237,10 @@ public Expression visitExpression(Expression expr, Object o) { @Override public J.VariableDeclarations.NamedVariable visitVariable(J.VariableDeclarations.NamedVariable variable, Object o) { System.out.println("variable = <" + print(getCursor()) + "> " + variable.getClass().getSimpleName()); - if (print(getCursor()).equals("u")) { + if (print(getCursor()).equals("0")) { System.out.println(); } - Collection pp = DataFlowGraph.previous(getCursor()); + Collection pp = DataFlowGraph.primitiveSources(getCursor()); if (pp == null) { System.out.println(" (null)"); } else {