update tranistions 2

This commit is contained in:
2026-06-28 09:56:05 +02:00
parent fc9d6f1f1c
commit 8d3fb0d90c
5 changed files with 122 additions and 12 deletions

View File

@@ -98,7 +98,7 @@ public class HeuristicBeanResolutionEngine implements BeanResolutionEngine {
hasPositiveMatch = true;
}
if (isDomainMismatch(smPackage, chainPackage, smPrefix, chainPrefix)) {
if (isDomainMismatch(smPackage, chainPackage, smPrefix, chainPrefix, smSimple, chainSimple)) {
hasStrongMismatch = true;
}
}
@@ -146,7 +146,7 @@ public class HeuristicBeanResolutionEngine implements BeanResolutionEngine {
return false;
}
private boolean isDomainMismatch(String smPackage, String chainPackage, String smPrefix, String chainPrefix) {
private boolean isDomainMismatch(String smPackage, String chainPackage, String smPrefix, String chainPrefix, String smSimple, String chainSimple) {
if (smPackage == null || chainPackage == null || smPackage.isEmpty() || chainPackage.isEmpty()) return false;
if (smPrefix == null || chainPrefix == null) return false;
@@ -155,7 +155,9 @@ public class HeuristicBeanResolutionEngine implements BeanResolutionEngine {
// Ignore generic/technical class prefixes
if (smLower.equals("state") || smLower.equals("statemachine") || smLower.equals("config") || smLower.equals("configuration") || smLower.equals("adapter") ||
chainLower.equals("state") || chainLower.equals("statemachine") || chainLower.equals("config") || chainLower.equals("configuration") || chainLower.equals("adapter")) {
smLower.equals("enterprise") || smLower.equals("app") || smLower.equals("global") || smLower.equals("core") || smLower.equals("project") || smLower.equals("main") || smLower.equals("base") || smLower.equals("common") || smLower.equals("shared") ||
chainLower.equals("state") || chainLower.equals("statemachine") || chainLower.equals("config") || chainLower.equals("configuration") || chainLower.equals("adapter") ||
chainLower.equals("enterprise") || chainLower.equals("app") || chainLower.equals("global") || chainLower.equals("core") || chainLower.equals("project") || chainLower.equals("main") || chainLower.equals("base") || chainLower.equals("common") || chainLower.equals("shared")) {
return false;
}
@@ -178,7 +180,33 @@ public class HeuristicBeanResolutionEngine implements BeanResolutionEngine {
}
}
if (matchIdx >= 1) {
return true; // Diverges under a shared root
// If they diverge under a shared root, check if the divergence is only on generic package layers
boolean onlyGenericDivergence = true;
Set<String> genericLayers = Set.of(
"config", "configuration", "service", "services", "impl", "api", "web",
"controller", "controllers", "messaging", "listener", "listeners",
"repository", "repositories", "db", "model", "models", "domain",
"constants", "utils", "helper", "helpers", "event", "events",
"state", "states", "transition", "transitions"
);
for (int i = matchIdx + 1; i < p1.length; i++) {
if (!genericLayers.contains(p1[i].toLowerCase())) {
onlyGenericDivergence = false;
break;
}
}
if (onlyGenericDivergence) {
for (int i = matchIdx + 1; i < p2.length; i++) {
if (!genericLayers.contains(p2[i].toLowerCase())) {
onlyGenericDivergence = false;
break;
}
}
}
if (!onlyGenericDivergence) {
return true; // Mismatch under a shared root
}
}
}
@@ -325,4 +353,12 @@ public class HeuristicBeanResolutionEngine implements BeanResolutionEngine {
if (type2.equals("java.lang.String") || type2.equals("String") || type2.equals("java.lang.Object") || type2.equals("Object")) return false;
return !type1.equals(type2);
}
private boolean isSingleStateMachine(CodebaseContext context) {
if (context == null) return false;
int count = 0;
count += context.findEntryPointClasses(java.util.List.of("EnableStateMachineFactory", "EnableStateMachine")).size();
count += context.findBeanMethodsReturning(java.util.Set.of("StateMachine", "StateMachineFactory", "StateMachineModelFactory")).size();
return count <= 1;
}
}

View File

