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 <[email protected]>
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;
+ }
}