From 28df9fc99f8dcb6818d651c7cd1fa2e713e3757a Mon Sep 17 00:00:00 2001 From: Kamil Patryk Kozakowski Date: Mon, 6 Jul 2026 18:07:02 +0200 Subject: [PATCH] 6 --- .../analysis/service/CallGraphPathFinder.java | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CallGraphPathFinder.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CallGraphPathFinder.java index f13f2b6..29d34d4 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CallGraphPathFinder.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/CallGraphPathFinder.java @@ -50,14 +50,31 @@ public class CallGraphPathFinder { } public List> findAllPaths(String start, String target, Map> graph, Set visited) { - return findAllPaths(start, target, graph, visited, new HashSet<>(), new boolean[]{false}); + return findAllPaths(start, target, graph, visited, new HashSet<>(), new boolean[]{false}, new HashMap<>()); } - public List> findAllPaths(String start, String target, Map> graph, Set visited, Set unreachable, boolean[] parentHitCycle) { + public List> findAllPaths(String start, String target, Map> graph, Set visited, Set unreachable, boolean[] parentHitCycle, Map>> memo) { List> result = new ArrayList<>(); if (unreachable.contains(start)) { return result; } + if (memo.containsKey(start)) { + List> cached = memo.get(start); + for (List path : cached) { + boolean hasCycle = false; + for (String node : path) { + if (visited.contains(node)) { + hasCycle = true; + parentHitCycle[0] = true; + break; + } + } + if (!hasCycle) { + result.add(new ArrayList<>(path)); + } + } + return result; + } if (start.equals(target)) { result.add(new ArrayList<>(List.of(start))); return result; @@ -78,7 +95,7 @@ public class CallGraphPathFinder { List path = new ArrayList<>(List.of(start, target)); result.add(path); } else { - List> subPaths = findAllPaths(neighbor, target, graph, visited, unreachable, localHitCycle); + List> subPaths = findAllPaths(neighbor, target, graph, visited, unreachable, localHitCycle, memo); for (List subPath : subPaths) { List path = new ArrayList<>(); path.add(start); @@ -102,7 +119,7 @@ public class CallGraphPathFinder { if (superclass != null) { String superMethod = superclass + "." + methodName; if (graph.containsKey(superMethod)) { - List> superPaths = findAllPaths(superMethod, target, graph, visited, unreachable, localHitCycle); + List> superPaths = findAllPaths(superMethod, target, graph, visited, unreachable, localHitCycle, memo); for (List superPath : superPaths) { List path = new ArrayList<>(); path.add(start); @@ -126,7 +143,7 @@ public class CallGraphPathFinder { for (String impl : impls) { String implMethod = impl + "." + methodName; if (graph.containsKey(implMethod)) { - List> implPaths = findAllPaths(implMethod, target, graph, visited, unreachable, localHitCycle); + List> implPaths = findAllPaths(implMethod, target, graph, visited, unreachable, localHitCycle, memo); for (List implPath : implPaths) { List path = new ArrayList<>(); path.add(start); @@ -143,6 +160,12 @@ public class CallGraphPathFinder { parentHitCycle[0] = true; } else if (result.isEmpty()) { unreachable.add(start); + } else { + List> toCache = new ArrayList<>(); + for (List path : result) { + toCache.add(new ArrayList<>(path)); + } + memo.put(start, toCache); } return result;