1 Commits

Author SHA1 Message Date
1655f5285c stage next 2026-06-27 20:03:48 +02:00
3 changed files with 63 additions and 24 deletions

View File

@@ -1,26 +1,71 @@
# Execution Plan for Extended Analysis (Revised for Robustness)
## Phase 11: Formal Compiler & Static Analysis Alignment (Limitations & Missing Features) ## Phase 0: Surgical Refactoring (The Enrichment Hook)
While the custom AST-based `JdtDataFlowModel` supports advanced OOP data flow (like flow-sensitive local mutations, fluent builders, and polymorphic union fallbacks), the following compiler/static analysis behaviors are missing or simplified: - [x] Create `AnalysisResult` and `CodebaseMetadata` models.
- [x] Update `ExportService.generateOutputs` to accept `AnalysisResult`.
- [x] Implement `EnrichmentService` and `AnalysisEnricher` interface.
- [x] Wrap current parser outputs in `AnalysisResult` within `ExportService`.
1. **Full Pointer & Alias Analysis**: ## Phase 1: Foundation & Semantic Core
- If two variables alias the same object (e.g., `Command cmd1 = cmd2;`), a mutation on `cmd1` (e.g., `cmd1.setEvent("A")`) is not reflected when reading the fields of `cmd2` unless they resolve to the exact same AST node reference. A formal pointer/alias analysis (like Anderson's or Steensgaard's algorithm) would map abstract heap locations rather than AST nodes. - [ ] **JDT Binding Resolution**: Configure `ASTParser` with project classpath and `setResolveBindings(true)`.
- [ ] **Workspace Scoping**: Implement scanner with configurable exclude patterns (`test/`, `build/`, `node_modules/`).
- [ ] **ConstantResolver**: Implement lookup for `public static final` constants across class boundaries using JDT bindings.
- [ ] **Basic PropertyResolver**: Scan `application.properties/yml` for simple key-value pairs.
- [ ] Implement `JdtIntelligenceProvider` as the primary semantic analyzer.
2. **Advanced Loop Fixpoints for Fields**: ## Phase 2: Trigger Discovery & Instance Identity
- If a loop mutates a field based on its previous values (e.g., `while(cond) { builder.count(builder.getCount() + 1); }`), a simple sequential pass will miss the cyclic dependency. A formal data flow framework uses a mathematical lattice and runs a fixpoint iteration algorithm (using meet/join operators) to compute the stable approximation of values. - [ ] **GenericEventDetector**: Find `sendEvent` calls using `ASTVisitor`.
- [ ] **InstanceIdentifier**: Detect which State Machine is being targeted (via `@Qualifier`, bean names, or generic types `StateMachine<S, E>`).
- [ ] **Trigger Filter**: Link `sendEvent` calls to specific SM instances to avoid noise in multi-SM projects.
- [ ] Enhance `CodebaseContext` to provide mapping from `MethodDeclaration` to its callers using bindings.
3. **Exception Path Analysis (Exception CFG)**: ## Phase 3: Entry Point Mapping
- Edges for exception flows (`throw` statements, `try-catch-finally` blocks, and implicit unchecked runtime exceptions like `NullPointerException`) are not modeled. Consequently, mutations or return paths within catch/finally blocks may be missed or evaluated out of order. - [ ] **SpringMvcDetector**: Detect REST endpoints (using `ConstantResolver` for paths).
- [ ] **MessageListenerDetector**: Detect Kafka/JMS listeners (using `ConstantResolver` for topics/queues).
- [ ] **ConfigurableTriggerDetector**: Support user-defined patterns for custom frameworks.
4. **Collection & Array Tracking**: ## Phase 4: Call Graph Integration
- Arrays and Collections (such as `List`, `Map`, `Set`) are treated as opaque objects, and their operations (like `list.add(val)` or `map.put(key, val)`) are evaluated as general method calls. Modifying a collection does not propagate the values to its getter calls (e.g. `list.get(0)`). - [x] Develop a call graph builder to link `Entry Points` to `Trigger Points` via intermediate service calls.
- [ ] Support inheritance in call graph resolution (using JDT bindings to resolve method overrides).
5. **Field Shadowing and Inheritance Semantics**: ## Phase 4.5: Hierarchical Robustness (Inheritance Support)
- If a subclass shadows a superclass field (declaring a field with the same name), our resolver might resolve the wrong field binding. Also, implicit superclass constructors and field initializers from superclass hierarchies are not fully simulated. - [ ] **Hierarchical Annotation Lookup**: Update `SpringMvcDetector` to scan interfaces and superclasses for inherited mapping annotations.
- [ ] **Interface Implementation Mapping**: Enhance `CodebaseContext` to index "Class -> Interfaces" and "Interface -> Classes" relationships.
6. **Static Initialization Blocks and Static Mutable State**: - [ ] **Polymorphic Call Trace**: Update `CallGraphBuilder` to follow calls from an interface method to all known implementations in the project.
- Class loading execution order (i.e. static block initializations `static { ... }`) is not modeled. A mutation on a static field in one method is not propagated to reads in another method. - [ ] **Base Class Trigger Discovery**: Ensure triggers in abstract base classes are correctly attributed to their concrete subclasses.
7. **Type Erasure & Generics Precision**:
- Generics type bounds (e.g., wildcards `? extends T`, type parameter replacements) are not fully tracked, which can result in incorrect polymorphic resolution when method signatures differ slightly from erased bindings.
## Phase 5: Visualization & Diagnostics
- [ ] Update `ExportService` to include trigger information.
- [ ] Update DOT/SCXML exporters to show entry points.
- [ ] **Diagnostic Nodes**: Show "Potential/Unresolved Trigger" nodes when a `sendEvent` is found but the event name or SM instance cannot be resolved.
## Phase 6: Validation (Milestone 1)
- [ ] Create a "Complex Sample Project" with REST controllers, services, and multiple state machines.
- [ ] Add unit tests for each detector and the aggregator.
- [ ] Verify that inheritance in both state machine config and controllers is correctly handled.
## Phase 7: Advanced Resolution & Data Flow
- [ ] **Variable Propagation**: Track values from fields/constructors to their usage in the State Machine configuration (e.g., resolving `initial(initialState)` where `initialState` is a field).
- [ ] **@Value Resolution**: Link `@Value` annotations to the `PropertyResolver` to substitute placeholders with literal values in the diagram.
- [ ] **Spring Profile Support**: Update `PropertyResolver` to handle `application-{profile}.properties` and prioritize them based on an "active profiles" setting.
- [ ] **Complex ValueResolver**: Handle string concatenations (e.g., `"PREFIX_" + MyConstants.SUFFIX`) and variable references.
- [ ] **Payload Analysis**: Extract payload types from entry points and track field usage in `sendEvent` calls.
## Phase 8: Persistence & Lifecycle Mapping
- [ ] Detect persistence restoration logic (`persister.restore`).
- [ ] Map "Resume" points where the machine state is loaded from a DB based on external identifiers.
- [ ] Update metadata to distinguish between "New Instance" and "Restored Instance" triggers.
## Phase 9: Advanced Ecosystem Support
- [ ] **Reactive Chains**: Analyze WebFlux/Project Reactor lambdas (`doOnNext`, `flatMap`) for hidden triggers.
- [ ] **Interceptors & Filters**: Detect `HandlerInterceptor` and `Filter` implementations and map them to endpoints.
## Phase 10: External Dependency Interop
- [x] **Library Hints**: Implementation complete. Supports `hints.json` in project root or `src/main/resources/`.
- **Format**: `[{"methodFqn": "class.method", "event": "EVENT"}]`
- **Purpose**: Maps external/compiled library calls to State Machine events when source code is unavailable.
- [ ] **External JAR Analysis**: (Optional) Configure JDT to scan source-attachments of dependencies if available.
**Note on Library Hints**: This feature is an optional "Power User" escape hatch. The analyzer works automatically for all local source code; `hints.json` is only required to bridge the gap for third-party libraries.

View File

@@ -629,9 +629,6 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
} }
protected String resolveArgument(Expression expr) { protected String resolveArgument(Expression expr) {
if (expr == null) {
return "null";
}
if (expr instanceof LambdaExpression le) { if (expr instanceof LambdaExpression le) {
ASTNode body = le.getBody(); ASTNode body = le.getBody();
if (body instanceof Expression bodyExpr) { if (body instanceof Expression bodyExpr) {

View File

@@ -124,9 +124,6 @@ public class JdtCallGraphEngine extends AbstractCallGraphEngine {
@Override @Override
protected String resolveArgument(org.eclipse.jdt.core.dom.Expression expr) { protected String resolveArgument(org.eclipse.jdt.core.dom.Expression expr) {
if (expr == null) {
return "null";
}
// Extract from constructor args (e.g., new CustomMessage(OrderEvent.PROCESS, ...)) // Extract from constructor args (e.g., new CustomMessage(OrderEvent.PROCESS, ...))
org.eclipse.jdt.core.dom.Expression unwrappedBuilder = unwrapMessageBuilder(expr); org.eclipse.jdt.core.dom.Expression unwrappedBuilder = unwrapMessageBuilder(expr);
if (unwrappedBuilder != expr) { if (unwrappedBuilder != expr) {