better things extraction of constants

This commit is contained in:
2026-06-22 07:30:05 +02:00
parent 07d241a060
commit 24a9be3a4e
2 changed files with 109 additions and 4 deletions

View File

@@ -737,15 +737,15 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
extractConstantsFromExpression(aa.getArray(), constants);
} else if (expr instanceof org.eclipse.jdt.core.dom.ArrayCreation ac && ac.getInitializer() != null) {
for (Object expObj : ac.getInitializer().expressions()) {
extractConstantsFromExpression((org.eclipse.jdt.core.dom.Expression) expObj, constants);
extractConstantsFromArgument((org.eclipse.jdt.core.dom.Expression) expObj, constants);
}
} else if (expr instanceof org.eclipse.jdt.core.dom.ArrayInitializer ai) {
for (Object expObj : ai.expressions()) {
extractConstantsFromExpression((org.eclipse.jdt.core.dom.Expression) expObj, constants);
extractConstantsFromArgument((org.eclipse.jdt.core.dom.Expression) expObj, constants);
}
} else if (expr instanceof org.eclipse.jdt.core.dom.ClassInstanceCreation cic) {
for (Object argObj : cic.arguments()) {
extractConstantsFromExpression((org.eclipse.jdt.core.dom.Expression) argObj, constants);
extractConstantsFromArgument((org.eclipse.jdt.core.dom.Expression) argObj, constants);
}
} else if (expr instanceof org.eclipse.jdt.core.dom.MethodInvocation mi) {
String methodName = mi.getName().getIdentifier();
@@ -826,7 +826,7 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
}
} else {
for (Object argObj : cic.arguments()) {
extractConstantsFromExpression((org.eclipse.jdt.core.dom.Expression) argObj, constants);
extractConstantsFromArgument((org.eclipse.jdt.core.dom.Expression) argObj, constants);
}
}
}
@@ -852,6 +852,17 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
}
}
private void extractConstantsFromArgument(org.eclipse.jdt.core.dom.Expression argObj, List<String> constants) {
if (argObj instanceof org.eclipse.jdt.core.dom.ClassInstanceCreation innerCic) {
String typeName = click.kamil.springstatemachineexporter.ast.common.AstUtils.extractSimpleTypeName(innerCic.getType());
if ("String".equals(typeName)) {
extractConstantsFromExpression(argObj, constants);
}
} else {
extractConstantsFromExpression(argObj, constants);
}
}
protected org.eclipse.jdt.core.dom.Block findEnclosingBlock(org.eclipse.jdt.core.dom.ASTNode node) {
org.eclipse.jdt.core.dom.ASTNode parent = node.getParent();
while (parent != null && !(parent instanceof org.eclipse.jdt.core.dom.Block)) {

View File

@@ -2610,4 +2610,98 @@ class HeuristicCallGraphEngineTest {
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents())
.containsExactly("CORRECT_EVENT"); // If heuristic rips both, it will fail because it contains WRONG_EVENT too!
}
@Test
void shouldNotExtractConstantsFromNestedClassInstanceCreations() throws IOException {
String source = """
package com.example;
public class OrderController {
private OrderService service;
public void handleNestedConstructors() {
// The event contains a nested constructor. The heuristic should NOT extract WRONG_EVENT.
OuterEvent e = new OuterEvent("CORRECT_EVENT", new InnerPayload("WRONG_EVENT"));
service.process(e.getEventType());
}
}
class OrderService {
public void process(String event) {}
}
class OuterEvent {
private String eventType;
private InnerPayload payload;
public OuterEvent(String eventType, InnerPayload payload) {
this.eventType = eventType;
this.payload = payload;
}
public String getEventType() { return eventType; }
}
class InnerPayload {
private String someData;
public InnerPayload(String someData) { this.someData = someData; }
}
""";
Path tempDir = Files.createTempDirectory("callgraph_nested_constructor");
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
HeuristicCallGraphEngine builder = new HeuristicCallGraphEngine(context);
EntryPoint entryPoint = EntryPoint.builder().className("com.example.OrderController").methodName("handleNestedConstructors").build();
TriggerPoint trigger = TriggerPoint.builder().className("com.example.OrderService").methodName("process").event("event").build();
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
org.assertj.core.api.Assertions.assertThat(chains).hasSize(1);
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents())
.containsExactly("CORRECT_EVENT");
}
@Test
void shouldNotExtractConstantsFromNestedArraysOfObjects() throws IOException {
String source = """
package com.example;
public class OrderController {
private OrderService service;
public void handleNestedArrays() {
// The event contains a nested array of objects. The heuristic should NOT extract WRONG_EVENT.
OuterEvent e = new OuterEvent("CORRECT_EVENT", new InnerPayload[] { new InnerPayload("WRONG_EVENT") });
service.process(e.getEventType());
}
}
class OrderService {
public void process(String event) {}
}
class OuterEvent {
private String eventType;
private InnerPayload[] payloads;
public OuterEvent(String eventType, InnerPayload[] payloads) {
this.eventType = eventType;
this.payloads = payloads;
}
public String getEventType() { return eventType; }
}
class InnerPayload {
private String someData;
public InnerPayload(String someData) { this.someData = someData; }
}
""";
Path tempDir = Files.createTempDirectory("callgraph_nested_array");
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
HeuristicCallGraphEngine builder = new HeuristicCallGraphEngine(context);
EntryPoint entryPoint = EntryPoint.builder().className("com.example.OrderController").methodName("handleNestedArrays").build();
TriggerPoint trigger = TriggerPoint.builder().className("com.example.OrderService").methodName("process").event("event").build();
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
org.assertj.core.api.Assertions.assertThat(chains).hasSize(1);
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents())
.containsExactly("CORRECT_EVENT");
}
}