From 2251a587d93ac73b1700f8aacfb557d129872a5d Mon Sep 17 00:00:00 2001 From: Kamil Patryk Kozakowski Date: Sat, 13 Jun 2026 09:04:02 +0200 Subject: [PATCH] analysis update --- plan-extended-anaylis-v1/PLAN.md | 35 ------ plan-extended-anaylis-v1/architecture.md | 68 ------------ .../generic_extensibility.md | 92 ---------------- .../implementation_details.md | 102 ------------------ .../property_resolution.md | 71 ------------ plan-extended-anaylis/PLAN.md | 80 +++++++------- 6 files changed, 37 insertions(+), 411 deletions(-) delete mode 100644 plan-extended-anaylis-v1/PLAN.md delete mode 100644 plan-extended-anaylis-v1/architecture.md delete mode 100644 plan-extended-anaylis-v1/generic_extensibility.md delete mode 100644 plan-extended-anaylis-v1/implementation_details.md delete mode 100644 plan-extended-anaylis-v1/property_resolution.md diff --git a/plan-extended-anaylis-v1/PLAN.md b/plan-extended-anaylis-v1/PLAN.md deleted file mode 100644 index f102831..0000000 --- a/plan-extended-anaylis-v1/PLAN.md +++ /dev/null @@ -1,35 +0,0 @@ -# Execution Plan for Extended Analysis - -## Phase 1: Foundation (Current Topic) -- [ ] Define the `TriggerPoint` and `TriggerContext` models. -- [ ] Implement `TriggerDetector` interface. -- [ ] Create `TriggerAggregator` to coordinate multiple detectors. - -## Phase 2: Direct Trigger Detection -- [ ] Implement `GenericEventDetector` using `ASTVisitor` to find `sendEvent` calls. -- [ ] Enhance `CodebaseContext` to provide mapping from `MethodDeclaration` to its callers (within the same codebase). - -## Phase 3: Entry Point Mapping -- [ ] Implement `SpringMvcDetector` for REST endpoints. -- [ ] Implement `MessageListenerDetector` for Kafka/JMS. -- [ ] Implement `ConfigurableTriggerDetector` for user-defined patterns. - -## Phase 4: Call Graph Integration -- [ ] Develop a simple call graph builder to link `Entry Points` to `Trigger Points` via intermediate service calls. -- [ ] Support inheritance in call graph resolution (e.g., calling a method defined in an interface/base class). - -## Phase 5: Correlation and Visualization -- [ ] Update `ExportService` to include trigger information. -- [ ] Update DOT exporter to show "external" entry points as boxes pointing to transitions. -- [ ] Update SCXML exporter to include trigger metadata in `` tags. - -## Phase 6: Validation -- [ ] 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 Value Resolution -- [ ] Implement `PropertyResolver` to scan `application.properties/yml`. -- [ ] Add support for `@Value` tracking in fields and constructors. -- [ ] Implement constant resolution for cross-class references in annotations. -- [ ] Integrate value propagation into the call graph analysis (linking injected values to `sendEvent` arguments). diff --git a/plan-extended-anaylis-v1/architecture.md b/plan-extended-anaylis-v1/architecture.md deleted file mode 100644 index 3fc99bd..0000000 --- a/plan-extended-anaylis-v1/architecture.md +++ /dev/null @@ -1,68 +0,0 @@ -# Extended State Machine Analysis: Trigger Point Mapping - -## Overview -The goal of this extension is to bridge the gap between state machine definitions and their real-world usage in application code. By identifying where events are triggered (e.g., REST endpoints, message listeners), we can provide a more holistic view of the system's behavior. - -## Key Concepts -- **Trigger Point**: A location in the source code where an event is sent to a state machine (e.g., `stateMachine.sendEvent(E)`). -- **Entry Point**: A high-level application component (e.g., a REST Controller or Message Listener) that ultimately leads to a Trigger Point. -- **Event Linkage**: The process of connecting an Entry Point to one or more state machine transitions via the event that triggers them. - -## Proposed Architecture - -### 1. TriggerDetector -A generic interface for identifying trigger points and extracting context. -```java -public interface TriggerDetector { - List detect(CompilationUnit cu, CodebaseContext context); -} -``` - -### 2. Predefined Detectors -- **SpringMvcDetector**: Looks for `@RestController` / `@Controller` and mappings like `@PostMapping`. -- **SpringWebFluxDetector**: - - **Annotation-based**: Similar to MVC but handles `Mono`/`Flux` return types. - - **Functional-based**: Scans for `RouterFunction` beans and extracts routes/handlers. -- **MessageListenerDetector**: - - **Kafka**: `@KafkaListener`. - - **RabbitMQ**: `@RabbitListener`. - - **JMS**: `@JmsListener`. -- **GenericEventDetector**: Looks for any `sendEvent` call and tries to find its context. - -### 3. TriggerPoint Model -```java -public record TriggerPoint( - String className, - String methodName, - String event, - TriggerContext context -) {} - -public record TriggerContext( - String type, // "REST", "KAFKA", "JMS", "GENERIC" - Map metadata // path="/api/submit", topic="orders", etc. -) {} -``` - -### 4. Analysis Flow -1. **Scan Phase**: Existing `CodebaseContext.scan(root)`. -2. **Configuration Phase**: Existing `StateMachineAggregator` finds states and transitions. -3. **Trigger Discovery Phase**: New `TriggerAggregator` runs various `TriggerDetector`s over the scanned codebase. -4. **Correlation Phase**: Match `TriggerPoint.event` with `Transition.event`. -5. **Export Phase**: Enhance DOT/SCXML or generate a new "System Flow Map". - -## 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` 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. diff --git a/plan-extended-anaylis-v1/generic_extensibility.md b/plan-extended-anaylis-v1/generic_extensibility.md deleted file mode 100644 index c36b420..0000000 --- a/plan-extended-anaylis-v1/generic_extensibility.md +++ /dev/null @@ -1,92 +0,0 @@ -# Generic and Extensible Endpoint Finder - -## The Need for Genericity -Applications use various frameworks and patterns to trigger state machine events. While Spring MVC and Kafka are common, others like Micronuat, Jakarta EE, or custom internal event buses might be used. - -## Configuration-Driven Detection -We can allow users to define "Entry Point" patterns via a configuration file (e.g., `analysis-config.json`). - -```json -{ - "entryPoints": [ - { - "name": "SpringMVC", - "classAnnotations": ["RestController", "Controller"], - "methodAnnotations": ["PostMapping", "GetMapping", "PutMapping", "DeleteMapping", "RequestMapping"], - "metadataExtractors": { - "path": ["value", "path"] - } - }, - { - "name": "Kafka", - "methodAnnotations": ["KafkaListener"], - "metadataExtractors": { - "topic": ["topics", "topicPartitions"] - } - } - ] -} -``` - -## Abstract EntryPoint Detector -A generic detector that uses the above configuration to identify entry points. - -```java -public class ConfigurableTriggerDetector implements TriggerDetector { - private final AnalysisConfig config; - - @Override - public List detect(CompilationUnit cu, CodebaseContext context) { - // 1. Find all classes - // 2. If class has any of config.classAnnotations - // 3. Scan methods for any of config.methodAnnotations - // 4. If found, look for sendEvent calls inside the method or its call tree - } -} -``` - -## Indirect Flow Detection (Call Tree Analysis) -Oftentimes, the `sendEvent` call is not directly in the controller method but in a service called by the controller. - -### Simple Call Tree Analysis -1. Find all methods that call `sendEvent(E)`. Let's call them "Direct Triggers". -2. Find all methods that call "Direct Triggers". -3. Recursively build this "Trigger Path". -4. If a "Trigger Path" starts at an "Entry Point" (Controller/Listener), we have a complete flow. - -Example: -`OrderController.submitOrder()` -> `OrderService.processOrder()` -> `StateMachine.sendEvent(SUBMIT)` - -Analysis: -1. `OrderService.processOrder()` is a Direct Trigger for `SUBMIT`. -2. `OrderController.submitOrder()` calls `OrderService.processOrder()`. -3. `OrderController.submitOrder()` is an Entry Point (annotated with `@PostMapping`). -4. Result: `POST /order` -> `SUBMIT` transition. - -## Handling Reactive Chains Statically -In WebFlux/Project Reactor, the logic is decoupled into a pipeline. Static analysis must "connect the dots" across operators. - -**Strategy**: -1. When analyzing a method, identify if it returns a reactive type (`Mono`, `Flux`). -2. If so, inspect all lambdas within that method. -3. If a lambda calls `sendEvent`, treat the method as a "Trigger Point". -4. If the method is also an "Entry Point" (via annotations or `RouterFunction`), we have a direct reactive flow. - -## Supporting Inheritance in Listeners -Often, base classes or interfaces define generic listeners: -```java -public interface BaseConsumer { - @RabbitListener(queues = "${app.queue}") - void handle(T payload); -} -``` -The `CodebaseContext` must resolve the `${app.queue}` if possible (via `application.properties` scanning) or at least note that it's a parameterized listener. - -## Advanced Call Graph: The "Data Flow" -For a truly detailed analysis, we should track NOT just method calls, but also how the "Event" object is passed around. -- Is the event hardcoded? `sm.sendEvent(Events.CREATE)` -- Is it derived from a payload field? `sm.sendEvent(payload.getEvent())` -- Is it mapped via a `switch` or `Map`? - -**Static Mapping Inference**: -If we see a `switch` statement on a payload field that leads to different `sendEvent` calls, we can report multiple possible flows from the same endpoint. diff --git a/plan-extended-anaylis-v1/implementation_details.md b/plan-extended-anaylis-v1/implementation_details.md deleted file mode 100644 index 4bcfa4a..0000000 --- a/plan-extended-anaylis-v1/implementation_details.md +++ /dev/null @@ -1,102 +0,0 @@ -# Implementation Details: Trigger Detection with JDT - -## 1. Finding `sendEvent` Calls -We can use an `ASTVisitor` to find all `MethodInvocation` nodes. - -```java -public class SendEventVisitor extends ASTVisitor { - @Override - public boolean visit(MethodInvocation node) { - if ("sendEvent".equals(node.getName().getIdentifier())) { - // Found a call! - // 1. Extract event (first argument) - // 2. Identify the enclosing method and class - } - return super.visit(node); - } -} -``` - -### Challenges in Event Extraction -Events can be: -- Enum constants: `Events.SUBMIT` -- Strings: `"SUBMIT"` -- Variables: `sm.sendEvent(eventFromPayload)` (Hard to resolve statically) - -We should reuse `CodebaseContext.resolveState` logic (which is basically resolving an expression to a value/fqn). - -## 2. Identifying Enclosing Context -Once a `sendEvent` is found, we can traverse up the AST to find the `MethodDeclaration` and `TypeDeclaration`. - -```java -ASTNode parent = node.getParent(); -while (parent != null && !(parent instanceof MethodDeclaration)) { - parent = parent.getParent(); -} -// parent is now the MethodDeclaration -``` - -### 2. Extracting Annotations -From `MethodDeclaration`, we can check for mappings: -- `@PostMapping`, `@GetMapping`, etc. -- `@KafkaListener`: Extract `topics`, `groupId`. -- `@RabbitListener`: Extract `queues`, `bindings` (Exchange/RoutingKey). - -From `TypeDeclaration`, we can check for: -- `@RestController`, `@Controller` -- `@RequestMapping` at class level (to get base path) - -## 3. Specialized WebFlux Analysis - -### Annotation-based WebFlux -This is largely identical to Spring MVC. The challenge is if the `sendEvent` is wrapped in a reactive operator. -```java -public Mono submit(Order order) { - return service.save(order) - .doOnNext(o -> stateMachine.sendEvent(Events.SUBMIT)) - .then(); -} -``` -**Static Strategy**: We need to look inside `LambdaExpression` nodes passed to reactive operators (`doOnNext`, `flatMap`, `map`, `subscribe`). The `ASTVisitor` should traverse into these lambdas. - -### Functional WebFlux (RouterFunctions) -Functional endpoints are often defined as Beans returning `RouterFunction`. -```java -@Bean -public RouterFunction route(OrderHandler handler) { - return RouterFunctions.route(POST("/orders"), handler::submitOrder); -} -``` -**Static Strategy**: -1. Find methods returning `RouterFunction`. -2. Analyze the `MethodInvocation` chain (`route`, `andRoute`, `nest`). -3. Extract the URI pattern and the `HandlerFunction` reference. -4. If the handler is a method reference (`handler::submitOrder`), link it to the corresponding `MethodDeclaration`. - -## 4. Specialized RabbitMQ Analysis -`@RabbitListener` can be complex: -```java -@RabbitListener(bindings = @QueueBinding( - value = @Queue(value = "orderQueue", durable = "true"), - exchange = @Exchange(value = "orderExchange"), - key = "order.created" -)) -public void onOrder(Order order) { ... } -``` -**Static Strategy**: -1. Find `@RabbitListener`. -2. If it has `bindings`, drill down into `@QueueBinding`, `@Queue`, `@Exchange` to extract the topology. -3. If it only has `queues`, resolve the queue name (might be a SpEL expression or property placeholder, which we can try to resolve or just keep as-is). - -## 5. Indirect Flow Detection (The "Service Link") -If the project has multiple state machines, we need to know which one is being targeted. -Usually, this is done via: -- Autowiring by type: `StateMachine sm;` -- Autowiring by name: `@Qualifier("mySm") StateMachine sm;` - -We can look at the fields of the class where `sendEvent` is called. - -## 6. Output Enhancement -The `Exporter` should be modified to: -- In DOT: Add nodes for Endpoints/Listeners and link them to the Events/Transitions. -- In SCXML: Add metadata to transitions. diff --git a/plan-extended-anaylis-v1/property_resolution.md b/plan-extended-anaylis-v1/property_resolution.md deleted file mode 100644 index d0d123e..0000000 --- a/plan-extended-anaylis-v1/property_resolution.md +++ /dev/null @@ -1,71 +0,0 @@ -# Spring Property and Value Resolution Strategy - -## 1. The Challenge of "Injected" Metadata -In Spring, metadata (like Queue names, Topic names, or even Event names) is often not hardcoded but injected using various mechanisms. To provide an accurate map, the analyzer must resolve these values. - -## 2. Supported Injection Patterns - -### Field Injection -```java -@Value("${app.order-queue}") -private String orderQueue; -``` -**Static Strategy**: -1. Scan all fields for `@Value`. -2. Map `FieldName` -> `Placeholder/Value`. -3. If `${...}` is found, resolve it via the `PropertyResolver`. - -### Constructor and Setter Injection -```java -public OrderService(@Value("${app.event.submit}") String submitEvent) { - this.submitEvent = submitEvent; -} -``` -**Static Strategy**: -1. Scan constructor/method parameters for `@Value`. -2. Trace the assignment to a class field (`this.submitEvent = ...`). -3. Store the mapping for that field. - -### @ConfigurationProperties -```java -@ConfigurationProperties(prefix = "app.messaging") -public class AppProps { - private String queueName; -} -``` -**Static Strategy**: -1. Identify `@ConfigurationProperties` classes. -2. Index their fields with the prefix (e.g., `app.messaging.queueName`). -3. When these beans are injected into a service, link the service's usage to the resolved property value. - -## 3. Property Resolver (The "Config Scanner") -A component dedicated to building a global map of available properties. - -1. **File Scanning**: Parse `application.properties`, `application.yml`, and `bootstrap.yml`. -2. **Profile Support**: Handle `application-{profile}.yml` if a profile is active. -3. **Property Map**: Create a `Map` of all key-value pairs. - -## 4. Value Propagation (Data Flow) -Once a value is resolved or its placeholder is identified, we track its usage. - -**Example Trace**: -1. `application.yml` -> `app.queue: "orders"` -2. `OrderService` -> `@Value("${app.queue}") String q;` -> `this.queue = q;` -3. `OrderService.send()` -> `sm.sendEvent(this.queue);` -4. **Resolution**: The "Event" for this trigger is "orders". - -## 5. SpEL (Spring Expression Language) Lite -Full SpEL support is hard for static analysis, but we can support "Common Patterns": -- Simple bean property access: `#{myBean.name}` -- System properties: `#{systemProperties['user.dir']}` -- Ternary operators: `${app.enabled ? 'active' : 'inactive'}` - -## 6. Constant Resolution -If an annotation uses a reference to a constant: -```java -@RabbitListener(queues = MyConstants.ORDER_QUEUE) -``` -**Static Strategy**: -1. Use JDT to resolve the `QualifiedName` (`MyConstants.ORDER_QUEUE`). -2. Fetch the `TypeDeclaration` for `MyConstants`. -3. Find the `VariableDeclarationFragment` for `ORDER_QUEUE` and extract its literal initializer. diff --git a/plan-extended-anaylis/PLAN.md b/plan-extended-anaylis/PLAN.md index c73cb35..81be21f 100644 --- a/plan-extended-anaylis/PLAN.md +++ b/plan-extended-anaylis/PLAN.md @@ -1,63 +1,57 @@ -# Execution Plan for Extended Analysis +# Execution Plan for Extended Analysis (Revised for Robustness) ## Phase 0: Surgical Refactoring (The Enrichment Hook) -- [ ] Create `AnalysisResult` and `CodebaseMetadata` models. -- [ ] Update `ExportService.generateOutputs` to accept `AnalysisResult`. -- [ ] Implement `EnrichmentService` and `AnalysisEnricher` interface. -- [ ] Wrap current parser outputs in `AnalysisResult` within `ExportService`. +- [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`. -## Phase 1: Foundation +## Phase 1: Foundation & Semantic Core +- [ ] **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. -- [ ] Implement `RegexIntelligenceProvider` for fast, lightweight metadata extraction. -... -## Phase 2: Direct Trigger Detection -- [ ] Implement `GenericEventDetector` using `ASTVisitor` to find `sendEvent` calls. -- [ ] Enhance `CodebaseContext` to provide mapping from `MethodDeclaration` to its callers (within the same codebase). +## Phase 2: Trigger Discovery & Instance Identity +- [ ] **GenericEventDetector**: Find `sendEvent` calls using `ASTVisitor`. +- [ ] **InstanceIdentifier**: Detect which State Machine is being targeted (via `@Qualifier`, bean names, or generic types `StateMachine`). +- [ ] **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. ## Phase 3: Entry Point Mapping -- [ ] Implement `SpringMvcDetector` for REST endpoints. -- [ ] Implement `MessageListenerDetector` for Kafka/JMS. -- [ ] Implement `ConfigurableTriggerDetector` for user-defined patterns. +- [ ] **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. ## Phase 4: Call Graph Integration -- [ ] Develop a simple call graph builder to link `Entry Points` to `Trigger Points` via intermediate service calls. -- [ ] Support inheritance in call graph resolution (e.g., calling a method defined in an interface/base class). +- [ ] 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). -## Phase 5: Correlation and Visualization +## Phase 5: Visualization & Diagnostics - [ ] Update `ExportService` to include trigger information. -- [ ] Update DOT exporter to show "external" entry points as boxes pointing to transitions. -- [ ] Update SCXML exporter to include trigger metadata in `` tags. +- [ ] 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 +## 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 Value Resolution -- [ ] Implement `PropertyResolver` to scan `application.properties/yml`. -- [ ] Add support for `@Value` tracking in fields and constructors. -- [ ] Implement constant resolution for cross-class references in annotations. -- [ ] Integrate value propagation into the call graph analysis (linking injected values to `sendEvent` arguments). +## Phase 7: Advanced Resolution & Data Flow +- [ ] **Complex ValueResolver**: Handle string concatenations and variable references in annotations/logic. +- [ ] **Payload Analysis**: Extract payload types from entry points and track field usage in `sendEvent` calls. +- [ ] **@Value Propagation**: Track property values injected into fields and constructors. -## Phase 8: Advanced String Expression Resolution -- [ ] Implement `ValueResolver` to handle string concatenations and variable references. -- [ ] Support cross-class constant lookup using JDT. -- [ ] Update all Enrichers (MVC, Rabbit, JMS) to use `ValueResolver` for metadata extraction. -- [ ] Verify with complex path patterns in the integration test suite. - -## Phase 9: Instance Identification & Persistence Mapping -- [ ] Implement `InstanceIdentifier` to track State Machine IDs (via `@Qualifier`, bean names, or factories). +## Phase 8: Persistence & Lifecycle Mapping - [ ] Detect persistence restoration logic (`persister.restore`). -- [ ] Update all Enrichers to include `stateMachineId` and `isRestoredFromPersistence` in metadata. -- [ ] Verify multi-SM identification in the integration test suite. +- [ ] 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 10: Incoming Payload Analysis -- [ ] Implement payload type extraction for REST and Message entry points. -- [ ] Detect usage of payload fields in `sendEvent` or `restore` calls. -- [ ] Add `payloadType` to `EntryPoint` and `TriggerPoint` models. +## 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 11: Interceptor & Filter Mapping -- [ ] Implement detection of `HandlerInterceptor` and `Filter` implementations. -- [ ] Map interceptors to endpoints using `WebMvcConfigurer` analysis. -- [ ] Provide "Interceptor Context" metadata for each mapped endpoint. +## Phase 10: External Dependency Interop +- [ ] **Library Hints**: Allow users to provide a JSON map of "Method -> Event" for third-party libraries where source is unavailable. +- [ ] **External JAR Analysis**: (Optional) Configure JDT to scan source-attachments of dependencies if available.