This commit is contained in:
2026-07-06 17:56:19 +02:00
parent 61f5549589
commit 092fbe49fa
2 changed files with 71 additions and 2 deletions

View File

@@ -502,13 +502,13 @@ public class VariableTracer {
public String resolveArgumentValue(String argValue, String callerMethod, List<String> path, int pathIndex, Map<String, List<CallEdge>> callGraph) {
if (argValue == null) return null;
if (argValue.contains(".") || argValue.startsWith("new ") || argValue.matches(".*[0-9].*")) {
if (argValue.contains(".") || argValue.startsWith("new ") || argValue.matches(".*[0-9].*") || (argValue.startsWith("\"") && argValue.endsWith("\""))) {
return argValue;
}
String tracedLocal = traceLocalVariable(callerMethod, argValue);
if (tracedLocal != null && !tracedLocal.equals(argValue)) {
if (tracedLocal.contains(".") || tracedLocal.startsWith("new ") || tracedLocal.matches(".*[0-9].*") || tracedLocal.contains("(")) {
if (tracedLocal.contains(".") || tracedLocal.startsWith("new ") || tracedLocal.matches(".*[0-9].*") || tracedLocal.contains("(") || (tracedLocal.startsWith("\"") && tracedLocal.endsWith("\""))) {
return tracedLocal;
}
argValue = tracedLocal;

View File

@@ -0,0 +1,69 @@
package click.kamil.springstatemachineexporter.analysis.service;
import click.kamil.springstatemachineexporter.analysis.resolver.ConstantResolver;
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class VariableTracerTest {
@Test
void shouldShortCircuitLiteralStringResolution() {
CodebaseContext context = new CodebaseContext();
VariableTracer tracer = new VariableTracer(context, new ConstantResolver());
// Even with an empty context and call graph, passing a raw String literal should return instantly
// without trying to recursively traverse the path or crash.
String resolved = tracer.resolveArgumentValue("\"PAY_EVENT\"", "com.example.Order.process", List.of("com.example.Order.process"), 0, Map.of());
assertThat(resolved).isEqualTo("\"PAY_EVENT\"");
}
@Test
void shouldBridgePolymorphicParametersPositionally(@TempDir Path tempDir) throws IOException {
Path comFoo = tempDir.resolve("com/foo");
Files.createDirectories(comFoo);
// Setup an interface and implementation with DIFFERENT parameter names
Files.writeString(comFoo.resolve("PaymentService.java"),
"package com.foo;\n" +
"public interface PaymentService {\n" +
" void submit(String eventName);\n" +
"}"
);
Files.writeString(comFoo.resolve("PaymentServiceImpl.java"),
"package com.foo;\n" +
"public class PaymentServiceImpl implements PaymentService {\n" +
" @Override\n" +
" public void submit(String e) {}\n" +
"}"
);
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
VariableTracer tracer = new VariableTracer(context, new ConstantResolver());
// Simulate tracing from the Interface backwards to the Implementation.
// Because this is a polymorphic bridge, there is NO direct call edge in the AST call graph.
Map<String, String> params = tracer.buildParameterValuesMap(
"com.foo.PaymentService.submit",
"com.foo.PaymentServiceImpl.submit",
Map.of(), // Empty call graph (no direct edges)
List.of("com.foo.PaymentService.submit", "com.foo.PaymentServiceImpl.submit"),
0
);
// The tracer should have scanned both ASTs and mapped parameter 0 -> parameter 0
assertThat(params).hasSize(1);
assertThat(params).containsEntry("e", "eventName");
}
}