aboutsummaryrefslogtreecommitdiff
path: root/core/content-matcher-test-utils/src/main/kotlin
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-11-10 11:46:54 +0100
committerGitHub <noreply@github.com>2023-11-10 11:46:54 +0100
commit8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch)
tree1b915207b2b9f61951ddbf0ff2e687efd053d555 /core/content-matcher-test-utils/src/main/kotlin
parenta44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff)
downloaddokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.gz
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.bz2
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.zip
Restructure the project to utilize included builds (#3174)
* Refactor and simplify artifact publishing * Update Gradle to 8.4 * Refactor and simplify convention plugins and build scripts Fixes #3132 --------- Co-authored-by: Adam <897017+aSemy@users.noreply.github.com> Co-authored-by: Oleg Yukhnevich <whyoleg@gmail.com>
Diffstat (limited to 'core/content-matcher-test-utils/src/main/kotlin')
-rw-r--r--core/content-matcher-test-utils/src/main/kotlin/matchers/content/ContentMatchersDsl.kt191
-rw-r--r--core/content-matcher-test-utils/src/main/kotlin/matchers/content/contentMatchers.kt191
2 files changed, 0 insertions, 382 deletions
diff --git a/core/content-matcher-test-utils/src/main/kotlin/matchers/content/ContentMatchersDsl.kt b/core/content-matcher-test-utils/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
deleted file mode 100644
index 026f7b6b..00000000
--- a/core/content-matcher-test-utils/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package matchers.content
-
-import org.jetbrains.dokka.model.withDescendants
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.test.tools.matchers.content.*
-import kotlin.reflect.KClass
-import kotlin.test.assertEquals
-import kotlin.test.asserter
-
-// entry point:
-public fun ContentNode.assertNode(block: ContentMatcherBuilder<ContentComposite>.() -> Unit) {
- val matcher = ContentMatcherBuilder(ContentComposite::class).apply(block).build()
- try {
- matcher.tryMatch(this)
- } catch (e: MatcherError) {
- throw AssertionError(e.message + "\n" + matcher.toDebugString(e.anchor, e.anchorAfter))
- }
-}
-
-
-// DSL:
-@DslMarker
-public annotation class ContentMatchersDsl
-
-@ContentMatchersDsl
-public class ContentMatcherBuilder<T : ContentComposite> @PublishedApi internal constructor(private val kclass: KClass<T>) {
- @PublishedApi
- internal val children: MutableList<MatcherElement> = mutableListOf()
- internal val assertions = mutableListOf<T.() -> Unit>()
-
- public fun build(): CompositeMatcher<T> = CompositeMatcher(kclass, childrenOrSkip()) { assertions.forEach { it() } }
-
- // part of DSL that cannot be defined as an extension
- public operator fun String.unaryPlus() {
- children += TextMatcher(this)
- }
-
- private fun childrenOrSkip() = if (children.isEmpty() && assertions.isNotEmpty()) listOf(Anything) else children
-}
-
-public fun <T : ContentComposite> ContentMatcherBuilder<T>.check(assertion: T.() -> Unit) {
- assertions += assertion
-}
-
-private val ContentComposite.extractedText
- get() = withDescendants().filterIsInstance<ContentText>().joinToString(separator = "") { it.text }
-
-public fun <T : ContentComposite> ContentMatcherBuilder<T>.hasExactText(expected: String) {
- assertions += {
- assertEquals(expected, this.extractedText)
- }
-}
-
-public inline fun <reified S : ContentComposite> ContentMatcherBuilder<*>.composite(
- block: ContentMatcherBuilder<S>.() -> Unit
-) {
- children += ContentMatcherBuilder(S::class).apply(block).build()
-}
-
-public inline fun <reified S : ContentNode> ContentMatcherBuilder<*>.node(noinline assertions: S.() -> Unit = {}) {
- children += NodeMatcher(S::class, assertions)
-}
-
-public fun ContentMatcherBuilder<*>.skipAllNotMatching() {
- children += Anything
-}
-
-
-// Convenience functions:
-public fun ContentMatcherBuilder<*>.group(block: ContentMatcherBuilder<ContentGroup>.() -> Unit) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<*>.tabbedGroup(
- block: ContentMatcherBuilder<ContentGroup>.() -> Unit
-) {
- composite<ContentGroup> {
- block()
- check { assertContains(this.style, ContentStyle.TabbedContent) }
- }
-}
-
-public fun ContentMatcherBuilder<*>.tab(
- tabbedContentType: TabbedContentType, block: ContentMatcherBuilder<ContentGroup>.() -> Unit
-) {
- composite<ContentGroup> {
- block()
- check {
- assertEquals(tabbedContentType, this.extra[TabbedContentTypeExtra]?.value)
- }
- }
-}
-
-public fun ContentMatcherBuilder<*>.header(expectedLevel: Int? = null, block: ContentMatcherBuilder<ContentHeader>.() -> Unit) {
- composite<ContentHeader> {
- block()
- check { if (expectedLevel != null) assertEquals(expectedLevel, this.level) }
- }
-}
-
-public fun ContentMatcherBuilder<*>.p(block: ContentMatcherBuilder<ContentGroup>.() -> Unit) {
- composite<ContentGroup> {
- block()
- check { assertContains(this.style, TextStyle.Paragraph) }
- }
-}
-
-public fun ContentMatcherBuilder<*>.link(block: ContentMatcherBuilder<ContentLink>.() -> Unit) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<*>.table(block: ContentMatcherBuilder<ContentTable>.() -> Unit) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<*>.platformHinted(block: ContentMatcherBuilder<ContentGroup>.() -> Unit) {
- composite<PlatformHintedContent> { group(block) }
-}
-
-public fun ContentMatcherBuilder<*>.list(block: ContentMatcherBuilder<ContentList>.() -> Unit) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<*>.codeBlock(block: ContentMatcherBuilder<ContentCodeBlock>.() -> Unit) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<*>.codeInline(block: ContentMatcherBuilder<ContentCodeInline>.() -> Unit) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<*>.caption(block: ContentMatcherBuilder<ContentGroup>.() -> Unit) {
- composite<ContentGroup> {
- block()
- check { assertContains(this.style, ContentStyle.Caption) }
- }
-}
-
-public fun ContentMatcherBuilder<*>.br() {
- node<ContentBreakLine>()
-}
-
-public fun ContentMatcherBuilder<*>.somewhere(block: ContentMatcherBuilder<*>.() -> Unit) {
- skipAllNotMatching()
- block()
- skipAllNotMatching()
-}
-
-public fun ContentMatcherBuilder<*>.divergentGroup(
- block: ContentMatcherBuilder<ContentDivergentGroup>.() -> Unit
-) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<ContentDivergentGroup>.divergentInstance(
- block: ContentMatcherBuilder<ContentDivergentInstance>.() -> Unit
-) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<ContentDivergentInstance>.before(
- block: ContentMatcherBuilder<ContentComposite>.() -> Unit
-) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<ContentDivergentInstance>.divergent(
- block: ContentMatcherBuilder<ContentComposite>.() -> Unit
-) {
- composite(block)
-}
-
-public fun ContentMatcherBuilder<ContentDivergentInstance>.after(
- block: ContentMatcherBuilder<ContentComposite>.() -> Unit
-) {
- composite(block)
-}
-
-/*
- * TODO replace with kotlin.test.assertContains after migrating to Kotlin language version 1.5+
- */
-private fun <T> assertContains(iterable: Iterable<T>, element: T) {
- asserter.assertTrue(
- { "Expected the collection to contain the element.\nCollection <$iterable>, element <$element>." },
- iterable.contains(element)
- )
-}
diff --git a/core/content-matcher-test-utils/src/main/kotlin/matchers/content/contentMatchers.kt b/core/content-matcher-test-utils/src/main/kotlin/matchers/content/contentMatchers.kt
deleted file mode 100644
index 412f728b..00000000
--- a/core/content-matcher-test-utils/src/main/kotlin/matchers/content/contentMatchers.kt
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("PackageDirectoryMismatch")
-
-package org.jetbrains.dokka.test.tools.matchers.content
-
-import org.jetbrains.dokka.model.asPrintableTree
-import org.jetbrains.dokka.pages.ContentComposite
-import org.jetbrains.dokka.pages.ContentNode
-import org.jetbrains.dokka.pages.ContentText
-import kotlin.reflect.KClass
-import kotlin.reflect.full.cast
-import kotlin.reflect.full.safeCast
-
-public sealed class MatcherElement
-
-public class TextMatcher(
- public val text: String
-) : MatcherElement()
-
-public open class NodeMatcher<T : ContentNode>(
- public val kclass: KClass<T>,
- public val assertions: T.() -> Unit = {}
-) : MatcherElement() {
-
- public open fun tryMatch(node: ContentNode) {
- kclass.safeCast(node)?.apply {
- try {
- assertions()
- } catch (e: AssertionError) {
- throw MatcherError(
- "${e.message.orEmpty()}\nin node:\n${node.debugRepresentation()}",
- this@NodeMatcher,
- cause = e
- )
- }
- } ?: throw MatcherError("Expected ${kclass.simpleName} but got:\n${node.debugRepresentation()}", this)
- }
-}
-
-public class CompositeMatcher<T : ContentComposite>(
- kclass: KClass<T>,
- private val children: List<MatcherElement>,
- assertions: T.() -> Unit = {}
-) : NodeMatcher<T>(kclass, assertions) {
-
- internal val normalizedChildren: List<MatcherElement> by lazy {
- children.fold(listOf()) { acc, e ->
- when {
- acc.lastOrNull() is Anything && e is Anything -> acc
- acc.lastOrNull() is TextMatcher && e is TextMatcher ->
- acc.dropLast(1) + TextMatcher((acc.lastOrNull() as TextMatcher).text + e.text)
- else -> acc + e
- }
- }
- }
-
- override fun tryMatch(node: ContentNode) {
- super.tryMatch(node)
- kclass.cast(node).children.asSequence()
- .filter { it !is ContentText || it.text.isNotBlank() }
- .fold(FurtherSiblings(normalizedChildren, this).pop()) { acc, n -> acc.next(n) }.finish()
- }
-}
-
-public object Anything : MatcherElement()
-
-private sealed class MatchWalkerState {
- abstract fun next(node: ContentNode): MatchWalkerState
- abstract fun finish()
-}
-
-private class TextMatcherState(
- val text: String,
- val rest: FurtherSiblings,
- val anchor: TextMatcher
-) : MatchWalkerState() {
- override fun next(node: ContentNode): MatchWalkerState {
- node as? ContentText ?: throw MatcherError("Expected text: \"$text\" but got\n${node.debugRepresentation()}", anchor)
- return when {
- text == node.text -> rest.pop()
- text.startsWith(node.text) -> TextMatcherState(text.removePrefix(node.text), rest, anchor)
- else -> throw MatcherError("Expected text: \"$text\", but got: \"${node.text}\"", anchor)
- }
- }
-
- override fun finish() = throw MatcherError("\"$text\" was not found" + rest.messageEnd, anchor)
-}
-
-private class EmptyMatcherState(val parent: CompositeMatcher<*>) : MatchWalkerState() {
- override fun next(node: ContentNode): MatchWalkerState {
- throw MatcherError("Unexpected node:\n${node.debugRepresentation()}", parent, anchorAfter = true)
- }
-
- override fun finish() = Unit
-}
-
-private class NodeMatcherState(
- val matcher: NodeMatcher<*>,
- val rest: FurtherSiblings
-) : MatchWalkerState() {
- override fun next(node: ContentNode): MatchWalkerState {
- matcher.tryMatch(node)
- return rest.pop()
- }
-
- override fun finish() =
- throw MatcherError("Content of type ${matcher.kclass} was not found" + rest.messageEnd, matcher)
-}
-
-private class SkippingMatcherState(
- val innerState: MatchWalkerState
-) : MatchWalkerState() {
- override fun next(node: ContentNode): MatchWalkerState = runCatching { innerState.next(node) }.getOrElse { this }
-
- override fun finish() = innerState.finish()
-}
-
-private class FurtherSiblings(val list: List<MatcherElement>, val parent: CompositeMatcher<*>) {
- fun pop(): MatchWalkerState = when (val head = list.firstOrNull()) {
- is TextMatcher -> TextMatcherState(head.text, drop(), head)
- is NodeMatcher<*> -> NodeMatcherState(head, drop())
- is Anything -> SkippingMatcherState(drop().pop())
- null -> EmptyMatcherState(parent)
- }
-
- fun drop() = FurtherSiblings(list.drop(1), parent)
-
- val messageEnd: String
- get() = list.count { it !is Anything }.takeIf { it > 0 }
- ?.let { " and $it further matchers were not satisfied" } ?: ""
-}
-
-
-internal fun MatcherElement.toDebugString(anchor: MatcherElement?, anchorAfter: Boolean): String {
- fun Appendable.append(element: MatcherElement, ownPrefix: String, childPrefix: String) {
- if (anchor != null) {
- if (element != anchor || anchorAfter) append(" ".repeat(4))
- else append("--> ")
- }
-
- append(ownPrefix)
- when (element) {
- is Anything -> append("skipAllNotMatching\n")
- is TextMatcher -> append("\"${element.text}\"\n")
- is CompositeMatcher<*> -> {
- append("${element.kclass.simpleName.toString()}\n")
- if (element.normalizedChildren.isNotEmpty()) {
- val newOwnPrefix = "$childPrefix├─ "
- val lastOwnPrefix = "$childPrefix└─ "
- val newChildPrefix = "$childPrefix│ "
- val lastChildPrefix = "$childPrefix "
- element.normalizedChildren.forEachIndexed { n, e ->
- if (n != element.normalizedChildren.lastIndex) append(e, newOwnPrefix, newChildPrefix)
- else append(e, lastOwnPrefix, lastChildPrefix)
- }
- }
- if (element == anchor && anchorAfter) {
- append("--> $childPrefix\n")
- }
- }
- is NodeMatcher<*> -> append("${element.kclass.simpleName}\n")
- }
- }
-
- return buildString { append(this@toDebugString, "", "") }
-}
-
-private fun ContentNode.debugRepresentation() = asPrintableTree { element ->
- append(if (element is ContentText) """"${element.text}"""" else element::class.simpleName)
- append(
- " { " +
- "kind=${element.dci.kind}, " +
- "dri=${element.dci.dri}, " +
- "style=${element.style}, " +
- "sourceSets=${element.sourceSets} " +
- "}"
- )
-}
-
-public data class MatcherError(
- override val message: String,
- val anchor: MatcherElement,
- val anchorAfter: Boolean = false,
- override val cause: Throwable? = null
-) : AssertionError(message, cause)
-
-// Creating this whole mechanism was most scala-like experience I had since I stopped using scala.
-// I don't know how I should feel about it.