diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CallGraphBuilder.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CallGraphBuilder.java index 8904b41..96e3ca5 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CallGraphBuilder.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CallGraphBuilder.java @@ -437,7 +437,7 @@ public class CallGraphBuilder { }); if (initializer[0] != null) { - Expression expr = traceVariable(initializer[0]); + Expression expr = traceVariable(initializer[0], new HashSet<>()); if (expr instanceof MethodInvocation mi) { // Unwrapper logic: If wrapper method is called, extract its arguments recursively Expression innerMost = unwrapMethodInvocation(mi, 0); @@ -636,7 +636,7 @@ public class CallGraphBuilder { } // Extract from constructor args (e.g., new CustomMessage(OrderEvent.PROCESS, ...)) - Expression tracedExpr = traceVariable(expr); + Expression tracedExpr = traceVariable(expr, new HashSet<>()); if (tracedExpr instanceof QualifiedName || tracedExpr instanceof ClassInstanceCreation || tracedExpr instanceof StringLiteral || tracedExpr instanceof NumberLiteral) { expr = tracedExpr; // Only accept trace if it resolves to a pure constant/primitive/constructor } @@ -917,7 +917,10 @@ public class CallGraphBuilder { } return (TypeDeclaration) parent; } - private Expression traceVariable(Expression expr) { + private Expression traceVariable(Expression expr, Set visited) { + if (!visited.add(expr)) { + return expr; // Cycle detected + } if (expr instanceof SimpleName sn) { String varName = sn.getIdentifier(); MethodDeclaration enclosingMethod = findEnclosingMethod(expr); @@ -940,7 +943,7 @@ public class CallGraphBuilder { } }); if (initializer[0] != null) { - return traceVariable(initializer[0]); + return traceVariable(initializer[0], visited); } } }