diff options
author | Ignat Beresnev <ignat.beresnev@jetbrains.com> | 2023-11-10 11:46:54 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-10 11:46:54 +0100 |
commit | 8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch) | |
tree | 1b915207b2b9f61951ddbf0ff2e687efd053d555 /dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains | |
parent | a44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff) | |
download | dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.gz dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.bz2 dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.zip |
Restructure the project to utilize included builds (#3174)
* Refactor and simplify artifact publishing
* Update Gradle to 8.4
* Refactor and simplify convention plugins and build scripts
Fixes #3132
---------
Co-authored-by: Adam <897017+aSemy@users.noreply.github.com>
Co-authored-by: Oleg Yukhnevich <whyoleg@gmail.com>
Diffstat (limited to 'dokka-subprojects/plugin-javadoc/src/test/kotlin/org/jetbrains')
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 = "Benjamin Franklin")", 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 = "Franklin D. Roosevelt")", 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><T extends <a href=https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html>Serializable</a>>", + 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 <D extends <a href=Generic.html>T</a>> <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(" ", 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(" ", 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 <T extends <a href=https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html>Any</a>> " + + "<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") + } + } + } +} |