This commit is contained in:
2026-07-06 18:07:02 +02:00
parent e3dd26c0d4
commit 28df9fc99f

View File

@@ -50,14 +50,31 @@ public class CallGraphPathFinder {
}
public List<List<String>> findAllPaths(String start, String target, Map<String, List<CallEdge>> graph, Set<String> 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<List<String>> findAllPaths(String start, String target, Map<String, List<CallEdge>> graph, Set<String> visited, Set<String> unreachable, boolean[] parentHitCycle) {
public List<List<String>> findAllPaths(String start, String target, Map<String, List<CallEdge>> graph, Set<String> visited, Set<String> unreachable, boolean[] parentHitCycle, Map<String, List<List<String>>> memo) {
List<List<String>> result = new ArrayList<>();
if (unreachable.contains(start)) {
return result;
}
if (memo.containsKey(start)) {
List<List<String>> cached = memo.get(start);
for (List<String> 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<String> path = new ArrayList<>(List.of(start, target));
result.add(path);
} else {
List<List<String>> subPaths = findAllPaths(neighbor, target, graph, visited, unreachable, localHitCycle);
List<List<String>> subPaths = findAllPaths(neighbor, target, graph, visited, unreachable, localHitCycle, memo);
for (List<String> subPath : subPaths) {
List<String> 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<List<String>> superPaths = findAllPaths(superMethod, target, graph, visited, unreachable, localHitCycle);
List<List<String>> superPaths = findAllPaths(superMethod, target, graph, visited, unreachable, localHitCycle, memo);
for (List<String> superPath : superPaths) {
List<String> 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<List<String>> implPaths = findAllPaths(implMethod, target, graph, visited, unreachable, localHitCycle);
List<List<String>> implPaths = findAllPaths(implMethod, target, graph, visited, unreachable, localHitCycle, memo);
for (List<String> implPath : implPaths) {
List<String> 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<List<String>> toCache = new ArrayList<>();
for (List<String> path : result) {
toCache.add(new ArrayList<>(path));
}
memo.put(start, toCache);
}
return result;