Method (@NotNull ClassType type, @NotNull String name, @Nullable String signature) { Processor<Method> signatureChecker = signature != null ? m -> m.signature().equals(signature) : CommonProcessors.alwaysTrue(); LinkedList<ReferenceType> types = new LinkedList<>(); // first check classes while (type != null) { for (Method candidate : type.methods()) { if (candidate.name().equals(name) && signatureChecker.process(candidate)) { return !candidate.isAbstract() ? candidate : null; } } types.add(type); type = type.superclass(); } // then interfaces Set<ReferenceType> checkedInterfaces = new HashSet<>(); ReferenceType t; while ((t = types.poll()) != null) { if (t instanceof ClassType) { types.addAll(0, ((ClassType)t).interfaces()); } else if (t instanceof InterfaceType && checkedInterfaces.add(t)) { for (Method candidate : t.methods()) { if (candidate.name().equals(name) && signatureChecker.process(candidate) && !candidate.isAbstract()) { return candidate; } } types.addAll(0, ((InterfaceType)t).superinterfaces()); } } return null; }