This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push: new d8789c4954 ISIS-3327: fixes _ClassCache MethodKey clash handling d8789c4954 is described below commit d8789c4954ddbcacacbe46ef14cd401b18c77cef Author: Andi Huber <ahu...@apache.org> AuthorDate: Thu Jan 19 11:25:03 2023 +0100 ISIS-3327: fixes _ClassCache MethodKey clash handling --- .../commons/internal/reflection/_ClassCache.java | 37 ++++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java index 7d310367dc..7280dec668 100644 --- a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java +++ b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java @@ -243,6 +243,7 @@ public final class _ClassCache implements AutoCloseable { val declaredFields = type.getDeclaredFields(); val declaredMethods = //type.getDeclaredMethods(); ... cannot detect non overridden inherited methods Can.ofStream(_Reflect.streamAllMethods(type, true)); + val publicMethods = type.getMethods(); //XXX[ISIS-3327] order of methods returned might differ among JVM instances val model = new ClassModel( Can.ofArray(declaredFields), @@ -273,11 +274,19 @@ public final class _ClassCache implements AutoCloseable { } // process public only - for(val method : type.getMethods()) { + for(val method : publicMethods) { if(Modifier.isStatic(method.getModifiers())) continue; val key = MethodKey.of(type, method); - model.publicMethodsByKey.put(key, method); + val methodWithSameKey = model.publicMethodsByKey.get(key); + if(methodWithSameKey==null) { + model.publicMethodsByKey.put(key, method); + } else { + // key-clash originating from one method overriding the other + // we need to figure out which is the overriding one (not the overwritten one) + model.publicMethodsByKey.put(key, whichIsOverridingTheOther(methodWithSameKey, method)); + } + model.nonPublicDeclaredMethodsByKey.remove(key); } @@ -379,6 +388,28 @@ public final class _ClassCache implements AutoCloseable { return _Strings.decapitalize(fieldName); } - + /** + * If MethodKey(type, a) equals MethodKey(type, b), which one wins, that is, + * which one overrides the other? + * @implNote if both declaring type and return type are the same we don't care + */ + private Method whichIsOverridingTheOther(final Method a, final Method b) { + val aType = a.getDeclaringClass(); + val bType = b.getDeclaringClass(); + if(aType.equals(bType)) { + val aReturn = a.getReturnType(); + val bReturn = b.getReturnType(); + if(aReturn.equals(bReturn)) { + // we should not care, arbitrarily picking b + return b; + } + return aReturn.isAssignableFrom(bReturn) + ? b + : a; + } + return aType.isAssignableFrom(bType) + ? b + : a; + } }