aboutsummaryrefslogtreecommitdiff
path: root/dokka-subprojects/plugin-base/src/test/kotlin/model
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-11-10 11:46:54 +0100
committerGitHub <noreply@github.com>2023-11-10 11:46:54 +0100
commit8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch)
tree1b915207b2b9f61951ddbf0ff2e687efd053d555 /dokka-subprojects/plugin-base/src/test/kotlin/model
parenta44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff)
downloaddokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.gz
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.bz2
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.zip
Restructure the project to utilize included builds (#3174)
* Refactor and simplify artifact publishing * Update Gradle to 8.4 * Refactor and simplify convention plugins and build scripts Fixes #3132 --------- Co-authored-by: Adam <897017+aSemy@users.noreply.github.com> Co-authored-by: Oleg Yukhnevich <whyoleg@gmail.com>
Diffstat (limited to 'dokka-subprojects/plugin-base/src/test/kotlin/model')
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/ClassesTest.kt594
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/CommentTest.kt338
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/ExtensionsTest.kt159
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/FunctionsTest.kt403
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/InheritorsTest.kt428
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/JavaTest.kt491
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/MultiLanguageInheritanceTest.kt365
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/ObjectTest.kt43
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/PackagesTest.kt123
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/PropertyTest.kt277
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt181
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsTest.kt195
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt105
13 files changed, 3702 insertions, 0 deletions
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/model/ClassesTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/model/ClassesTest.kt
new file mode 100644
index 00000000..c18dfafb
--- /dev/null
+++ b/dokka-subprojects/plugin-base/src/test/kotlin/model/ClassesTest.kt
@@ -0,0 +1,594 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package model
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.TypeConstructor
+import org.jetbrains.dokka.links.sureClassNames
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.KotlinModifier.*
+import kotlin.test.assertNull
+import kotlin.test.Test
+import utils.*
+
+
+class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "classes") {
+
+ @Test
+ fun emptyClass() {
+ inlineModelTest(
+ """
+ |class Klass {}"""
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 4
+ }
+ }
+ }
+
+ @Test
+ fun classWithConstructor() {
+ inlineModelTest(
+ """
+ |class Klass(name: String)
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 4
+
+ with(constructors.firstOrNull().assertNotNull("Constructor")) {
+ visibility.values allEquals KotlinVisibility.Public
+ parameters counts 1
+ with(parameters.firstOrNull().assertNotNull("Constructor parameter")) {
+ name equals "name"
+ type.name equals "String"
+ }
+ }
+
+ }
+ }
+ }
+
+ @Test
+ fun classWithFunction() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | fun fn() {}
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 5
+
+ with((this / "fn").cast<DFunction>()) {
+ type.name equals "Unit"
+ parameters counts 0
+ visibility.values allEquals KotlinVisibility.Public
+ }
+ }
+ }
+ }
+
+ @Test
+ fun classWithProperty() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | val name: String = ""
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 5
+
+ with((this / "name").cast<DProperty>()) {
+ name equals "name"
+ // TODO property name
+ }
+ }
+ }
+ }
+
+ @Test
+ fun classWithCompanionObject() {
+ inlineModelTest(
+ """
+ |class Klass() {
+ | companion object {
+ | val x = 1
+ | fun foo() {}
+ | }
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 5
+
+ with((this / "Companion").cast<DObject>()) {
+ name equals "Companion"
+ children counts 5
+
+ with((this / "x").cast<DProperty>()) {
+ name equals "x"
+ }
+
+ with((this / "foo").cast<DFunction>()) {
+ name equals "foo"
+ parameters counts 0
+ type.name equals "Unit"
+ }
+ }
+
+ with((this.companion).cast<DObject>()) {
+ name equals "Companion"
+ children counts 5
+
+ with((this / "x").cast<DProperty>()) {
+ name equals "x"
+ }
+
+ with((this / "foo").cast<DFunction>()) {
+ name equals "foo"
+ parameters counts 0
+ type.name equals "Unit"
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun dataClass() {
+ inlineModelTest(
+ """
+ |data class Klass() {}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ visibility.values allEquals KotlinVisibility.Public
+ with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("Extras")) {
+ this counts 1
+ first() equals ExtraModifiers.KotlinOnlyModifiers.Data
+ }
+ }
+ }
+ }
+
+ @Test
+ fun sealedClass() {
+ inlineModelTest(
+ """
+ |sealed class Klass() {}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ modifier.values.forEach { it equals Sealed }
+ }
+ }
+ }
+
+ @Test
+ fun annotatedClassWithAnnotationParameters() {
+ inlineModelTest(
+ """
+ |@Deprecated("should no longer be used") class Foo() {}
+ """
+ ) {
+ with((this / "classes" / "Foo").cast<DClass>()) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "Deprecated"
+ params.entries counts 1
+ (params["message"].assertNotNull("message") as StringValue).value equals "should no longer be used"
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun notOpenClass() {
+ inlineModelTest(
+ """
+ |open class C() {
+ | open fun f() {}
+ |}
+ |
+ |class D() : C() {
+ | override fun f() {}
+ |}
+ """
+ ) {
+ val C = (this / "classes" / "C").cast<DClass>()
+ val D = (this / "classes" / "D").cast<DClass>()
+
+ with(C) {
+ modifier.values.forEach { it equals Open }
+ with((this / "f").cast<DFunction>()) {
+ modifier.values.forEach { it equals Open }
+ }
+ }
+ with(D) {
+ modifier.values.forEach { it equals Final }
+ with((this / "f").cast<DFunction>()) {
+ modifier.values.forEach { it equals Open }
+ }
+ D.supertypes.flatMap { it.component2() }.firstOrNull()?.typeConstructor?.dri equals C.dri
+ }
+ }
+ }
+
+ @Test
+ fun indirectOverride() {
+ inlineModelTest(
+ """
+ |abstract class C() {
+ | abstract fun foo()
+ |}
+ |
+ |abstract class D(): C()
+ |
+ |class E(): D() {
+ | override fun foo() {}
+ |}
+ """
+ ) {
+ val C = (this / "classes" / "C").cast<DClass>()
+ val D = (this / "classes" / "D").cast<DClass>()
+ val E = (this / "classes" / "E").cast<DClass>()
+
+ with(C) {
+ modifier.values.forEach { it equals Abstract }
+ ((this / "foo").cast<DFunction>()).modifier.values.forEach { it equals Abstract }
+ }
+
+ with(D) {
+ modifier.values.forEach { it equals Abstract }
+ }
+
+ with(E) {
+ modifier.values.forEach { it equals Final }
+
+ }
+ D.supers.single().typeConstructor.dri equals C.dri
+ E.supers.single().typeConstructor.dri equals D.dri
+ }
+ }
+
+ @Test
+ fun innerClass() {
+ inlineModelTest(
+ """
+ |class C {
+ | inner class D {}
+ |}
+ """
+ ) {
+ with((this / "classes" / "C").cast<DClass>()) {
+
+ with((this / "D").cast<DClass>()) {
+ with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("AdditionalModifiers")) {
+ this counts 1
+ first() equals ExtraModifiers.KotlinOnlyModifiers.Inner
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun companionObjectExtension() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | companion object Default {}
+ |}
+ |
+ |/**
+ | * The def
+ | */
+ |val Klass.Default.x: Int get() = 1
+ """
+ ) {
+ with((this / "classes").cast<DPackage>()) {
+ properties.single().name equals "x"
+ (properties.single().receiver?.dri?.callable?.receiver as? TypeConstructor)?.fullyQualifiedName equals "classes.Klass.Default"
+ }
+ }
+ }
+
+ @Test
+ fun secondaryConstructor() {
+ inlineModelTest(
+ """
+ |class C() {
+ | /** This is a secondary constructor. */
+ | constructor(s: String): this() {}
+ |}
+ """
+ ) {
+ with((this / "classes" / "C").cast<DClass>()) {
+ name equals "C"
+ constructors counts 2
+
+ constructors.map { it.name } allEquals "C"
+
+ with(constructors.find { it.parameters.isEmpty() } notNull "C()") {
+ parameters counts 0
+ }
+
+ with(constructors.find { it.parameters.isNotEmpty() } notNull "C(String)") {
+ parameters counts 1
+ with(parameters.firstOrNull() notNull "Constructor parameter") {
+ name equals "s"
+ type.name equals "String"
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun sinceKotlin() {
+ inlineModelTest(
+ """
+ |/**
+ | * Useful
+ | */
+ |@SinceKotlin("1.1")
+ |class C
+ """
+ ) {
+ with((this / "classes" / "C").cast<DClass>()) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "SinceKotlin"
+ params.entries counts 1
+ (params["version"].assertNotNull("version") as StringValue).value equals "1.1"
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun privateCompanionObject() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | private companion object {
+ | fun fn() {}
+ | val a = 0
+ | }
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ assertNull(companion, "Companion should not be visible by default")
+ }
+ }
+ }
+
+ @Test
+ fun companionObject() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | companion object {
+ | fun fn() {}
+ | val a = 0
+ | }
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ with((this / "Companion").cast<DObject>()) {
+ name equals "Companion"
+ visibility.values allEquals KotlinVisibility.Public
+
+ with((this / "fn").cast<DFunction>()) {
+ name equals "fn"
+ parameters counts 0
+ receiver equals null
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun annotatedClass() {
+ inlineModelTest(
+ """@Suppress("abc") class Foo() {}"""
+ ) {
+ with((this / "classes" / "Foo").cast<DClass>()) {
+ with(
+ extra[Annotations]?.directAnnotations?.values?.firstOrNull()?.firstOrNull()
+ .assertNotNull("annotations")
+ ) {
+ dri.toString() equals "kotlin/Suppress///PointingToDeclaration/"
+ (params["names"].assertNotNull("param") as ArrayValue).value equals listOf(StringValue("abc"))
+ }
+ }
+ }
+ }
+
+ @OnlyDescriptors("Bug in descriptors, DRI of entry should have [EnumEntryDRIExtra]")
+ @Test
+ fun javaAnnotationClass() {
+ inlineModelTest(
+ """
+ |import java.lang.annotation.Retention
+ |import java.lang.annotation.RetentionPolicy
+ |
+ |@Retention(RetentionPolicy.SOURCE)
+ |public annotation class throws()
+ """
+ ) {
+ with((this / "classes" / "throws").cast<DAnnotation>()) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "Retention"
+ params["value"].assertNotNull("value") equals EnumValue(
+ "RetentionPolicy.SOURCE",
+ DRI("java.lang.annotation", "RetentionPolicy.SOURCE")
+ )
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun genericAnnotationClass() {
+ inlineModelTest(
+ """annotation class Foo<A,B,C,D:Number>() {}"""
+ ) {
+ with((this / "classes" / "Foo").cast<DAnnotation>()) {
+ generics.map { it.name to it.bounds.first().name } equals listOf(
+ "A" to "Any",
+ "B" to "Any",
+ "C" to "Any",
+ "D" to "Number"
+ )
+ }
+ }
+ }
+
+ @Test
+ fun nestedGenericClasses() {
+ inlineModelTest(
+ """
+ |class Outer<OUTER> {
+ | inner class Inner<INNER, T : OUTER> { }
+ |}
+ """.trimMargin()
+ ) {
+ with((this / "classes" / "Outer").cast<DClass>()) {
+ val inner = classlikes.single().cast<DClass>()
+ inner.generics.map { it.name to it.bounds.first().name } equals listOf("INNER" to "Any", "T" to "OUTER")
+ }
+ }
+ }
+
+ @Test
+ fun allImplementedInterfaces() {
+ inlineModelTest(
+ """
+ | interface Highest { }
+ | open class HighestImpl: Highest { }
+ | interface Lower { }
+ | interface LowerImplInterface: Lower { }
+ | class Tested : HighestImpl(), LowerImplInterface { }
+ """.trimIndent()
+ ) {
+ with((this / "classes" / "Tested").cast<DClass>()) {
+ extra[ImplementedInterfaces]?.interfaces?.entries?.single()?.value?.map { it.dri.sureClassNames }
+ ?.sorted() equals listOf("Highest", "Lower", "LowerImplInterface").sorted()
+ }
+ }
+ }
+
+ @Test
+ fun multipleClassInheritance() {
+ inlineModelTest(
+ """
+ | open class A { }
+ | open class B: A() { }
+ | class Tested : B() { }
+ """.trimIndent()
+ ) {
+ with((this / "classes" / "Tested").cast<DClass>()) {
+ supertypes.entries.single().value.map { it.typeConstructor.dri.sureClassNames }.single() equals "B"
+ }
+ }
+ }
+
+ @Test
+ fun multipleClassInheritanceWithInterface() {
+ inlineModelTest(
+ """
+ | open class A { }
+ | open class B: A() { }
+ | interface X { }
+ | interface Y : X { }
+ | class Tested : B(), Y { }
+ """.trimIndent()
+ ) {
+ with((this / "classes" / "Tested").cast<DClass>()) {
+ supertypes.entries.single().value.map { it.typeConstructor.dri.sureClassNames to it.kind }
+ .sortedBy { it.first } equals listOf(
+ "B" to KotlinClassKindTypes.CLASS,
+ "Y" to KotlinClassKindTypes.INTERFACE
+ )
+ }
+ }
+ }
+
+ @Test
+ fun doublyTypealiasedException() {
+ inlineModelTest(
+ """
+ | typealias B = RuntimeException
+ | typealias A = B
+ """.trimMargin()
+ ) {
+ with((this / "classes" / "A").cast<DTypeAlias>()) {
+ extra[ExceptionInSupertypes].assertNotNull("Typealias A should have ExceptionInSupertypes in its extra field")
+ }
+ with((this / "classes" / "B").cast<DTypeAlias>()) {
+ extra[ExceptionInSupertypes].assertNotNull("Typealias B should have ExceptionInSupertypes in its extra field")
+ }
+ }
+ }
+
+ @Test
+ fun `inline classes`() {
+ inlineModelTest(
+ """
+ | inline class X(val example: String)
+ |
+ | @JvmInline
+ | value class InlineTest(val x: String)
+ """.trimMargin()
+ ) {
+ with((this / "classes" / "X").cast<DClass>()) {
+ name equals "X"
+ properties.first().name equals "example"
+ extra[AdditionalModifiers]?.content?.values?.firstOrNull()
+ ?.firstOrNull() equals ExtraModifiers.KotlinOnlyModifiers.Inline
+ }
+ }
+ }
+
+ @Test
+ fun `value classes`() {
+ inlineModelTest(
+ """
+ | @JvmInline
+ | value class InlineTest(val example: String)
+ """.trimMargin()
+ ) {
+ val classlike = packages.flatMap { it.classlikes }.first() as DClass
+ classlike.name equals "InlineTest"
+ classlike.properties.first().name equals "example"
+ classlike.extra[AdditionalModifiers]?.content?.values?.firstOrNull()
+ ?.firstOrNull() equals ExtraModifiers.KotlinOnlyModifiers.Value
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/model/CommentTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/model/CommentTest.kt
new file mode 100644
index 00000000..6b00f2f0
--- /dev/null
+++ b/dokka-subprojects/plugin-base/src/test/kotlin/model/CommentTest.kt
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package model
+
+import org.jetbrains.dokka.model.DClass
+import org.jetbrains.dokka.model.DProperty
+import org.jetbrains.dokka.model.doc.*
+import utils.AbstractModelTest
+import utils.assertNotNull
+import utils.comments
+import utils.docs
+import kotlin.test.Test
+
+class CommentTest : AbstractModelTest("/src/main/kotlin/comment/Test.kt", "comment") {
+
+ @Test
+ fun codeBlockComment() {
+ inlineModelTest(
+ """
+ |/**
+ | * ```brainfuck
+ | * ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
+ | * ```
+ | */
+ |val prop1 = ""
+ |
+ |
+ |/**
+ | * ```
+ | * a + b - c
+ | * ```
+ | */
+ |val prop2 = ""
+ """
+ ) {
+ with((this / "comment" / "prop1").cast<DProperty>()) {
+ name equals "prop1"
+ with(this.docs().firstOrNull()?.children?.firstOrNull()?.assertNotNull("Code")) {
+ (this?.children?.firstOrNull() as? Text)
+ ?.body equals "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."
+
+ this?.params?.get("lang") equals "brainfuck"
+ }
+ }
+ with((this / "comment" / "prop2").cast<DProperty>()) {
+ name equals "prop2"
+ with(this.docs().firstOrNull()?.children?.firstOrNull()?.assertNotNull("Code")) {
+ (this?.children?.firstOrNull() as? Text)
+ ?.body equals "a + b - c"
+
+ this?.params?.get("lang") equals null
+ }
+ }
+ }
+ }
+
+ @Test
+ fun codeBlockWithIndentationComment() {
+ inlineModelTest(
+ """
+ |/**
+ | * 1.
+ | * ```
+ | * line 1
+ | * line 2
+ | * ```
+ | */
+ |val prop1 = ""
+ """
+ ) {
+ with((this / "comment" / "prop1").cast<DProperty>()) {
+ name equals "prop1"
+ with(this.docs().firstOrNull()?.children?.firstOrNull()?.assertNotNull("Code")) {
+ val codeBlockChildren = ((this?.children?.firstOrNull() as? Li)?.children?.firstOrNull() as? CodeBlock)?.children
+ (codeBlockChildren?.get(0) as? Text)?.body equals " line 1"
+ (codeBlockChildren?.get(1) as? Br) notNull "Br"
+ (codeBlockChildren?.get(2) as? Text)?.body equals " line 2"
+ }
+ }
+ }
+ }
+
+ @Test
+ fun emptyDoc() {
+ inlineModelTest(
+ """
+ val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ name equals "property"
+ comments() equals ""
+ }
+ }
+ }
+
+ @Test
+ fun emptyDocButComment() {
+ inlineModelTest(
+ """
+ |/* comment */
+ |val property = "test"
+ |fun tst() = property
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals ""
+ }
+ }
+ }
+
+ @Test
+ fun multilineDoc() {
+ inlineModelTest(
+ """
+ |/**
+ | * doc1
+ | *
+ | * doc2
+ | * doc3
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc1\ndoc2 doc3\n"
+ }
+ }
+ }
+
+ @Test
+ fun multilineDocWithComment() {
+ inlineModelTest(
+ """
+ |/**
+ | * doc1
+ | *
+ | * doc2
+ | * doc3
+ | */
+ |// comment
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc1\ndoc2 doc3\n"
+ }
+ }
+ }
+
+ @Test
+ fun oneLineDoc() {
+ inlineModelTest(
+ """
+ |/** doc */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc\n"
+ }
+ }
+ }
+
+ @Test
+ fun oneLineDocWithComment() {
+ inlineModelTest(
+ """
+ |/** doc */
+ |// comment
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc\n"
+ }
+ }
+ }
+
+ @Test
+ fun oneLineDocWithEmptyLine() {
+ inlineModelTest(
+ """
+ |/** doc */
+ |
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc\n"
+ }
+ }
+ }
+
+ @Test
+ fun emptySection() {
+ inlineModelTest(
+ """
+ |/**
+ | * Summary
+ | * @one
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Summary\n\none: []"
+ with(docs().find { it is CustomTagWrapper && it.name == "one" }.assertNotNull("'one' entry")) {
+ root.children counts 0
+ root.params.keys counts 0
+ }
+ }
+ }
+ }
+
+ @Test
+ fun quotes() {
+ inlineModelTest(
+ """
+ |/** it's "useful" */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals """it's "useful"
+"""
+ }
+ }
+ }
+
+ @Test
+ fun section1() {
+ inlineModelTest(
+ """
+ |/**
+ | * Summary
+ | * @one section one
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Summary\n\none: [section one\n]"
+ }
+ }
+ }
+
+
+ @Test
+ fun section2() {
+ inlineModelTest(
+ """
+ |/**
+ | * Summary
+ | * @one section one
+ | * @two section two
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Summary\n\none: [section one\n]\ntwo: [section two\n]"
+ }
+ }
+ }
+
+ @Test
+ fun multilineSection() {
+ inlineModelTest(
+ """
+ |/**
+ | * Summary
+ | * @one
+ | * line one
+ | * line two
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Summary\n\none: [line one line two\n]"
+ }
+ }
+ }
+
+ @Test
+ fun `should be space between Markdown nodes`() {
+ inlineModelTest(
+ """
+ |/**
+ | * Rotates paths by `amount` **radians** around (`x`, `y`).
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Rotates paths by amount radians around (x, y).\n"
+ }
+ }
+ }
+
+ @Test
+ fun `should remove spaces inside indented code block`() {
+ inlineModelTest(
+ """
+ |/**
+ | * Welcome:
+ | *
+ | * ```kotlin
+ | * fun main() {
+ | * println("Hello World!")
+ | * }
+ | * ```
+ | *
+ | * fun thisIsACodeBlock() {
+ | * val butWhy = "per markdown spec, because four-spaces prefix"
+ | * }
+ | */
+ |class Foo
+ """
+ ) {
+ with((this / "comment" / "Foo").cast<DClass>()) {
+ docs()[0].children[2] equals CodeBlock(
+ listOf(
+ Text(
+ "fun thisIsACodeBlock() {\n" +
+ " val butWhy = \"per markdown spec, because four-spaces prefix\"\n" +
+ "}"
+ )
+ )
+ )
+ }
+ }
+ }
+
+}
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/model/ExtensionsTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/model/ExtensionsTest.kt
new file mode 100644
index 00000000..a428dd1d
--- /dev/null
+++ b/