Fix identifier consistency on JSON re-export and after property resolution.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-12 11:38:55 +02:00
parent 8d954804b2
commit cc2cf1845b
4 changed files with 123 additions and 3 deletions

View File

@@ -7,6 +7,8 @@ import click.kamil.springstatemachineexporter.analysis.model.CallChain;
import click.kamil.springstatemachineexporter.analysis.model.CodebaseMetadata;
import click.kamil.springstatemachineexporter.analysis.model.MatchedTransition;
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
import click.kamil.springstatemachineexporter.analysis.resolver.MachineEnumCanonicalizer;
import click.kamil.springstatemachineexporter.analysis.resolver.StateMachineTypeResolver;
import click.kamil.springstatemachineexporter.model.Transition;
import lombok.Builder;
import lombok.Getter;
@@ -117,6 +119,37 @@ public class AnalysisResult {
.properties(metadata.getProperties())
.build();
}
canonicalizeResolvedIdentifiers();
}
private void canonicalizeResolvedIdentifiers() {
if (stateTypeFqn == null && eventTypeFqn == null) {
return;
}
StateMachineTypeResolver.MachineTypes machineTypes =
new StateMachineTypeResolver.MachineTypes(stateTypeFqn, eventTypeFqn);
MachineEnumCanonicalizer.canonicalizeTransitions(transitions, machineTypes);
if (states != null) {
this.states = MachineEnumCanonicalizer.canonicalizeStates(states, stateTypeFqn);
}
if (startStates != null) {
startStates = MachineEnumCanonicalizer.canonicalizeStateLabels(startStates, stateTypeFqn);
}
if (endStates != null) {
endStates = MachineEnumCanonicalizer.canonicalizeStateLabels(endStates, stateTypeFqn);
}
if (metadata != null && metadata.getTriggers() != null) {
List<TriggerPoint> canonicalTriggers = metadata.getTriggers().stream()
.map(trigger -> MachineEnumCanonicalizer.canonicalizeTriggerPoint(trigger, machineTypes))
.collect(java.util.stream.Collectors.toList());
metadata = CodebaseMetadata.builder()
.triggers(canonicalTriggers)
.entryPoints(metadata.getEntryPoints())
.callChains(metadata.getCallChains())
.properties(metadata.getProperties())
.build();
}
}
private static TriggerPoint resolveTrigger(

View File

@@ -59,7 +59,23 @@ public final class AnalysisResultFinalizer {
result.setEventTypeFqn(machineTypes.eventTypeFqn());
}
private static void applyCanonicalization(
/**
* Canonicalizes transitions, states, triggers, and matched transitions without validation.
* Safe to call before transition relinking when machine types are known.
*/
public static void applyCanonicalization(
AnalysisResult result,
StateMachineTypeResolver.MachineTypes machineTypes) {
if (result == null || machineTypes == null) {
return;
}
if (machineTypes.stateTypeFqn() == null && machineTypes.eventTypeFqn() == null) {
return;
}
applyCanonicalizationFields(result, machineTypes);
}
private static void applyCanonicalizationFields(
AnalysisResult result,
StateMachineTypeResolver.MachineTypes machineTypes) {
MachineEnumCanonicalizer.canonicalizeTransitions(result.getTransitions(), machineTypes);

View File

@@ -187,14 +187,14 @@ public class ExportService {
log.info("JSON re-export: no source project found; using embedded machine types if present");
}
enrichmentService.relinkAfterPropertyResolution(result, context, null);
StateMachineTypeResolver.MachineTypes machineTypes =
click.kamil.springstatemachineexporter.analysis.service.JsonExportContextFactory.resolveMachineTypes(
result.getName(),
result.getStateTypeFqn(),
result.getEventTypeFqn(),
context);
AnalysisResultFinalizer.applyCanonicalization(result, machineTypes);
enrichmentService.relinkAfterPropertyResolution(result, context, null);
AnalysisResultFinalizer.finalizeResult(result, context, machineTypes);
generateOutputs(outputDir, result, selectedFormats, eventFormat, stateFormat);