aboutsummaryrefslogtreecommitdiff
path: root/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains
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-javadoc/src/test/kotlin/org/jetbrains
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-javadoc/src/test/kotlin/org/jetbrains')
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt132
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/Asserts.kt22
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt93
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt54
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt461
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocDeprecatedTest.kt196
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt186
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocLocationTemplateMapTest.kt42
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocModuleTemplateMapTest.kt150
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocPackageTemplateMapTest.kt204
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocTest.kt4
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLinkingTest.kt78
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt272
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/packagelist/JavadocPackageListTest.kt80
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/search/JavadocIndexSearchTest.kt66
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/transformers/documentables/JavadocDocumentableJVMSourceSetFilterTest.kt94
-rw-r--r--dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt96
17 files changed, 2230 insertions, 0 deletions
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt
new file mode 100644
index 00000000..60265e33
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jetbrains.dokka.javadoc.location.JavadocLocationProvider
+import org.jetbrains.dokka.javadoc.pages.JavadocPageNode
+import org.jetbrains.dokka.javadoc.renderer.JavadocContentToTemplateMapTranslator
+import org.jetbrains.dokka.jdk
+import org.jetbrains.dokka.kotlinStdlib
+import org.jetbrains.dokka.model.withDescendants
+import org.jetbrains.dokka.pages.RootPageNode
+import org.jetbrains.dokka.plugability.*
+
+internal abstract class AbstractJavadocTemplateMapTest : BaseAbstractTest() {
+ protected var config: DokkaConfigurationImpl = dokkaConfiguration {
+ format = "javadoc"
+ suppressObviousFunctions = false
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src")
+ analysisPlatform = "jvm"
+ externalDocumentationLinks = listOf(
+ DokkaConfiguration.ExternalDocumentationLink.jdk(8),
+ DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib()
+ )
+ classpath = listOfNotNull(jvmStdlibPath)
+ }
+ }
+ }
+
+ data class Result(
+ val rootPageNode: RootPageNode,
+ val context: DokkaContext
+ ) {
+
+ val translator: JavadocContentToTemplateMapTranslator by lazy {
+ val locationProvider = context.plugin<JavadocPlugin>()
+ .querySingle { locationProviderFactory }
+ .getLocationProvider(rootPageNode) as JavadocLocationProvider
+
+ JavadocContentToTemplateMapTranslator(locationProvider, context)
+ }
+
+ val JavadocPageNode.templateMap: Map<String, Any?> get() = translator.templateMapForPageNode(this)
+
+ inline fun <reified T : JavadocPageNode> allPagesOfType(): List<T> {
+ return rootPageNode.withDescendants().filterIsInstance<T>().toList()
+ }
+
+ inline fun <reified T : JavadocPageNode> firstPageOfType(): T {
+ return rootPageNode.withDescendants().filterIsInstance<T>().first()
+ }
+
+ inline fun <reified T : JavadocPageNode> firstPageOfTypeOrNull(): T? {
+ return rootPageNode.withDescendants().filterIsInstance<T>().firstOrNull()
+ }
+
+ inline fun <reified T : JavadocPageNode> singlePageOfType(): T {
+ return rootPageNode.withDescendants().filterIsInstance<T>().single()
+ }
+ }
+
+ fun testTemplateMapInline(
+ query: String,
+ configuration: DokkaConfigurationImpl = config,
+ pluginsOverride: List<DokkaPlugin> = emptyList(),
+ assertions: Result.() -> Unit
+ ) {
+ testInline(query, configuration, pluginOverrides = pluginsOverride) {
+ renderingStage = { rootPageNode, dokkaContext ->
+ val preprocessors = dokkaContext.plugin<JavadocPlugin>().query { javadocPreprocessors }
+ val transformedRootPageNode = preprocessors.fold(rootPageNode) { acc, pageTransformer ->
+ pageTransformer(acc)
+ }
+
+ Result(transformedRootPageNode, dokkaContext).assertions()
+ }
+ }
+ }
+
+ fun dualTestTemplateMapInline(
+ kotlin: String? = null,
+ java: String? = null,
+ configuration: DokkaConfigurationImpl = config,
+ pluginsOverride: List<DokkaPlugin> = emptyList(),
+ assertions: Result.() -> Unit
+ ) {
+ val kotlinException = kotlin?.let {
+ runCatching {
+ testTemplateMapInline(
+ query = kotlin,
+ configuration = configuration,
+ pluginsOverride = pluginsOverride,
+ assertions = assertions
+ )
+ }.exceptionOrNull()
+ }
+
+ val javaException = java?.let {
+ runCatching {
+ testTemplateMapInline(
+ query = java,
+ configuration = configuration,
+ pluginsOverride = pluginsOverride,
+ assertions = assertions
+ )
+ }.exceptionOrNull()
+ }
+
+ if (kotlinException != null && javaException != null) {
+ throw AssertionError(
+ "Kotlin and Java Code failed assertions\n" +
+ "Kotlin: ${kotlinException.message}\n" +
+ "Java : ${javaException.message}",
+ kotlinException
+ )
+ }
+
+ if (kotlinException != null) {
+ throw AssertionError("Kotlin Code failed assertions", kotlinException)
+ }
+
+ if (javaException != null) {
+ throw AssertionError("Java Code failed assertions", javaException)
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/Asserts.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/Asserts.kt
new file mode 100644
index 00000000..2854ac7c
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/Asserts.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc
+
+import kotlin.contracts.ExperimentalContracts
+import kotlin.contracts.contract
+
+// TODO replace with assertIs<T> from kotlin-test as part of #2924
+@OptIn(ExperimentalContracts::class)
+inline fun <reified T> assertIsInstance(obj: Any?): T {
+ contract {
+ returns() implies (obj is T)
+ }
+
+ if (obj is T) {
+ return obj
+ }
+
+ throw AssertionError("Expected instance of type ${T::class.qualifiedName} but found $obj")
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt
new file mode 100644
index 00000000..95ce4d27
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc
+
+import org.jsoup.Jsoup
+import utils.TestOutputWriterPlugin
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+internal class JavadocAccessorNamingTest : AbstractJavadocTemplateMapTest() {
+
+ val configuration = dokkaConfiguration {
+ suppressObviousFunctions = true
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ classpath = listOfNotNull(jvmStdlibPath)
+ }
+ }
+ }
+
+ /**
+ * This is a quick sanity check for the AccessorMethodNamingTest
+ */
+ @Test
+ fun verifySpecialIsRuleIsApplied() {
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ """
+ /src/main/kotlin/sample/TestCase.kt
+ package sample
+
+ /**
+ * Test links:
+ * - [TestCase.issuesFetched]
+ * - [TestCase.isFoo]
+ */
+ data class TestCase(
+ var issuesFetched: Int,
+ var isFoo: String,
+ )
+ """.trimIndent(),
+ configuration,
+ cleanupOutput = false,
+ pluginOverrides = listOf(writerPlugin, JavadocPlugin())
+ ) {
+ renderingStage = { _, _ ->
+ val html = writerPlugin.writer.contents.getValue("sample/TestCase.html").let { Jsoup.parse(it) }
+ val props = html
+ .select("#memberSummary_tabpanel")
+ .select("th[scope=row].colSecond")
+ .select("code")
+ .map { it.text() }
+ .toSet()
+ // In K2 name of accessors parameter is `value`
+ assertTrue(
+ setOf(
+ "getIssuesFetched()",
+ "setIssuesFetched(Integer issuesFetched)",
+ "isFoo()",
+ "setFoo(String isFoo)",
+ ) == props || setOf(
+ "getIssuesFetched()",
+ "setIssuesFetched(Integer value)",
+ "isFoo()",
+ "setFoo(String value)",
+ ) == props
+ )
+
+ val descriptionLinks = html
+ .select("div.description")
+ .select("p")
+ .select("a")
+ .eachAttr("href")
+ .map { a -> a.takeLastWhile { it != '#' } }
+
+ assertEquals(setOf(
+ "issuesFetched",
+ "isFoo()",
+ ), descriptionLinks.toSet())
+
+ // Make sure that the ids from above actually exist
+ assertEquals(1, html.select("[id = isFoo()]").size)
+ // Bug! Nothing in the doc has the right id
+ assertEquals(0, html.select("[id = issuesFetched]").size)
+ }
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt
new file mode 100644
index 00000000..8d7ff1ea
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc
+
+import org.jetbrains.dokka.javadoc.pages.AllClassesPage
+import org.jetbrains.dokka.javadoc.pages.LinkJavadocListEntry
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.pages.ContentKind
+import org.junit.jupiter.api.Tag
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+internal class JavadocAllClassesTemplateMapTest : AbstractJavadocTemplateMapTest() {
+ @Test
+ @Tag("onlyDescriptors") // https://github.com/Kotlin/dokka/issues/3250
+ fun `two classes from different packages`() {
+ dualTestTemplateMapInline(
+ """
+ /src/source0.kt
+ package package0
+ /**
+ * Documentation for ClassA
+ */
+ class ClassA
+
+ /src/source1.kt
+ package package1
+ /**
+ * Documentation for ClassB
+ */
+ class ClassB
+ """
+ ) {
+ val map = singlePageOfType<AllClassesPage>().templateMap
+ assertEquals("main", map["kind"])
+ assertEquals("All Classes", map["title"])
+
+ val list = assertIsInstance<List<*>>(map["list"])
+ assertEquals(2, list.size, "Expected two classes")
+
+ val classA = assertIsInstance<LinkJavadocListEntry>(list[0])
+ assertEquals("ClassA", classA.name)
+ assertEquals(DRI("package0", "ClassA"), classA.dri.single())
+ assertEquals(ContentKind.Classlikes, classA.kind)
+
+ val classB = assertIsInstance<LinkJavadocListEntry>(list[1])
+ assertEquals("ClassB", classB.name)
+ assertEquals(DRI("package1", "ClassB"), classB.dri.single())
+ assertEquals(ContentKind.Classlikes, classB.kind)
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
new file mode 100644
index 00000000..fd382d42
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.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 org.jetbrains.dokka.javadoc
+
+import org.jetbrains.dokka.javadoc.pages.JavadocClasslikePageNode
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+internal class JavadocClasslikeTemplateMapTest : AbstractJavadocTemplateMapTest() {
+
+ @Test
+ fun `empty class`() {
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ /**
+ * Documentation for TestClass
+ */
+ class TestClass
+ """,
+ java =
+ """
+ /src/com/test/package0/TestClass.java
+ package com.test.package0;
+ /**
+ * Documentation for TestClass
+ */
+ public final class TestClass {}
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ assertEquals("TestClass", map["name"])
+ assertEquals("TestClass", map["title"])
+ assertEquals("com.test.package0", map["packageName"])
+ assertEquals("<p>Documentation for TestClass</p>", map["classlikeDocumentation"])
+ assertEquals("Documentation for TestClass", map["subtitle"])
+ assertEquals("public final class <a href=TestClass.html>TestClass</a>", map.signatureWithModifiers())
+ }
+ }
+
+ @Test
+ fun `single function`() {
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ /**
+ * Documentation for TestClass
+ */
+ class TestClass {
+ /**
+ * Documentation for testFunction
+ */
+ fun testFunction(): String = ""
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/TestClass.java
+ package com.test.package0
+ /**
+ * Documentation for TestClass
+ */
+ public final class TestClass {
+ /**
+ * Documentation for testFunction
+ */
+ public final String testFunction() {
+ return "";
+ }
+ }
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+
+ assertEquals("TestClass", map["name"])
+ assertEquals("TestClass", map["title"])
+ assertEquals("com.test.package0", map["packageName"])
+ assertEquals("<p>Documentation for TestClass</p>", map["classlikeDocumentation"])
+ assertEquals("Documentation for TestClass", map["subtitle"])
+ assertEquals("public final class", map.modifiers())
+ assertEquals("<a href=TestClass.html>TestClass</a>", map.signatureWithoutModifiers())
+
+ val methods = assertIsInstance<Map<Any, Any?>>(map["methods"])
+ val ownMethods = assertIsInstance<List<*>>(methods["own"])
+ assertEquals(1, ownMethods.size, "Expected only one method")
+ val method = assertIsInstance<Map<String, Any?>>(ownMethods.single())
+ assertEquals("Documentation for testFunction", method["brief"])
+ assertEquals("testFunction", method["name"])
+ assertEquals(
+ 0, assertIsInstance<List<*>>(method["parameters"]).size,
+ "Expected no parameters"
+ )
+ assertEquals("final <a href=https://docs.oracle.com/javase/8/docs/api/java/lang/String.html>String</a>", method.modifiers())
+ assertEquals("<a href=TestClass.html#testFunction()>testFunction</a>()", method.signatureWithoutModifiers())
+ }
+ }
+
+ @Test
+ fun `class with annotation`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ @MustBeDocumented
+ annotation class Author(val name: String)
+
+ @Author(
+ name = "Benjamin Franklin"
+ )
+ class TestClass {`
+
+ @Author(
+ name = "Franklin D. Roosevelt"
+ )
+ fun testFunction(): String = ""
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/Author.java
+ package com.test.package0
+ import java.lang.annotation.Documented;
+
+ @Documented
+ public @interface Author {
+ String name();
+ }
+ /src/com/test/package0/TestClass.java
+ package com.test.package0
+
+ @Author(
+ name = "Benjamin Franklin"
+ )
+ public final class TestClass {
+
+ @Author(
+ name = "Franklin D. Roosevelt"
+ )
+ public final String testFunction() {
+ return "";
+ }
+ }
+ """
+ ){
+ val map = allPagesOfType<JavadocClasslikePageNode>().first { it.name == "TestClass" }.templateMap
+ assertEquals("TestClass", map["name"])
+ val signature = assertIsInstance<Map<String, Any?>>(map["signature"])
+ assertEquals("@<a href=Author.html>Author</a>(name = &quot;Benjamin Franklin&quot;)", signature["annotations"])
+
+ val methods = assertIsInstance<Map<Any, Any?>>(map["methods"])
+ val ownMethods = assertIsInstance<List<*>>(methods["own"])
+ val method = assertIsInstance<Map<String, Any?>>(ownMethods.single())
+ val methodSignature = assertIsInstance<Map<String, Any?>>(method["signature"])
+ assertEquals("@<a href=Author.html>Author</a>(name = &quot;Franklin D. Roosevelt&quot;)", methodSignature["annotations"])
+ }
+ }
+
+ @Test
+ fun `simple enum`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ enum class ClockDays {
+ /**
+ * Sample docs for first
+ */
+ FIRST,
+ /**
+ * Sample docs for second
+ */
+ SECOND
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/TestClass.java
+ package com.test.package0;
+ public enum ClockDays {
+ /**
+ * Sample docs for first
+ */
+ FIRST,
+ /**
+ * Sample docs for second
+ */
+ SECOND
+ }
+ """
+ ){
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ assertEquals("ClockDays", map["name"])
+ assertEquals("enum", map["kind"])
+ val entries = assertIsInstance<List<Map<String, Any?>>>(map["entries"])
+ assertEquals(2, entries.size)
+
+ val (first, second) = entries.sortedBy { it["brief"] as String }
+ assertEquals("<p>Sample docs for first</p>", first["brief"])
+ assertEquals("<p>Sample docs for second</p>", second["brief"])
+
+ assertEquals("<a href=ClockDays.html#FIRST>FIRST</a>", first.signatureWithoutModifiers())
+ assertEquals("<a href=ClockDays.html#SECOND>SECOND</a>", second.signatureWithoutModifiers())
+ }
+ }
+
+ @Test
+ fun `documented function parameters`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ class TestClass {
+ /**
+ * Simple parameters list to check out
+ * @param simple simple String parameter
+ * @param parameters simple Integer parameter
+ * @param list simple Boolean parameter
+ * @return just a String
+ */
+ fun testFunction(simple: String?, parameters: Int?, list: Boolean?): String {
+ return ""
+ }
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/TestClass.java
+ package com.test.package0;
+ public final class TestClass {
+ /**
+ * Simple parameters list to check out
+ * @param simple simple String parameter
+ * @param parameters simple Integer parameter
+ * @param list simple Boolean parameter
+ * @return just a String
+ */
+ public final String testFunction(String simple, Integer parameters, Boolean list) {
+ return "";
+ }
+ }
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ assertEquals("TestClass", map["name"])
+
+ val methods = assertIsInstance<Map<String, Any?>>(map["methods"])
+ val testFunction = assertIsInstance<List<Map<String, Any?>>>(methods["own"]).single()
+ assertEquals("Simple parameters list to check out", testFunction["brief"])
+
+ val (first, second, third) = assertIsInstance<List<Map<String, Any?>>>(testFunction["parameters"])
+ assertParameterNode(
+ node = first,
+ expectedName = "simple",
+ expectedType = "<a href=https://docs.oracle.com/javase/8/docs/api/java/lang/String.html>String</a>",
+ expectedDescription = "simple String parameter"
+ )
+ assertParameterNode(
+ node = second,
+ expectedName = "parameters",
+ expectedType = "<a href=https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html>Integer</a>",
+ expectedDescription = "simple Integer parameter"
+ )
+ assertParameterNode(
+ node = third,
+ expectedName = "list",
+ expectedType = "<a href=https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html>Boolean</a>",
+ expectedDescription = "simple Boolean parameter"
+ )
+ }
+ }
+
+ @Test
+ fun `with generic parameters`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ import java.io.Serializable
+
+ class Generic<T : Serializable?> {
+ fun <D : T> sampleFunction(): D = TODO()
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/Generic.java
+ package com.test.package0;
+ import java.io.Serializable;
+
+ public final class Generic<T extends Serializable> {
+ public final <D extends T> D sampleFunction(){
+ return null;
+ }
+ }
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ assertEquals("Generic", map["name"])
+
+ assertEquals(
+ "public final class <a href=Generic.html>Generic</a>&lt;T extends <a href=https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html>Serializable</a>&gt;",
+ map.signatureWithModifiers()
+ )
+ val methods = assertIsInstance<Map<Any, Any?>>(map["methods"])
+ val ownMethods = assertIsInstance<List<*>>(methods["own"]).first()
+ val sampleFunction = assertIsInstance<Map<String, Any?>>(ownMethods)
+
+ assertEquals("final &lt;D extends <a href=Generic.html>T</a>&gt; <a href=Generic.html#sampleFunction()>D</a> <a href=Generic.html#sampleFunction()>sampleFunction</a>()", sampleFunction.signatureWithModifiers())
+ }
+ }
+
+ @Test
+ fun `class with top-level const`() {
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/Test.kt
+ package com.test.package0
+
+ const val TEST_VAL = "test"
+ """,
+ java =
+ """
+ /src/com/test/package0/TestKt.java
+ package com.test.package0;
+
+ public final class TestKt {
+ public static final String TEST_VAL = "test";
+ }
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ val properties = assertIsInstance<List<*>>(map["properties"])
+ val property = assertIsInstance<Map<String, Any?>>(properties.first())
+ assertEquals("public final static <a href=https://docs.oracle.com/javase/8/docs/api/java/lang/String.html>String</a> <a href=TestKt.html#TEST_VAL>TEST_VAL</a>", "${property["modifiers"]} ${property["signature"]}")
+ }
+ }
+
+ @Test
+ fun `@author @since @return method tags`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ class TestClass {
+ /**
+ * Testing @author @since @return method tags
+ * @since 1.2
+ * @since 08 april 2023
+ * @return parameter's value in lower case
+ */
+ fun testFunction(testParam: String?): String {
+ return testParam?.lowercase() ?: ""
+ }
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/TestClass.java
+ package com.test.package0;
+ public final class TestClass {
+ /**
+ * Testing @author @since @return method tags
+ * @since 1.2
+ * @since 08 april 2023
+ * @return parameter's value in lower case
+ */
+ public final String testFunction(String testParam) {
+ return testParam.toLowerCase();
+ }
+ }
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ assertEquals("TestClass", map["name"])
+
+ val methods = assertIsInstance<Map<String, Any?>>(map["methods"])
+ val testFunction = assertIsInstance<List<Map<String, Any?>>>(methods["own"]).single()
+ assertEquals("Testing @author @since @return method tags", testFunction["brief"])
+
+ assertEquals("testFunction", testFunction["name"])
+ assertEquals(listOf("<p>1.2</p>", "<p>08 april 2023</p>"), testFunction["sinceTagContent"])
+ assertEquals("<p>parameter's value in lower case</p>", testFunction["returnTagContent"])
+ }
+ }
+
+ @Test
+ fun `@author @since class tags`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ /**
+ * Testing @author @since class tags
+ * @author Test Author
+ * @author Test Author2
+ * @author Test Author3
+ * @since 1.2
+ * @since 08 april 2023
+ */
+ class TestClass {
+ fun testFunction(testParam: String?): String {
+ return testParam?.lowercase() ?: ""
+ }
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/TestClass.java
+ package com.test.package0;
+ /**
+ * Testing @author @since class tags
+ * @author Test Author
+ * @author Test Author2
+ * @author Test Author3
+ * @since 1.2
+ * @since 08 april 2023
+ */
+ public final class TestClass {
+ public final String testFunction(String testParam) {
+ return testParam.toLowerCase();
+ }
+ }
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+
+ assertEquals("TestClass", map["name"])
+ assertEquals("<p>Testing @author @since class tags</p>", map["classlikeDocumentation"])
+ assertEquals(listOf("<p>Test Author</p>", "<p>Test Author2</p>", "<p>Test Author3</p>"), map["authorTagContent"])
+ assertEquals(listOf("<p>1.2</p>", "<p>08 april 2023</p>"), map["sinceTagContent"])
+ }
+ }
+
+ private fun assertParameterNode(node: Map<String, Any?>, expectedName: String, expectedType: String, expectedDescription: String){
+ assertEquals(expectedName, node["name"])
+ assertEquals(expectedType, node["type"])
+ assertEquals(expectedDescription, node["description"])
+ }
+
+ private fun Map<String, Any?>.signatureWithModifiers(): String = "${modifiers()} ${signatureWithoutModifiers()}"
+
+ @Suppress("UNCHECKED_CAST")
+ private fun Map<String, Any?>.signatureWithoutModifiers(): String = (get("signature") as Map<String, Any?>)["signatureWithoutModifiers"] as String
+
+ @Suppress("UNCHECKED_CAST")
+ private fun Map<String, Any?>.modifiers(): String = (get("signature") as Map<String, Any?>)["modifiers"] as String
+
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocDeprecatedTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocDeprecatedTest.kt
new file mode 100644
index 00000000..404e1aed
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocDeprecatedTest.kt
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc
+
+import org.jetbrains.dokka.javadoc.pages.DeprecatedPage
+import org.jetbrains.dokka.javadoc.renderer.TemplateMap
+import org.junit.jupiter.api.Tag
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+internal class JavadocDeprecatedTest : AbstractJavadocTemplateMapTest() {
+
+ @Test
+ fun `generates correct number of sections`() {
+ testDeprecatedPageTemplateMaps { templateMap ->
+ @Suppress("UNCHECKED_CAST")
+ assertEquals(6, (templateMap["sections"] as List<TemplateMap>).size)
+ }
+ }
+
+ @Test
+ fun `finds correct number of element for removal`() {
+ testDeprecatedPageTemplateMaps { templateMap ->
+ val map = templateMap.section("For Removal")
+ assertEquals(1, map.elements().size)
+ }
+ }
+
+ @Test
+ fun `finds correct number of deprecated constructors`() {
+ testDeprecatedPageTemplateMaps { templateMap ->
+ val map = templateMap.section("Constructors")
+ assertEquals(1, map.elements().size)
+ }
+ }
+
+ @Test
+ fun `finds correct number of deprecated classes`() {
+ testDeprecatedPageTemplateMaps { templateMap ->
+ val map = templateMap.section("Classes")
+ assertEquals(1, map.elements().size)
+ }
+ }
+
+ @Test
+ fun `finds correct number of deprecated enums`() {
+ testDeprecatedPageTemplateMaps { templateMap ->
+ val map = templateMap.section("Enums")
+ assertEquals(1, map.elements().size)
+ }
+ }
+
+ @Test
+ fun `finds correct number of deprecated exceptions`() {
+ testDeprecatedPageTemplateMaps { templateMap ->
+ val map = templateMap.section("Exceptions")
+ assertEquals(2, map.elements().size)
+ }
+ }
+
+ @Tag("onlyDescriptors") // https://github.com/Kotlin/dokka/issues/3266 - `describeConstable` is in deprecated page on Java 17
+ @Test
+ fun `finds correct number of deprecated methods`() {
+ testDeprecatedPageTemplateMaps { templateMap ->
+ //We are checking whether we will have an additional function for enum classes
+ fun hasAdditionalFunction() =
+ AnnotationTarget.ANNOTATION_CLASS::class.java.methods.any { it.name == "describeConstable" }
+
+ val map = templateMap.section("Methods")
+ assertEquals(if (hasAdditionalFunction()) 5 else 4, map.elements().size)
+ }
+ }
+
+ @Test
+ fun `should be sorted by position`() {
+ testDeprecatedPageTemplateMaps { templateMap ->
+ @Suppress("UNCHECKED_CAST")
+ val contents = (templateMap["sections"] as List<TemplateMap>).map { it["caption"] }
+
+ // maybe some other ordering is required by the javadoc spec
+ // but it has to be deterministic
+ val expected = "Classes, Exceptions, Methods, Constructors, Enums, For Removal"
+ val actual = contents.joinToString(separator = ", ")
+
+ assertEquals(expected, actual)
+ }
+ }
+
+ @Test
+ fun `provides correct information for deprecated element`() {
+ testDeprecatedPageTemplateMaps { templateMap ->
+ val map = templateMap.section("Enums")
+ map.elements().first().let { element ->
+ assertEquals("package1.ClassCEnum", element["name"])
+ assertEquals("package1/ClassCEnum.html", element["address"])
+ assertEquals("Documentation for ClassCEnum", element["description"])
+ }
+ }
+ }
+
+ private val query = """
+ /src/source0.kt
+ package package0
+ /**
+ * Documentation for ClassA
+ */
+ @Deprecated("Bo tak")
+ class ClassA {
+ fun a() {}
+ @Deprecated("Bo tak")
+ fun b() {}
+ fun c() {}
+ }
+
+ /src/source1.kt
+ package package1
+ /**
+ * Documentation for ClassB
+ */
+ class ClassB {
+ fun d() {}
+ @Deprecated("Bo tak")
+ fun e() {}
+ @Deprecated("Bo tak")
+ fun f() {}
+ }
+
+ /src/source2.kt
+ package package1
+ /**
+ * Documentation for ClassB
+ */
+ class ClassC {
+ fun g() {}
+ fun h() {}
+ fun j() {}
+
+ class InnerClass {
+ fun k() {}
+ }
+ }
+
+ /src/source3.kt
+ package package1
+ /**
+ * Documentation for ClassCEnum
+ */
+ @Deprecated("Bo tak")
+ enum class ClassCEnum {
+ A, D, E
+ }
+
+ /src/source4.java
+ package package1;
+ /**
+ * Documentation for ClassJava
+ */
+ public class ClassJava {
+ @Deprecated
+ public ClassJava() {}
+ @Deprecated(forRemoval = true)
+ public void deprecatedMethod() {}
+ }
+
+ /src/source5.java
+ package package1;
+ /**
+ * Documentation for ClassJavaException
+ */
+ @Deprecated
+ public class ClassJavaException extends Exception { }
+
+ /src/source6.kt
+ package package1
+ /**
+ * Documentation for ClassKotlinException
+ */
+ @Deprecated
+ class ClassKotlinException: Exception() {}
+ """.trimIndent()
+
+ private fun testDeprecatedPageTemplateMaps(operation: (TemplateMap) -> Unit) =
+ testTemplateMapInline(query) {
+ operation(firstPageOfType<DeprecatedPage>().templateMap)
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun TemplateMap.section(name: String) =
+ (this["sections"] as List<TemplateMap>).first { it["caption"] == name }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun TemplateMap.elements() =
+ this["elements"] as List<TemplateMap>
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt
new file mode 100644
index 00000000..e574aeac
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc
+
+import org.jetbrains.dokka.javadoc.pages.IndexPage
+import org.jetbrains.dokka.javadoc.renderer.TemplateMap
+import org.jetbrains.dokka.links.DRI
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+
+internal class JavadocIndexTest : AbstractJavadocTemplateMapTest() {
+
+ private val commonTestQuery = """
+ /src/source0.kt
+ package package0
+ /**
+ * Documentation for ClassA
+ */
+ class ClassA {
+ fun a() {}
+ fun b() {}
+ fun c() {}
+ }
+
+ /src/source1.kt
+ package package1
+ /**
+ * Documentation for ClassB
+ */
+ class ClassB {
+ fun d() {}
+ fun e() {}
+ fun f() {}
+ }
+
+ /src/source2.kt
+ package package1
+ /**
+ * Documentation for ClassB
+ */
+ class ClassC {
+ fun g() {}
+ fun h() {}
+ fun j() {}
+
+ class InnerClass {
+ fun k() {}
+ }
+ }
+
+ /src/source3.kt
+ package package1
+ /**
+ * Documentation for ClassCEnum
+ */
+ enum class ClassCEnum {
+ A, D, E
+ }
+ """.trimIndent()
+
+ @Test
+ fun `generates correct number of index pages`() {
+ testIndexPages(commonTestQuery) { indexPages ->
+ // index pages with letters of the alphabet, so A, B, C, D, E, etc
+ assertEquals(13, indexPages.size)
+ }
+ }
+
+ @Test
+ fun `handles correct number of elements`() {
+ //We are checking whether we will have an additional function for enum classes
+ // e.g. since Java 12 it has `describeConstable`
+ fun hasAdditionalFunction() =
+ AnnotationTarget.ANNOTATION_CLASS::class.java.methods.any { it.name == "describeConstable" }
+
+ testIndexPages(commonTestQuery) { indexPages ->
+ assertEquals("A-index: a, A\n" +
+ "B-index: b\n" +
+ "C-index: c, ClassA, ClassB, ClassC, ClassC.InnerClass, ClassCEnum, compareTo\n" +
+ (if (hasAdditionalFunction()) "D-index: d, D, describeConstable\n" else "D-index: d, D\n") +
+ "E-index: e, E, equals, equals\n" +
+ "F-index: f\n" +
+ "G-index: g, getDeclaringClass, getEntries, getName, getOrdinal\n" +
+ "H-index: h, hashCode, hashCode\n" +
+ "J-index: j\n" +
+ "K-index: k\n" +
+ "P-index: package0, package1\n" +
+ "T-index: toString, toString\n" +
+ "V-index: valueOf, values",
+ indexPages.joinToString("\n") { it.title + ": " + it.elements.joinToString { it.getId() } })
+ assertEquals(if (hasAdditionalFunction()) 34 else 33, indexPages.sumBy { it.elements.size })
+ }
+ }
+
+ @Test
+ fun `templateMap for class index`() {
+ testIndexPagesTemplateMaps(commonTestQuery) { templateMaps ->
+ @Suppress("UNCHECKED_CAST")
+ val element = (templateMaps[2]["elements"] as List<TemplateMap>)[1]
+ assertEquals("../package0/ClassA.html", element["address"])
+ assertEquals("ClassA", element["name"])
+ assertEquals("class", element["type"])
+ assertEquals("Documentation for ClassA", element["description"])
+ assertEquals("package0", element["origin"])
+
+ }
+ }
+
+ @Test
+ fun `templateMap for enum entry index`() {
+ testIndexPagesTemplateMaps(commonTestQuery) { templateMaps ->
+ @Suppress("UNCHECKED_CAST")
+ val element = (templateMaps[0]["elements"] as List<TemplateMap>).last()
+ assertEquals("../package1/ClassCEnum.html#A", element["address"])
+ assertEquals("A", element["name"])
+ assertEquals("enum entry", element["type"])
+ assertEquals("&nbsp;", element["description"])
+ assertEquals("package1.<a href=../package1/ClassCEnum.html>ClassCEnum</a>", element["origin"])
+
+ }
+ }
+
+ @Test
+ fun `templateMap for function index`() {
+ testIndexPagesTemplateMaps(commonTestQuery) { templateMaps ->
+ @Suppress("UNCHECKED_CAST")
+ val element = (templateMaps[0]["elements"] as List<TemplateMap>).first()
+ assertEquals("../package0/ClassA.html#a()", element["address"])
+ assertEquals("a()", element["name"])
+ assertEquals("function", element["type"])
+ assertEquals("&nbsp;", element["description"])
+ assertEquals("package0.<a href=../package0/ClassA.html>ClassA</a>", element["origin"])
+
+ }
+ }
+
+ @Test
+ fun `should sort overloaded functions deterministically`() {
+ val query = """
+ /src/overloaded.kt
+ package overloaded
+
+ class Clazz {
+ fun funName(param: List<String>) {}
+ fun funName(param: String) {}
+ fun funName(param: Map<String, String>>) {}
+ fun funName(param: Int) {}
+ }
+ """.trimIndent()
+
+ testIndexPages(query) { allPages ->
+ val indexPage = allPages.find { it.elements.any { el -> el.getId() == "funName" } }
+ assertNotNull(indexPage) { "Index page with functions not found" }
+
+ val indexElementDRIs = indexPage.elements.map { it.getDRI() }
+ assertEquals(4, indexElementDRIs.size)
+ indexElementDRIs.forEach {
+ assertEquals("overloaded", it.packageName)
+ assertEquals("Clazz", it.classNames)
+ assertEquals("funName", it.callable!!.name)
+ assertEquals(1, it.callable!!.params.size)
+ }
+
+ assertEquals("kotlin.Int", indexElementDRIs[0].getParam(0))
+ assertEquals("kotlin.String", indexElementDRIs[1].getParam(0))
+ assertEquals("kotlin.collections.List[kotlin.String]", indexElementDRIs[2].getParam(0))
+ assertEquals("kotlin.collections.Map[kotlin.String,kotlin.String]", indexElementDRIs[3].getParam(0))
+ }
+ }
+
+ private fun DRI.getParam(index: Int) = this.callable!!.params[index].toString()
+
+ private fun testIndexPages(query: String, operation: (List<IndexPage>) -> Unit) {
+ testTemplateMapInline(query) {
+ operation(allPagesOfType())
+ }
+ }
+
+ private fun testIndexPagesTemplateMaps(query: String, operation: (List<TemplateMap>) -> Unit) =
+ testTemplateMapInline(query) {
+ operation(allPagesOfType<IndexPage>().map { it.templateMap })
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocLocationTemplateMapTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocLocationTemplateMapTest.kt
new file mode 100644
index 00000000..1e11dd39
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocLocationTemplateMapTest.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc
+
+import org.jetbrains.dokka.javadoc.pages.JavadocClasslikePageNode
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+internal class JavadocLocationTemplateMapTest : AbstractJavadocTemplateMapTest() {
+ @Test
+ fun `should have correct location to root from class`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ /**
+ * Documentation for TestClass
+ */
+ class TestClass
+ """,
+ java =
+ """
+ /src/com/test/package0/TestClass.java
+ package com.test.package0;
+ /**
+ * Documentation for TestClass
+ */
+ public final class TestClass {}
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ assertEquals("TestClass", map["name"])
+ assertEquals("TestClass", map["title"])
+ //This is taken from the expected location of files based on the package, so:
+ //com -> test -> package0
+ assertEquals("../../../", map["pathToRoot"])
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocModuleTemplateMapTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocModuleTemplateMapTest.kt
new file mode 100644
index 00000000..674c9af3
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocModuleTemplateMapTest.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc
+
+import org.jetbrains.dokka.javadoc.pages.JavadocModulePageNode
+import org.jetbrains.dokka.javadoc.pages.RowJavadocListEntry
+import org.jetbrains.dokka.links.DRI
+import java.io.File
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+internal class JavadocModuleTemplateMapTest : AbstractJavadocTemplateMapTest() {
+
+ @Test
+ fun singleEmptyClass() {
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source.kt
+ package com.test.package
+ class Test
+ """,
+ java =
+ """
+ /src/com/test/package/Source.java
+ package com.test.package;
+ public class Test { }
+ """
+ ) {
+ val moduleTemplateMap = singlePageOfType<JavadocModulePageNode>().templateMap
+ assertEquals("main", moduleTemplateMap["kind"])
+ assertEquals("root", moduleTemplateMap["title"])
+ assertEquals("", moduleTemplateMap["subtitle"])
+ assertEquals("Packages", moduleTemplateMap["tabTitle"])
+ assertEquals("Package", moduleTemplateMap["colTitle"])
+ assertEquals("", moduleTemplateMap["pathToRoot"])
+
+ val list = moduleTemplateMap["list"] as List<*>
+ assertEquals(1, list.size, "Expected only one entry in 'list'")
+ val rowListEntry = assertIsInstance<RowJavadocListEntry>(list.first())
+
+ assertEquals("com.test", rowListEntry.link.name)
+ assertEquals(DRI("com.test"), rowListEntry.link.dri.single())
+ }
+ }
+
+ @Test
+ fun multiplePackages() {
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ class Test0
+
+ /src/source1.kt
+ package com.test.package1
+ class Test1
+ """,
+ java =
+ """
+ /src/com/test/package0/Test0.java
+ package com.test.package0;
+ public class Test0 {}
+
+ /src/com/test/package1/Test1.java
+ package com.test.package1;
+ public class Test1 {}
+ """,
+ configuration = config.copy(moduleVersion = "1.2.3-SNAPSHOT")
+ ) {
+ val moduleTemplateMap = singlePageOfType<JavadocModulePageNode>().templateMap
+ assertEquals("1.2.3-SNAPSHOT", moduleTemplateMap["version"])
+ val list = assertIsInstance<List<*>>(moduleTemplateMap["list"])
+ assertEquals(2, list.size, "Expected two entries in 'list'")
+ assertEquals("com.test.package0", assertIsInstance<RowJavadocListEntry>(list[0]).link.name)
+ assertEquals("com.test.package1", assertIsInstance<RowJavadocListEntry>(list[1]).link.name)
+ assertEquals(DRI("com.test.package0"), assertIsInstance<RowJavadocListEntry>(list[0]).link.dri.single())
+ assertEquals(DRI("com.test.package1"), assertIsInstance<RowJavadocListEntry>(list[1]).link.dri.single())
+ }
+ }
+
+ @Test
+ fun `single class with module documentation (kotlin)`() {
+ testTemplateMapInline(
+ query =
+ """
+ /src/module.md
+ # Module module1
+ ABC
+
+ /src/source0.kt
+ package com.test.package0
+ class Test
+ """,
+ configuration = config.copy(
+ sourceSets = config.sourceSets.map { sourceSet ->
+ sourceSet.copy(
+ includes = setOf(File("src/module.md"))
+ )
+ },
+ moduleName = "module1"
+ )
+ ) {
+ val modulePage = singlePageOfType<JavadocModulePageNode>()
+
+ val map = modulePage.templateMap
+ assertEquals("<p>ABC</p>", map["subtitle"].toString().trim())
+ }
+ }
+
+ @Test
+ fun `single class with long module documentation (kotlin)`() {
+ testTemplateMapInline(
+ query =
+ """
+ /src/module.md
+ # Module module1
+ Aliquam rerum est vel. Molestiae eos expedita animi repudiandae sed commodi.
+ Omnis qui ducimus ut et perspiciatis sint.
+
+ Veritatis nam eaque sequi laborum voluptas voluptate aut.
+
+ /src/source0.kt
+ package com.test.package0
+ class Test
+ """,
+ configuration = config.copy(
+ sourceSets = config.sourceSets.map { sourceSet ->
+ sourceSet.copy(
+ includes = setOf(File("src/module.md"))
+ )
+ },
+ moduleName = "module1"
+ )
+ ) {
+ val modulePage = singlePageOfType<JavadocModulePageNode>()
+
+ val map = modulePage.templateMap
+ val expectedText = """
+ <p>Aliquam rerum est vel. Molestiae eos expedita animi repudiandae sed commodi.
+ Omnis qui ducimus ut et perspiciatis sint.</p>
+ <p>Veritatis nam eaque sequi laborum voluptas voluptate aut.</p>
+ """.trimIndent().replace("\n", "")
+ assertEquals(expectedText, map["subtitle"].toString().trim())
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocPackageTemplateMapTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocPackageTemplateMapTest.kt
new file mode 100644
index 00000000..12e2485e
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocPackageTemplateMapTest.kt
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc
+
+import org.jetbrains.dokka.javadoc.pages.JavadocContentKind
+import org.jetbrains.dokka.javadoc.pages.JavadocPackagePageNode
+import org.jetbrains.dokka.javadoc.pages.RowJavadocListEntry
+import org.jetbrains.dokka.links.DRI
+import java.io.File
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+internal class JavadocPackageTemplateMapTest : AbstractJavadocTemplateMapTest() {
+
+ @Test
+ @Suppress("UNCHECKED_CAST")
+ fun `single class`() {
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source.kt
+ package com.test.package0
+ class Test
+ """,
+ java =
+ """
+ /src/com/test/package0/Test.java
+ package com.test.package0;
+ public class Test {}
+ """
+ ) {
+ val map = singlePageOfType<JavadocPackagePageNode>().templateMap
+ assertEquals("Class Summary", ((map["lists"] as List<*>).first() as Map<String, *>)["tabTitle"])
+ assertEquals("Class", ((map["lists"] as List<*>).first() as Map<String, *>)["colTitle"])
+ assertEquals("Package com.test.package0", map["title"])
+ assertEquals("", map["subtitle"])
+ assertEquals("package", map["kind"])
+
+ val list = assertIsInstance<List<*>>(((map["lists"] as List<*>).first() as Map<String, *>)["list"])
+ val entry = assertIsInstance<RowJavadocListEntry>(list.single())
+ assertEquals("Test", entry.link.name)
+ assertEquals(JavadocContentKind.Class, entry.link.kind)
+ assertEquals(DRI("com.test.package0", "Test"), entry.link.dri.single())
+ }
+ }
+
+ @Test
+ @Suppress("UNCHECKED_CAST")
+ fun `multiple packages`() {
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ class Test0
+
+ /src/source1.kt
+ package com.test.package1
+ class Test1
+ """,
+ java =
+ """
+ /src/com/test/package0/Test0.java
+ package com.test.package0;
+ public class Test0 {}
+
+ /src/com/test/package1/Test1.java
+ package com.test.package1;
+ public class Test1 {}
+ """
+ ) {
+ val packagePages = allPagesOfType<JavadocPackagePageNode>()
+ packagePages.forEach { page ->
+ val map = page.templateMap
+ assertEquals("Class Summary", ((map["lists"] as List<*>).first() as Map<String, *>)["tabTitle"])
+ assertEquals("Class", ((map["lists"] as List<*>).first() as Map<String, *>)["colTitle"])
+ assertEquals("", map["subtitle"])
+ assertEquals("package", map["kind"])
+ }
+
+ assertEquals(2, packagePages.size, "Expected two package pages")
+ }
+ }
+
+ @Test
+ fun `single class with package documentation (java)`() {
+ testTemplateMapInline(
+ query =
+ """
+ /src/com/test/package0/package-info.java
+ /**
+ * ABC
+ */
+ package com.test.package0;
+
+ /src/com/test/package0/Test.java
+ package com.test.package0;
+ public class Test{}
+ """
+ ) {
+ val packagePage = singlePageOfType<JavadocPackagePageNode>()
+
+ val map = packagePage.templateMap
+ assertEquals("<p>ABC</p>", map["subtitle"].toString().trim())
+ }
+ }
+
+ @Test
+ fun `single class with package documentation (kotlin)`() {
+ testTemplateMapInline(
+ query =
+ """
+ /src/packages.md
+ # Package com.test.package0
+ ABC
+
+ /src/source0.kt
+ package com.test.package0
+ class Test
+ """,
+ configuration = config.copy(
+ sourceSets = config.sourceSets.map { sourceSet ->
+ sourceSet.copy(
+ includes = setOf(File("src/packages.md"))
+ )
+ }
+ )
+ ) {
+ val packagePage = singlePageOfType<JavadocPackagePageNode>()
+
+ val map = packagePage.templateMap
+ assertEquals("<p>ABC</p>", map["subtitle"].toString().trim())
+ }
+ }
+
+ @Test
+ fun `single class with long package documentation (java)`() {
+ testTemplateMapInline(
+ query =
+ """
+ /src/com/test/package0/package-info.java
+ /**
+ * Aliquam rerum est vel. Molestiae eos expedita animi repudiandae sed commodi.
+ * Omnis qui ducimus ut et perspiciatis sint.
+ *
+ * Veritatis nam eaque sequi laborum voluptas voluptate aut.
+ */
+ package com.test.package0;
+
+ /src/com/test/package0/Test.java
+ package com.test.package0;
+ public class Test{}
+ """
+ ) {
+ val packagePage = singlePageOfType<JavadocPackagePageNode>()
+
+ val map = packagePage.templateMap
+ val expectedText = """
+ <p>Aliquam rerum est vel. Molestiae eos expedita animi repudiandae sed commodi.
+ Omnis qui ducimus ut et perspiciatis sint.
+ Veritatis nam eaque sequi laborum voluptas voluptate aut.</p>
+ """.trimIndent().replace("\n", "")
+ assertEquals(expectedText, map["subtitle"].toString().trim())
+ }
+ }
+
+ @Test
+ fun `single class with long package documentation (kotlin)`() {
+ testTemplateMapInline(
+ query =
+ """
+ /src/packages.md
+ # Package com.test.package0
+ Aliquam rerum est vel. Molestiae eos expedita animi repudiandae sed commodi.
+ Omnis qui ducimus ut et perspiciatis sint.
+
+ Veritatis nam eaque sequi laborum voluptas voluptate aut.
+
+ /src/source0.kt
+ package com.test.package0
+ class Test
+ """,
+ configuration = config.copy(
+ sourceSets = config.sourceSets.map { sourceSet ->
+ sourceSet.copy(
+ includes = setOf(File("src/packages.md"))
+ )
+ }
+ )
+ ) {
+ val packagePage = singlePageOfType<JavadocPackagePageNode>()
+
+ val map = packagePage.templateMap
+ val expectedText = """
+ <p>Aliquam rerum est vel. Molestiae eos expedita animi repudiandae sed commodi.
+ Omnis qui ducimus ut et perspiciatis sint.</p>
+ <p>Veritatis nam eaque sequi laborum voluptas voluptate aut.</p>
+ """.trimIndent().replace("\n", "")
+ assertEquals(expectedText, map["subtitle"].toString().trim())
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocTest.kt
new file mode 100644
index 00000000..4dd61777
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocTest.kt
@@ -0,0 +1,4 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLinkingTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLinkingTest.kt
new file mode 100644
index 00000000..fac8edea
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLinkingTest.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc.location
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jetbrains.dokka.jdk
+import org.jetbrains.dokka.kotlinStdlib
+import org.jetbrains.dokka.model.doc.DocumentationLink
+import org.jetbrains.dokka.model.doc.Text
+import org.jetbrains.dokka.utilities.cast
+import utils.TestOutputWriterPlugin
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class JavadocLinkingTest : BaseAbstractTest() {
+
+ @Test
+ fun lineBrokenLink() {
+ val config = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("jvmSrc/")
+ externalDocumentationLinks = listOf(
+ DokkaConfiguration.ExternalDocumentationLink.jdk(8),
+ DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib(),
+ )
+ analysisPlatform = "jvm"
+ }
+ }
+ }
+ testInline(
+ """
+ |/jvmSrc/javadoc/test/SomeClass.kt
+ |
+ |package example
+ |
+ |class SomeClass {
+ | fun someFun(x: Int): Int = 1
+ |}
+ |
+ |/jvmSrc/javadoc/test/SomeJavaDocExample.java
+ |
+ |package example;
+ |
+ |/**
+ | * Here comes some comment
+ | *
+ | * {@link example.SomeClass#someFun(int) someName(ads,
+ | * dsa)}
+ | *
+ | * longer comment
+ | */
+ |public class SomeJavaDocExample {
+ | public void someFunc(int integer, Object object) {
+ | }
+ |}
+ """.trimMargin(),
+ config,
+ pluginOverrides = listOf(TestOutputWriterPlugin())
+ ) {
+ documentablesMergingStage = {
+ it.packages.single()
+ .classlikes.single { classlike -> classlike.name == "SomeJavaDocExample" }
+ .documentation.values.single()
+ .children.single()
+ .children.single()
+ .children.single {
+ it is DocumentationLink
+ }.children.filterIsInstance<Text>().single { it.body.contains("someName") }.cast<Text>().body.run {
+ assertEquals("someName(ads, dsa)", this)
+ }
+ }
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt
new file mode 100644
index 00000000..bef81372
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc.location
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jetbrains.dokka.javadoc.JavadocPlugin
+import org.jetbrains.dokka.javadoc.pages.JavadocClasslikePageNode
+import org.jetbrains.dokka.javadoc.pages.JavadocFunctionNode
+import org.jetbrains.dokka.javadoc.pages.JavadocPackagePageNode
+import org.jetbrains.dokka.javadoc.renderer.JavadocContentToHtmlTranslator
+import org.jetbrains.dokka.jdk
+import org.jetbrains.dokka.kotlinStdlib
+import org.jetbrains.dokka.model.firstChildOfType
+import org.jetbrains.dokka.pages.RootPageNode
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.querySingle
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class JavadocLocationTest : BaseAbstractTest() {
+
+ @Test
+ fun `resolved signature with external links`() {
+ val query = """
+ |/jvmSrc/javadoc/test/Test.kt
+ |package javadoc.test
+ |import java.io.Serializable
+ |class Test : Serializable, Cloneable {}
+ """.trimIndent()
+
+ locationTestInline(query) { rootPageNode, dokkaContext ->
+ val transformer = htmlTranslator(rootPageNode, dokkaContext)
+ val testClass = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.test" }
+ .firstChildOfType<JavadocClasslikePageNode>()
+ assertEquals(
+ " implements <a href=https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html>Serializable</a>, <a href=https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html>Cloneable</a>",
+ transformer.htmlForContentNode(testClass.signature.supertypes!!, null)
+ )
+ }
+ }
+
+ @Test
+ fun `resolved signature to no argument function`() {
+ val query = """
+ |/jvmSrc/javadoc/test/Test.kt
+ |package javadoc.test
+ |class Test {
+ | fun test() {}
+ |}
+ """.trimIndent()
+
+ locationTestInline(query) { rootPageNode, dokkaContext ->
+ val transformer = htmlTranslator(rootPageNode, dokkaContext)
+ val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.test" }
+ .firstChildOfType<JavadocClasslikePageNode> { it.name == "Test" }
+ val testFunctionNode = testClassNode.methods.first { it.name == "test" }
+ assertEquals(
+ """<a href=Test.html#test()>test</a>()""",
+ transformer.htmlForContentNode(
+ testFunctionNode.signature.signatureWithoutModifiers,
+ testClassNode
+ )
+ )
+ }
+ }
+
+ @Test
+ fun `resolved signature to one argument function`() {
+ val query = """
+ |/jvmSrc/javadoc/test/Test.kt
+ |package javadoc.test
+ |class Test {
+ | fun test2(s: String) {}
+ |}
+ """.trimIndent()
+
+ locationTestInline(query) { rootPageNode, dokkaContext ->
+ val transformer = htmlTranslator(rootPageNode, dokkaContext)
+ val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.test" }
+ .firstChildOfType<JavadocClasslikePageNode> { it.name == "Test" }
+ val testFunctionNode = testClassNode.methods.first { it.name == "test2" }
+ assertEquals(
+ """<a href=Test.html#test2(java.lang.String)>test2</a>(<a href=https://docs.oracle.com/javase/8/docs/api/java/lang/String.html>String</a> s)""",
+ transformer.htmlForContentNode(
+ testFunctionNode.signature.signatureWithoutModifiers,
+ testClassNode
+ )
+ )
+ }
+ }
+
+ @Test
+ fun `resolved signature to generic function`() {
+ val query = """
+ |/jvmSrc/javadoc/test/Test.kt
+ |package javadoc.test
+ |class Test<A>() {
+ | fun <T> test3(a: A, t: T) {}
+ |}
+ """.trimIndent()
+
+ locationTestInline(query) { rootPageNode, dokkaContext ->
+ val transformer = htmlTranslator(rootPageNode, dokkaContext)
+ val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.test" }
+ .firstChildOfType<JavadocClasslikePageNode> { it.name == "Test" }
+ val testFunctionNode = testClassNode.methods.first { it.name == "test3" }
+ assertEquals(
+ """<a href=Test.html#test3(A,T)>test3</a>(<a href=Test.html>A</a> a, <a href=Test.html#test3(A,T)>T</a> t)""",
+ transformer.htmlForContentNode(
+ testFunctionNode.signature.signatureWithoutModifiers,
+ testClassNode
+ )
+ )
+ }
+ }
+
+ @Test
+ fun `resolved package path`() {
+ val query = """
+ |/jvmSrc/javadoc/test/Test.kt
+ |package javadoc.test
+ |class Test {}
+ """.trimIndent()
+
+ locationTestInline(query) { rootPageNode, dokkaContext ->
+ val locationProvider = dokkaContext.plugin<JavadocPlugin>().querySingle { locationProviderFactory }
+ .getLocationProvider(rootPageNode)
+ val packageNode = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.test" }
+ val packagePath = locationProvider.resolve(packageNode)
+
+ assertEquals("javadoc/test/package-summary", packagePath)
+ }
+ }
+
+ @Test
+ fun `resolve link from another package`(){
+ val query = """
+ |/jvmSrc/javadoc/test/Test.kt
+ |package javadoc.test
+ |class Test {}
+ |
+ |/jvmSrc/another/javadoc/example/Referenced.kt
+ |package javadoc.example.another
+ |
+ |/**
+ | * Referencing element from another package: [javadoc.test.Test]
+ | */
+ |class Referenced {}
+ """.trimIndent()
+
+ locationTestInline(query) { rootPageNode, dokkaContext ->
+ val transformer = htmlTranslator(rootPageNode, dokkaContext)
+ val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.example.another" }
+ .firstChildOfType<JavadocClasslikePageNode> { it.name == "Referenced" }
+ assertEquals(
+ """<p>Referencing element from another package: <a href=../../test/Test.html>javadoc.test.Test</a></p>""",
+ transformer.htmlForContentNode(
+ testClassNode.description.single(),
+ testClassNode
+ )
+ )
+ }
+ }
+
+ @Test
+ fun `should resolve typealias function parameter`() {
+ val query = """
+ |/jvmSrc/javadoc/test/FunctionParameters.kt
+ |package javadoc.test.functionparams
+ |
+ |typealias StringTypealias = String
+ |
+ |class FunctionParameters {
+ | fun withTypealias(typeAliasParam: StringTypealias) {}
+ |}
+ """.trimIndent()
+
+ locationTestInline(query) { rootPageNode, dokkaContext ->
+ val transformer = htmlTranslator(rootPageNode, dokkaContext)
+ val methodWithTypealiasParam = rootPageNode.findFunctionNodeWithin(
+ packageName = "javadoc.test.functionparams",
+ className = "FunctionParameters",
+ methodName = "withTypealias"
+ )
+ val methodSignatureHtml = transformer.htmlForContentNode(methodWithTypealiasParam.signature, null)
+
+ val expectedSignatureHtml = "final <a href=https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html>Unit</a> " +
+ "<a href=javadoc/test/functionparams/FunctionParameters.html#withTypealias(javadoc.test.functionparams.StringTypealias)>withTypealias</a>" +
+ "(<a href=https://docs.oracle.com/javase/8/docs/api/java/lang/String.html>String</a> typeAliasParam)"
+
+ assertEquals(expectedSignatureHtml, methodSignatureHtml)
+ }
+ }
+
+ @Test
+ fun `should resolve definitely non nullable function parameter`() {
+ val query = """
+ |/jvmSrc/javadoc/test/FunctionParameters.kt
+ |package javadoc.test.functionparams
+ |
+ |class FunctionParameters {
+ | fun <T> withDefinitelyNonNullableType(definitelyNonNullable: T & Any) {}
+ |}
+ """.trimIndent()
+
+ locationTestInline(query) { rootPageNode, dokkaContext ->
+ val transformer = htmlTranslator(rootPageNode, dokkaContext)
+ val methodWithVoidParam = rootPageNode.findFunctionNodeWithin(
+ packageName = "javadoc.test.functionparams",
+ className = "FunctionParameters",
+ methodName = "withDefinitelyNonNullableType"
+ )
+ val methodSignatureHtml = transformer.htmlForContentNode(methodWithVoidParam.signature, null)
+
+ val expectedSignatureHtml = "final &lt;T extends <a href=https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html>Any</a>&gt; " +
+ "<a href=https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html>Unit</a> " +
+ "<a href=javadoc/test/functionparams/FunctionParameters.html#withDefinitelyNonNullableType(T)>withDefinitelyNonNullableType</a>" +
+ "(<a href=javadoc/test/functionparams/FunctionParameters.html#withDefinitelyNonNullableType(T)>T</a> definitelyNonNullable)"
+
+ assertEquals(expectedSignatureHtml, methodSignatureHtml)
+ }
+ }
+
+ private fun RootPageNode.findFunctionNodeWithin(
+ packageName: String,
+ className: String,
+ methodName: String
+ ): JavadocFunctionNode {
+ return this
+ .firstChildOfType<JavadocPackagePageNode> { it.name == packageName }
+ .firstChildOfType<JavadocClasslikePageNode> { it.name == className }
+ .methods.single { it.name == methodName }
+ }
+
+ private fun locationTestInline(query: String, testHandler: (RootPageNode, DokkaContext) -> Unit) {
+ val config = dokkaConfiguration {
+ format = "javadoc"
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("jvmSrc/")
+ externalDocumentationLinks = listOf(
+ DokkaConfiguration.ExternalDocumentationLink.jdk(8),
+ DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib()
+ )
+ analysisPlatform = "jvm"
+ classpath = listOfNotNull(jvmStdlibPath)
+ }
+ }
+ }
+ testInline(
+ query = query,
+ configuration = config,
+ cleanupOutput = false,
+ pluginOverrides = listOf(JavadocPlugin())
+ ) { renderingStage = testHandler }
+ }
+
+ private fun htmlTranslator(rootPageNode: RootPageNode, dokkaContext: DokkaContext): JavadocContentToHtmlTranslator {
+ val locationProvider = dokkaContext.plugin<JavadocPlugin>().querySingle { locationProviderFactory }
+ .getLocationProvider(rootPageNode) as JavadocLocationProvider
+ return htmlTranslator(dokkaContext, locationProvider)
+ }
+
+ private fun htmlTranslator(
+ dokkaContext: DokkaContext,
+ locationProvider: JavadocLocationProvider
+ ) = JavadocContentToHtmlTranslator(locationProvider, dokkaContext)
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/packagelist/JavadocPackageListTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/packagelist/JavadocPackageListTest.kt
new file mode 100644
index 00000000..25883836
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/packagelist/JavadocPackageListTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc.packagelist
+
+import org.jetbrains.dokka.javadoc.AbstractJavadocTemplateMapTest
+import utils.TestOutputWriterPlugin
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+internal class JavadocPackageListTest : AbstractJavadocTemplateMapTest() {
+ @Test
+ fun `package list should be generated for a flat structure`(){
+ val writerPlugin = TestOutputWriterPlugin()
+ dualTestTemplateMapInline(
+ java = """
+ /src/package0/ClassA.java
+ package package0
+ public class ClassA {
+
+ }
+
+ /src/package1/ClassB.java
+ package package1
+ public class ClassB {
+ }
+ """,
+ pluginsOverride = listOf(writerPlugin)
+ ){
+ val contents = writerPlugin.writer.contents
+ val expected = """
+ ${'$'}dokka.format:javadoc-v1
+ ${'$'}dokka.linkExtension:html
+
+ package0
+ package1
+ """.trimIndent()
+ assertEquals(expected, contents["element-list"]?.trimIndent())
+ assertEquals(expected, contents["package-list"]?.trimIndent())
+ }
+ }
+
+ @Test
+ fun `package list should be generated for nested structure`(){
+ val writerPlugin = TestOutputWriterPlugin()
+ dualTestTemplateMapInline(
+ java = """
+ /src/package0/ClassA.java
+ package package0
+ public class ClassA {
+
+ }
+
+ /src/package0/package0Inner/ClassB.java
+ package package0.package0Inner
+ public class ClassB {
+ }
+
+ /src/package1/package1Inner/package1InnerInner/ClassC.java
+ package package1.package1Inner.package1InnerInner
+ public class ClassC {
+ }
+ """,
+ pluginsOverride = listOf(writerPlugin)
+ ){
+ val contents = writerPlugin.writer.contents
+ val expected = """
+ ${'$'}dokka.format:javadoc-v1
+ ${'$'}dokka.linkExtension:html
+
+ package0
+ package0.package0Inner
+ package1.package1Inner.package1InnerInner
+ """.trimIndent()
+ assertEquals(expected, contents["element-list"]?.trimIndent())
+ assertEquals(expected, contents["package-list"]?.trimIndent())
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/search/JavadocIndexSearchTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/search/JavadocIndexSearchTest.kt
new file mode 100644
index 00000000..074b3487
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/search/JavadocIndexSearchTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc.search
+
+import org.jetbrains.dokka.javadoc.AbstractJavadocTemplateMapTest
+import utils.TestOutputWriterPlugin
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+internal class JavadocIndexSearchTest : AbstractJavadocTemplateMapTest() {
+ @Test
+ fun `javadoc index search tag`(){
+ val writerPlugin = TestOutputWriterPlugin()
+ dualTestTemplateMapInline(
+ java = """
+ /src/ClassA.java
+ package package0;
+ /**
+ * Documentation for ClassA
+ * Defines the implementation of the system Java compiler and its command line equivalent, {@index javac}, as well as javah.
+ */
+ public class ClassA {
+
+ }
+ """,
+ pluginsOverride = listOf(writerPlugin)
+ ) {
+ val contents = writerPlugin.writer.contents
+ val expectedSearchTagJson = """var tagSearchIndex = [{"p":"package0","c":"ClassA","l":"javac","url":"package0/ClassA.html#javac"}]"""
+ assertEquals(expectedSearchTagJson, contents["tag-search-index.js"])
+ }
+ }
+
+ @Test
+ fun `javadoc type with member search`(){
+ val writerPlugin = TestOutputWriterPlugin()
+ dualTestTemplateMapInline(
+ java = """
+ /src/ClassA.java
+ package package0;
+ public class ClassA {
+ public String propertyOfClassA = "Sample";
+
+ public void sampleFunction(){
+
+ }
+ }
+ """,
+ pluginsOverride = listOf(writerPlugin)
+ ) {
+ val contents = writerPlugin.writer.contents
+ val expectedPackageJson =
+ """var packageSearchIndex = [{"l":"package0","url":"package0/package-summary.html"}, {"l":"All packages","url":"index.html"}]"""
+ val expectedClassesJson =
+ """var typeSearchIndex = [{"p":"package0","l":"ClassA","url":"package0/ClassA.html"}, {"l":"All classes","url":"allclasses.html"}]"""
+ val expectedMembersJson =
+ """var memberSearchIndex = [{"p":"package0","c":"ClassA","l":"ClassA()","url":"package0/ClassA.html#ClassA()"}, {"p":"package0","c":"ClassA","l":"sampleFunction()","url":"package0/ClassA.html#sampleFunction()"}, {"p":"package0","c":"ClassA","l":"propertyOfClassA","url":"package0/ClassA.html#propertyOfClassA"}]"""
+
+ assertEquals(expectedPackageJson, contents["package-search-index.js"])
+ assertEquals(expectedClassesJson, contents["type-search-index.js"])
+ assertEquals(expectedMembersJson, contents["member-search-index.js"])
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/transformers/documentables/JavadocDocumentableJVMSourceSetFilterTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/transformers/documentables/JavadocDocumentableJVMSourceSetFilterTest.kt
new file mode 100644
index 00000000..39dac05d
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/transformers/documentables/JavadocDocumentableJVMSourceSetFilterTest.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc.transformers.documentables
+
+import org.jetbrains.dokka.DokkaSourceSetID
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class JavadocDocumentableJVMSourceSetFilterTest: BaseAbstractTest() {
+
+ private val config = dokkaConfiguration {
+ format = "javadoc"
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("jvmSrc/")
+ analysisPlatform = "jvm"
+ name = "jvm"
+ dependentSourceSets = setOf(DokkaSourceSetID("root", "common"))
+ }
+ sourceSet {
+ sourceRoots = listOf("jsSrc/")
+ analysisPlatform = "js"
+ name = "js"
+ }
+ sourceSet {
+ sourceRoots = listOf("commonSrc/")
+ analysisPlatform = "common"
+ name = "common"
+ }
+ sourceSet {
+ sourceRoots = listOf("otherCommonSrc/")
+ analysisPlatform = "common"
+ name = "otherCommon"
+ }
+ }
+ }
+ private val query = """
+ /jvmSrc/source0.kt
+ package package0
+ /**
+ * Documentation for ClassA
+ */
+ class ClassA {
+ fun a() {}
+ fun b() {}
+ fun c() {}
+ }
+
+ /jsSrc/source1.kt
+ package package1
+ /**
+ * Documentation for ClassB
+ */
+ class ClassB {
+ fun d() {}
+ fun e() {}
+ fun f() {}
+ }
+
+ /commonSrc/source2.kt
+ package package1
+ /**
+ * Documentation for ClassC
+ */
+ class ClassC {
+ fun g() {}
+ fun h() {}
+ fun j() {}
+ }
+
+ /otherCommonSrc/source3.kt
+ package package1
+ /**
+ * Documentation for ClassD
+ */
+ class ClassD {
+ fun l() {}
+ fun m() {}
+ fun n() {}
+ }
+ """.trimIndent()
+
+ @Test
+ fun `non-jvm and not dependent common source sets are ommited`() {
+ testInline(query, config) {
+ preMergeDocumentablesTransformationStage = { modules ->
+ assertEquals(2, modules.size)
+ }
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt
new file mode 100644
index 00000000..cea32026
--- /dev/null
+++ b/dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.javadoc.validity
+
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.DokkaException
+import org.jetbrains.dokka.ExternalDocumentationLink
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import kotlin.test.Test
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
+
+class MultiplatformConfiguredCheckerTest : BaseAbstractTest() {
+
+ val mppConfig: DokkaConfigurationImpl = dokkaConfiguration {
+ format = "javadoc"
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/jvm")
+ analysisPlatform = "jvm"
+ externalDocumentationLinks = listOf(
+ ExternalDocumentationLink("https://docs.oracle.com/javase/8/docs/api/"),
+ ExternalDocumentationLink("https://kotlinlang.org/api/latest/jvm/stdlib/")
+ )
+ }
+ sourceSet {
+ sourceRoots = listOf("src/js")
+ analysisPlatform = "js"
+ externalDocumentationLinks = listOf(
+ ExternalDocumentationLink("https://docs.oracle.com/javase/8/docs/api/"),
+ ExternalDocumentationLink("https://kotlinlang.org/api/latest/jvm/stdlib/")
+ )
+ }
+ }
+ }
+
+ val sppConfig: DokkaConfigurationImpl = dokkaConfiguration {
+ format = "javadoc"
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src")
+ analysisPlatform = "jvm"
+ externalDocumentationLinks = listOf(
+ ExternalDocumentationLink("https://docs.oracle.com/javase/8/docs/api/"),
+ ExternalDocumentationLink("https://kotlinlang.org/api/latest/jvm/stdlib/")
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `mpp config should fail for javadoc`() {
+ testInline(
+ """
+ |/src/jvm/kotlin/example/Test.kt
+ |class Test
+ |/src/js/kotlin/example/Test.kt
+ |class Test
+ """.trimMargin(), mppConfig
+ ) {
+ verificationStage = { verification ->
+ var mppDetected = false
+ try {
+ verification()
+ } catch (e: DokkaException) {
+ mppDetected =
+ e.localizedMessage == "Pre-generation validity check failed: ${MultiplatformConfiguredChecker.errorMessage}"
+ }
+ assertTrue(mppDetected, "MPP configuration not detected")
+ }
+ }
+ }
+
+ @Test
+ fun `spp config should not fail for javadoc`() {
+ testInline(
+ """
+ |/src/main/kotlin/example/Test.kt
+ |class Test
+ """.trimMargin(), sppConfig
+ ) {
+ verificationStage = { verification ->
+ var mppDetected = false
+ try {
+ verification()
+ } catch (e: DokkaException) {
+ mppDetected =
+ e.localizedMessage == "Pre-generation validity check failed: ${MultiplatformConfiguredChecker.errorMessage}"
+ }
+ assertFalse(mppDetected, "SPP taken as multiplatform")
+ }
+ }
+ }
+}