@@ -7,6 +7,7 @@ package kotlinx.coroutines
7
7
import java.lang.reflect.*
8
8
import java.util.*
9
9
import java.util.Collections.*
10
+ import kotlin.collections.ArrayList
10
11
11
12
object FieldWalker {
12
13
@@ -22,12 +23,6 @@ object FieldWalker {
22
23
val element = stack.removeLast()
23
24
val type = element.javaClass
24
25
type.visit(element, result, stack)
25
-
26
- var superclass = type.superclass
27
- while (superclass != Any ::class .java && superclass != null ) {
28
- superclass.visit(element, result, stack)
29
- superclass = superclass.superclass
30
- }
31
26
}
32
27
return result
33
28
}
@@ -56,9 +51,65 @@ object FieldWalker {
56
51
}
57
52
}
58
53
59
- private fun Class <* >.fields () = declaredFields.filter {
60
- ! it.type.isPrimitive
61
- && ! Modifier .isStatic(it.modifiers)
62
- && ! (it.type.isArray && it.type.componentType.isPrimitive)
54
+ private fun Class <* >.fields (): List <Field > {
55
+ val result = ArrayList <Field >()
56
+ var type = this
57
+ while (type != Any ::class .java) {
58
+ val fields = type.declaredFields.filter {
59
+ ! it.type.isPrimitive
60
+ && ! Modifier .isStatic(it.modifiers)
61
+ && ! (it.type.isArray && it.type.componentType.isPrimitive)
62
+ }
63
+ result.addAll(fields)
64
+ type = type.superclass
65
+ }
66
+
67
+ return result
68
+ }
69
+
70
+ // Debugging-only
71
+ @Suppress(" UNUSED" )
72
+ fun printPath (from : Any , to : Any ) {
73
+ val pathNodes = ArrayList <String >()
74
+ val visited = newSetFromMap<Any >(IdentityHashMap ())
75
+ visited.add(from)
76
+ if (findPath(from, to, visited, pathNodes)) {
77
+ pathNodes.reverse()
78
+ println (pathNodes.joinToString(" -> " , from.javaClass.simpleName + " -> " , " -> " + to.javaClass.simpleName))
79
+ } else {
80
+ println (" Path from $from to $to not found" )
81
+ }
82
+ }
83
+
84
+ private fun findPath (from : Any , to : Any , visited : MutableSet <Any >, pathNodes : MutableList <String >): Boolean {
85
+ if (from == = to) {
86
+ return true
87
+ }
88
+
89
+ val type = from.javaClass
90
+ if (type.isArray) {
91
+ if (type.componentType.isPrimitive) return false
92
+ val array = from as Array <Any ?>
93
+ array.filterNotNull().forEach {
94
+ if (findPath(it, to, visited, pathNodes)) {
95
+ return true
96
+ }
97
+ }
98
+ return false
99
+ }
100
+
101
+ val fields = type.fields()
102
+ fields.forEach {
103
+ it.isAccessible = true
104
+ val value = it.get(from) ? : return @forEach
105
+ if (! visited.add(value)) return @forEach
106
+ val found = findPath(value, to, visited, pathNodes)
107
+ if (found) {
108
+ pathNodes + = from.javaClass.simpleName + " :" + it.name
109
+ return true
110
+ }
111
+ }
112
+
113
+ return false
63
114
}
64
115
}
0 commit comments