heuristic code

This commit is contained in:
2026-07-05 22:00:26 +02:00
parent 180a283383
commit c390f02389

View File

@@ -9,6 +9,7 @@ import java.util.*;
@Slf4j @Slf4j
public class CallGraphPathFinder { public class CallGraphPathFinder {
private final CodebaseContext context; private final CodebaseContext context;
private final Map<String, Boolean> heuristicCache = new HashMap<>();
public CallGraphPathFinder(CodebaseContext context) { public CallGraphPathFinder(CodebaseContext context) {
this.context = context; this.context = context;
@@ -49,15 +50,25 @@ public class CallGraphPathFinder {
} }
public List<List<String>> findAllPaths(String start, String target, Map<String, List<CallEdge>> graph, Set<String> visited) { 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});
}
public List<List<String>> findAllPaths(String start, String target, Map<String, List<CallEdge>> graph, Set<String> visited, Set<String> unreachable, boolean[] parentHitCycle) {
List<List<String>> result = new ArrayList<>(); List<List<String>> result = new ArrayList<>();
if (unreachable.contains(start)) {
return result;
}
if (start.equals(target)) { if (start.equals(target)) {
result.add(new ArrayList<>(List.of(start))); result.add(new ArrayList<>(List.of(start)));
return result; return result;
} }
if (!visited.add(start)) { if (!visited.add(start)) {
parentHitCycle[0] = true;
return result; return result;
} }
boolean[] localHitCycle = new boolean[]{false};
List<CallEdge> neighbors = graph.get(start); List<CallEdge> neighbors = graph.get(start);
if (neighbors != null) { if (neighbors != null) {
for (CallEdge edge : neighbors) { for (CallEdge edge : neighbors) {
@@ -67,7 +78,7 @@ public class CallGraphPathFinder {
List<String> path = new ArrayList<>(List.of(start, target)); List<String> path = new ArrayList<>(List.of(start, target));
result.add(path); result.add(path);
} else { } else {
List<List<String>> subPaths = findAllPaths(neighbor, target, graph, visited); List<List<String>> subPaths = findAllPaths(neighbor, target, graph, visited, unreachable, localHitCycle);
for (List<String> subPath : subPaths) { for (List<String> subPath : subPaths) {
List<String> path = new ArrayList<>(); List<String> path = new ArrayList<>();
path.add(start); path.add(start);
@@ -91,7 +102,7 @@ public class CallGraphPathFinder {
if (superclass != null) { if (superclass != null) {
String superMethod = superclass + "." + methodName; String superMethod = superclass + "." + methodName;
if (graph.containsKey(superMethod)) { if (graph.containsKey(superMethod)) {
List<List<String>> superPaths = findAllPaths(superMethod, target, graph, visited); List<List<String>> superPaths = findAllPaths(superMethod, target, graph, visited, unreachable, localHitCycle);
for (List<String> superPath : superPaths) { for (List<String> superPath : superPaths) {
List<String> path = new ArrayList<>(); List<String> path = new ArrayList<>();
path.add(start); path.add(start);
@@ -115,7 +126,7 @@ public class CallGraphPathFinder {
for (String impl : impls) { for (String impl : impls) {
String implMethod = impl + "." + methodName; String implMethod = impl + "." + methodName;
if (graph.containsKey(implMethod)) { if (graph.containsKey(implMethod)) {
List<List<String>> implPaths = findAllPaths(implMethod, target, graph, visited); List<List<String>> implPaths = findAllPaths(implMethod, target, graph, visited, unreachable, localHitCycle);
for (List<String> implPath : implPaths) { for (List<String> implPath : implPaths) {
List<String> path = new ArrayList<>(); List<String> path = new ArrayList<>();
path.add(start); path.add(start);
@@ -127,6 +138,13 @@ public class CallGraphPathFinder {
} }
} }
visited.remove(start); visited.remove(start);
if (localHitCycle[0]) {
parentHitCycle[0] = true;
} else if (result.isEmpty()) {
unreachable.add(start);
}
return result; return result;
} }
@@ -151,6 +169,18 @@ public class CallGraphPathFinder {
if (neighbor == null || target == null) return false; if (neighbor == null || target == null) return false;
if (neighbor.equals(target)) return true; if (neighbor.equals(target)) return true;
String cacheKey = neighbor + "|" + target;
Boolean cached = heuristicCache.get(cacheKey);
if (cached != null) return cached;
boolean result = calculateHeuristicMatch(neighbor, target);
heuristicCache.put(cacheKey, result);
return result;
}
private boolean calculateHeuristicMatch(String neighbor, String target) {
if (neighbor.equals(target)) return true;
if (isFullyQualifiedMethod(neighbor) && isFullyQualifiedMethod(target)) { if (isFullyQualifiedMethod(neighbor) && isFullyQualifiedMethod(target)) {
int lastDotNeighbor = neighbor.lastIndexOf('.'); int lastDotNeighbor = neighbor.lastIndexOf('.');
int lastDotTarget = target.lastIndexOf('.'); int lastDotTarget = target.lastIndexOf('.');