diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/AbstractCallGraphEngine.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/AbstractCallGraphEngine.java index f270d91..7e7a8f6 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/AbstractCallGraphEngine.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/AbstractCallGraphEngine.java @@ -26,6 +26,94 @@ import java.util.*; String resolve(Expression rhs, Map paramValues, TypeDeclaration td); } + protected Map buildParameterValuesMap(String caller, String target, + Map> callGraph, List path, int pathIndex) { + Map paramValues = new HashMap<>(); + List edges = callGraph.get(caller); + if (edges == null) { + return paramValues; + } + + for (CallEdge edge : edges) { + if (edge.getTargetMethod().equals(target) || isHeuristicMatch(edge.getTargetMethod(), target)) { + List args = edge.getArguments(); + if (args == null || args.isEmpty()) break; + + int lastDot = target.lastIndexOf('.'); + if (lastDot < 0) break; + String className = target.substring(0, lastDot); + String methodName = target.substring(lastDot + 1); + + TypeDeclaration td = context.getTypeDeclaration(className); + if (td == null) break; + + MethodDeclaration md = context.findMethodDeclaration(td, methodName, true); + if (md == null) break; + + List paramNames = new ArrayList<>(); + for (Object paramObj : md.parameters()) { + SingleVariableDeclaration param = (SingleVariableDeclaration) paramObj; + paramNames.add(param.getName().getIdentifier()); + } + + int minSize = Math.min(paramNames.size(), args.size()); + for (int j = 0; j < minSize; j++) { + String argValue = args.get(j); + String resolvedArgValue = resolveArgumentValue(argValue, caller, path, pathIndex, callGraph); + paramValues.put(paramNames.get(j), resolvedArgValue); + } + break; + } + } + return paramValues; + } + + protected String resolveArgumentValue(String argValue, String callerMethod, List path, int pathIndex, Map> callGraph) { + if (argValue == null) return null; + if (argValue.contains(".") || argValue.startsWith("new ") || argValue.matches(".*[0-9].*")) { + return argValue; + } + + int callerIndex = path.indexOf(callerMethod); + if (callerIndex <= 0) return argValue; + + String prevCaller = path.get(callerIndex - 1); + List prevEdges = callGraph.get(prevCaller); + if (prevEdges == null) return argValue; + + for (CallEdge edge : prevEdges) { + if (edge.getTargetMethod().equals(callerMethod) || isHeuristicMatch(edge.getTargetMethod(), callerMethod)) { + List prevArgs = edge.getArguments(); + if (prevArgs == null || prevArgs.isEmpty()) break; + + int lastDot = callerMethod.lastIndexOf('.'); + if (lastDot < 0) break; + String className = callerMethod.substring(0, lastDot); + String methodName = callerMethod.substring(lastDot + 1); + + TypeDeclaration td = context.getTypeDeclaration(className); + if (td == null) break; + + MethodDeclaration md = context.findMethodDeclaration(td, methodName, true); + if (md == null) break; + + List paramNames = new ArrayList<>(); + for (Object paramObj : md.parameters()) { + SingleVariableDeclaration param = (SingleVariableDeclaration) paramObj; + paramNames.add(param.getName().getIdentifier()); + } + + int paramIdx = paramNames.indexOf(argValue); + if (paramIdx >= 0 && paramIdx < prevArgs.size()) { + String prevArg = prevArgs.get(paramIdx); + return resolveArgumentValue(prevArg, prevCaller, path, pathIndex, callGraph); + } + break; + } + } + return argValue; + } + public List findChains(List entryPoints, List triggers) { Map> callGraph = buildCallGraph(); List chains = new ArrayList<>();