diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/ast/common/BindingResolver.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/ast/common/BindingResolver.java index 1117dd6..b718ee0 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/ast/common/BindingResolver.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/ast/common/BindingResolver.java @@ -1,6 +1,7 @@ package click.kamil.springstatemachineexporter.ast.common; import org.eclipse.jdt.core.dom.*; +import java.util.Set; public final class BindingResolver { @@ -72,12 +73,18 @@ public final class BindingResolver { return binding.getErasure().getQualifiedName(); } - /** - * Checks if childBinding is compatible with (extends or implements) targetFqn. - */ public static boolean isSubtypeOf(ITypeBinding childBinding, String targetFqn) { + return isSubtypeOf(childBinding, targetFqn, new java.util.HashSet<>()); + } + + private static boolean isSubtypeOf(ITypeBinding childBinding, String targetFqn, Set visited) { if (childBinding == null || targetFqn == null) return false; + String key = childBinding.getKey(); + if (key != null && !visited.add(key)) { + return false; + } + // Direct match if (targetFqn.equals(childBinding.getErasure().getQualifiedName())) { return true; @@ -85,7 +92,7 @@ public final class BindingResolver { // Check interfaces for (ITypeBinding intf : childBinding.getInterfaces()) { - if (isSubtypeOf(intf, targetFqn)) { + if (isSubtypeOf(intf, targetFqn, visited)) { return true; } } @@ -93,7 +100,7 @@ public final class BindingResolver { // Check superclass ITypeBinding superclass = childBinding.getSuperclass(); if (superclass != null) { - return isSubtypeOf(superclass, targetFqn); + return isSubtypeOf(superclass, targetFqn, visited); } return false; diff --git a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/ast/common/CodebaseContext.java b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/ast/common/CodebaseContext.java index be0af46..2606842 100644 --- a/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/ast/common/CodebaseContext.java +++ b/state_machine_exporter/src/main/java/click/kamil/springstatemachineexporter/ast/common/CodebaseContext.java @@ -492,6 +492,16 @@ public class CodebaseContext { } private IMethodBinding findMethodBinding(ITypeBinding typeBinding, String methodName) { + return findMethodBinding(typeBinding, methodName, new java.util.HashSet<>()); + } + + private IMethodBinding findMethodBinding(ITypeBinding typeBinding, String methodName, Set visited) { + if (typeBinding == null) return null; + String key = typeBinding.getKey(); + if (key != null && !visited.add(key)) { + return null; + } + for (IMethodBinding mb : typeBinding.getDeclaredMethods()) { if (mb.getName().equals(methodName)) { return mb; @@ -500,12 +510,12 @@ public class CodebaseContext { ITypeBinding superclass = typeBinding.getSuperclass(); if (superclass != null) { - IMethodBinding mb = findMethodBinding(superclass, methodName); + IMethodBinding mb = findMethodBinding(superclass, methodName, visited); if (mb != null) return mb; } for (ITypeBinding intf : typeBinding.getInterfaces()) { - IMethodBinding mb = findMethodBinding(intf, methodName); + IMethodBinding mb = findMethodBinding(intf, methodName, visited); if (mb != null) return mb; }