Files
spring-state-machine-renderer/plan-extended-anaylis/architecture.md

3.5 KiB

Decoupled Analysis Architecture: The "Modular Provider" Approach

Core Philosophy

We decouple the State Machine Definition (what the machine IS) from the Codebase Intelligence (how the machine IS USED). This allows for swappable analysis tools and prevents the state machine parser from becoming a monolithic "all-knowing" beast.

1. The Intelligence Interface (The Bridge)

We introduce an abstraction layer that provides information about the code without tying us to a specific implementation (like JDT).

public interface CodebaseIntelligenceProvider {
    // Event Triggers
    List<TriggerPoint> findTriggerPoints();
    
    // Entry Points
    List<EntryPoint> findEntryPoints();
    
    // Call Graphs
    List<CallChain> traceCallChain(MethodReference target);
    
    // Resolution
    String resolveValue(ExpressionReference ref);
}

2. Swappable Implementations

This allows us to offer different "tiers" of analysis or even different tools:

  • JdtProvider (Current): High-precision, understands hierarchy, but heavy.
  • RegexProvider: Lightweight, fast, good for simple projects or quick scans.
  • ExternalLspProvider (Future): Could query a running Language Server (like Eclipse JDT.LS) for ultra-accurate cross-project resolution.

3. The "State Machine Model" is the Sink

The State Machine Exporter now becomes a "Consumer" of intelligence.

  1. SM Parser: Extracts the core states and transitions.
  2. Intelligence Service: Discovers where events are triggered.
  3. Correlation Engine: Merges the two models based on Event IDs.

4. Benefits

  • Testability: We can mock the CodebaseIntelligenceProvider to test state machine rendering without needing a full Java project on disk.
  • Maintainability: Adding support for a new framework (e.g., Micronaut) only requires updating the IntelligenceProvider, not touching the core state machine logic.
  • Performance: We can run the SM Parser and the Intelligence Scanner in parallel since they are now independent.

5. Monorepo and Multi-Module Support

Applications are often split into multiple modules (e.g., core, api, workers).

  • Workspace Scanning: The analyzer should treat the entire monorepo as a single codebase context.
  • Source Tracking: Each metadata item (TriggerPoint, EntryPoint) includes a sourceModule identifier to show exactly where it was found.
  • Cross-Module Resolution: Properties defined in one module's application.yml and used in another should be resolved globally.
  • Internal Dependency Following: If the analyzer finds a call to a method in another module, it should continue the call-chain analysis into that module's source.

Challenges

  • Multiple State Machines: How to know which StateMachine instance is being used?
    • Initial heuristic: If there's only one, assume it's that one.
    • If multiple, check generic types StateMachine<S, E> or variable names.
  • Indirect Calls: Method A (Controller) calls B (Service), and B calls sendEvent.
    • Static analysis might need to follow call graphs.
    • Use JDT's cross-reference capabilities if possible, or build a simple call graph.
  • Inheritance:
    • Controllers might extend base classes with common mappings.
    • State machine configurations already handle inheritance; Trigger detection should too.

Next Steps

  1. Create a PoC TriggerDetector for Spring MVC.
  2. Integrate TriggerAggregator into the main analysis pipeline.
  3. Update the Exporter to visualize these links.