From 0a2a5896ece71f9d37930274c86b09a5fdf38644 Mon Sep 17 00:00:00 2001 From: Paweł Marks Date: Wed, 5 Aug 2020 15:38:00 +0200 Subject: Add tests checking omitting of obvious types --- .../kotlin/signatures/ObviousTypeSkippingTest.kt | 195 +++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 plugins/base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt (limited to 'plugins/base/src/test/kotlin') 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 > underTest(arg: T) {}", "fun > underTest(arg: T)"), + forFunction("fun > underTest(arg: T) {}", "fun > underTest(arg: T)"), + forFunction("fun underTest(arg: T) {}", "fun underTest(arg: T)"), + forFunction("fun underTest(arg: T) {}", "fun underTest(arg: T)"), + forFunction("fun underTest(arg: T) {}", "fun 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.underTest() {}", "fun > T.underTest()"), + forFunction("fun > T.underTest() {}", "fun > T.underTest()"), + forFunction("fun ?> T.underTest() {}", "fun ?> T.underTest()"), + forFunction("fun T.underTest() {}", "fun T.underTest()"), + forFunction("fun T.underTest() {}", "fun T.underTest()"), + forFunction("fun T.underTest() {}", "fun T.underTest()"), + forClass("class Testable", "class Testable"), + forClass("class Testable", "class Testable"), + forClass("class Testable(t: T)", "class Testable(t: T)"), + forClass("class Testable", "class Testable"), + 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 { it.name == place.name }.content + .firstMemberOfType { it.dci.kind == ContentKind.Symbol } + .assertNode { hasExactText(expectedSignature) } + is OnParentPage -> + root.firstMemberOfType { + place.pageType.isInstance(it) && (place.parentName.isNullOrBlank() || place.parentName == it.name) + } + .content + .firstMemberOfType { + it.dci.kind == place.section && (place.selfName.isNullOrBlank() || + it.dci.dri.toString().contains(place.selfName)) + } + .firstMemberOfType { 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, + val section: Kind, + val parentName: String? = null, + val selfName: String? = null +) : Place() + +data class TestData( + val codeFragment: String, + val expectedSignature: String, + val placesToTest: Iterable +) { + 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 -- cgit