@@ -822,7 +822,7 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
String varName = receiverName;
Expression initExpr = findVariableInitializer(entryMethod, varName);
if (initExpr instanceof MethodInvocation initMi) {
initExpr = unwrapMethodInvocation(initMi, 0);
initExpr = unwrapMethodInvocation(initMi, 0, entryMethod);
}
if (!(initExpr instanceof ClassInstanceCreation cic)) {
return null;
@@ -922,7 +922,40 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
return new String[] { paramName, currentSuffix };
}
private int getReturnedParameterIndex(MethodDeclaration md) {
if (md.getBody() == null) return -1;
List<?> parameters = md.parameters();
if (parameters.isEmpty()) return -1;
final List<String> returnedExprs = new ArrayList<>();
md.getBody().accept(new ASTVisitor() {
@Override
public boolean visit(ReturnStatement node) {
if (node.getExpression() != null) {
returnedExprs.add(node.getExpression().toString());
}
return super.visit(node);
}
});
if (returnedExprs.size() == 1) {
String retStr = returnedExprs.get(0);
for (int i = 0; i < parameters.size(); i++) {
if (parameters.get(i) instanceof SingleVariableDeclaration svd) {
if (svd.getName().getIdentifier().equals(retStr)) {
return i;
}
}
}
}
return -1;
}
protected Expression unwrapMethodInvocation(MethodInvocation mi, int depth) {
return unwrapMethodInvocation(mi, depth, null);
}
protected Expression unwrapMethodInvocation(MethodInvocation mi, int depth, String methodFqn) {
if (depth > 5) return mi;
if (mi.getExpression() != null) {
String exprStr = mi.getExpression().toString();
@@ -930,6 +963,23 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
return mi;
}
} else {
if (methodFqn != null && methodFqn.contains(".")) {
String className = methodFqn.substring(0, methodFqn.lastIndexOf('.'));
TypeDeclaration td = context.getTypeDeclaration(className);
if (td != null) {
MethodDeclaration localMd = context.findMethodDeclaration(td, mi.getName().getIdentifier(), true);
if (localMd != null) {
int paramIdx = getReturnedParameterIndex(localMd);
if (paramIdx >= 0 && paramIdx < mi.arguments().size()) {
Expression arg = (Expression) mi.arguments().get(paramIdx);
if (arg instanceof MethodInvocation innerMi) {
return unwrapMethodInvocation(innerMi, depth + 1, methodFqn);
}
return arg;
}
}
}
}
return mi;
}
@@ -951,7 +1001,7 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
Expression arg = (Expression) mi.arguments().get(0);
if (arg instanceof MethodInvocation innerMi) {
return unwrapMethodInvocation(innerMi, depth + 1);
return unwrapMethodInvocation(innerMi, depth + 1, methodFqn);
}
return arg;
}

View File

@@ -282,10 +282,11 @@ public class HeuristicCallGraphEngine extends AbstractCallGraphEngine {
}
}
// 2. Check fields in enclosing class
// 2. Check fields in enclosing class and its superclasses
TypeDeclaration enclosingType = findEnclosingType(receiverNameNode);
if (enclosingType != null) {
for (FieldDeclaration field : enclosingType.getFields()) {
TypeDeclaration currentType = enclosingType;
while (currentType != null) {
for (FieldDeclaration field : currentType.getFields()) {
for (Object fragObj : field.fragments()) {
VariableDeclarationFragment frag = (VariableDeclarationFragment) fragObj;
if (frag.getName().getIdentifier().equals(varName)) {
@@ -293,6 +294,8 @@ public class HeuristicCallGraphEngine extends AbstractCallGraphEngine {
}
}
}
String superclass = context.getSuperclassFqn(currentType);
currentType = superclass != null ? context.getTypeDeclaration(superclass) : null;
}
return null;
@@ -604,6 +607,9 @@ public class HeuristicCallGraphEngine extends AbstractCallGraphEngine {
}
if (receiverType != null) {
if (receiverType.contains("<")) {
receiverType = receiverType.substring(0, receiverType.indexOf('<'));
}
String methodName = mi.getName().getIdentifier();
TypeDeclaration td = context.getTypeDeclaration(receiverType);
if (td == null && receiverType.contains(".")) {

View File

@@ -288,10 +288,11 @@ public class JdtCallGraphEngine extends AbstractCallGraphEngine {
}
}
// 2. Check fields in enclosing class
// 2. Check fields in enclosing class and its superclasses
TypeDeclaration enclosingType = findEnclosingType(receiverNameNode);
if (enclosingType != null) {
for (FieldDeclaration field : enclosingType.getFields()) {
TypeDeclaration currentType = enclosingType;
while (currentType != null) {
for (FieldDeclaration field : currentType.getFields()) {
for (Object fragObj : field.fragments()) {
VariableDeclarationFragment frag = (VariableDeclarationFragment) fragObj;
if (frag.getName().getIdentifier().equals(varName)) {
@@ -299,6 +300,8 @@ public class JdtCallGraphEngine extends AbstractCallGraphEngine {
}
}
}
String superclass = context.getSuperclassFqn(currentType);
currentType = superclass != null ? context.getTypeDeclaration(superclass) : null;
}
return null;
@@ -376,6 +379,9 @@ public class JdtCallGraphEngine extends AbstractCallGraphEngine {
}
if (receiverType != null) {
if (receiverType.contains("<")) {
receiverType = receiverType.substring(0, receiverType.indexOf('<'));
}
String methodName = mi.getName().getIdentifier();
TypeDeclaration td = context.getTypeDeclaration(receiverType);
if (td == null && receiverType.contains(".")) {