Add --inline-accessors CLI flag, layered dispatcher regression goldens, and accessor index docs.

Expose accessor index toggling through ExportService and picocli, lock in layered_dispatcher_sample exports as golden fixtures, and document the static analysis pipeline in the README.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-11 20:29:07 +02:00
parent a108d8cc6e
commit 8fa6a44e75
14 changed files with 2430 additions and 2 deletions

View File

@@ -45,6 +45,7 @@ public class CodebaseContext {
private Path projectRoot;
private final Map<String, Object> cache = new HashMap<>();
private AccessorIndex accessorIndex = AccessorIndex.empty();
private boolean inlineAccessors = true;
public Map<String, Object> getCache() {
return cache;
@@ -54,6 +55,14 @@ public class CodebaseContext {
return accessorIndex;
}
public boolean isInlineAccessors() {
return inlineAccessors;
}
public void setInlineAccessors(boolean inlineAccessors) {
this.inlineAccessors = inlineAccessors;
}
public void setProjectRoot(Path root) {
this.projectRoot = root;
}
@@ -247,7 +256,15 @@ public class CodebaseContext {
}
}
this.accessorIndex = new AccessorIndexBuilder().build(this);
this.accessorIndex = inlineAccessors
? new AccessorIndexBuilder().build(this)
: AccessorIndex.empty();
if (inlineAccessors) {
log.info("Built accessor index: {} trivial accessors across {} types",
accessorIndex.trivialCount(), accessorIndex.typeCount());
} else {
log.info("Accessor inlining disabled; skipping accessor index build.");
}
}
private void indexType(TypeDeclaration td, String parentFqn, Path javaFile) {

View File

@@ -60,6 +60,9 @@ public class ExporterCommand implements Callable<Integer> {
@Option(names = {"--include-generated-sources"}, description = "Scan existing Maven target/ and Gradle build/ trees for pre-generated .java sources (MapStruct, annotation processors, etc.). Does not run Maven or Gradle.", negatable = true, defaultValue = "true", fallbackValue = "true")
private boolean includeGeneratedSources = true;
@Option(names = {"--inline-accessors"}, description = "Index trivial JavaBean/record accessors at scan time and inline them during call-chain and constant resolution.", negatable = true, defaultValue = "true", fallbackValue = "true")
private boolean inlineAccessors = true;
@Override
public Integer call() throws Exception {
var out = spec.commandLine().getOut();
@@ -90,7 +93,7 @@ public class ExporterCommand implements Callable<Integer> {
if (jsonFile != null) {
exportService.runJsonExporter(jsonFile, outputDir, selectedFormats, profiles, eventFormat, stateFormat);
} else {
exportService.runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, profiles, null, null, eventFormat, stateFormat, includeGeneratedSources);
exportService.runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, profiles, null, null, eventFormat, stateFormat, includeGeneratedSources, inlineAccessors);
}
out.println(CommandLine.Help.Ansi.AUTO.string("%n@|bold,green SUCCESS:|@ All state machines have been exported to " + outputDir.toAbsolutePath()));
return 0;

View File

@@ -75,8 +75,13 @@ public class ExportService {
}
public void runExporter(Path inputDir, Path outputDir, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<String> activeProfiles, Path flowsOverride, String machineFilter, click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat, click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat, boolean includeGeneratedSources) throws IOException {
runExporter(inputDir, outputDir, selectedFormats, renderChoicesAsDiamonds, activeProfiles, flowsOverride, machineFilter, eventFormat, stateFormat, includeGeneratedSources, true);
}
public void runExporter(Path inputDir, Path outputDir, List<String> selectedFormats, boolean renderChoicesAsDiamonds, List<String> activeProfiles, Path flowsOverride, String machineFilter, click.kamil.springstatemachineexporter.exporter.EnumFormat eventFormat, click.kamil.springstatemachineexporter.exporter.EnumFormat stateFormat, boolean includeGeneratedSources, boolean inlineAccessors) throws IOException {
CodebaseContext context = new CodebaseContext();
context.setActiveProfiles(activeProfiles);
context.setInlineAccessors(inlineAccessors);
click.kamil.springstatemachineexporter.analysis.resolver.SiblingDependencyResolver siblingResolver =
new click.kamil.springstatemachineexporter.analysis.resolver.SiblingDependencyResolver();