From 6eb33bae24694c4970e8e368883a455ecd55f389 Mon Sep 17 00:00:00 2001 From: Tom Prince Date: Thu, 23 Jan 2025 17:40:50 -0700 Subject: [PATCH] Allow implementing methods from superclasses of directly implemented interfaces. --- .../dev/latvian/mods/rhino/JavaAdapter.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/latvian/mods/rhino/JavaAdapter.java b/src/main/java/dev/latvian/mods/rhino/JavaAdapter.java index 50bd0d4..7517ea0 100644 --- a/src/main/java/dev/latvian/mods/rhino/JavaAdapter.java +++ b/src/main/java/dev/latvian/mods/rhino/JavaAdapter.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.ArrayDeque; import java.util.Map; public final class JavaAdapter implements IdFunctionCall { @@ -359,16 +360,29 @@ public static byte[] createAdapterCode(ObjToIntMap functionNames, String adapter static Method[] getOverridableMethods(Class clazz) { ArrayList list = new ArrayList<>(); HashSet skip = new HashSet<>(); + ArrayDeque> interfaces = new ArrayDeque<>(); + HashSet> visitedInterfaces = new HashSet<>(); // Check superclasses before interfaces so we always choose // implemented methods over abstract ones, even if a subclass // re-implements an interface already implemented in a superclass // (e.g. java.util.ArrayList) for (Class c = clazz; c != null; c = c.getSuperclass()) { appendOverridableMethods(c, list, skip); - } - for (Class c = clazz; c != null; c = c.getSuperclass()) { for (Class intf : c.getInterfaces()) { - appendOverridableMethods(intf, list, skip); + interfaces.add(intf); + } + } + // Visit interfaces in depth first order. + while (!interfaces.isEmpty()) { + var intf = interfaces.remove(); + if (visitedInterfaces.contains(intf)) { + continue; + } + visitedInterfaces.add(intf); + appendOverridableMethods(intf, list, skip); + var subIntf = intf.getInterfaces(); + for (int j = subIntf.length -1; j >= 0; j--) { + interfaces.addFirst(subIntf[j]); } } return list.toArray(new Method[0]);