stage 3
This commit is contained in:
@@ -104,6 +104,8 @@ class JdtDataFlowModelTest {
|
||||
);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
context.scan(tempDir);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration("com.foo.Test");
|
||||
@@ -134,6 +136,8 @@ class JdtDataFlowModelTest {
|
||||
);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
context.scan(tempDir);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration("com.foo.Test");
|
||||
@@ -179,6 +183,8 @@ class JdtDataFlowModelTest {
|
||||
);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
context.scan(tempDir);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration("com.foo.Test");
|
||||
@@ -219,6 +225,8 @@ class JdtDataFlowModelTest {
|
||||
);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
context.scan(tempDir);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration("com.foo.Test");
|
||||
@@ -250,4 +258,259 @@ class JdtDataFlowModelTest {
|
||||
}
|
||||
assertThat(hasLoopBackToBody).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstructorAssignmentPropagation(@TempDir Path tempDir) throws IOException {
|
||||
Path comFoo = tempDir.resolve("com/foo");
|
||||
Files.createDirectories(comFoo);
|
||||
Files.writeString(comFoo.resolve("Test.java"),
|
||||
"package com.foo;\n" +
|
||||
"public class Test {\n" +
|
||||
" private final String myVar;\n" +
|
||||
" public Test() {\n" +
|
||||
" this.myVar = \"CONSTRUCTOR_VAL\";\n" +
|
||||
" }\n" +
|
||||
" public void run() {\n" +
|
||||
" String a = myVar;\n" +
|
||||
" }\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
context.scan(tempDir);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration("com.foo.Test");
|
||||
assertThat(td).isNotNull();
|
||||
|
||||
MethodDeclaration md = null;
|
||||
for (MethodDeclaration m : td.getMethods()) {
|
||||
if (m.getName().getIdentifier().equals("run")) {
|
||||
md = m;
|
||||
}
|
||||
}
|
||||
assertThat(md).isNotNull();
|
||||
|
||||
VariableDeclarationStatement aStmt = (VariableDeclarationStatement) md.getBody().statements().get(0);
|
||||
VariableDeclarationFragment aFrag = (VariableDeclarationFragment) aStmt.fragments().get(0);
|
||||
Expression initializer = aFrag.getInitializer();
|
||||
|
||||
DataFlowModel model = new JdtDataFlowModel(context);
|
||||
String val = model.resolveValue(initializer, context);
|
||||
assertThat(val).isEqualTo("CONSTRUCTOR_VAL");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testObjectSensitiveInstanceFieldTracing(@TempDir Path tempDir) throws IOException {
|
||||
Path comFoo = tempDir.resolve("com/foo");
|
||||
Files.createDirectories(comFoo);
|
||||
Files.writeString(comFoo.resolve("Test.java"),
|
||||
"package com.foo;\n" +
|
||||
"public class Test {\n" +
|
||||
" public static class Builder {\n" +
|
||||
" private final String val;\n" +
|
||||
" public Builder(String val) {\n" +
|
||||
" this.val = val;\n" +
|
||||
" }\n" +
|
||||
" public String getVal() {\n" +
|
||||
" return this.val;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" public void run() {\n" +
|
||||
" Builder b = new Builder(\"OBJECT_SENSITIVE\");\n" +
|
||||
" String res = b.getVal();\n" +
|
||||
" }\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
context.scan(tempDir);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration("com.foo.Test");
|
||||
assertThat(td).isNotNull();
|
||||
|
||||
MethodDeclaration md = null;
|
||||
for (MethodDeclaration m : td.getMethods()) {
|
||||
if (m.getName().getIdentifier().equals("run")) {
|
||||
md = m;
|
||||
}
|
||||
}
|
||||
assertThat(md).isNotNull();
|
||||
|
||||
VariableDeclarationStatement resStmt = (VariableDeclarationStatement) md.getBody().statements().get(1);
|
||||
VariableDeclarationFragment resFrag = (VariableDeclarationFragment) resStmt.fragments().get(0);
|
||||
Expression initializer = resFrag.getInitializer(); // b.getVal()
|
||||
|
||||
DataFlowModel model = new JdtDataFlowModel(context);
|
||||
String val = model.resolveValue(initializer, context);
|
||||
assertThat(val).isEqualTo("OBJECT_SENSITIVE");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstructorChaining(@TempDir Path tempDir) throws IOException {
|
||||
Path comFoo = tempDir.resolve("com/foo");
|
||||
Files.createDirectories(comFoo);
|
||||
Files.writeString(comFoo.resolve("Test.java"),
|
||||
"package com.foo;\n" +
|
||||
"public class Test {\n" +
|
||||
" public static class Command {\n" +
|
||||
" private final String event;\n" +
|
||||
" private final String info;\n" +
|
||||
" public Command(String event, String info) {\n" +
|
||||
" this.event = event;\n" +
|
||||
" this.info = info;\n" +
|
||||
" }\n" +
|
||||
" public Command(String event) {\n" +
|
||||
" this(event, \"DEFAULT_INFO\");\n" +
|
||||
" }\n" +
|
||||
" public Command() {\n" +
|
||||
" this(\"DEFAULT_EVENT\");\n" +
|
||||
" }\n" +
|
||||
" public String getEvent() { return this.event; }\n" +
|
||||
" public String getInfo() { return this.info; }\n" +
|
||||
" }\n" +
|
||||
" public void run() {\n" +
|
||||
" Command cmd = new Command();\n" +
|
||||
" String ev = cmd.getEvent();\n" +
|
||||
" String inf = cmd.getInfo();\n" +
|
||||
" }\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
context.scan(tempDir);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration("com.foo.Test");
|
||||
assertThat(td).isNotNull();
|
||||
|
||||
MethodDeclaration md = null;
|
||||
for (MethodDeclaration m : td.getMethods()) {
|
||||
if (m.getName().getIdentifier().equals("run")) {
|
||||
md = m;
|
||||
}
|
||||
}
|
||||
assertThat(md).isNotNull();
|
||||
|
||||
VariableDeclarationStatement evStmt = (VariableDeclarationStatement) md.getBody().statements().get(1);
|
||||
VariableDeclarationFragment evFrag = (VariableDeclarationFragment) evStmt.fragments().get(0);
|
||||
Expression initEv = evFrag.getInitializer();
|
||||
|
||||
DataFlowModel model = new JdtDataFlowModel(context);
|
||||
String valEv = model.resolveValue(initEv, context);
|
||||
assertThat(valEv).isEqualTo("DEFAULT_EVENT");
|
||||
|
||||
VariableDeclarationStatement infStmt = (VariableDeclarationStatement) md.getBody().statements().get(2);
|
||||
VariableDeclarationFragment infFrag = (VariableDeclarationFragment) infStmt.fragments().get(0);
|
||||
Expression initInf = infFrag.getInitializer();
|
||||
|
||||
String valInf = model.resolveValue(initInf, context);
|
||||
assertThat(valInf).isEqualTo("DEFAULT_INFO");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExplicitSuperCalls(@TempDir Path tempDir) throws IOException {
|
||||
Path comFoo = tempDir.resolve("com/foo");
|
||||
Files.createDirectories(comFoo);
|
||||
Files.writeString(comFoo.resolve("Test.java"),
|
||||
"package com.foo;\n" +
|
||||
"public class Test {\n" +
|
||||
" public static class Base {\n" +
|
||||
" public String getValue() {\n" +
|
||||
" return \"BASE_VAL\";\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" public static class Sub extends Base {\n" +
|
||||
" @Override\n" +
|
||||
" public String getValue() {\n" +
|
||||
" return super.getValue();\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" public void run() {\n" +
|
||||
" Sub sub = new Sub();\n" +
|
||||
" String val = sub.getValue();\n" +
|
||||
" }\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
context.scan(tempDir);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration("com.foo.Test");
|
||||
assertThat(td).isNotNull();
|
||||
|
||||
MethodDeclaration md = null;
|
||||
for (MethodDeclaration m : td.getMethods()) {
|
||||
if (m.getName().getIdentifier().equals("run")) {
|
||||
md = m;
|
||||
}
|
||||
}
|
||||
assertThat(md).isNotNull();
|
||||
|
||||
VariableDeclarationStatement valStmt = (VariableDeclarationStatement) md.getBody().statements().get(1);
|
||||
VariableDeclarationFragment valFrag = (VariableDeclarationFragment) valStmt.fragments().get(0);
|
||||
Expression initVal = valFrag.getInitializer();
|
||||
|
||||
DataFlowModel model = new JdtDataFlowModel(context);
|
||||
String val = model.resolveValue(initVal, context);
|
||||
assertThat(val).isEqualTo("BASE_VAL");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDynamicDispatchNarrowing(@TempDir Path tempDir) throws IOException {
|
||||
Path comFoo = tempDir.resolve("com/foo");
|
||||
Files.createDirectories(comFoo);
|
||||
Files.writeString(comFoo.resolve("Test.java"),
|
||||
"package com.foo;\n" +
|
||||
"public class Test {\n" +
|
||||
" public interface Service {\n" +
|
||||
" String getEvent();\n" +
|
||||
" }\n" +
|
||||
" public static class PayService implements Service {\n" +
|
||||
" public String getEvent() { return \"PAY\"; }\n" +
|
||||
" }\n" +
|
||||
" public static class CancelService implements Service {\n" +
|
||||
" public String getEvent() { return \"CANCEL\"; }\n" +
|
||||
" }\n" +
|
||||
" public void run() {\n" +
|
||||
" Service s = new PayService();\n" +
|
||||
" String ev = s.getEvent();\n" +
|
||||
" }\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.setResolveBindings(true);
|
||||
context.setSourcepath(List.of(tempDir.toAbsolutePath().toString()));
|
||||
context.scan(tempDir);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration("com.foo.Test");
|
||||
assertThat(td).isNotNull();
|
||||
|
||||
MethodDeclaration md = null;
|
||||
for (MethodDeclaration m : td.getMethods()) {
|
||||
if (m.getName().getIdentifier().equals("run")) {
|
||||
md = m;
|
||||
}
|
||||
}
|
||||
assertThat(md).isNotNull();
|
||||
|
||||
VariableDeclarationStatement evStmt = (VariableDeclarationStatement) md.getBody().statements().get(1);
|
||||
VariableDeclarationFragment evFrag = (VariableDeclarationFragment) evStmt.fragments().get(0);
|
||||
Expression initEv = evFrag.getInitializer();
|
||||
|
||||
DataFlowModel model = new JdtDataFlowModel(context);
|
||||
List<Expression> defs = model.getReachingDefinitions(initEv);
|
||||
assertThat(defs).isNotEmpty();
|
||||
|
||||
String val = model.resolveValue(initEv, context);
|
||||
assertThat(val).isEqualTo("PAY");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@
|
||||
},
|
||||
"methodChain" : [ "click.kamil.examples.statemachine.polymorphic.PolymorphicController.payCast", "click.kamil.examples.statemachine.polymorphic.OrderService.processEvent" ],
|
||||
"triggerPoint" : {
|
||||
"event" : "(BaseEvent)new PayEvent()",
|
||||
"event" : "new PayEvent()",
|
||||
"className" : "click.kamil.examples.statemachine.polymorphic.OrderService",
|
||||
"methodName" : "processEvent",
|
||||
"sourceFile" : "src/main/java/click/kamil/examples/statemachine/polymorphic/OrderService.java",
|
||||
|
||||
Reference in New Issue
Block a user