@@ -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,64 @@ 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
+ fun printPath (from : Any , to : Any ) {
72
+ val pathNodes = ArrayList <String >()
73
+ val visited = newSetFromMap<Any >(IdentityHashMap ())
74
+ visited.add(from)
75
+ if (findPath(from, to, visited, pathNodes)) {
76
+ pathNodes.reverse()
77
+ println (pathNodes.joinToString(" -> " , from.javaClass.simpleName + " -> " , " -> " + to.javaClass.simpleName))
78
+ } else {
79
+ println (" Path from $from to $to not found" )
80
+ }
81
+ }
82
+
83
+ private fun findPath (from : Any , to : Any , visited : MutableSet <Any >, pathNodes : MutableList <String >): Boolean {
84
+ if (from == = to) {
85
+ return true
86
+ }
87
+
88
+ val type = from.javaClass
89
+ if (type.isArray) {
90
+ if (type.componentType.isPrimitive) return false
91
+ val array = from as Array <Any ?>
92
+ array.filterNotNull().forEach {
93
+ if (findPath(it, to, visited, pathNodes)) {
94
+ return true
95
+ }
96
+ }
97
+ return false
98
+ }
99
+
100
+ val fields = type.fields()
101
+ fields.forEach {
102
+ it.isAccessible = true
103
+ val value = it.get(from) ? : return @forEach
104
+ if (! visited.add(value)) return @forEach
105
+ val found = findPath(value, to, visited, pathNodes)
106
+ if (found) {
107
+ pathNodes + = from.javaClass.simpleName + " :" + it.name
108
+ return true
109
+ }
110
+ }
111
+
112
+ return false
63
113
}
64
114
}
0 commit comments