call graph fix + tests
This commit is contained in:
@@ -215,8 +215,743 @@ class CallGraphBuilderTest {
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
assertThat(chain.getTriggerPoint().getPolymorphicEvents())
|
||||
.as("Resolved event was: " + chain.getTriggerPoint().getEvent())
|
||||
.containsExactlyInAnyOrder("OrderEvents.PAY");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolvePolymorphicInheritanceAcrossChain() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent(RichOrderEvent domainEvent) {
|
||||
doProcessOrderEvent(domainEvent);
|
||||
}
|
||||
|
||||
private void doProcessOrderEvent(RichOrderEvent domainEvent) {
|
||||
OrderEvents eventType = assertSupportedOrderEvent(domainEvent.getType());
|
||||
service.updateOrderState(eventType);
|
||||
}
|
||||
|
||||
private OrderEvents assertSupportedOrderEvent(OrderEvents e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {
|
||||
// sendEvent
|
||||
}
|
||||
}
|
||||
|
||||
interface RichOrderEvent {
|
||||
OrderEvents getType();
|
||||
}
|
||||
|
||||
class CancelOrderEvent implements RichOrderEvent {
|
||||
public OrderEvents getType() { return OrderEvents.CANCELLED; }
|
||||
}
|
||||
|
||||
class ReceiveOrderEvent implements RichOrderEvent {
|
||||
public OrderEvents getType() { return OrderEvents.RECEIVED; }
|
||||
}
|
||||
|
||||
enum OrderEvents { CREATE, PAY, CANCELLED, RECEIVED }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_poly");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
assertThat(chain.getTriggerPoint().getPolymorphicEvents())
|
||||
.as("Resolved event was: " + chain.getTriggerPoint().getEvent())
|
||||
.containsExactlyInAnyOrder("OrderEvents.CANCELLED", "OrderEvents.RECEIVED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUnwrapDeepMethodWrappers() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent(RichOrderEvent domainEvent) {
|
||||
OrderEvents eventType = wrap3(wrap2(wrap1(domainEvent.getType())));
|
||||
service.updateOrderState(eventType);
|
||||
}
|
||||
|
||||
private OrderEvents wrap1(OrderEvents e) { return e; }
|
||||
private OrderEvents wrap2(OrderEvents e) { return e; }
|
||||
private OrderEvents wrap3(OrderEvents e) { return e; }
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) { }
|
||||
}
|
||||
|
||||
class RichOrderEvent {
|
||||
public OrderEvents getType() { return OrderEvents.CREATE; }
|
||||
}
|
||||
|
||||
enum OrderEvents { CREATE }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_deep_wrap");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
assertThat(chain.getTriggerPoint().getPolymorphicEvents())
|
||||
.as("Resolved event was: " + chain.getTriggerPoint().getEvent())
|
||||
.containsExactlyInAnyOrder("OrderEvents.CREATE");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolvePolymorphicInheritanceThroughDelegation() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent(BaseEvent domainEvent) {
|
||||
service.updateOrderState(domainEvent.getType());
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
interface BaseEvent {
|
||||
OrderEvents getType();
|
||||
}
|
||||
|
||||
abstract class AbstractEvent implements BaseEvent {
|
||||
protected OrderEvents internalGetType() {
|
||||
return OrderEvents.PAY;
|
||||
}
|
||||
}
|
||||
|
||||
class ConcreteEvent extends AbstractEvent {
|
||||
public OrderEvents getType() {
|
||||
return internalGetType();
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherConcreteEvent implements BaseEvent {
|
||||
public OrderEvents getType() {
|
||||
return delegateToHelper();
|
||||
}
|
||||
private OrderEvents delegateToHelper() {
|
||||
return OrderEvents.CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
enum OrderEvents { PAY, CANCELLED }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_poly_delegation");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
assertThat(chain.getTriggerPoint().getPolymorphicEvents())
|
||||
.containsExactlyInAnyOrder("OrderEvents.PAY", "OrderEvents.CANCELLED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleMissingImplementationsGracefully() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent(UnknownEvent domainEvent) {
|
||||
service.updateOrderState(domainEvent.getType());
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
// UnknownEvent is not defined in the source (e.g. from a third-party library)
|
||||
|
||||
enum OrderEvents { CREATE }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_missing_impl");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
assertThat(chain.getTriggerPoint().getEvent()).isEqualTo("domainEvent.getType()");
|
||||
assertThat(chain.getTriggerPoint().getPolymorphicEvents()).isNullOrEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldTraceMultipleLocalVariableAssignments() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent(RichOrderEvent domainEvent) {
|
||||
OrderEvents type1 = domainEvent.getType();
|
||||
OrderEvents type2 = type1;
|
||||
OrderEvents type3 = type2;
|
||||
service.updateOrderState(type3);
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
class RichOrderEvent {
|
||||
public OrderEvents getType() { return OrderEvents.RECEIVED; }
|
||||
}
|
||||
|
||||
enum OrderEvents { RECEIVED }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_multiple_assign");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
assertThat(chain.getTriggerPoint().getPolymorphicEvents())
|
||||
.containsExactlyInAnyOrder("OrderEvents.RECEIVED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveMethodInheritedFromAbstractBaseClass() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent(BaseEvent domainEvent) {
|
||||
service.updateOrderState(domainEvent.getType());
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
interface BaseEvent {
|
||||
OrderEvents getType();
|
||||
}
|
||||
|
||||
abstract class AbstractEvent implements BaseEvent {
|
||||
public OrderEvents getType() {
|
||||
return OrderEvents.PAY;
|
||||
}
|
||||
}
|
||||
|
||||
// Concrete subclass inherits getType() but doesn't override it!
|
||||
class InheritingEvent extends AbstractEvent {
|
||||
}
|
||||
|
||||
enum OrderEvents { PAY }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_inherited");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
assertThat(chain.getTriggerPoint().getPolymorphicEvents())
|
||||
.containsExactlyInAnyOrder("OrderEvents.PAY");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldStopTracingRecursiveMethodsGracefully() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent(RecursiveEvent domainEvent) {
|
||||
service.updateOrderState(domainEvent.getType());
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
class RecursiveEvent {
|
||||
public OrderEvents getType() {
|
||||
return this.getType();
|
||||
}
|
||||
}
|
||||
|
||||
enum OrderEvents { PAY }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_recursive");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
// Should safely complete without stack overflow and return an empty result
|
||||
assertThat(chain.getTriggerPoint().getEvent()).isEqualTo("domainEvent.getType()");
|
||||
assertThat(chain.getTriggerPoint().getPolymorphicEvents()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleChainedMethodCallsGracefully() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent(EventWrapper wrapper) {
|
||||
service.updateOrderState(wrapper.getEvent().getType());
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
class EventWrapper {
|
||||
public RichEvent getEvent() { return new RichEvent(); }
|
||||
}
|
||||
|
||||
class RichEvent {
|
||||
public OrderEvents getType() { return OrderEvents.PAY; }
|
||||
}
|
||||
|
||||
enum OrderEvents { PAY }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_chained");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
// It might not fully resolve chained method calls, but it must not crash!
|
||||
assertThat(chain.getTriggerPoint().getEvent()).isEqualTo("wrapper.getEvent().getType()");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldTraceStaticFieldReferences() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private static final OrderEvents CONSTANT_EVENT = OrderEvents.CANCELLED;
|
||||
private OrderService service;
|
||||
public void processOrderEvent() {
|
||||
service.updateOrderState(CONSTANT_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
enum OrderEvents { CANCELLED }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_static_field");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
assertThat(chain.getTriggerPoint().getEvent()).isEqualTo("OrderEvents.CANCELLED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleAnonymousInnerClassesGracefully() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent() {
|
||||
RichEvent event = new RichEvent() {
|
||||
public OrderEvents getType() {
|
||||
return OrderEvents.CREATE;
|
||||
}
|
||||
};
|
||||
service.updateOrderState(event.getType());
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
interface RichEvent {
|
||||
OrderEvents getType();
|
||||
}
|
||||
|
||||
enum OrderEvents { CREATE }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_anonymous");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
// It successfully traces the local variable 'event' to its anonymous class initializer
|
||||
assertThat(chain.getTriggerPoint().getEvent()).startsWith("new RichEvent(){");
|
||||
assertThat(chain.getTriggerPoint().getEvent()).endsWith(".getType()");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldLinkCallsInsideLambdasToEnclosingMethod() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent() {
|
||||
Runnable r = () -> service.updateOrderState(OrderEvents.PAY);
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
enum OrderEvents { PAY }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_lambda_scope");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
assertThat(chain.getTriggerPoint().getEvent()).isEqualTo("OrderEvents.PAY");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleTernaryOperatorsGracefully() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent(boolean flag) {
|
||||
OrderEvents event = flag ? OrderEvents.PAY : OrderEvents.CANCELLED;
|
||||
service.updateOrderState(event);
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
enum OrderEvents { PAY, CANCELLED }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_ternary");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
// It should gracefully fallback to the string representation of the ternary operator
|
||||
assertThat(chain.getTriggerPoint().getEvent()).isEqualTo("flag ? OrderEvents.PAY : OrderEvents.CANCELLED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldTraceLastTextualAssignmentInTryCatchBlocks() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent() {
|
||||
OrderEvents event;
|
||||
try {
|
||||
event = OrderEvents.PAY;
|
||||
} catch (Exception e) {
|
||||
event = OrderEvents.CANCELLED;
|
||||
}
|
||||
service.updateOrderState(event);
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
enum OrderEvents { PAY, CANCELLED }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_try_catch");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
// The ASTVisitor picks up Assignments in textual order.
|
||||
// CANCELLED is the last one textually in the method.
|
||||
assertThat(chain.getTriggerPoint().getEvent()).isEqualTo("OrderEvents.CANCELLED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldTraceArrayAndCollectionAccessGracefully() throws IOException {
|
||||
String source = """
|
||||
package com.example;
|
||||
public class OrderController {
|
||||
private OrderService service;
|
||||
public void processOrderEvent() {
|
||||
OrderEvents[] events = new OrderEvents[]{OrderEvents.PAY};
|
||||
service.updateOrderState(events[0]);
|
||||
}
|
||||
}
|
||||
|
||||
class OrderService {
|
||||
public void updateOrderState(OrderEvents event) {}
|
||||
}
|
||||
|
||||
enum OrderEvents { PAY }
|
||||
""";
|
||||
Path tempDir = Files.createTempDirectory("callgraph_test_array");
|
||||
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||
|
||||
CodebaseContext context = new CodebaseContext();
|
||||
context.scan(tempDir);
|
||||
|
||||
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||
|
||||
EntryPoint entryPoint = EntryPoint.builder()
|
||||
.className("com.example.OrderController")
|
||||
.methodName("processOrderEvent")
|
||||
.build();
|
||||
|
||||
TriggerPoint trigger = TriggerPoint.builder()
|
||||
.className("com.example.OrderService")
|
||||
.methodName("updateOrderState")
|
||||
.event("event")
|
||||
.build();
|
||||
|
||||
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||
|
||||
assertThat(chains).hasSize(1);
|
||||
CallChain chain = chains.get(0);
|
||||
// We don't dynamically resolve array indexes, but it shouldn't crash.
|
||||
// It returns the array access expression as a string.
|
||||
assertThat(chain.getTriggerPoint().getEvent()).isEqualTo("events[0]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "PLACE_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.service.OrderServiceImpl",
|
||||
@@ -17,7 +18,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 16
|
||||
"lineNumber" : 16,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "CANCEL_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.service.OrderServiceImpl",
|
||||
@@ -26,7 +28,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 21
|
||||
"lineNumber" : 21,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "PAY_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.service.ReactivePaymentService",
|
||||
@@ -35,7 +38,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "SHIP_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.messaging.ShippingJmsListener",
|
||||
@@ -44,7 +48,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "RETURN_ORDER",
|
||||
"className" : "click.kamil.examples.enterprise.messaging.ReturnsRabbitListener",
|
||||
@@ -53,7 +58,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
@@ -185,7 +191,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 16
|
||||
"lineNumber" : 16,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -219,7 +226,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 21
|
||||
"lineNumber" : 21,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -248,7 +256,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : null
|
||||
@@ -278,7 +287,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -312,7 +322,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -346,7 +357,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 17
|
||||
"lineNumber" : 17,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 34
|
||||
"lineNumber" : 34,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "AUDIT_EVENT",
|
||||
"className" : "click.kamil.examples.statemachine.extended.web.AuditInterceptor",
|
||||
@@ -17,7 +18,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 16
|
||||
"lineNumber" : 16,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "EXTERNAL_TRIGGER",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
@@ -26,7 +28,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 19
|
||||
"lineNumber" : 19,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "SUBMIT_EVENT",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
@@ -35,7 +38,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 20
|
||||
"lineNumber" : 20,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "CANCEL_EVENT",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
@@ -44,7 +48,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "[LIFECYCLE:RESTORE]",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
@@ -53,7 +58,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 29
|
||||
"lineNumber" : 29,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "REACTIVE_EVENT",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.ReactiveOrderService",
|
||||
@@ -62,7 +68,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
@@ -160,7 +167,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 19
|
||||
"lineNumber" : 19,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -190,7 +198,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 20
|
||||
"lineNumber" : 20,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -220,7 +229,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -250,7 +260,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 34
|
||||
"lineNumber" : 34,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -284,7 +295,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 29
|
||||
"lineNumber" : 29,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : "orderId",
|
||||
"matchedTransitions" : null
|
||||
@@ -314,7 +326,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -343,7 +356,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 16
|
||||
"lineNumber" : 16,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 34
|
||||
"lineNumber" : 34,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "AUDIT_EVENT",
|
||||
"className" : "click.kamil.examples.statemachine.extended.web.AuditInterceptor",
|
||||
@@ -17,7 +18,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 16
|
||||
"lineNumber" : 16,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "EXTERNAL_TRIGGER",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
@@ -26,7 +28,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 19
|
||||
"lineNumber" : 19,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "SUBMIT_EVENT",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
@@ -35,7 +38,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 20
|
||||
"lineNumber" : 20,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "CANCEL_EVENT",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
@@ -44,7 +48,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "[LIFECYCLE:RESTORE]",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.OrderService",
|
||||
@@ -53,7 +58,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 29
|
||||
"lineNumber" : 29,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "REACTIVE_EVENT",
|
||||
"className" : "click.kamil.examples.statemachine.extended.service.ReactiveOrderService",
|
||||
@@ -62,7 +68,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
@@ -160,7 +167,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 19
|
||||
"lineNumber" : 19,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -190,7 +198,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 20
|
||||
"lineNumber" : 20,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -220,7 +229,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -250,7 +260,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 34
|
||||
"lineNumber" : 34,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -284,7 +295,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 29
|
||||
"lineNumber" : 29,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : "orderId",
|
||||
"matchedTransitions" : null
|
||||
@@ -314,7 +326,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -343,7 +356,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 16
|
||||
"lineNumber" : 16,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 15
|
||||
"lineNumber" : 15,
|
||||
"polymorphicEvents" : null
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
@@ -55,7 +56,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 15
|
||||
"lineNumber" : 15,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 40
|
||||
"lineNumber" : 40,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "ORDER_EVENT",
|
||||
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderService",
|
||||
@@ -17,7 +18,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 52
|
||||
"lineNumber" : 52,
|
||||
"polymorphicEvents" : null
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
@@ -103,7 +105,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 40
|
||||
"lineNumber" : 40,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
@@ -67,7 +68,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 18
|
||||
"lineNumber" : 18,
|
||||
"polymorphicEvents" : null
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "eventProvider",
|
||||
"className" : "click.kamil.service.StateMachineServiceImpl",
|
||||
@@ -17,7 +18,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 50
|
||||
"lineNumber" : 50,
|
||||
"polymorphicEvents" : null
|
||||
}, {
|
||||
"event" : "customMessage",
|
||||
"className" : "click.kamil.service.StateMachineServiceImpl",
|
||||
@@ -26,7 +28,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 78
|
||||
"lineNumber" : 78,
|
||||
"polymorphicEvents" : null
|
||||
} ],
|
||||
"entryPoints" : [ {
|
||||
"type" : "REST",
|
||||
@@ -140,7 +143,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : [ ]
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -170,7 +174,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : [ ]
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -200,7 +205,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : [ ]
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -234,7 +240,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : [ ]
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -268,7 +275,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 78
|
||||
"lineNumber" : 78,
|
||||
"polymorphicEvents" : [ ]
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -302,7 +310,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 25
|
||||
"lineNumber" : 25,
|
||||
"polymorphicEvents" : [ ]
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
@@ -336,7 +345,8 @@
|
||||
"sourceModule" : null,
|
||||
"stateMachineId" : null,
|
||||
"sourceState" : null,
|
||||
"lineNumber" : 50
|
||||
"lineNumber" : 50,
|
||||
"polymorphicEvents" : [ ]
|
||||
},
|
||||
"contextMachineId" : null,
|
||||
"matchedTransitions" : [ {
|
||||
|
||||
Reference in New Issue
Block a user