blob: 59a14acc9775cccede93bee3f27b1239df076d03 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
package org.jetbrains.dokka.model
interface WithChildren<out T> {
val children: List<T>
}
inline fun <reified T> WithChildren<*>.firstChildOfTypeOrNull(): T? =
children.filterIsInstance<T>().firstOrNull()
inline fun <reified T> WithChildren<*>.firstChildOfTypeOrNull(predicate: (T) -> Boolean): T? =
children.filterIsInstance<T>().firstOrNull(predicate)
inline fun <reified T> WithChildren<*>.firstChildOfType(): T =
children.filterIsInstance<T>().first()
inline fun <reified T> WithChildren<*>.childrenOfType(): List<T> =
children.filterIsInstance<T>()
inline fun <reified T> WithChildren<*>.firstChildOfType(predicate: (T) -> Boolean): T =
children.filterIsInstance<T>().first(predicate)
inline fun <reified T> WithChildren<WithChildren<*>>.firstMemberOfType(): T where T : WithChildren<*> {
return withDescendants().filterIsInstance<T>().first()
}
inline fun <reified T> WithChildren<WithChildren<*>>.firstMemberOfType(
predicate: (T) -> Boolean
): T where T : WithChildren<*> = withDescendants().filterIsInstance<T>().first(predicate)
inline fun <reified T> WithChildren<WithChildren<*>>.firstMemberOfTypeOrNull(): T? where T : WithChildren<*> {
return withDescendants().filterIsInstance<T>().firstOrNull()
}
fun <T> T.withDescendants(): Sequence<T> where T : WithChildren<T> {
return sequence {
yield(this@withDescendants)
children.forEach { child ->
yieldAll(child.withDescendants())
}
}
}
@JvmName("withDescendantsProjection")
fun WithChildren<*>.withDescendants(): Sequence<Any?> {
return sequence {
yield(this@withDescendants)
children.forEach { child ->
if (child is WithChildren<*>) {
yieldAll(child.withDescendants())
}
}
}
}
@JvmName("withDescendantsAny")
fun WithChildren<Any>.withDescendants(): Sequence<Any> {
return sequence {
yield(this@withDescendants)
children.forEach { child ->
if (child is WithChildren<*>) {
yieldAll(child.withDescendants().filterNotNull())
}
}
}
}
fun <T> T.dfs(predicate: (T) -> Boolean): T? where T : WithChildren<T> = if (predicate(this)) {
this
} else {
children.asSequence().mapNotNull { it.dfs(predicate) }.firstOrNull()
}
fun <T : WithChildren<T>> T.asPrintableTree(
nodeNameBuilder: Appendable.(T) -> Unit = { append(it.toString()) }
): String {
fun Appendable.append(element: T, ownPrefix: String, childPrefix: String) {
append(ownPrefix)
nodeNameBuilder(element)
appendLine()
element.children.takeIf(Collection<*>::isNotEmpty)?.also { children ->
val newOwnPrefix = childPrefix + '\u251c' + '\u2500' + ' '
val lastOwnPrefix = childPrefix + '\u2514' + '\u2500' + ' '
val newChildPrefix = childPrefix + '\u2502' + ' ' + ' '
val lastChildPrefix = childPrefix + ' ' + ' ' + ' '
children.forEachIndexed { n, e ->
if (n != children.lastIndex) append(e, newOwnPrefix, newChildPrefix)
else append(e, lastOwnPrefix, lastChildPrefix)
}
}
}
return buildString { append(this@asPrintableTree, "", "") }
}
|