aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/main/kotlin/model/WithChildren.kt7
-rw-r--r--plugins/base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt195
-rw-r--r--test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt4
3 files changed, 204 insertions, 2 deletions
diff --git a/core/src/main/kotlin/model/WithChildren.kt b/core/src/main/kotlin/model/WithChildren.kt
index 4aba51c6..59a14acc 100644
--- a/core/src/main/kotlin/model/WithChildren.kt
+++ b/core/src/main/kotlin/model/WithChildren.kt
@@ -23,6 +23,11 @@ inline fun <reified T> WithChildren<WithChildren<*>>.firstMemberOfType(): T wher
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()
}
@@ -66,7 +71,7 @@ fun <T> T.dfs(predicate: (T) -> Boolean): T? where T : WithChildren<T> = if (pre
children.asSequence().mapNotNull { it.dfs(predicate) }.firstOrNull()
}
-fun <T: WithChildren<T>> T.asPrintableTree(
+fun <T : WithChildren<T>> T.asPrintableTree(
nodeNameBuilder: Appendable.(T) -> Unit = { append(it.toString()) }
): String {
fun Appendable.append(element: T, ownPrefix: String, childPrefix: String) {
diff --git a/plugins/base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt b/plugins/base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt
new file mode 100644
index 00000000..e8265667
--- /dev/null
+++ b/plugins/base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt
@@ -0,0 +1,195 @@
+package signatures
+
+import matchers.content.assertNode
+import matchers.content.hasExactText
+import org.jetbrains.dokka.model.firstMemberOfType
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.testApi.logger.FilteringLogger
+import org.jetbrains.dokka.testApi.logger.TestLogger
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.jetbrains.dokka.utilities.DokkaConsoleLogger
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.MethodSource
+import kotlin.reflect.KClass
+
+class ObviousTypeSkippingTest : AbstractCoreTest(
+ logger = TestLogger(FilteringLogger(minLevel = FilteringLogger.Level.Warn, DokkaConsoleLogger))
+) {
+
+ private fun source(signature: String) =
+ """
+ |/src/test.kt
+ |package example
+ |
+ | $signature
+ """.trimIndent()
+
+ private val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src")
+ classpath = listOfNotNull(jvmStdlibPath)
+ }
+ }
+ }
+
+ companion object TestDataSources {
+ @JvmStatic
+ fun `run tests for obvious types omitting`() = listOf(
+ forFunction("fun underTest(): Int = 5", "fun underTest(): Int"),
+ forFunction("fun underTest() = 5", "fun underTest(): Int"),
+ forFunction("fun underTest() {}", "fun underTest()"),
+ forFunction("fun underTest() = println(6)", "fun underTest()"),
+ forFunction("fun underTest(): Unit = println(6)", "fun underTest()"),
+ forFunction("fun underTest(): Unit? = if (true) println(6) else null", "fun underTest(): Unit?"),
+ forFunction("fun underTest() = if (true) println(6) else null", "fun underTest(): Unit?"),
+ forFunction("fun underTest(): Any = if (true) 7 else true", "fun underTest(): Any"),
+ forFunction("fun underTest() = if (true) 7 else true", "fun underTest(): Any"),
+ forFunction("fun underTest(): Any? = if (true) 7 else (null as String?)", "fun underTest(): Any?"),
+ forFunction("fun underTest() = if (true) 7 else (null as String?)", "fun underTest(): Any?"),
+ forFunction("fun underTest(arg: Int) {}", "fun underTest(arg: Int)"),
+ forFunction("fun underTest(arg: Unit) {}", "fun underTest(arg: Unit)"),
+ forFunction("fun <T: Iterable<Any>> underTest(arg: T) {}", "fun <T : Iterable<Any>> underTest(arg: T)"),
+ forFunction("fun <T: Iterable<Any?>> underTest(arg: T) {}", "fun <T : Iterable<Any?>> underTest(arg: T)"),
+ forFunction("fun <T> underTest(arg: T) {}", "fun <T> underTest(arg: T)"),
+ forFunction("fun <T: Any> underTest(arg: T) {}", "fun <T : Any> underTest(arg: T)"),
+ forFunction("fun <T: Any?> underTest(arg: T) {}", "fun <T> underTest(arg: T)"),
+ forProperty("val underTest: Int = 5", "val underTest: Int"),
+ forProperty("val underTest = 5", "val underTest: Int"),
+ forProperty("val underTest: Unit = println(5)", "val underTest: Unit"),
+ forProperty("val underTest = println(5)", "val underTest: Unit"),
+ forProperty("val underTest: Unit? = if (true) println(5) else null", "val underTest: Unit?"),
+ forProperty("val underTest = if (true) println(5) else null", "val underTest: Unit?"),
+ forProperty("val underTest: Any = if (true) println(5) else 5", "val underTest: Any"),
+ forProperty("val underTest = if (true) println(5) else 5", "val underTest: Any"),
+ forFunction("fun <T: Iterable<Any>> T.underTest() {}", "fun <T : Iterable<Any>> T.underTest()"),
+ forFunction("fun <T: Iterable<Any?>> T.underTest() {}", "fun <T : Iterable<Any?>> T.underTest()"),
+ forFunction("fun <T: Iterable<Any?>?> T.underTest() {}", "fun <T : Iterable<Any?>?> T.underTest()"),
+ forFunction("fun <T: Any> T.underTest() {}", "fun <T : Any> T.underTest()"),
+ forFunction("fun <T: Any?> T.underTest() {}", "fun <T> T.underTest()"),
+ forFunction("fun <T> T.underTest() {}", "fun <T> T.underTest()"),
+ forClass("class Testable<T: Any>", "class Testable<T : Any>"),
+ forClass("class Testable<T: Any?>", "class Testable<T>"),
+ forClass("class Testable<T: Any?>(t: T)", "class Testable<T>(t: T)"),
+ forClass("class Testable<T>", "class Testable<T>"),
+ forClass("class Testable(butWhy: Unit)", "class Testable(butWhy: Unit)"),
+ forMethod("class Testable { fun underTest(): Int = 5 }", "fun underTest(): Int"),
+ forMethod("class Testable { fun underTest() = 5 }", "fun underTest(): Int"),
+ forMethod("class Testable { fun underTest() {} }", "fun underTest()"),
+ forMethod("class Testable { fun underTest() = println(6) }", "fun underTest()"),
+ forMethod("class Testable { fun underTest(): Unit = println(6) }", "fun underTest()"),
+ forMethod(
+ "class Testable { fun underTest(): Unit? = if (true) println(6) else null }",
+ "fun underTest(): Unit?"
+ ),
+ forClassProperty("class Testable { val underTest: Unit = println(5) }", "val underTest: Unit"),
+ forClassProperty("class Testable { val underTest = println(5) }", "val underTest: Unit"),
+ forClassProperty(
+ "class Testable { val underTest: Unit? = if (true) println(5) else null }",
+ "val underTest: Unit?"
+ ),
+ forClassProperty(
+ "class Testable { val underTest = if (true) println(5) else null }",
+ "val underTest: Unit?"
+ ),
+ forClassProperty(
+ "class Testable { val underTest: Any = if (true) println(5) else 5 }",
+ "val underTest: Any"
+ ),
+ forClassProperty("class Testable { val underTest = if (true) println(5) else 5 }", "val underTest: Any"),
+ )
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource
+ fun `run tests for obvious types omitting`(testData: TestData) {
+ val (codeFragment, expectedSignature, placesToTest) = testData
+ testInline(
+ query = source(codeFragment),
+ configuration = configuration
+ ) {
+ pagesTransformationStage = { root ->
+ placesToTest.forEach { place ->
+ try {
+ when (place) {
+ is OnOwnPage ->
+ root.firstMemberOfType<ContentPage> { it.name == place.name }.content
+ .firstMemberOfType<ContentGroup> { it.dci.kind == ContentKind.Symbol }
+ .assertNode { hasExactText(expectedSignature) }
+ is OnParentPage ->
+ root.firstMemberOfType<ContentPage> {
+ place.pageType.isInstance(it) && (place.parentName.isNullOrBlank() || place.parentName == it.name)
+ }
+ .content
+ .firstMemberOfType<ContentGroup> {
+ it.dci.kind == place.section && (place.selfName.isNullOrBlank() ||
+ it.dci.dri.toString().contains(place.selfName))
+ }
+ .firstMemberOfType<ContentGroup> { it.dci.kind == ContentKind.Symbol }
+ .assertNode { hasExactText(expectedSignature) }
+ }
+ } catch (e: Throwable) {
+ logger.warn("$testData") // Because gradle has serious problem rendering custom test names
+ throw e
+ }
+ }
+ }
+ }
+ }
+
+}
+
+sealed class Place
+data class OnOwnPage(val name: String) : Place()
+data class OnParentPage(
+ val pageType: KClass<out ContentPage>,
+ val section: Kind,
+ val parentName: String? = null,
+ val selfName: String? = null
+) : Place()
+
+data class TestData(
+ val codeFragment: String,
+ val expectedSignature: String,
+ val placesToTest: Iterable<Place>
+) {
+ constructor(codeFragment: String, expectedSignature: String, vararg placesToTest: Place)
+ : this(codeFragment, expectedSignature, placesToTest.asIterable())
+
+ override fun toString() = "[code = \"$codeFragment\"]"
+}
+
+private fun forFunction(codeFragment: String, expectedSignature: String, functionName: String = "underTest") =
+ TestData(
+ codeFragment,
+ expectedSignature,
+ OnParentPage(PackagePageNode::class, ContentKind.Functions),
+ OnOwnPage(functionName)
+ )
+
+private fun forMethod(
+ codeFragment: String,
+ expectedSignature: String,
+ functionName: String = "underTest",
+ className: String = "Testable"
+) =
+ TestData(
+ codeFragment,
+ expectedSignature,
+ OnParentPage(ClasslikePageNode::class, ContentKind.Functions, className, functionName),
+ OnOwnPage(functionName)
+ )
+
+private fun forProperty(codeFragment: String, expectedSignature: String) =
+ TestData(codeFragment, expectedSignature, OnParentPage(PackagePageNode::class, ContentKind.Properties))
+
+private fun forClassProperty(codeFragment: String, expectedSignature: String, className: String = "Testable") =
+ TestData(codeFragment, expectedSignature, OnParentPage(ClasslikePageNode::class, ContentKind.Properties, className))
+
+private fun forClass(codeFragment: String, expectedSignature: String, className: String = "Testable") =
+ TestData(
+ codeFragment,
+ expectedSignature,
+ OnParentPage(PackagePageNode::class, ContentKind.Classlikes),
+ OnOwnPage(className)
+ ) \ No newline at end of file
diff --git a/test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt b/test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
index e1026a97..67c0e692 100644
--- a/test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
+++ b/test-tools/src/main/kotlin/matchers/content/ContentMatchersDsl.kt
@@ -30,12 +30,14 @@ class ContentMatcherBuilder<T : ContentComposite> @PublishedApi internal constru
internal val children = mutableListOf<MatcherElement>()
internal val assertions = mutableListOf<T.() -> Unit>()
- fun build() = CompositeMatcher(kclass, children) { assertions.forEach { it() } }
+ fun build() = CompositeMatcher(kclass, childrenOrSkip()) { assertions.forEach { it() } }
// part of DSL that cannot be defined as an extension
operator fun String.unaryPlus() {
children += TextMatcher(this)
}
+
+ private fun childrenOrSkip() = if (children.isEmpty() && assertions.isNotEmpty()) listOf(Anything) else children
}
fun <T : ContentComposite> ContentMatcherBuilder<T>.check(assertion: T.() -> Unit) {