aboutsummaryrefslogtreecommitdiff
path: root/dokka-subprojects/plugin-base/src/test/kotlin/signatures
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-11-10 11:46:54 +0100
committerGitHub <noreply@github.com>2023-11-10 11:46:54 +0100
commit8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch)
tree1b915207b2b9f61951ddbf0ff2e687efd053d555 /dokka-subprojects/plugin-base/src/test/kotlin/signatures
parenta44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff)
downloaddokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.gz
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.bz2
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.zip
Restructure the project to utilize included builds (#3174)
* Refactor and simplify artifact publishing * Update Gradle to 8.4 * Refactor and simplify convention plugins and build scripts Fixes #3132 --------- Co-authored-by: Adam <897017+aSemy@users.noreply.github.com> Co-authored-by: Oleg Yukhnevich <whyoleg@gmail.com>
Diffstat (limited to 'dokka-subprojects/plugin-base/src/test/kotlin/signatures')
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/signatures/AbstractRenderingTest.kt65
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/signatures/DivergentSignatureTest.kt73
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt312
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/signatures/InheritedAccessorsSignatureTest.kt461
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt206
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/signatures/RawHtmlRenderingTest.kt70
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/signatures/SignatureTest.kt1035
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/signatures/VarianceSignatureTest.kt108
8 files changed, 2330 insertions, 0 deletions
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/signatures/AbstractRenderingTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/signatures/AbstractRenderingTest.kt
new file mode 100644
index 00000000..4c4bbc4c
--- /dev/null
+++ b/dokka-subprojects/plugin-base/src/test/kotlin/signatures/AbstractRenderingTest.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package signatures
+
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Element
+import org.jsoup.select.Elements
+import utils.TestOutputWriterPlugin
+import java.nio.file.Path
+import java.nio.file.Paths
+
+abstract class AbstractRenderingTest : BaseAbstractTest() {
+ val testDataDir: Path = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath()
+
+ val configuration = dokkaConfiguration {
+ moduleName = "example"
+ sourceSets {
+ val common = sourceSet {
+ name = "common"
+ displayName = "common"
+ analysisPlatform = "common"
+ sourceRoots = listOf(Paths.get("$testDataDir/commonMain/kotlin").toString())
+ }
+ val jvmAndJsSecondCommonMain = sourceSet {
+ name = "jvmAndJsSecondCommonMain"
+ displayName = "jvmAndJsSecondCommonMain"
+ analysisPlatform = "common"
+ dependentSourceSets = setOf(common.value.sourceSetID)
+ sourceRoots = listOf(Paths.get("$testDataDir/jvmAndJsSecondCommonMain/kotlin").toString())
+ }
+ sourceSet {
+ name = "js"
+ displayName = "js"
+ analysisPlatform = "js"
+ dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID)
+ sourceRoots = listOf(Paths.get("$testDataDir/jsMain/kotlin").toString())
+ }
+ sourceSet {
+ name = "jvm"
+ displayName = "jvm"
+ analysisPlatform = "jvm"
+ dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID)
+ sourceRoots = listOf(Paths.get("$testDataDir/jvmMain/kotlin").toString())
+ }
+ }
+ }
+
+ fun TestOutputWriterPlugin.renderedContent(path: String): Element = writer.contents.getValue(path)
+ .let { Jsoup.parse(it) }.select("#content").single()
+
+ fun TestOutputWriterPlugin.renderedDivergentContent(path: String): Elements =
+ renderedContent(path).select("div.divergent-group")
+
+ fun TestOutputWriterPlugin.renderedSourceDependentContent(path: String): Elements =
+ renderedContent(path).select("div.sourceset-dependent-content")
+
+ val Element.brief: String
+ get() = children().select("p").text()
+
+ val Element.rawBrief: String
+ get() = children().select("p").html()
+}
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/signatures/DivergentSignatureTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/signatures/DivergentSignatureTest.kt
new file mode 100644
index 00000000..509dd6e7
--- /dev/null
+++ b/dokka-subprojects/plugin-base/src/test/kotlin/signatures/DivergentSignatureTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package signatures
+
+import utils.TestOutputWriterPlugin
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+
+class DivergentSignatureTest : AbstractRenderingTest() {
+
+ @Test
+ fun `group { common + jvm + js }`() {
+
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testFromData(
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ val content = writerPlugin.renderedSourceDependentContent("example/example/-clock/get-time.html")
+
+ assertEquals(3, content.count())
+ val sourceSets = listOf("example/common", "example/js", "example/jvm")
+ sourceSets.forEach {
+ assertEquals("", content.select("[data-togglable=$it]").single().brief)
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `group { common + jvm }, group { js }`() {
+
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testFromData(
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ val content = writerPlugin.renderedSourceDependentContent("example/example/-clock/get-times-in-millis.html")
+
+ assertEquals(3, content.count())
+ assertEquals("Time in minis", content.select("[data-togglable=example/common]").single().brief)
+ assertEquals("Time in minis", content.select("[data-togglable=example/jvm]").single().brief)
+ assertEquals("JS implementation of getTimeInMillis", content.select("[data-togglable=example/js]").single().brief)
+ }
+ }
+ }
+
+ @Test
+ fun `group { js }, group { jvm }, group { js }`() {
+
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testFromData(
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ val content = writerPlugin.renderedSourceDependentContent("example/example/-clock/get-year.html")
+ assertEquals(3, content.count())
+ assertEquals("JVM custom kdoc", content.select("[data-togglable=example/jvm]").single().brief)
+ assertEquals("JS custom kdoc", content.select("[data-togglable=example/js]").single().brief)
+ assertEquals("", content.select("[data-togglable=example/common]").single().brief)
+ }
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt
new file mode 100644
index 00000000..13d1947f
--- /dev/null
+++ b/dokka-subprojects/plugin-base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package signatures
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jetbrains.dokka.jdk
+import utils.A
+import utils.Span
+import utils.TestOutputWriterPlugin
+import utils.match
+import kotlin.test.Ignore
+import kotlin.test.Test
+
+class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() {
+ private val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ classpath = listOf(commonStdlibPath!!, jvmStdlibPath!!)
+ externalDocumentationLinks = listOf(
+ stdlibExternalDocumentationLink,
+ DokkaConfiguration.ExternalDocumentationLink.Companion.jdk(8)
+ )
+ }
+ }
+ }
+
+ private val jvmConfiguration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ classpath = listOf(jvmStdlibPath ?: throw IllegalStateException("JVM stdlib is not found"))
+ externalDocumentationLinks = listOf(
+ stdlibExternalDocumentationLink,
+ DokkaConfiguration.ExternalDocumentationLink.Companion.jdk(8)
+ )
+ }
+ }
+ }
+
+ fun source(signature: String) =
+ """
+ |/src/main/kotlin/test/Test.kt
+ |package example
+ |
+ | $signature
+ """.trimIndent()
+
+ @Test
+ fun `kotlin normal function`() {
+ val source = source("val nF: Function1<Int, String> = { _ -> \"\" }")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match(
+ "val ", A("nF"), ": (", A("Int"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `kotlin syntactic sugar function`() {
+ val source = source("val nF: (Int) -> String = { _ -> \"\" }")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match(
+ "val ", A("nF"), ": (", A("Int"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `kotlin syntactic sugar extension function`() {
+ val source = source("val nF: Boolean.(Int) -> String = { _ -> \"\" }")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match(
+ "val ", A("nF"), ": ", A("Boolean"), ".(", A("Int"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `kotlin syntactic sugar function with param name`() {
+ val source = source("val nF: (param: Int) -> String = { _ -> \"\" }")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match(
+ "val ", A("nF"), ": (param: ", A("Int"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `kotlin syntactic sugar function with param name of generic and functional type`() {
+ val source = source("""
+ | @Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
+ | @MustBeDocumented
+ | annotation class Fancy
+ |
+ | fun <T> f(): (param1: T, param2: @Fancy ()->Unit) -> String "
+ """.trimIndent())
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source, configuration, pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").lastSignature().match(
+ "fun <", A("T"), "> ",
+ A("f"), "(): (param1:", A("T"),
+ ", param2: ", Span("@", A("Fancy")), " () -> ", A("Unit"),
+ ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+ @Ignore // Add coroutines on classpath and get proper import
+ @Test
+ fun `kotlin normal suspendable function`() {
+ val source = source("val nF: SuspendFunction1<Int, String> = { _ -> \"\" }")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match(
+ "val ", A("nF"), ": suspend (", A("Int"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `kotlin syntactic sugar suspendable function`() {
+ val source = source("val nF: suspend (Int) -> String = { _ -> \"\" }")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match(
+ "val ", A("nF"), ": suspend (", A("Int"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `kotlin syntactic sugar suspendable extension function`() {
+ val source = source("val nF: suspend Boolean.(Int) -> String = { _ -> \"\" }")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match(
+ "val ", A("nF"), ": suspend ", A("Boolean"), ".(", A("Int"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `kotlin syntactic sugar suspendable function with param name`() {
+ val source = source("val nF: suspend (param: Int) -> String = { _ -> \"\" }")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match(
+ "val ", A("nF"), ": suspend (param: ", A("Int"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `kotlin syntactic sugar suspendable fancy function with param name`() {
+ val source =
+ source("val nF: suspend (param1: suspend Boolean.(param2: List<Int>) -> Boolean) -> String = { _ -> \"\" }")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match(
+ "val ",
+ A("nF"),
+ ": suspend (param1: suspend",
+ A("Boolean"),
+ ".(param2: ",
+ A("List"),
+ "<",
+ A("Int"),
+ ">) -> ",
+ A("Boolean"),
+ ") -> ",
+ A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `java with java function`() {
+ val source = """
+ |/src/main/kotlin/test/JavaClass.java
+ |package example
+ |
+ |public class JavaClass {
+ | public java.util.function.Function<Integer, String> javaFunction = null;
+ |}
+ """.trimIndent()
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/-java-class/index.html").lastSignature().match(
+ "open var ", A("javaFunction"), ": (", A("Integer"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `java with kotlin function`() {
+ val source = """
+ |/src/main/kotlin/test/JavaClass.java
+ |package example
+ |
+ |public class JavaClass {
+ | public kotlin.jvm.functions.Function1<Integer, String> kotlinFunction = null;
+ |}
+ """.trimIndent()
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ jvmConfiguration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/-java-class/index.html").lastSignature().match(
+ "open var ", A("kotlinFunction"), ": (", A("Integer"), ") -> ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/signatures/InheritedAccessorsSignatureTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/signatures/InheritedAccessorsSignatureTest.kt
new file mode 100644
index 00000000..b5e2a9c3
--- /dev/null
+++ b/dokka-subprojects/plugin-base/src/test/kotlin/signatures/InheritedAccessorsSignatureTest.kt
@@ -0,0 +1,461 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package signatures
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import utils.A
+import utils.Span
+import utils.TestOutputWriterPlugin
+import utils.match
+import utils.OnlyDescriptors
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class InheritedAccessorsSignatureTest : BaseAbstractTest() {
+
+ private val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ classpath = listOf(
+ commonStdlibPath ?: throw IllegalStateException("Common stdlib is not found"),
+ jvmStdlibPath ?: throw IllegalStateException("JVM stdlib is not found")
+ )
+ externalDocumentationLinks = listOf(stdlibExternalDocumentationLink)
+ }
+ }
+ }
+
+ @OnlyDescriptors("'var' expected but found: 'open var'")
+ @Test
+ fun `should collapse accessor functions inherited from java into the property`() {
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ """
+ |/src/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; }
+ |}
+ |
+ |/src/test/B.kt
+ |package test
+ |class B : A {}
+ """.trimIndent(),
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/test/-b/index.html").let { kotlinClassContent ->
+ val signatures = kotlinClassContent.signature().toList()
+ assertEquals(
+ 3, signatures.size,
+ "Expected 3 signatures: class signature, constructor and property"
+ )
+
+ val property = signatures[2]
+ property.match(
+ "var ", A("a"), ":", A("Int"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+
+ writerPlugin.writer.renderedContent("root/test/-a/index.html").let { javaClassContent ->
+ val signatures = javaClassContent.signature().toList()
+ assertEquals(
+ 3, signatures.size,
+ "Expected 3 signatures: class signature, default constructor and property"
+ )
+
+ val property = signatures[2]
+ property.match(
+ "open var ", A("a"), ":", A("Int"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+ }
+
+ @OnlyDescriptors("'var' expected but found: 'open var'")
+ @Test
+ fun `should render as val if inherited java property has no setter`() {
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ """
+ |/src/test/A.java
+ |package test;
+ |public class A {
+ | private int a = 1;
+ | public int getA() { return a; }
+ |}
+ |
+ |/src/test/B.kt
+ |package test
+ |class B : A {}
+ """.trimIndent(),
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/test/-b/index.html").let { kotlinClassContent ->
+ val signatures = kotlinClassContent.signature().toList()
+ assertEquals(3, signatures.size, "Expected 3 signatures: class signature, constructor and property")
+
+ val property = signatures[2]
+ property.match(
+ "val ", A("a"), ":", A("Int"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+
+ writerPlugin.writer.renderedContent("root/test/-a/index.html").let { javaClassContent ->
+ val signatures = javaClassContent.signature().toList()
+ assertEquals(
+ 3,
+ signatures.size,
+ "Expected 3 signatures: class signature, default constructor and property"
+ )
+
+ val property = signatures[2]
+ property.match(
+ "open val ", A("a"), ":", A("Int"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `should keep inherited java setter as a regular function due to inaccessible property`() {
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ """
+ |/src/test/A.java
+ |package test;
+ |public class A {
+ | private int a = 1;
+ | public void setA(int a) { this.a = a; }
+ |}
+ |
+ |/src/test/B.kt
+ |package test
+ |class B : A {}
+ """.trimIndent(),
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/test/-b/index.html").let { kotlinClassContent ->
+ val signatures = kotlinClassContent.signature().toList()
+ assertEquals(3, signatures.size, "Expected 3 signatures: class signature, constructor and setter")
+
+ val setterFunction = signatures[2]
+ setterFunction.match(
+ "open fun ", A("setA"), "(", Parameters(
+ Parameter("a: ", A("Int"))
+ ), ")",
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+
+ writerPlugin.writer.renderedContent("root/test/-a/index.html").let { javaClassContent ->
+ val signatures = javaClassContent.signature().toList()
+ assertEquals(
+ 3,
+ signatures.size,
+ "Expected 3 signatures: class signature, default constructor and setter"
+ )
+
+ val setterFunction = signatures[2]
+ setterFunction.match(
+ "open fun ", A("setA"), "(", Parameters(
+ Parameter("a: ", A("Int"))
+ ), ")",
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+ }
+
+ @OnlyDescriptors("'var' expected but found: 'open var'")
+ @Test
+ fun `should keep inherited java accessor lookalikes if underlying function is public`() {
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ """
+ |/src/test/A.java
+ |package test;
+ |public class A {
+ | public int a = 1;
+ | public int getA() { return a; }
+ | public void setA(int a) { this.a = a; }
+ |}
+ |
+ |/src/test/B.kt
+ |package test
+ |class B : A {}
+ """.trimIndent(),
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ val signatures = writerPlugin.writer.renderedContent("root/test/-b/index.html").signature().toList()
+ assertEquals(
+ 5, signatures.size,
+ "Expected 5 signatures: class signature, constructor, property and two accessor lookalikes"
+ )
+
+ val getterLookalikeFunction = signatures[3]
+ getterLookalikeFunction.match(
+ "open fun ", A("getA"), "():", A("Int"),
+ ignoreSpanWithTokenStyle = true
+ )
+
+ val setterLookalikeFunction = signatures[4]
+ setterLookalikeFunction.match(
+ "open fun ", A("setA"), "(", Parameters(
+ Parameter("a: ", A("Int"))
+ ), ")",
+ ignoreSpanWithTokenStyle = true
+ )
+
+ val property = signatures[2]
+ property.match(
+ "var ", A("a"), ":", A("Int"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `should keep kotlin property with no accessors when java inherits kotlin a var`() {
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ """
+ |/src/test/JavaClass.java
+ |package test;
+ |public class JavaClass extends KotlinClass {}
+ |
+ |/src/test/KotlinClass.kt
+ |package test
+ |open class KotlinClass {
+ | var variable: String = "s"
+ |}
+ """.trimIndent(),
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/test/-java-class/index.html").let { kotlinClassContent ->
+ val signatures = kotlinClassContent.signature().toList()
+ assertEquals(
+ 3,
+ signatures.size,
+ "Expected to find 3 signatures: class, default constructor and property"
+ )
+
+ val property = signatures[2]
+ property.match(
+ "open var ", A("variable"), ": ", Span("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `kotlin property with compute get and set`() {
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ """
+ |/src/test/JavaClass.java
+ |package test;
+ |public class JavaClass extends KotlinClass {}
+ |
+ |/src/test/KotlinClass.kt
+ |package test
+ |open class KotlinClass {
+ | var variable: String
+ | get() = "asd"
+ | set(value) {}
+ |}
+ """.trimIndent(),
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/test/-kotlin-class/index.html").let { kotlinClassContent ->
+ val signatures = kotlinClassContent.signature().toList()
+ assertEquals(3, signatures.size, "Expected to find 3 signatures: class, constructor and property")
+
+ val property = signatures[2]
+ property.match(
+ "var ", A("variable"), ": ", A("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+
+ // it's actually unclear how it should react in this situation. It should most likely not
+ // break the abstraction and display it as a simple variable just like can be seen from Kotlin,
+ // test added to control changes
+ writerPlugin.writer.renderedContent("root/test/-java-class/index.html").let { javaClassContent ->
+ val signatures = javaClassContent.signature().toList()
+ assertEquals(
+ 4,
+ signatures.size,
+ "Expected to find 4 signatures: class, default constructor and two accessors"
+ )
+
+ val getter = signatures[2]
+ getter.match(
+ "fun ", A("getVariable"), "(): ", Span("String"),
+ ignoreSpanWithTokenStyle = true
+ )
+
+ val setter = signatures[3]
+ setter.match(
+ "fun ", A("setVariable"), "(", Parameters(
+ Parameter("value: ", Span("String"))
+ ), ")",
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+ }
+ }
+ }
+
+ @OnlyDescriptors("'var' expected but found: 'open var'")
+ @Test
+ fun `inherited property should inherit getter's visibility`() {
+ val configWithProtectedVisibility = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ classpath = listOf(
+ commonStdlibPath ?: throw IllegalStateException("Common stdlib is not found"),
+ jvmStdlibPath ?: throw IllegalStateException("JVM stdlib is not found")
+ )
+ externalDocumentationLinks = listOf(stdlibExternalDocumentationLink)
+ documentedVisibilities = setOf(
+ DokkaConfiguration.Visibility.PUBLIC,
+ DokkaConfiguration.Visibility.PROTECTED
+ )
+ }
+ }
+ }
+
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ """
+ |/src/test/JavaClass.java
+ |package test;
+ |public class JavaClass {
+ | private int protectedGetterAndProtectedSetter = 0;
+ |
+ | protected int getProtectedGetterAndProtectedSetter() {
+ | return protectedGetterAndProtectedSetter;
+ | }
+ |
+ | protected void setProtectedGetterAndProtectedSetter(int protectedGetterAndProtectedSetter) {
+ | this.protectedGetterAndProtectedSetter = protectedGetterAndProtectedSetter;
+ | }
+ |}
+ |
+ |/src/test/KotlinClass.kt
+ |package test
+ |open class KotlinClass : JavaClass() { }
+ """.trimIndent(),
+ configWithProtectedVisibility,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/test/-kotlin-class/index.html").let { kotlinClassContent ->
+ val signatures = kotlinClassContent.signature().toList()
+ assertEquals(3, signatures.size, "Expected 3 signatures: class signature, constructor and property")
+
+ val property = signatures[2]
+ property.match(
+ "protected var ", A("protectedGetterAndProtectedSetter"), ":", A("Int"),
+ ignoreSpanWithTokenStyle = true
+ )
+ }
+
+ writerPlugin.writer.renderedContent("root/tes