From 711717a7a2f6b22050b1418173d7097b5f6bcd8d Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 29 Oct 2018 17:50:41 +0300 Subject: Implement node selection dsl for test usage --- core/src/test/kotlin/NodeSelect.kt | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 core/src/test/kotlin/NodeSelect.kt (limited to 'core/src') diff --git a/core/src/test/kotlin/NodeSelect.kt b/core/src/test/kotlin/NodeSelect.kt new file mode 100644 index 00000000..fe0394f9 --- /dev/null +++ b/core/src/test/kotlin/NodeSelect.kt @@ -0,0 +1,90 @@ +package org.jetbrains.dokka.tests + +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.NodeKind +import org.jetbrains.dokka.RefKind + +class SelectBuilder { + private val root = ChainFilterNode(SubgraphTraverseFilter(), null) + private var activeNode = root + private val chainEnds = mutableListOf() + + fun withName(name: String) = matching { it.name == name } + + fun withKind(kind: NodeKind) = matching{ it.kind == kind } + + fun matching(block: (DocumentationNode) -> Boolean) { + attachFilterAndMakeActive(PredicateFilter(block)) + } + + fun subgraph() { + attachFilterAndMakeActive(SubgraphTraverseFilter()) + } + + fun subgraphOf(kind: RefKind) { + attachFilterAndMakeActive(DirectEdgeFilter(kind)) + } + + private fun attachFilterAndMakeActive(next: SelectFilter) { + activeNode = ChainFilterNode(next, activeNode) + } + + private fun endChain() { + chainEnds += activeNode + } + + fun build(): SelectFilter { + endChain() + return CombineFilterNode(chainEnds) + } +} + +private class ChainFilterNode(val filter: SelectFilter, val previous: SelectFilter?): SelectFilter() { + override fun select(roots: Sequence): Sequence { + return filter.select(previous?.select(roots) ?: roots) + } +} + +private class CombineFilterNode(val previous: List): SelectFilter() { + override fun select(roots: Sequence): Sequence { + return previous.asSequence().flatMap { it.select(roots) } + } +} + +abstract class SelectFilter { + abstract fun select(roots: Sequence): Sequence +} + +private class SubgraphTraverseFilter: SelectFilter() { + override fun select(roots: Sequence): Sequence { + val visited = mutableSetOf() + return roots.flatMap { + generateSequence(listOf(it)) { nodes -> + nodes.flatMap { it.allReferences() } + .map { it.to } + .filter { visited.add(it) } + .takeUnless { it.isEmpty() } + } + }.flatten() + } + +} + +private class PredicateFilter(val condition: (DocumentationNode) -> Boolean): SelectFilter() { + override fun select(roots: Sequence): Sequence { + return roots.filter(condition) + } +} + +private class DirectEdgeFilter(val kind: RefKind): SelectFilter() { + override fun select(roots: Sequence): Sequence { + return roots.flatMap { it.references(kind).asSequence() }.map { it.to } + } +} + + +fun selectNodes(root: DocumentationNode, block: SelectBuilder.() -> Unit): List { + val builder = SelectBuilder() + builder.apply(block) + return builder.build().select(sequenceOf(root)).toMutableSet().toList() +} \ No newline at end of file -- cgit