beans fix more

This commit is contained in:
2026-06-21 11:36:32 +02:00
parent bf82cc3562
commit e00f4dca81
11 changed files with 413 additions and 768 deletions

View File

@@ -683,16 +683,46 @@ public class JdtCallGraphEngine implements CallGraphEngine {
nameBinding = fa.resolveFieldBinding();
}
if (nameBinding instanceof IVariableBinding varBinding) {
System.out.println("CALLGRAPH RESOLVING BEAN FOR BINDING: " + varBinding.getName() + " calling " + methodName);
String concreteFqn = injectionAnalyzer.resolveInjectedBeanFqn(varBinding);
if (concreteFqn != null) {
System.out.println(" -> RESOLVED CONCRETE FQN: " + concreteFqn);
return concreteFqn + "." + methodName;
} else {
System.out.println(" -> RESOLVE FAILED, RETURNED NULL");
}
} else {
System.out.println("CALLGRAPH NAME BINDING IS NOT VARIABLE: " + nameBinding + " calling " + methodName);
}
}
ITypeBinding binding = receiver.resolveTypeBinding();
if (binding != null) {
return binding.getErasure().getQualifiedName() + "." + methodName;
String typeName = null;
try {
if (binding.getErasure() != null) {
typeName = binding.getErasure().getQualifiedName();
if (typeName == null || typeName.isEmpty()) {
typeName = binding.getErasure().getName();
}
}
} catch (Exception e) {
// Ignore JDT internal exceptions
}
if (typeName == null || typeName.isEmpty()) {
typeName = binding.getQualifiedName();
if (typeName == null || typeName.isEmpty()) {
typeName = binding.getName();
}
if (typeName != null && typeName.contains("<")) {
typeName = typeName.replaceAll("<.*>", "");
}
}
if (typeName != null && !typeName.isEmpty()) {
return typeName + "." + methodName;
}
}
if (receiver instanceof ThisExpression) {
@@ -832,7 +862,15 @@ public class JdtCallGraphEngine implements CallGraphEngine {
}
private boolean isHeuristicMatch(String neighbor, String target) {
if (neighbor.equals(target)) return true;
if (target.endsWith("." + neighbor)) return true;
if (neighbor.endsWith("." + target)) return true;
// If both are fully qualified (contain a dot) and didn't match above, they are definitely different methods
if (neighbor.contains(".") && target.contains(".")) {
return false;
}
String simpleTarget = target.contains(".") ? target.substring(target.lastIndexOf('.') + 1) : target;
String simpleNeighbor = neighbor.contains(".") ? neighbor.substring(neighbor.lastIndexOf('.') + 1) : neighbor;
return simpleNeighbor.equals(simpleTarget);

View File

@@ -48,13 +48,23 @@ public class InjectionPointAnalyzer {
org.eclipse.jdt.core.dom.ITypeBinding declaringClass = binding.getDeclaringClass();
if (declaringClass != null) {
for (org.eclipse.jdt.core.dom.IMethodBinding method : declaringClass.getDeclaredMethods()) {
if (method.isConstructor()) {
boolean isAutowiredMethod = false;
for (IAnnotationBinding ann : method.getAnnotations()) {
if (ann.getAnnotationType() != null && "org.springframework.beans.factory.annotation.Autowired".equals(ann.getAnnotationType().getQualifiedName())) {
isAutowiredMethod = true;
break;
}
}
if (method.isConstructor() || isAutowiredMethod) {
for (int i = 0; i < method.getParameterTypes().length; i++) {
org.eclipse.jdt.core.dom.ITypeBinding paramType = method.getParameterTypes()[i];
try {
IAnnotationBinding[] paramAnns = method.getParameterAnnotations(i);
String paramQual = getQualifierValue(paramAnns);
if (paramQual != null && paramType.getErasure().isEqualTo(binding.getType().getErasure())) {
// For setters, verify it roughly matches the field name or just rely on type.
// We will rely on type equality for now as a heuristic.
return paramQual;
}
} catch (Exception e) {

View File

@@ -23,12 +23,15 @@ public class SpringDependencyResolver {
if (requiredTypeFqn == null) return new ArrayList<>();
// 1. Filter by Type (Exact FQN or Assignable Type)
System.out.println("RESOLVING " + requiredTypeFqn + " qual=" + qualifier + " injectionName=" + injectionName);
List<SpringBean> candidates = registry.getBeans().stream()
.filter(bean -> requiredTypeFqn.equals(bean.getTypeFqn()) || bean.getAssignableTypes().contains(requiredTypeFqn))
.collect(Collectors.toList());
System.out.println("CANDIDATES AFTER TYPE: " + candidates.stream().map(c -> c.getTypeFqn() + " (primary=" + c.isPrimary() + " names=" + c.getBeanNames() + " qual=" + c.getQualifiers() + ")").collect(Collectors.toList()));
if (candidates.isEmpty() || candidates.size() == 1) {
return candidates;
System.out.println("RETURNING: " + candidates.size());
return candidates;
}
// 2. Filter by Qualifier (if provided)
@@ -72,12 +75,13 @@ public class SpringDependencyResolver {
List<SpringBean> orderedCandidates = candidates.stream()
.filter(bean -> bean.getOrder() != null && bean.getOrder().equals(minOrder))
.collect(Collectors.toList());
if (orderedCandidates.size() == 1) {
return orderedCandidates;
if (!orderedCandidates.isEmpty()) {
candidates = orderedCandidates;
}
}
// Return whatever candidates remain (could be ambiguous)
System.out.println("RETURNING: " + candidates.size());
return candidates;
}
}

View File

@@ -292,6 +292,15 @@ public class AstTransitionParser {
// Try same file
ASTNode declNode = cu.findDeclaringNode(binding.getKey());
if (declNode instanceof MethodDeclaration md) {
if (md.getBody() != null && md.getBody().statements().size() == 1) {
Object stmt = md.getBody().statements().get(0);
if (stmt instanceof org.eclipse.jdt.core.dom.ReturnStatement rs) {
Expression retExpr = rs.getExpression();
if (isLambdaOrAnonymous(retExpr)) {
return retExpr.toString();
}
}
}
return md.toString();
}

View File

@@ -238,6 +238,7 @@ public class CodebaseContext {
public List<String> getImplementations(String interfaceName) {
Set<String> allImpls = new HashSet<>();
collectImplementations(interfaceName, allImpls, new HashSet<>());
System.out.println("GET IMPLEMENTATIONS FOR: " + interfaceName + " -> " + allImpls);
return new ArrayList<>(allImpls);
}