Defer trigger event qualification and resolve types from bindings

Stop rewriting trigger events in TriggerPoint construction; qualify with context during property resolution and export. Upgrade heuristic simple names to JDT binding FQNs for user types only, preserving java.* platform types.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-14 06:24:40 +02:00
parent 57686c575e
commit 8c4f15133e
8 changed files with 140 additions and 21 deletions

View File

@@ -92,4 +92,22 @@ class MachineEnumCanonicalizerCrossPackageTest {
"com.example.order.OrderEvent.PAY",
"com.example.order.OrderEvent.SHIP");
}
@Test
void shouldNotQualifyAmbiguousImportStyleEventReference(@TempDir Path tempDir) throws Exception {
Files.createDirectories(tempDir.resolve("a"));
Files.createDirectories(tempDir.resolve("b"));
Files.writeString(tempDir.resolve("a/OrderEvent.java"),
"package a; public enum OrderEvent { PAY }");
Files.writeString(tempDir.resolve("b/OrderEvent.java"),
"package b; public enum OrderEvent { CANCEL }");
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
assertThat(MachineEnumCanonicalizer.qualifyEventIdentifier(
"OrderEvent.PAY", "a.OrderEvent", context)).isEqualTo("OrderEvent.PAY");
assertThat(MachineEnumCanonicalizer.isMachineEnumReference(
"OrderEvent.PAY", "a.OrderEvent", context)).isFalse();
}
}

View File

@@ -110,9 +110,12 @@ class AnalysisResultFinalizerTest {
.metadata(CodebaseMetadata.builder().triggers(List.of(trigger)).build())
.build();
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
result.applyResolution(Map.of(
"app.event", "OrderEvent.PAY",
"app.state", "OrderState.NEW"));
"app.state", "OrderState.NEW"), context);
TriggerPoint resolved = result.getMetadata().getTriggers().get(0);
assertThat(resolved.getEvent()).isEqualTo("com.example.order.OrderEvent.PAY");

View File

@@ -1,6 +1,10 @@
package click.kamil.springstatemachineexporter.analysis.service;
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
@@ -48,4 +52,54 @@ class TypeResolverTest {
assertThat(resolver.isTypeCompatible("a.OrderEvent", "b.OrderEvent")).isFalse();
assertThat(resolver.isTypeCompatible("a.OrderEvent", "a.OrderEvent")).isTrue();
}
@Test
void shouldUpgradeSimpleHeuristicTypeToBindingFqnForUserTypes(@TempDir Path tempDir) throws Exception {
Files.createDirectories(tempDir.resolve("com/example/order"));
Files.writeString(tempDir.resolve("com/example/order/OrderEvent.java"), """
package com.example.order;
public enum OrderEvent { PAY }
""");
Files.writeString(tempDir.resolve("App.java"), """
package com.example;
import com.example.order.OrderEvent;
class StateMachine {
void sendEvent(OrderEvent e) {}
}
""");
CodebaseContext context = new CodebaseContext();
context.setResolveBindings(true);
context.scan(tempDir);
TypeResolver resolver = new TypeResolver(context);
TypeDeclaration td = context.getTypeDeclaration("com.example.StateMachine");
MethodDeclaration md = context.findMethodDeclaration(td, "sendEvent", true);
SingleVariableDeclaration param = (SingleVariableDeclaration) md.parameters().get(0);
assertThat(resolver.resolveTypeToFqn(param.getType(), (CompilationUnit) td.getRoot()))
.isEqualTo("com.example.order.OrderEvent");
}
@Test
void shouldKeepHeuristicStringTypeWhenBindingsWouldReturnJavaLangString(@TempDir Path tempDir) throws Exception {
Files.writeString(tempDir.resolve("App.java"), """
package com.example;
class Api {
void handle(String value) {}
}
""");
CodebaseContext context = new CodebaseContext();
context.setResolveBindings(true);
context.scan(tempDir);
TypeResolver resolver = new TypeResolver(context);
TypeDeclaration td = context.getTypeDeclaration("com.example.Api");
MethodDeclaration md = context.findMethodDeclaration(td, "handle", true);
SingleVariableDeclaration param = (SingleVariableDeclaration) md.parameters().get(0);
assertThat(resolver.resolveTypeToFqn(param.getType(), (CompilationUnit) td.getRoot()))
.isEqualTo("String");
}
}