diff options
author | Ignat Beresnev <ignat.beresnev@jetbrains.com> | 2023-11-10 11:46:54 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-10 11:46:54 +0100 |
commit | 8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch) | |
tree | 1b915207b2b9f61951ddbf0ff2e687efd053d555 /plugins/base/src/test/kotlin/translators | |
parent | a44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff) | |
download | dokka-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 'plugins/base/src/test/kotlin/translators')
9 files changed, 0 insertions, 3264 deletions
diff --git a/plugins/base/src/test/kotlin/translators/AccessorMethodNamingTest.kt b/plugins/base/src/test/kotlin/translators/AccessorMethodNamingTest.kt deleted file mode 100644 index ff36337a..00000000 --- a/plugins/base/src/test/kotlin/translators/AccessorMethodNamingTest.kt +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DProperty -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -/** - * https://kotlinlang.org/docs/java-to-kotlin-interop.html#properties - * https://kotlinlang.org/docs/java-interop.html#getters-and-setters - */ -class AccessorMethodNamingTest : BaseAbstractTest() { - - @Test - fun `standard property`() { - testAccessors("data class TestCase(var standardString: String, var standardBoolean: Boolean)") { - doTest("standardString", "getStandardString", "setStandardString") - doTest("standardBoolean", "getStandardBoolean", "setStandardBoolean") - } - } - - @Test - fun `properties that start with the word 'is' use the special is rules`() { - testAccessors("data class TestCase(var isFoo: String, var isBar: Boolean)") { - doTest("isFoo", "isFoo", "setFoo") - doTest("isBar", "isBar", "setBar") - } - } - - @Test - fun `properties that start with a word that starts with 'is' use get and set`() { - testAccessors("data class TestCase(var issuesFetched: Int, var issuesWereDisplayed: Boolean)") { - doTest("issuesFetched", "getIssuesFetched", "setIssuesFetched") - doTest("issuesWereDisplayed", "getIssuesWereDisplayed", "setIssuesWereDisplayed") - } - } - - @Test - fun `properties that start with the word 'is' followed by underscore use the special is rules`() { - testAccessors("data class TestCase(var is_foo: String, var is_bar: Boolean)") { - doTest("is_foo", "is_foo", "set_foo") - doTest("is_bar", "is_bar", "set_bar") - } - } - - @Test - fun `properties that start with the word 'is' followed by a number use the special is rules`() { - testAccessors("data class TestCase(var is1of: String, var is2of: Boolean)") { - doTest("is1of", "is1of", "set1of") - doTest("is2of", "is2of", "set2of") - } - } - - @Test - fun `sanity check short names`() { - testAccessors( - """ - data class TestCase( - var i: Boolean, - var `is`: Boolean, - var isz: Boolean, - var isA: Int, - var isB: Boolean, - ) - """.trimIndent() - ) { - doTest("i", "getI", "setI") - doTest("is", "getIs", "setIs") - doTest("isz", "getIsz", "setIsz") - doTest("isA", "isA", "setA") - doTest("isB", "isB", "setB") - } - } - - private fun testAccessors(code: String, block: PropertyTestCase.() -> Unit) { - val configuration = dokkaConfiguration { - suppressObviousFunctions = false - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - - testInline(""" - /src/main/kotlin/sample/TestCase.kt - package sample - - $code - """.trimIndent(), - configuration) { - documentablesMergingStage = { module -> - val properties = module.packages.single().classlikes.first().properties - PropertyTestCase(properties).apply { - block() - finish() - } - } - } - } - - private class PropertyTestCase(private val properties: List<DProperty>) { - private var testsDone: Int = 0 - - fun doTest(kotlinName: String, getter: String? = null, setter: String? = null) { - properties.first { it.name == kotlinName }.let { - assertEquals(getter, it.getter?.name) - assertEquals(setter, it.setter?.name) - } - testsDone += 1 - } - - fun finish() { - assertTrue(testsDone > 0, "No tests in TestCase") - assertEquals(testsDone, properties.size) - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/Bug1341.kt b/plugins/base/src/test/kotlin/translators/Bug1341.kt deleted file mode 100644 index 6a7bfc97..00000000 --- a/plugins/base/src/test/kotlin/translators/Bug1341.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import kotlin.test.Test -import kotlin.test.assertEquals - -class Bug1341 : BaseAbstractTest() { - @Test - fun `reproduce bug #1341`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - analysisPlatform = "jvm" - } - } - } - - testInline( - """ - /src/com/sample/OtherClass.kt - package com.sample - class OtherClass internal constructor() { - internal annotation class CustomAnnotation - } - - /src/com/sample/ClassUsingAnnotation.java - package com.sample - public class ClassUsingAnnotation { - @OtherClass.CustomAnnotation - public int doSomething() { - return 1; - } - } - """.trimIndent(), - configuration - ) { - this.documentablesMergingStage = { module -> - assertEquals(DRI("com.sample"), module.packages.single().dri) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt b/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt deleted file mode 100644 index 6812f0b4..00000000 --- a/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt +++ /dev/null @@ -1,1107 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.modifiers -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.doc.* -import utils.text -import kotlin.test.* -import utils.OnlyDescriptors - -class DefaultDescriptorToDocumentableTranslatorTest : BaseAbstractTest() { - val configuration = dokkaConfiguration { - suppressObviousFunctions = false - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - classpath = listOf(commonStdlibPath!!, jvmStdlibPath!!) - } - } - } - - @Suppress("DEPRECATION") // for includeNonPublic - val javaConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - includeNonPublic = true - } - } - } - - @Test - fun `data class kdocs over generated methods`() { - testInline( - """ - |/src/main/kotlin/sample/XD.kt - |package sample - |/** - | * But the fat Hobbit, he knows. Eyes always watching. - | */ - |data class XD(val xd: String) { - | /** - | * But the fat Hobbit, he knows. Eyes always watching. - | */ - | fun custom(): String = "" - | - | /** - | * Memory is not what the heart desires. That is only a mirror. - | */ - | override fun equals(other: Any?): Boolean = true - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals("", module.documentationOf("XD", "copy")) - assertEquals( - "Memory is not what the heart desires. That is only a mirror.", - module.documentationOf( - "XD", - "equals" - ) - ) - assertEquals("", module.documentationOf("XD", "hashCode")) - assertEquals("", module.documentationOf("XD", "toString")) - assertEquals("But the fat Hobbit, he knows. Eyes always watching.", module.documentationOf("XD", "custom")) - } - } - } - - @Test - fun `simple class kdocs`() { - testInline( - """ - |/src/main/kotlin/sample/XD.kt - |package sample - |/** - | * But the fat Hobbit, he knows. Eyes always watching. - | */ - |class XD(val xd: String) { - | /** - | * But the fat Hobbit, he knows. Eyes always watching. - | */ - | fun custom(): String = "" - | - | /** - | * Memory is not what the heart desires. That is only a mirror. - | */ - | override fun equals(other: Any?): Boolean = true - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals("But the fat Hobbit, he knows. Eyes always watching.", module.documentationOf("XD", "custom")) - assertEquals( - "Memory is not what the heart desires. That is only a mirror.", - module.documentationOf( - "XD", - "equals" - ) - ) - } - } - } - - @Test - fun `kdocs with code block`() { - testInline( - """ - |/src/main/kotlin/sample/TestForCodeInDocs.kt - |package sample - |/** - | * Utility for building a String that represents an XML document. - | * The XmlBlob object is immutable and the passed values are copied where it makes sense. - | * - | * Note the XML Declaration is not output as part of the XmlBlob - | * - | * - | * val soapAttrs = attrs("soap-env" to "http://www.w3.org/2001/12/soap-envelope", - | * "soap-env:encodingStyle" to "http://www.w3.org/2001/12/soap-encoding") - | * val soapXml = node("soap-env:Envelope", soapAttrs, - | * node("soap-env:Body", attrs("xmlns:m" to "http://example"), - | * node("m:GetExample", - | * node("m:GetExampleName", "BasePair") - | * ) - | * ) - | * ) - | * - | * - | */ - |class TestForCodeInDocs { - |} - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val description = module.descriptionOf("TestForCodeInDocs") - val expected = listOf( - P( - children = listOf(Text("Utility for building a String that represents an XML document. The XmlBlob object is immutable and the passed values are copied where it makes sense.")) - ), - P( - children = listOf(Text("Note the XML Declaration is not output as part of the XmlBlob")) - ), - CodeBlock( - children = listOf( - Text( - """val soapAttrs = attrs("soap-env" to "http://www.w3.org/2001/12/soap-envelope", - "soap-env:encodingStyle" to "http://www.w3.org/2001/12/soap-encoding") -val soapXml = node("soap-env:Envelope", soapAttrs, - node("soap-env:Body", attrs("xmlns:m" to "http://example"), - node("m:GetExample", - node("m:GetExampleName", "BasePair") - ) - ) -)""" - ) - ) - ) - ) - assertEquals(expected, description?.root?.children) - } - } - } - - private fun runTestSuitesAgainstGivenClasses(classlikes: List<DClasslike>, testSuites: List<List<TestSuite>>) { - classlikes.zip(testSuites).forEach { (classlike, testSuites) -> - testSuites.forEach { testSuite -> - when (testSuite) { - is TestSuite.PropertyDoesntExist -> assertEquals( - null, - classlike.properties.firstOrNull { it.name == testSuite.propertyName }, - "Test for class ${classlike.name} failed" - ) - is TestSuite.PropertyExists -> classlike.properties.single { it.name == testSuite.propertyName } - .run { - assertEquals( - testSuite.modifier, - modifier.values.single(), - "Test for class ${classlike.name} with property $name failed" - ) - assertEquals( - testSuite.visibility, - visibility.values.single(), - "Test for class ${classlike.name} with property $name failed" - ) - assertEquals( - testSuite.additionalModifiers, - extra[AdditionalModifiers]?.content?.values?.single() ?: emptySet<ExtraModifiers>(), - "Test for class ${classlike.name} with property $name failed" - ) - } - is TestSuite.FunctionDoesntExist -> assertEquals( - null, - classlike.functions.firstOrNull { it.name == testSuite.propertyName }, - "Test for class ${classlike.name} failed" - ) - is TestSuite.FunctionExists -> classlike.functions.single { it.name == testSuite.propertyName } - .run { - assertEquals( - testSuite.modifier, - modifier.values.single(), - "Test for class ${classlike.name} with function $name failed" - ) - assertEquals( - testSuite.visibility, - visibility.values.single(), - "Test for class ${classlike.name} with function $name failed" - ) - assertEquals( - testSuite.additionalModifiers, - extra[AdditionalModifiers]?.content?.values?.single() ?: emptySet<ExtraModifiers>(), - "Test for class ${classlike.name} with function $name failed" - ) - } - } - } - } - } - - @Test - fun `derived properties with non-public code included`() { - - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PRIVATE, - DokkaConfiguration.Visibility.PROTECTED, - DokkaConfiguration.Visibility.INTERNAL, - ) - } - } - } - - testInline( - """ - |/src/main/kotlin/sample/XD.kt - |package sample - | - |open class A { - | private val privateProperty: Int = 1 - | protected val protectedProperty: Int = 2 - | internal val internalProperty: Int = 3 - | val publicProperty: Int = 4 - | open val propertyToOverride: Int = 5 - | - | private fun privateFun(): Int = 6 - | protected fun protectedFun(): Int = 7 - | internal fun internalFun(): Int = 8 - | fun publicFun(): Int = 9 - | open fun funToOverride(): Int = 10 - |} - | - |open class B : A() { - | override val propertyToOverride: Int = 11 - | - | override fun funToOverride(): Int = 12 - |} - |class C : B() - """.trimIndent(), - configuration - ) { - - documentablesMergingStage = { module -> - val classes = module.packages.single().classlikes.sortedBy { it.name } - - val testSuites: List<List<TestSuite>> = listOf( - listOf( - TestSuite.PropertyExists( - "privateProperty", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.PropertyExists( - "protectedProperty", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.PropertyExists( - "internalProperty", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "privateFun", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.FunctionExists( - "protectedFun", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.FunctionExists( - "internalFun", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ) - ), - listOf( - TestSuite.PropertyExists( - "privateProperty", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.PropertyExists( - "protectedProperty", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.PropertyExists( - "internalProperty", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionExists( - "privateFun", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.FunctionExists( - "protectedFun", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.FunctionExists( - "internalFun", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ) - ), - listOf( - TestSuite.PropertyExists( - "privateProperty", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.PropertyExists( - "protectedProperty", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.PropertyExists( - "internalProperty", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionExists( - "privateFun", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.FunctionExists( - "protectedFun", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.FunctionExists( - "internalFun", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ) - ) - ) - - runTestSuitesAgainstGivenClasses(classes, testSuites) - } - } - } - - - @Test - fun `derived properties with only public code`() { - - @Suppress("DEPRECATION") // for includeNonPublic - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - includeNonPublic = false - } - } - } - - testInline( - """ - |/src/main/kotlin/sample/XD.kt - |package sample - | - |open class A { - | private val privateProperty: Int = 1 - | protected val protectedProperty: Int = 2 - | internal val internalProperty: Int = 3 - | val publicProperty: Int = 4 - | open val propertyToOverride: Int = 5 - | open val propertyToOverrideButCloseMeanwhile: Int = 6 - | - | private fun privateFun(): Int = 7 - | protected fun protectedFun(): Int = 8 - | internal fun internalFun(): Int = 9 - | fun publicFun(): Int = 10 - | open fun funToOverride(): Int = 11 - | open fun funToOverrideButCloseMeanwhile(): Int = 12 - |} - | - |open class B : A() { - | override val propertyToOverride: Int = 13 - | final override val propertyToOverrideButCloseMeanwhile: Int = 14 - | - | override fun funToOverride(): Int = 15 - | final override fun funToOverrideButCloseMeanwhile(): Int = 16 - |} - |class C : B() - """.trimIndent(), - configuration - ) { - - documentablesMergingStage = { module -> - val classes = module.packages.single().classlikes.sortedBy { it.name } - - val testSuites: List<List<TestSuite>> = listOf( - listOf( - TestSuite.PropertyDoesntExist("privateProperty"), - TestSuite.PropertyDoesntExist("protectedProperty"), - TestSuite.PropertyDoesntExist("internalProperty"), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverrideButCloseMeanwhile", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionDoesntExist("privateFun"), - TestSuite.FunctionDoesntExist("protectedFun"), - TestSuite.FunctionDoesntExist("internalFun"), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverrideButCloseMeanwhile", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ) - ), - listOf( - TestSuite.PropertyDoesntExist("privateProperty"), - TestSuite.PropertyDoesntExist("protectedProperty"), - TestSuite.PropertyDoesntExist("internalProperty"), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.PropertyExists( - "propertyToOverrideButCloseMeanwhile", - KotlinModifier.Final, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionDoesntExist("privateFun"), - TestSuite.FunctionDoesntExist("protectedFun"), - TestSuite.FunctionDoesntExist("internalFun"), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionExists( - "funToOverrideButCloseMeanwhile", - KotlinModifier.Final, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ) - ), - listOf( - TestSuite.PropertyDoesntExist("privateProperty"), - TestSuite.PropertyDoesntExist("protectedProperty"), - TestSuite.PropertyDoesntExist("internalProperty"), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.PropertyExists( - "propertyToOverrideButCloseMeanwhile", - KotlinModifier.Final, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionDoesntExist("privateFun"), - TestSuite.FunctionDoesntExist("protectedFun"), - TestSuite.FunctionDoesntExist("internalFun"), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionExists( - "funToOverrideButCloseMeanwhile", - KotlinModifier.Final, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ) - ) - ) - - runTestSuitesAgainstGivenClasses(classes, testSuites) - } - } - } - - @Ignore // The compiler throws away annotations on unresolved types upstream - @Test - fun `Can annotate unresolved type`() { - testInline( - """ - |/src/main/java/sample/FooLibrary.kt - |package sample; - |@MustBeDocumented - |@Target(AnnotationTarget.TYPE) - |annotation class Hello() - |fun bar(): @Hello() TypeThatDoesntResolve - """.trimMargin(), - javaConfiguration - ) { - documentablesMergingStage = { module -> - val type = module.packages.single().functions.single().type as GenericTypeConstructor - assertEquals( - Annotations.Annotation(DRI("sample", "Hello"), emptyMap()), - type.extra[Annotations]?.directAnnotations?.values?.single()?.single() - ) - } - } - } - - /** - * Kotlin Int becomes java int. Java int cannot be annotated in source, but Kotlin Int can be. - * This is paired with KotlinAsJavaPluginTest.`Java primitive annotations work`() - */ - @Test - fun `Java primitive annotations work`() { - testInline( - """ - |/src/main/java/sample/FooLibrary.kt - |package sample; - |@MustBeDocumented - |@Target(AnnotationTarget.TYPE) - |annotation class Hello() - |fun bar(): @Hello() Int - """.trimMargin(), - javaConfiguration - ) { - documentablesMergingStage = { module -> - val type = module.packages.single().functions.single().type as GenericTypeConstructor - assertEquals( - Annotations.Annotation(DRI("sample", "Hello"), emptyMap()), - type.extra[Annotations]?.directAnnotations?.values?.single()?.single() - ) - assertEquals("kotlin/Int///PointingToDeclaration/", type.dri.toString()) - } - } - } - - @Test - fun `should preserve regular functions that look like accessors, but are not accessors`() { - testInline( - """ - |/src/main/kotlin/A.kt - |package test - |class A { - | private var v: Int = 0 - | - | // not accessors because declared separately, just functions - | fun setV(new: Int) { v = new } - | fun getV(): Int = v - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } - val setterLookalike = testClass.functions.firstOrNull { it.name == "setV" } - assertNotNull(setterLookalike) { - "Expected regular function not found, wrongly categorized as setter?" - } - - val getterLookalike = testClass.functions.firstOrNull { it.name == "getV" } - assertNotNull(getterLookalike) { - "Expected regular function not found, wrongly categorized as getter?" - } - } - } - } - - @Test - fun `should correctly add IsVar extra for properties`() { - testInline( - """ - |/src/main/kotlin/A.kt - |package test - |class A { - | public var mutable: Int = 0 - | public val immutable: Int = 0 - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } - assertEquals(2, testClass.properties.size) - - val mutable = testClass.properties[0] - assertEquals("mutable", mutable.name) - assertNotNull(mutable.extra[IsVar]) - - val immutable = testClass.properties[1] - assertEquals("immutable", immutable.name) - assertNull(immutable.extra[IsVar]) - } - } - } - - @Test - fun `should correctly parse multiple see tags with static function and property links`() { - testInline( - """ - |/src/main/kotlin/com/example/package/CollectionExtensions.kt - |package com.example.util - | - |object CollectionExtensions { - | val property = "Hi" - | - | fun emptyList() {} - | fun emptyMap() {} - | fun emptySet() {} - |} - | - |/src/main/kotlin/com/example/foo.kt - |package com.example - | - |import com.example.util.CollectionExtensions.emptyMap - |import com.example.util.CollectionExtensions.emptyList - |import com.example.util.CollectionExtensions.emptySet - |import com.example.util.CollectionExtensions.property - | - |/** - | * @see [List] stdlib list - | * @see [Map] stdlib map - | * @see [emptyMap] static emptyMap - | * @see [emptyList] static emptyList - | * @see [emptySet] static emptySet - | * @see [property] static property - | */ - |fun foo() {} - """.trimIndent(), - configuration - ) { - fun assertSeeTag(tag: TagWrapper, expectedName: String, expectedDescription: String) { - assertTrue(tag is See) - assertEquals(expectedName, tag.name) - val description = tag.children.joinToString { it.text().trim() } - assertEquals(expectedDescription, description) - } - - documentablesMergingStage = { module -> - val testFunction = module.packages.find { it.name == "com.example" } - ?.functions - ?.single { it.name == "foo" } - assertNotNull(testFunction) - - val documentationTags = testFunction.documentation.values.single().children - assertEquals(7, documentationTags.size) - - val descriptionTag = documentationTags[0] - assertTrue(descriptionTag is Description, "Expected first tag to be empty description") - assertTrue(descriptionTag.children.isEmpty(), "Expected first tag to be empty description") - - assertSeeTag( - tag = documentationTags[1], - expectedName = "kotlin.collections.List", - expectedDescription = "stdlib list" - ) - assertSeeTag( - tag = documentationTags[2], - expectedName = "kotlin.collections.Map", - expectedDescription = "stdlib map" - ) - assertSeeTag( - tag = documentationTags[3], - expectedName = "com.example.util.CollectionExtensions.emptyMap", - expectedDescription = "static emptyMap" - ) - assertSeeTag( - tag = documentationTags[4], - expectedName = "com.example.util.CollectionExtensions.emptyList", - expectedDescription = "static emptyList" - ) - assertSeeTag( - tag = documentationTags[5], - expectedName = "com.example.util.CollectionExtensions.emptySet", - expectedDescription = "static emptySet" - ) - assertSeeTag( - tag = documentationTags[6], - expectedName = "com.example.util.CollectionExtensions.property", - expectedDescription = "static property" - ) - } - } - } - - @Test - fun `should have documentation for synthetic Enum values functions`() { - testInline( - """ - |/src/main/kotlin/test/KotlinEnum.kt - |package test - | - |enum class KotlinEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val kotlinEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "KotlinEnum" } - assertNotNull(kotlinEnum) - val valuesFunction = kotlinEnum.functions.single { it.name == "values" } - - val expectedValuesType = GenericTypeConstructor( - dri = DRI( - packageName = "kotlin", - classNames = "Array" - ), - projections = listOf( - Invariance( - GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "KotlinEnum" - ), - projections = emptyList() - ) - ) - ) - ) - assertEquals(expectedValuesType, valuesFunction.type) - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns an array containing the constants of this enum type, in the order " + - "they're declared." - ), - )), - P(listOf( - Text("This method may be used to iterate over the constants.") - )) - ), - name = "MARKDOWN_FILE" - ) - ) - )) - assertEquals(expectedDocumentation, valuesFunction.documentation.values.single()) - } - } - } - - @Test - fun `should have documentation for synthetic Enum entries property`() { - testInline( - """ - |/src/main/kotlin/test/KotlinEnum.kt - |package test - | - |enum class KotlinEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val kotlinEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "KotlinEnum" } - - assertNotNull(kotlinEnum) - - val entriesProperty = kotlinEnum.properties.single { it.name == "entries" } - val expectedEntriesType = GenericTypeConstructor( - dri = DRI( - packageName = "kotlin.enums", - classNames = "EnumEntries" - ), - projections = listOf( - Invariance( - GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "KotlinEnum" - ), - projections = emptyList() - ) - ) - ) - ) - assertEquals(expectedEntriesType, entriesProperty.type) - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns a representation of an immutable list of all enum entries, " + - "in the order they're declared." - ), - )), - P(listOf( - Text("This method may be used to iterate over the enum entries.") - )) - ), - name = "MARKDOWN_FILE" - ) - ) - )) - assertEquals(expectedDocumentation, entriesProperty.documentation.values.single()) - } - } - } - - @OnlyDescriptors("Fix kdoc link") // TODO - @Test - fun `should have documentation for synthetic Enum valueOf functions`() { - testInline( - """ - |/src/main/kotlin/test/KotlinEnum.kt - |package test - | - |enum class KotlinEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val kotlinEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "KotlinEnum" } - assertNotNull(kotlinEnum) - - val expectedValueOfType = GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "KotlinEnum" - ), - projections = emptyList() - ) - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns the enum constant of this type with the specified name. " + - "The string must match exactly an identifier used to declare an enum " + - "constant in this type. (Extraneous whitespace characters are not permitted.)" - ) - )) - ), - name = "MARKDOWN_FILE" - ) - ), - Throws( - root = CustomDocTag( - children = listOf( - P(listOf( - Text("if this enum type has no constant with the specified name") - )) - ), - name = "MARKDOWN_FILE" - ), - name = "kotlin.IllegalArgumentException", - exceptionAddress = DRI( - packageName = "kotlin", - classNames = "IllegalArgumentException", - target = PointingToDeclaration - ), - ) - )) - - val valueOfFunction = kotlinEnum.functions.single { it.name == "valueOf" } - assertEquals(expectedDocumentation, valueOfFunction.documentation.values.single()) - assertEquals(expectedValueOfType, valueOfFunction.type) - - val valueOfParamDRI = (valueOfFunction.parameters.single().type as GenericTypeConstructor).dri - assertEquals(DRI(packageName = "kotlin", classNames = "String"), valueOfParamDRI) - } - } - } - - @Test - fun `should add data modifier to data objects`() { - testInline( - """ - |/src/main/kotlin/test/KotlinDataObject.kt - |package test - | - |data object KotlinDataObject {} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val pckg = module.packages.single { it.name == "test" } - - val dataObject = pckg.classlikes.single { it.name == "KotlinDataObject" } - assertTrue(dataObject is DObject) - - val modifiers = dataObject.modifiers().values.flatten() - assertEquals(1, modifiers.size) - assertEquals(ExtraModifiers.KotlinOnlyModifiers.Data, modifiers[0]) - } - } - } -} - -private sealed class TestSuite { - abstract val propertyName: String - - data class PropertyDoesntExist( - override val propertyName: String - ) : TestSuite() - - - data class PropertyExists( - override val propertyName: String, - val modifier: KotlinModifier, - val visibility: KotlinVisibility, - val additionalModifiers: Set<ExtraModifiers.KotlinOnlyModifiers> - ) : TestSuite() - - data class FunctionDoesntExist( - override val propertyName: String, - ) : TestSuite() - - data class FunctionExists( - override val propertyName: String, - val modifier: KotlinModifier, - val visibility: KotlinVisibility, - val additionalModifiers: Set<ExtraModifiers.KotlinOnlyModifiers> - ) : TestSuite() -} diff --git a/plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt b/plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt deleted file mode 100644 index 7e9bff1e..00000000 --- a/plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.DokkaConfiguration.Visibility -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.doc.* -import kotlin.test.* - -class DefaultPsiToDocumentableTranslatorTest : BaseAbstractTest() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - } - } - } - - @Test - fun `method overriding two documented classes picks closest class documentation`() { - testInline( - """ - |/src/main/java/sample/BaseClass1.java - |package sample; - |public class BaseClass1 { - | /** B1 */ - | public void x() { } - |} - | - |/src/main/java/sample/BaseClass2.java - |package sample; - |public class BaseClass2 extends BaseClass1 { - | /** B2 */ - | public void x() { } - |} - | - |/src/main/java/sample/X.java - |package sample; - |public class X extends BaseClass2 { - | public void x() { } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val documentationOfFunctionX = module.documentationOf("X", "x") - assertTrue( - "B2" in documentationOfFunctionX, - "Expected nearest super method documentation to be parsed as documentation. " + - "Documentation: $documentationOfFunctionX" - ) - } - } - } - - @Test - fun `method overriding class and interface picks class documentation`() { - testInline( - """ - |/src/main/java/sample/BaseClass1.java - |package sample; - |public class BaseClass1 { - | /** B1 */ - | public void x() { } - |} - | - |/src/main/java/sample/Interface1.java - |package sample; - |public interface Interface1 { - | /** I1 */ - | public void x() {} - |} - | - |/src/main/java/sample/X.java - |package sample; - |public class X extends BaseClass1 implements Interface1 { - | public void x() { } - |} - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val documentationOfFunctionX = module.documentationOf("X", "x") - assertTrue( - "B1" in documentationOfFunctionX, - "Expected documentation of superclass being prioritized over interface " + - "Documentation: $documentationOfFunctionX" - ) - } - } - } - - @Test - fun `method overriding two classes picks closest documented class documentation`() { - testInline( - """ - |/src/main/java/sample/BaseClass1.java - |package sample; - |public class BaseClass1 { - | /** B1 */ - | public void x() { } - |} - | - |/src/main/java/sample/BaseClass2.java - |package sample; - |public class BaseClass2 extends BaseClass1 { - | public void x() {} - |} - | - |/src/main/java/sample/X.java - |package sample; - |public class X extends BaseClass2 { - | public void x() { } - |} - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val documentationOfFunctionX = module.documentationOf("X", "x") - assertTrue( - "B1" in documentationOfFunctionX, - "Expected Documentation \"B1\", found: \"$documentationOfFunctionX\"" - ) - } - } - } - - @Test - fun `java package-info package description`() { - testInline( - """ - |/src/main/java/sample/BaseClass1.java - |package sample; - |public class BaseClass1 { - | /** B1 */ - | void x() { } - |} - | - |/src/main/java/sample/BaseClass2.java - |package sample; - |public class BaseClass2 extends BaseClass1 { - | void x() {} - |} - | - |/src/main/java/sample/X.java - |package sample; - |public class X extends BaseClass2 { - | void x() { } - |} - | - |/src/main/java/sample/package-info.java - |/** - | * Here comes description from package-info - | */ - |package sample; - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val documentationOfPackage = module.packages.single().documentation.values.single().children.single() - .firstMemberOfType<Text>().body - assertEquals( - "Here comes description from package-info", documentationOfPackage - ) - } - } - } - - @Test - fun `java package-info package annotations`() { - testInline( - """ - |/src/main/java/sample/PackageAnnotation.java - |package sample; - |@java.lang.annotation.Target(java.lang.annotation.ElementType.PACKAGE) - |public @interface PackageAnnotation { - |} - | - |/src/main/java/sample/package-info.java - |@PackageAnnotation - |package sample; - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals( - Annotations.Annotation(DRI("sample", "PackageAnnotation"), emptyMap()), - module.packages.single().extra[Annotations]?.directAnnotations?.values?.single()?.single() - ) - } - } - } - - @Test - fun `should add default value to constant properties`() { - testInline( - """ - |/src/main/java/test/JavaConstants.java - |package test; - | - |public class JavaConstants { - | public static final byte BYTE = 1; - | public static final short SHORT = 2; - | public static final int INT = 3; - | public static final long LONG = 4L; - | public static final float FLOAT = 5.0f; - | public static final double DOUBLE = 6.0d; - | public static final String STRING = "Seven"; - | public static final char CHAR = 'E'; - | public static final boolean BOOLEAN = true; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "JavaConstants" } - - val constants = testedClass.properties - assertEquals(9, constants.size) - - val constantsByName = constants.associateBy { it.name } - fun getConstantExpression(name: String): Expression? { - return constantsByName.getValue(name).extra[DefaultValue]?.expression?.values?.first() - } - - assertEquals(IntegerConstant(1), getConstantExpression("BYTE")) - assertEquals(IntegerConstant(2), getConstantExpression("SHORT")) - assertEquals(IntegerConstant(3), getConstantExpression("INT")) - assertEquals(IntegerConstant(4), getConstantExpression("LONG")) - assertEquals(FloatConstant(5.0f), getConstantExpression("FLOAT")) - assertEquals(DoubleConstant(6.0), getConstantExpression("DOUBLE")) - assertEquals(StringConstant("Seven"), getConstantExpression("STRING")) - assertEquals(StringConstant("E"), getConstantExpression("CHAR")) - assertEquals(BooleanConstant(true), getConstantExpression("BOOLEAN")) - } - } - } - - @Test - fun `should resolve static imports used as annotation param values as literal values`() { - testInline( - """ - |/src/main/java/test/JavaClassUsingAnnotation.java - |package test; - | - |import static test.JavaConstants.STRING; - |import static test.JavaConstants.INTEGER; - |import static test.JavaConstants.LONG; - |import static test.JavaConstants.BOOLEAN; - |import static test.JavaConstants.DOUBLE; - |import static test.JavaConstants.FLOAT; - |import static test.JavaConstants.BYTE; - |import static test.JavaConstants.SHORT; - |import static test.JavaConstants.CHAR; - | - |@JavaAnnotation( - | byteValue = BYTE, shortValue = SHORT, intValue = INTEGER, longValue = LONG, booleanValue = BOOLEAN, - | doubleValue = DOUBLE, floatValue = FLOAT, stringValue = STRING, charValue = CHAR - |) - |public class JavaClassUsingAnnotation { - |} - | - |/src/main/java/test/JavaAnnotation.java - |package test; - |@Documented - |public @interface JavaAnnotation { - | byte byteValue(); - | short shortValue(); - | int intValue(); - | long longValue(); - | boolean booleanValue(); - | double doubleValue(); - | float floatValue(); - | String stringValue(); - | char charValue(); - |} - | - |/src/main/java/test/JavaConstants.java - |package test; - |public class JavaConstants { - | public static final byte BYTE = 3; - | public static final short SHORT = 4; - | public static final int INTEGER = 5; - | public static final long LONG = 6L; - | public static final boolean BOOLEAN = true; - | public static final double DOUBLE = 7.0d; - | public static final float FLOAT = 8.0f; - | public static final String STRING = "STRING_CONSTANT_VALUE"; - | public static final char CHAR = 'c'; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "JavaClassUsingAnnotation" } - - val annotation = (testedClass as DClass).extra[Annotations]?.directAnnotations?.values?.single()?.single() - assertNotNull(annotation) - - assertEquals("JavaAnnotation", annotation.dri.classNames) - - assertEquals(IntValue(3), annotation.params["byteValue"]) - assertEquals(IntValue(4), annotation.params["shortValue"]) - assertEquals(IntValue(5), annotation.params["intValue"]) - assertEquals(LongValue(6), annotation.params["longValue"]) - assertEquals(BooleanValue(true), annotation.params["booleanValue"]) - assertEquals(DoubleValue(7.0), annotation.params["doubleValue"]) - assertEquals(FloatValue(8.0f), annotation.params["floatValue"]) - assertEquals(StringValue("STRING_CONSTANT_VALUE"), annotation.params["stringValue"]) - assertEquals(StringValue("c"), annotation.params["charValue"]) - } - } - } - - // TODO [beresnev] fix -// class OnlyPsiPlugin : DokkaPlugin() { -// private val kotlinAnalysisPlugin by lazy { plugin<Kotlin>() } -// -// @Suppress("unused") -// val psiOverrideDescriptorTranslator by extending { -// (plugin<JavaAnalysisPlugin>().psiToDocumentableTranslator -// override kotlinAnalysisPlugin.descriptorToDocumentableTranslator) -// } -// -// @OptIn(DokkaPluginApiPreview::class) -// override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = -// PluginApiPreviewAcknowledgement -// } -// -// // for Kotlin classes from DefaultPsiToDocumentableTranslator -// @Test -// fun `should resolve ultralight class`() { -// val configurationWithNoJVM = dokkaConfiguration { -// sourceSets { -// sourceSet { -// sourceRoots = listOf("src/main/java") -// } -// } -// } -// -// testInline( -// """ -// |/src/main/java/example/Test.kt -// |package example -// | -// |open class KotlinSubClass { -// | fun kotlinSubclassFunction(bar: String): String { -// | return "KotlinSubClass" -// | } -// |} -// | -// |/src/main/java/example/JavaLeafClass.java -// |package example; -// | -// |public class JavaLeafClass extends KotlinSubClass { -// | public String javaLeafClassFunction(String baz) { -// | return "JavaLeafClass"; -// | } -// |} -// """.trimMargin(), -// configurationWithNoJVM, -// pluginOverrides = listOf(OnlyPsiPlugin()) // suppress a descriptor translator because of psi and descriptor translators work in parallel -// ) { -// documentablesMergingStage = { module -> -// val kotlinSubclassFunction = -// module.packages.single().classlikes.find { it.name == "JavaLeafClass" }?.functions?.find { it.name == "kotlinSubclassFunction" } -// .assertNotNull("kotlinSubclassFunction ") -// -// assertEquals( -// "String", -// (kotlinSubclassFunction.type as? TypeConstructor)?.dri?.classNames -// ) -// assertEquals( -// "String", -// (kotlinSubclassFunction.parameters.firstOrNull()?.type as? TypeConstructor)?.dri?.classNames -// ) -// } -// } -// } - - @Test - fun `should preserve regular functions that are named like getters, but are not getters`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | public String getA() { return "s"; } // wrong return type - | public int getA(String param) { return 123; } // shouldn't have params - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } - - val getterLookalikes = testClass.functions.filter { it.name == "getA" } - assertEquals(2, getterLookalikes.size, "Not all expected regular functions found, wrongly categorized as getters?") - } - } - } - - @Test - fun `should ignore additional non-accessor setters`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | - | public int getA() { return a; } - | - | public void setA(long a) { } - | public void setA(Number a) {} - | - | // the qualifying setter is intentionally in the middle - | // to rule out the order making a difference - | public void setA(int a) { } - | - | public void setA(String a) {} - | public void setA() {} - | - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testClass.properties.single { it.name == "a" } - assertNotNull(property.getter) - - val setter = property.setter - assertNotNull(setter) - assertEquals(1, setter.parameters.size) - assertEquals(PrimitiveJavaType("int"), setter.parameters[0].type) - - val regularSetterFunctions = testClass.functions.filter { it.name == "setA" } - assertEquals(4, regularSetterFunctions.size) - } - } - } - - @Test - fun `should not qualify methods with subtype parameters as type accessors`() { - testInline( - """ - |/src/main/java/test/Shape.java - |package test; - |public class Shape { } - | - |/src/main/java/test/Triangle.java - |package test; - |public class Triangle extends Shape { } - | - |/src/main/java/test/Square.java - |package test; - |public class Square extends Shape { } - | - |/src/main/java/test/Test.java - |package test; - |public class Test { - | private Shape foo = 1; - | - | public Shape getFoo() { return new Square(); } - | - | public void setFoo(Square foo) { } - | public void setFoo(Triangle foo) { } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "Test" } - - val field = testClass.properties.singleOrNull { it.name == "foo" } - assertNotNull(field) { - "Expected the foo property to exist because the field is private with a public getter" - } - assertNull(field.setter) - - val setterMethodsWithSubtypeParams = testClass.functions.filter { it.name == "setFoo" } - assertEquals( - 2, - setterMethodsWithSubtypeParams.size, - "Expected the setter methods to not qualify as accessors because of subtype parameters" - ) - } - } - } - - @Test - fun `should preserve private fields without getters even if they have qualifying setters`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | - | public void setA(int a) { } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val tetClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = tetClass.properties.firstOrNull { it.name == "a" } - assertNull(property, "Expected the property to stay private because there are no getters") - - val regularSetterFunction = tetClass.functions.firstOrNull { it.name == "setA" } - assertNotNull(regularSetterFunction) { - "The qualifying setter function should stay a regular function because the field is inaccessible" - } - } - } - } - - @Test - fun `should not mark a multi-param setter overload as an accessor`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int field = 1; - | - | public void setField(int a, int b) { } - | public int getField() { return a; } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } as DClass - - val property = testClass.properties.single { it.name == "field" } - assertEquals("getField", property.getter?.name) - assertNull(property.setter) - - - // the setField function should not qualify to be an accessor due to the second param - assertEquals(1, testClass.functions.size) - assertEquals("setField", testClass.functions[0].name) - } - } - } - - @Test - fun `should not associate accessors with field because field is public api`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PROTECTED - ) - } - } - } - - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | protected int a = 1; - | public int getA() { return a; } - | public void setA(int a) { this.a = a; } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testedClass.properties.single { it.name == "a" } - assertEquals(JavaVisibility.Protected, property.visibility.values.single()) - assertNull(property.getter) - assertNull(property.setter) - - assertEquals(2, testedClass.functions.size) - - assertEquals("getA", testedClass.functions[0].name) - assertEquals("setA", testedClass.functions[1].name) - } - } - } - - @Test - fun `should add IsVar extra for field with getter and setter`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | public int getA() { return a; } - | public void setA(int a) { this.a = a; } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testedClass.properties.single { it.name == "a" } - assertNotNull(property.extra[IsVar]) - } - } - } - - @Test - fun `should not add IsVar extra if field does not have a setter`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | public int getA() { return a; } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testedClass.properties.single { it.name == "a" } - assertNull(property.extra[IsVar]) - } - } - } - - @Test - fun `should add IsVar for non-final java field without any accessors`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | public int a = 1; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testedClass.properties.single { it.name == "a" } - assertNotNull(property.extra[IsVar]) - } - } - } - - @Test - fun `should not add IsVar for final java field`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | public final int a = 2; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val publicFinal = testedClass.properties.single { it.name == "a" } - assertNull(publicFinal.extra[IsVar]) - } - } - } - - @Test // see https://github.com/Kotlin/dokka/issues/2646 - fun `should resolve PsiImmediateClassType as class reference`() { - testInline( - """ - |/src/main/java/test/JavaEnum.java - |package test; - |public enum JavaEnum { - | FOO, BAR - |} - | - |/src/main/java/test/ContainingEnumType.java - |package test; - |public class ContainingEnumType { - | - | public JavaEnum returningEnumType() { - | return null; - | } - | - | public JavaEnum[] returningEnumTypeArray() { - | return null; - | } - | - | public void acceptingEnumType(JavaEnum javaEnum) {} - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val expectedType = GenericTypeConstructor( - dri = DRI(packageName = "test", classNames = "JavaEnum", target = PointingToDeclaration), - projections = emptyList() - ) - val expectedArrayType = GenericTypeConstructor( - dri = DRI("kotlin", "Array", target = PointingToDeclaration), - projections = listOf(expectedType) - ) - - val classWithEnumUsage = module.packages.single().classlikes.single { it.name == "ContainingEnumType" } - - val returningEnum = classWithEnumUsage.functions.single { it.name == "returningEnumType" } - assertEquals(expectedType, returningEnum.type) - - val acceptingEnum = classWithEnumUsage.functions.single { it.name == "acceptingEnumType" } - assertEquals(1, acceptingEnum.parameters.size) - assertEquals(expectedType, acceptingEnum.parameters[0].type) - - val returningArray = classWithEnumUsage.functions.single { it.name == "returningEnumTypeArray" } - assertEquals(expectedArrayType, returningArray.type) - } - } - } - - @Test - fun `should have documentation for synthetic Enum values functions`() { - testInline( - """ - |/src/main/java/test/JavaEnum.java - |package test - | - |public enum JavaEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val kotlinEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "JavaEnum" } - assertNotNull(kotlinEnum) - - val valuesFunction = kotlinEnum.functions.single { it.name == "values" } - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns an array containing the constants of this enum type, " + - "in the order they're declared. This method may be used to " + - "iterate over the constants." - ), - )) - ), - name = "MARKDOWN_FILE" - ) - ), - Return( - CustomDocTag( - children = listOf( - P(listOf( - Text("an array containing the constants of this enum type, in the order they're declared") - )) - ), - name = "MARKDOWN_FILE" - ) - ) - )) - assertEquals(expectedDocumentation, valuesFunction.documentation.values.single()) - - val expectedValuesType = GenericTypeConstructor( - dri = DRI( - packageName = "kotlin", - classNames = "Array" - ), - projections = listOf( - GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "JavaEnum" - ), - projections = emptyList() - ) - ) - ) - assertEquals(expectedValuesType, valuesFunction.type) - } - } - } - - @Test - fun `should have documentation for synthetic Enum valueOf functions`() { - testInline( - """ - |/src/main/java/test/JavaEnum.java - |package test - | - |public enum JavaEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val javaEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "JavaEnum" } - assertNotNull(javaEnum) - - val valueOfFunction = javaEnum.functions.single { it.name == "valueOf" } - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns the enum constant of this type with the " + - "specified name. The string must match exactly an identifier used " + - "to declare an enum constant in this type. (Extraneous whitespace " + - "characters are not permitted.)" - ) - )) - ), - name = "MARKDOWN_FILE" - ) - ), - Return( - root = CustomDocTag( - children = listOf( - P(listOf( - Text("the enum constant with the specified name") - )) - ), - name = "MARKDOWN_FILE" - ) - ), - Throws( - name = "java.lang.IllegalArgumentException", - exceptionAddress = DRI( - packageName = "java.lang", - classNames = "IllegalArgumentException", - target = PointingToDeclaration - ), - root = CustomDocTag( - children = listOf( - P(listOf( - Text("if this enum type has no constant with the specified name") - )) - ), - name = "MARKDOWN_FILE" - ) - ), - )) - assertEquals(expectedDocumentation, valueOfFunction.documentation.values.single()) - - val expectedValueOfType = GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "JavaEnum" - ), - projections = emptyList() - ) - assertEquals(expectedValueOfType, valueOfFunction.type) - - val valueOfParamDRI = (valueOfFunction.parameters.single().type as GenericTypeConstructor).dri - assertEquals(DRI(packageName = "java.lang", classNames = "String"), valueOfParamDRI) - } - } - } - - @Test - fun `should have public default constructor in public class`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.findClasslike(packageName = "test", "A") as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 default constructor") - assertTrue( - testedClass.constructors.first().parameters.isEmpty(), - "Expect default constructor doesn't have params" - ) - assertEquals(JavaVisibility.Public, testedClass.constructors.first().visibility()) - } - } - } - - @Test - fun `should have package-private default constructor in package-private class`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - documentedVisibilities = setOf(Visibility.PUBLIC, Visibility.PACKAGE) - } - } - } - - testInline( - """ - |/src/main/java/test/A.java - |package test; - |class A { - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.findClasslike(packageName = "test", "A") as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 default constructor") - assertEquals(JavaVisibility.Default, testedClass.constructors.first().visibility()) - } - } - } - - @Test - fun `should have private default constructor in private nested class`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - documentedVisibilities = setOf(Visibility.PUBLIC, Visibility.PRIVATE) - } - } - } - - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private static class PrivateNested{} - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val parentClass = module.findClasslike(packageName = "test", "A") as DClass - val testedClass = parentClass.classlikes.single { it.name == "PrivateNested" } as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 default constructor") - assertEquals(JavaVisibility.Private, testedClass.constructors.first().visibility()) - } - } - } - - @Test - fun `should not have a default public constructor because have explicit private`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - documentedVisibilities = setOf(Visibility.PUBLIC, Visibility.PRIVATE) - } - } - } - - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private A(){} - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.findClasslike(packageName = "test", "A") as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 declared constructor") - assertEquals(JavaVisibility.Private, testedClass.constructors.first().visibility()) - } - } - } - - @Test - fun `default constructor should get the package name`() { - testInline( - """ - |/src/main/java/org/test/A.java - |package org.test; - |public class A { - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.findClasslike(packageName = "org.test", "A") as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 default constructor") - - val constructorDRI = testedClass.constructors.first().dri - assertEquals("org.test", constructorDRI.packageName) - assertEquals("A", constructorDRI.classNames) - } - } - } -} - -private fun DFunction.visibility() = visibility.values.first() diff --git a/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt b/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt deleted file mode 100644 index 1879c538..00000000 --- a/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.analysis.kotlin.internal.ExternalDocumentablesProvider -import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DInterface -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.querySingle -import org.jetbrains.dokka.utilities.cast -import kotlin.test.Test -import kotlin.test.assertEquals - -class ExternalDocumentablesTest : BaseAbstractTest() { - @Test - fun `external documentable from java stdlib`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - analysisPlatform = "jvm" - classpath += jvmStdlibPath!! - } - } - } - - testInline( - """ - /src/com/sample/MyList.kt - package com.sample - class MyList: ArrayList<Int>() - """.trimIndent(), - configuration - ) { - lateinit var provider: ExternalDocumentablesProvider - pluginsSetupStage = { - provider = it.plugin<InternalKotlinAnalysisPlugin>().querySingle { externalDocumentablesProvider } - } - documentablesTransformationStage = { mod -> - val entry = mod.packages.single().classlikes.single().cast<DClass>().supertypes.entries.single() - val res = provider.findClasslike( - entry.value.single().typeConstructor.dri, - entry.key) - assertEquals("ArrayList", res?.name) - assertEquals("java.util/ArrayList///PointingToDeclaration/", res?.dri?.toString()) - - val supertypes = res?.cast<DClass>()?.supertypes?.values?.single() - ?.map { it.typeConstructor.dri.classNames } - assertEquals( - listOf("AbstractList", "RandomAccess", "Cloneable", "Serializable", "MutableList"), - supertypes - ) - } - } - } - - @Test - fun `external documentable from dependency`() { - val coroutinesPath = - ClassLoader.getSystemResource("kotlinx/coroutines/Job.class") - ?.file - ?.replace("file:", "") - ?.replaceAfter(".jar", "") - - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - analysisPlatform = "jvm" - classpath += listOf(jvmStdlibPath!!, coroutinesPath!!) - } - } - } - - testInline( - """ - /src/com/sample/MyJob.kt - package com.sample - import kotlinx.coroutines.Job - abstract class MyJob: Job - """.trimIndent(), - configuration - ) { - lateinit var provider: ExternalDocumentablesProvider - pluginsSetupStage = { - provider = it.plugin<InternalKotlinAnalysisPlugin>().querySingle { externalDocumentablesProvider } - } - documentablesTransformationStage = { mod -> - val entry = mod.packages.single().classlikes.single().cast<DClass>().supertypes.entries.single() - val res = provider.findClasslike( - entry.value.single().typeConstructor.dri, - entry.key) - assertEquals("Job", res?.name) - assertEquals("kotlinx.coroutines/Job///PointingToDeclaration/", res?.dri?.toString()) - - val supertypes = res?.cast<DInterface>()?.supertypes?.values?.single() - ?.map { it.typeConstructor.dri.classNames } - assertEquals( - listOf("CoroutineContext.Element"), - supertypes - ) - } - } - } - - @Test - fun `external documentable for nested class`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - analysisPlatform = "jvm" - classpath += jvmStdlibPath!! - } - } - } - - testInline( - """ - /src/com/sample/MyList.kt - package com.sample - abstract class MyEntry: Map.Entry<Int, String> - """.trimIndent(), - configuration - ) { - lateinit var provider: ExternalDocumentablesProvider - pluginsSetupStage = { - provider = it.plugin<InternalKotlinAnalysisPlugin>().querySingle { externalDocumentablesProvider } - } - documentablesTransformationStage = { mod -> - val entry = mod.packages.single().classlikes.single().cast<DClass>().supertypes.entries.single() - val res = provider.findClasslike( - entry.value.single().typeConstructor.dri, - entry.key) - assertEquals("Entry", res?.name) - assertEquals("kotlin.collections/Map.Entry///PointingToDeclaration/", res?.dri?.toString()) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/JavadocInheritDocsTest.kt b/plugins/base/src/test/kotlin/translators/JavadocInheritDocsTest.kt deleted file mode 100644 index 6413866f..00000000 --- a/plugins/base/src/test/kotlin/translators/JavadocInheritDocsTest.kt +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.doc.CustomDocTag -import org.jetbrains.dokka.model.doc.Description -import org.jetbrains.dokka.model.doc.P -import org.jetbrains.dokka.model.doc.Text -import kotlin.test.Ignore -import kotlin.test.Test -import kotlin.test.assertEquals - -class JavadocInheritDocsTest : BaseAbstractTest() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - } - } - } - - @Test - fun `work when whole description is inherited`() { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |/** - |* Superclass docs - |*/ - |public class Superclass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* {@inheritDoc} - |*/ - |public class Subclass extends Superclass { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Superclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - fun `work when inherited part is inside description`() { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |/** - |* Superclass docs - |*/ - |public class Superclass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public class Subclass extends Superclass { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. Superclass docs End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - fun `work when inherited part is empty`() { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |public class Superclass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public class Subclass extends Superclass { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - @Ignore // This should be enabled when we have proper tag inheritance in javadoc parser - fun `work when inherited part is empty in supertype but present in its supertype`() { - testInline( - """ - |/src/main/java/sample/SuperSuperclass.java - |package sample; - |/** - |* Super super docs - |*/ - |public class SuperSuperclass { } - |/src/main/java/sample/Superclass.java - |package sample; - |public class Superclass extends SuperSuperClass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public class Subclass extends Superclass { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. Super super docs End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - //Original javadoc doesn't treat interfaces as valid candidates for inherit doc - fun `work with interfaces`() { - testInline( - """ - |/src/main/java/sample/SuperInterface.java - |package sample; - |/** - |* Super super docs - |*/ - |public interface SuperInterface { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public interface Subclass extends SuperInterface { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - - @Test - fun `work with multiple supertypes`() { - testInline( - """ - |/src/main/java/sample/SuperInterface.java - |package sample; - |/** - |* Super interface docs - |*/ - |public interface SuperInterface { } - |/src/main/java/sample/Superclass.java - |package sample; - |/** - |* Super class docs - |*/ - |public class Superclass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public class Subclass extends Superclass implements SuperInterface { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. Super class docs End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - fun `work with methods`() { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |public class Superclass { - |/** - |* Sample super method - |* - |* @return super string - |* @throws RuntimeException super throws - |* @see java.lang.String super see - |* @deprecated super deprecated - |*/ - |public String test() { - | return ""; - |} - |} - |/src/main/java/sample/Subclass.java - |package sample; - |public class Subclass extends Superclass { - | /** - | * Sample sub method. {@inheritDoc} - | */ - | @Override - | public String test() { - | return super.test(); - | } - |} - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val function = module.findFunction("sample", "Subclass", "test") - val descriptionGot = function.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Sample sub method. Sample super method")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/JavadocInheritedDocTagsTest.kt b/plugins/base/src/test/kotlin/translators/JavadocInheritedDocTagsTest.kt deleted file mode 100644 index a20db4ca..00000000 --- a/plugins/base/src/test/kotlin/translators/JavadocInheritedDocTagsTest.kt +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.model.doc.* -import kotlin.test.Test -import kotlin.test.assertEquals -import org.jetbrains.dokka.model.doc.Deprecated as DokkaDeprecatedTag -import org.jetbrains.dokka.model.doc.Throws as DokkaThrowsTag - -class JavadocInheritedDocTagsTest : BaseAbstractTest() { - @Suppress("DEPRECATION") // for includeNonPublic - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - includeNonPublic = true - } - } - } - - private fun performTagsTest(test: (DModule) -> Unit) { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |/** - |* @author super author - |*/ - |class Superclass { - | /** - | * Sample super method - | * - | * @return super string - | * @throws RuntimeException super throws - | * @see java.lang.String super see - | * @deprecated super deprecated - | */ - | public String test(){ - | return ""; - | } - | - | /** - | * - | * @param xd String superclass - | * @param asd Integer superclass - | */ - | public void test2(String xd, Integer asd){ - | } - |} - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* @author Ja, {@inheritDoc} - |*/ - |class Subclass extends Superclass { - |/** - | * Sample sub method. {@inheritDoc} - | * - | * @return "sample string". {@inheritDoc} - | * @throws RuntimeException because i can, {@inheritDoc} - | * @throws IllegalStateException this should be it {@inheritDoc} - | * @see java.lang.String string, {@inheritDoc} - | * @deprecated do not use, {@inheritDoc} - | */ - | @Override - | public String test() { - | return super.test(); - | } - | - | /** - | * - | * @param asd2 integer subclass, {@inheritDoc} - | * @param xd2 string subclass, {@inheritDoc} - | */ - | public void test2(String xd2, Integer asd2){ - | } - |} - """.trimIndent(), configuration - ) { - documentablesMergingStage = test - } - } - - @Test - fun `work with return`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = function.documentation.values.first().children.filterIsInstance<Return>().first() - val expectedTag = Return( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("\"sample string\". super string")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with throws`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = - function.documentation.values.first().children.first { it is DokkaThrowsTag && it.name == "java.lang.RuntimeException" } - val expectedTag = DokkaThrowsTag( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("because i can, super throws")) - ) - ), - name = "MARKDOWN_FILE" - ), - "java.lang.RuntimeException", - DRI("java.lang", "RuntimeException", target = PointingToDeclaration) - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with throws when exceptions are different`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = - function.documentation.values.first().children.first { it is DokkaThrowsTag && it.name == "java.lang.IllegalStateException" } - val expectedTag = DokkaThrowsTag( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("this should be it")) - ) - ), - name = "MARKDOWN_FILE" - ), - "java.lang.IllegalStateException", - DRI("java.lang", "IllegalStateException", target = PointingToDeclaration) - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with deprecated`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = function.documentation.values.first().children.filterIsInstance<DokkaDeprecatedTag>().first() - val expectedTag = DokkaDeprecatedTag( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("do not use, Sample super method")) - ) - ), - name = "MARKDOWN_FILE" - ), - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with see also`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = function.documentation.values.first().children.filterIsInstance<See>().first() - val expectedTag = See( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("string,")) - ) - ), - name = "MARKDOWN_FILE" - ), - "java.lang.String", - DRI("java.lang", "String") - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with author`() { - performTagsTest { module -> - val classlike = module.findClasslike("sample", "Subclass") - val renderedTag = classlike.documentation.values.first().children.filterIsInstance<Author>().first() - val expectedTag = Author( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Ja, super author")) - ) - ), - name = "MARKDOWN_FILE" - ), - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with params`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test2") - val (asdTag, xdTag) = function.documentation.values.first().children.filterIsInstance<Param>() - .sortedBy { it.name } - - val expectedAsdTag = Param( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("integer subclass, Integer superclass")) - ) - ), - name = "MARKDOWN_FILE" - ), - "asd2" - ) - val expectedXdTag = Param( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("string subclass, String superclass")) - ) - ), - name = "MARKDOWN_FILE" - ), - "xd2" - ) - assertEquals(expectedAsdTag, asdTag) - assertEquals(expectedXdTag, xdTag) - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt b/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt deleted file mode 100644 index 3f83f462..00000000 --- a/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.model.childrenOfType -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.model.firstChildOfType -import org.jetbrains.dokka.model.firstMemberOfType -import utils.text -import kotlin.test.Test -import kotlin.test.assertEquals - -class JavadocParserTest : BaseAbstractTest() { - - private fun performJavadocTest(testOperation: (DModule) -> Unit) { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/Date2.java - |/** - | * The class <code>Date</code> represents a specific instant - | * in time, with millisecond precision. - | * <p> - | * Prior to JDK 1.1, the class <code>Date</code> had two additional - | * functions. It allowed the interpretation of dates as year, month, day, hour, - | * minute, and second values. It also allowed the formatting and parsing - | * of date strings. Unfortunately, the API for these functions was not - | * amenable to internationalization. As of JDK 1.1, the - | * <code>Calendar</code> class should be used to convert between dates and time - | * fields and the <code>DateFormat</code> class should be used to format and - | * parse date strings. - | * The corresponding methods in <code>Date</code> are deprecated. - | * <p> - | * Although the <code>Date</code> class is intended to reflect - | * coordinated universal time (UTC), it may not do so exactly, - | * depending on the host environment of the Java Virtual Machine. - | * Nearly all modern operating systems assume that 1 day = - | * 24 × 60 × 60 = 86400 seconds - | * in all cases. In UTC, however, about once every year or two there - | * is an extra second, called a "leap second." The leap - | * second is always added as the last second of the day, and always - | * on December 31 or June 30. For example, the last minute of the - | * year 1995 was 61 seconds long, thanks to an added leap second. - | * Most computer clocks are not accurate enough to be able to reflect - | * the leap-second distinction. - | * <p> - | * Some computer standards are defined in terms of Greenwich mean - | * time (GMT), which is equivalent to universal time (UT). GMT is - | * the "civil" name for the standard; UT is the - | * "scientific" name for the same standard. The - | * distinction between UTC and UT is that UTC is based on an atomic - | * clock and UT is based on astronomical observations, which for all - | * practical purposes is an invisibly fine hair to split. Because the - | * earth's rotation is not uniform (it slows down and speeds up - | * in complicated ways), UT does not always flow uniformly. Leap - | * seconds are introduced as needed into UTC so as to keep UTC within - | * 0.9 seconds of UT1, which is a version of UT with certain - | * corrections applied. There are other time and date systems as - | * well; for example, the time scale used by the satellite-based - | * global positioning system (GPS) is synchronized to UTC but is - | * <i>not</i> adjusted for leap seconds. An interesting source of - | * further information is the U.S. Naval Observatory, particularly - | * the Directorate of Time at: - | * <blockquote><pre> - | * <a href=http://tycho.usno.navy.mil>http://tycho.usno.navy.mil</a> - | * </pre></blockquote> - | * <p> - | * and their definitions of "Systems of Time" at: - | * <blockquote><pre> - | * <a href=http://tycho.usno.navy.mil/systime.html>http://tycho.usno.navy.mil/systime.html</a> - | * </pre></blockquote> - | * <p> - | * In all methods of class <code>Date</code> that accept or return - | * year, month, date, hours, minutes, and seconds values, the - | * following representations are used: - | * <ul> - | * <li>A year <i>y</i> is represented by the integer - | * <i>y</i> <code>- 1900</code>. - | * <li>A month is represented by an integer from 0 to 11; 0 is January, - | * 1 is February, and so forth; thus 11 is December. - | * <li>A date (day of month) is represented by an integer from 1 to 31 - | * in the usual manner. - | * <li>An hour is represented by an integer from 0 to 23. Thus, the hour - | * from midnight to 1 a.m. is hour 0, and the hour from noon to 1 - | * p.m. is hour 12. - | * <li>A minute is represented by an integer from 0 to 59 in the usual manner. - | * <li>A second is represented by an integer from 0 to 61; the values 60 and - | * 61 occur only for leap seconds and even then only in Java - | * implementations that actually track leap seconds correctly. Because - | * of the manner in which leap seconds are currently introduced, it is - | * extremely unlikely that two leap seconds will occur in the same - | * minute, but this specification follows the date and time conventions - | * for ISO C. - | * </ul> - | * <pre class="prettyprint"> - | * <androidx.fragment.app.FragmentContainerView - | * xmlns:android="http://schemas.android.com/apk/res/android" - | * xmlns:app="http://schemas.android.com/apk/res-auto" - | * android:id="@+id/fragment_container_view" - | * android:layout_width="match_parent" - | * android:layout_height="match_parent"> - | * </androidx.fragment.app.FragmentContainerView> - | * </pre> - | * <p> - | * In all cases, arguments given to methods for these purposes need - | * not fall within the indicated ranges; for example, a date may be - | * specified as January 32 and is interpreted as meaning February 1. - | * - | * <pre class="prettyprint"> - | * class MyFragment extends Fragment { - | * public MyFragment() { - | * super(R.layout.fragment_main); - | * } - | * } - | * </pre> - | - | * @author James Gosling - | * @author Arthur van Hoff - | * @author Alan Liu - | * @see java.text.DateFormat - | * @see java.util.Calendar - | * @since JDK1.0 - | * @apiSince 1 - | */ - |public class Date2 implements java.io.Serializable, java.lang.Cloneable, java.lang.Comparable<java.util.Date> { - | void x() { } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = testOperation - } - } - - @Test - fun `correctly parsed list`() { - performJavadocTest { module -> - val dateDescription = module.descriptionOf("Date2")!! - assertEquals(6, dateDescription.firstChildOfType<Ul>().children.filterIsInstance<Li>().size) - } - } - - @Test - fun `correctly parsed author tags`() { - performJavadocTest { module -> - val authors = module.findClasslike().documentation.values.single().childrenOfType<Author>() - assertEquals(3, authors.size) - assertEquals("James Gosling", authors[0].firstMemberOfType<Text>().text()) - assertEquals("Arthur van Hoff", authors[1].firstMemberOfType<Text>().text()) - assertEquals("Alan Liu", authors[2].firstMemberOfType<Text>().text()) - } - } - - @Test - fun `correctly parsed see tags`() { - performJavadocTest { module -> - val sees = module.findClasslike().documentation.values.single().childrenOfType<See>() - assertEquals(2, sees.size) - assertEquals(DRI("java.text", "DateFormat"), sees[0].address) - assertEquals("java.text.DateFormat", sees[0].name) - assertEquals(DRI("java.util", "Calendar"), sees[1].address) - assertEquals("java.util.Calendar", sees[1].name) - } - } - - @Test - fun `correctly parsed code block`(){ - performJavadocTest { module -> - val dateDescription = module.descriptionOf("Date2")!! - val preTagContent = dateDescription.firstChildOfType<Pre>().firstChildOfType<Text>() - val expectedText = """<androidx.fragment.app.FragmentContainerView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:id="@+id/fragment_container_view" - android:layout_width="match_parent" - android:layout_height="match_parent"> -</androidx.fragment.app.FragmentContainerView>""".trimIndent() - assertEquals(expectedText.trim(), preTagContent.body.trim()) - } - } - - @Test - fun `correctly parsed code block with curly braces (which PSI has problem with)`() { - performJavadocTest { module -> - val dateDescription = module.descriptionOf("Date2")!! - val preTagContent = dateDescription.childrenOfType<Pre>()[1].firstChildOfType<Text>() - val expectedText = """class MyFragment extends Fragment { - public MyFragment() { - super(R.layout.fragment_main); - } -}""".trimIndent() - assertEquals(expectedText.trim(), preTagContent.body.trim()) - } - } - -} diff --git a/plugins/base/src/test/kotlin/translators/utils.kt b/plugins/base/src/test/kotlin/translators/utils.kt deleted file mode 100644 index b1979f60..00000000 --- a/plugins/base/src/test/kotlin/translators/utils.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.doc.Description -import org.jetbrains.dokka.model.doc.Text - -fun DModule.documentationOf(className: String, functionName: String? = null): String = - descriptionOf(className, functionName) - ?.firstMemberOfType<Text>() - ?.body.orEmpty() - -fun DModule.descriptionOf(className: String, functionName: String? = null): Description? { - val classlike = packages.single() - .classlikes.single { it.name == className } - val target: Documentable = - if (functionName != null) classlike.functions.single { it.name == functionName } else classlike - return target.documentation.values.singleOrNull() - ?.firstChildOfTypeOrNull<Description>() -} - -fun DModule.findPackage(packageName: String? = null) = - packageName?.let { packages.firstOrNull { pkg -> pkg.packageName == packageName } - ?: throw NoSuchElementException("No packageName with name $packageName") } ?: packages.single() - -fun DModule.findClasslike(packageName: String? = null, className: String? = null): DClasslike { - val pkg = findPackage(packageName) - return className?.let { - pkg.classlikes.firstOrNull { cls -> cls.name == className } - ?: throw NoSuchElementException("No classlike with name $className") - } ?: pkg.classlikes.single() -} - -fun DModule.findFunction(packageName: String? = null, className: String, functionName: String? = null): DFunction { - val classlike = findClasslike(packageName, className) - return functionName?.let { - classlike.functions.firstOrNull { fn -> fn.name == functionName } - ?: throw NoSuchElementException("No classlike with name $functionName") - } ?: classlike.functions.single() -} |