diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/routing/HeuristicBeanResolutionEngine.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/routing/HeuristicBeanResolutionEngine.java index 8b80032..3a6dfc2 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/routing/HeuristicBeanResolutionEngine.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/enricher/routing/HeuristicBeanResolutionEngine.java @@ -237,12 +237,14 @@ public class HeuristicBeanResolutionEngine implements BeanResolutionEngine { org.eclipse.jdt.core.dom.TypeDeclaration td = context.getTypeDeclaration(machineName); if (td != null) { org.eclipse.jdt.core.dom.Type superclass = td.getSuperclassType(); - return findTypeArgumentsRecursively(superclass, context, (org.eclipse.jdt.core.dom.CompilationUnit) td.getRoot()); + Set visited = new HashSet<>(); + visited.add(machineName); + return findTypeArgumentsRecursively(superclass, context, (org.eclipse.jdt.core.dom.CompilationUnit) td.getRoot(), visited); } return new String[]{null, null}; } - private String[] findTypeArgumentsRecursively(org.eclipse.jdt.core.dom.Type type, CodebaseContext context, org.eclipse.jdt.core.dom.CompilationUnit cu) { + private String[] findTypeArgumentsRecursively(org.eclipse.jdt.core.dom.Type type, CodebaseContext context, org.eclipse.jdt.core.dom.CompilationUnit cu, Set visited) { if (type == null) return new String[]{null, null}; if (type instanceof org.eclipse.jdt.core.dom.ParameterizedType pt) { @@ -258,18 +260,26 @@ public class HeuristicBeanResolutionEngine implements BeanResolutionEngine { } // Recurse into the raw type declaration's superclass - org.eclipse.jdt.core.dom.TypeDeclaration td = context.getTypeDeclaration(rawTypeName, cu); + org.eclipse.jdt.core.dom.AbstractTypeDeclaration td = context.getAbstractTypeDeclaration(rawTypeName, cu); if (td != null) { - String[] res = findTypeArgumentsRecursively(td.getSuperclassType(), context, (org.eclipse.jdt.core.dom.CompilationUnit) td.getRoot()); - if (res[0] != null || res[1] != null) return res; + String fqn = context.getFqn(td); + if (visited.add(fqn)) { + org.eclipse.jdt.core.dom.Type superclass = (td instanceof org.eclipse.jdt.core.dom.TypeDeclaration) ? ((org.eclipse.jdt.core.dom.TypeDeclaration) td).getSuperclassType() : null; + String[] res = findTypeArgumentsRecursively(superclass, context, (org.eclipse.jdt.core.dom.CompilationUnit) td.getRoot(), visited); + if (res[0] != null || res[1] != null) return res; + } } } else { // It's a simple type (e.g. MyBaseConfig) String simpleName = type.toString(); - org.eclipse.jdt.core.dom.TypeDeclaration td = context.getTypeDeclaration(simpleName, cu); + org.eclipse.jdt.core.dom.AbstractTypeDeclaration td = context.getAbstractTypeDeclaration(simpleName, cu); if (td != null) { - String[] res = findTypeArgumentsRecursively(td.getSuperclassType(), context, (org.eclipse.jdt.core.dom.CompilationUnit) td.getRoot()); - if (res[0] != null || res[1] != null) return res; + String fqn = context.getFqn(td); + if (visited.add(fqn)) { + org.eclipse.jdt.core.dom.Type superclass = (td instanceof org.eclipse.jdt.core.dom.TypeDeclaration) ? ((org.eclipse.jdt.core.dom.TypeDeclaration) td).getSuperclassType() : null; + String[] res = findTypeArgumentsRecursively(superclass, context, (org.eclipse.jdt.core.dom.CompilationUnit) td.getRoot(), visited); + if (res[0] != null || res[1] != null) return res; + } } } diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/GenericEventDetector.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/GenericEventDetector.java index 89c565b..c4bcf9e 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/GenericEventDetector.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/analysis/service/GenericEventDetector.java @@ -422,7 +422,7 @@ public class GenericEventDetector { ITypeBinding binding = receiver.resolveTypeBinding(); if (binding != null) { - ITypeBinding smBinding = findStateMachineSupertype(binding); + ITypeBinding smBinding = findStateMachineSupertype(binding, new java.util.HashSet<>()); if (smBinding != null) { ITypeBinding[] typeArgs = smBinding.getTypeArguments(); if (typeArgs.length >= 2) { @@ -446,14 +446,18 @@ public class GenericEventDetector { return new String[]{null, null}; } - private ITypeBinding findStateMachineSupertype(ITypeBinding binding) { + private ITypeBinding findStateMachineSupertype(ITypeBinding binding, java.util.Set visited) { ITypeBinding current = binding; while (current != null) { - if (current.getErasure().getQualifiedName().equals("org.springframework.statemachine.StateMachine")) { + String erasureName = current.getErasure().getQualifiedName(); + if (erasureName != null && !visited.add(erasureName)) { + return null; + } + if ("org.springframework.statemachine.StateMachine".equals(erasureName)) { return current; } for (ITypeBinding iface : current.getInterfaces()) { - ITypeBinding res = findStateMachineSupertype(iface); + ITypeBinding res = findStateMachineSupertype(iface, visited); if (res != null) return res; } current = current.getSuperclass();