aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrzej Ratajczak <32793002+BarkingBad@users.noreply.github.com>2022-01-27 10:39:56 +0100
committerGitHub <noreply@github.com>2022-01-27 12:39:56 +0300
commit7c44db1ef0075e2b80a4723e0747bbf57c32e775 (patch)
treed20079f969fbb977603852ef4ea2234e54851f98
parentd884fa7ce3088ac9ae0ca1bbad70e698888610fa (diff)
downloaddokka-7c44db1ef0075e2b80a4723e0747bbf57c32e775.tar.gz
dokka-7c44db1ef0075e2b80a4723e0747bbf57c32e775.tar.bz2
dokka-7c44db1ef0075e2b80a4723e0747bbf57c32e775.zip
Fix resolving DRIs of Enum Entries (#2305)
* Fix resolving DRIs of Enum Entries * Unify DRIs for Kotlin and Java enums. Add EnumEntry linking tests * Updates EnumEntry extras in documentable translators * Fix tests * Apply requested changes * Apply requested changes
-rw-r--r--core/api/core.api1
-rw-r--r--core/src/main/kotlin/links/DRI.kt12
-rw-r--r--core/src/main/kotlin/utilities/Html.kt4
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRIFactory.kt14
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProvider.kt7
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt2
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt8
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt2
-rw-r--r--plugins/base/src/test/kotlin/enums/EnumsTest.kt4
-rw-r--r--plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt117
-rw-r--r--plugins/base/src/test/kotlin/locationProvider/JavadocExternalLocationProviderTest.kt4
-rw-r--r--plugins/base/src/test/kotlin/model/JavaTest.kt4
-rw-r--r--plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaEnum.java5
-rw-r--r--plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaLinker.java8
-rw-r--r--plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinEnum.kt5
-rw-r--r--plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinLinker.kt8
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt4
17 files changed, 183 insertions, 26 deletions
diff --git a/core/api/core.api b/core/api/core.api
index 8b9e5c7b..32d388f7 100644
--- a/core/api/core.api
+++ b/core/api/core.api
@@ -520,6 +520,7 @@ public final class org/jetbrains/dokka/links/DRIKt {
public static final fun getSureClassNames (Lorg/jetbrains/dokka/links/DRI;)Ljava/lang/String;
public static final fun nextTarget (Lorg/jetbrains/dokka/links/DriTarget;)Lorg/jetbrains/dokka/links/DriTarget;
public static final fun withClass (Lorg/jetbrains/dokka/links/DRI;Ljava/lang/String;)Lorg/jetbrains/dokka/links/DRI;
+ public static final fun withEnumEntryExtra (Lorg/jetbrains/dokka/links/DRI;)Lorg/jetbrains/dokka/links/DRI;
public static final fun withTargetToDeclaration (Lorg/jetbrains/dokka/links/DRI;)Lorg/jetbrains/dokka/links/DRI;
}
diff --git a/core/src/main/kotlin/links/DRI.kt b/core/src/main/kotlin/links/DRI.kt
index 2cbae8cc..a1322ef6 100644
--- a/core/src/main/kotlin/links/DRI.kt
+++ b/core/src/main/kotlin/links/DRI.kt
@@ -56,9 +56,19 @@ fun DRI.withClass(name: String) = copy(classNames = if (classNames.isNullOrBlank
fun DRI.withTargetToDeclaration() = copy(target = PointingToDeclaration)
+fun DRI.withEnumEntryExtra() = copy(
+ extra = DRIExtraContainer(this.extra).also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode()
+)
+
val DRI.parent: DRI
get() = when {
- extra != null -> copy(extra = null)
+ extra != null -> when {
+ DRIExtraContainer(extra)[EnumEntryDRIExtra] != null -> copy(
+ classNames = classNames?.substringBeforeLast(".", "")?.takeIf { it.isNotBlank() },
+ extra = null
+ )
+ else -> copy(extra = null)
+ }
target != PointingToDeclaration -> copy(target = PointingToDeclaration)
callable != null -> copy(callable = null)
classNames != null -> copy(classNames = classNames.substringBeforeLast(".", "").takeIf { it.isNotBlank() })
diff --git a/core/src/main/kotlin/utilities/Html.kt b/core/src/main/kotlin/utilities/Html.kt
index 3226ca9d..874c9fb1 100644
--- a/core/src/main/kotlin/utilities/Html.kt
+++ b/core/src/main/kotlin/utilities/Html.kt
@@ -7,9 +7,9 @@ import java.net.URLEncoder
* Replaces symbols reserved in HTML with their respective entities.
* Replaces & with &amp;, < with &lt; and > with &gt;
*/
-fun String.htmlEscape(): String = replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
+fun String.htmlEscape(): String = replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;")
fun String.urlEncoded(): String = URLEncoder.encode(this, "UTF-8")
fun String.formatToEndWithHtml() =
- if (endsWith(".html") || contains(Regex("\\.html#"))) this else "$this.html" \ No newline at end of file
+ if (endsWith(".html") || contains(Regex("\\.html#"))) this else "$this.html"
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRIFactory.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRIFactory.kt
index 5f74c429..33c99275 100644
--- a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRIFactory.kt
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRIFactory.kt
@@ -7,6 +7,7 @@ import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun DRI.Companion.from(descriptor: DeclarationDescriptor) = descriptor.parentsWithSelf.run {
val parameter = firstIsInstanceOrNull<ValueParameterDescriptor>()
@@ -20,7 +21,7 @@ fun DRI.Companion.from(descriptor: DeclarationDescriptor) = descriptor.parentsWi
?.joinToString(separator = ".") { it.name.asString() },
callable = callable?.let { Callable.from(it) },
target = DriTarget.from(parameter ?: descriptor),
- extra = if (descriptor is EnumEntrySyntheticClassDescriptor)
+ extra = if (descriptor is EnumEntrySyntheticClassDescriptor || descriptor.safeAs<ClassDescriptor>()?.kind == ClassKind.ENUM_ENTRY)
DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode()
else null
)
@@ -31,11 +32,16 @@ fun DRI.Companion.from(psi: PsiElement) = psi.parentsWithSelf.run {
val psiField = firstIsInstanceOrNull<PsiField>()
val classes = filterIsInstance<PsiClass>().filterNot { it is PsiTypeParameter }
.toList() // We only want exact PsiClass types, not PsiTypeParameter subtype
+ val additionalClasses = if (psi is PsiEnumConstant) listOfNotNull(psiField?.name) else emptyList()
DRI(
packageName = classes.lastOrNull()?.qualifiedName?.substringBeforeLast('.', "") ?: "",
- classNames = classes.toList().takeIf { it.isNotEmpty() }?.asReversed()?.mapNotNull { it.name }
- ?.joinToString("."),
- callable = psiMethod?.let { Callable.from(it) } ?: psiField?.let { Callable.from(it) },
+ classNames = (additionalClasses + classes.mapNotNull { it.name }).takeIf { it.isNotEmpty() }
+ ?.asReversed()?.joinToString("."),
+ // The fallback strategy test whether psi is not `PsiEnumConstant`. The reason behind this is that
+ // we need unified DRI for both Java and Kotlin enums, so we can link them properly and treat them alike.
+ // To achieve that, we append enum name to classNames list and leave the callable part set to null. For Kotlin enums
+ // it is by default, while for Java enums we have to explicitly test for that in this `takeUnless` condition.
+ callable = psiMethod?.let { Callable.from(it) } ?: psiField?.takeUnless { psi is PsiEnumConstant }?.let { Callable.from(it) },
target = DriTarget.from(psi),
extra = if (psi is PsiEnumConstant)
DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode()
diff --git a/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProvider.kt
index 84445d2a..a1f1542d 100644
--- a/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProvider.kt
+++ b/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProvider.kt
@@ -30,13 +30,10 @@ open class JavadocExternalLocationProvider(
return "$docWithModule$packageLink/package-summary$extension".htmlEscape()
}
- // in Kotlin DRI of enum entry is not callable
if (DRIExtraContainer(extra)[EnumEntryDRIExtra] != null) {
- val (classSplit, enumEntityAnchor) = if (callable == null) {
- val lastIndex = classNames?.lastIndexOf(".") ?: 0
+ val lastIndex = classNames?.lastIndexOf(".") ?: 0
+ val (classSplit, enumEntityAnchor) =
classNames?.substring(0, lastIndex) to classNames?.substring(lastIndex + 1)
- } else
- classNames to callable?.name
val classLink =
if (packageLink == null) "${classSplit}$extension" else "$packageLink/${classSplit}$extension"
diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
index e996a865..6078b54d 100644
--- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -317,7 +317,7 @@ private class DokkaDescriptorVisitor(
val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) }
DEnumEntry(
- dri = driWithPlatform.dri,
+ dri = driWithPlatform.dri.withEnumEntryExtra(),
name = descriptor.name.asString(),
documentation = descriptor.resolveDescriptorData(),
functions = functions.await(),
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index e7028ef0..79b4798c 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -21,11 +21,11 @@ import org.jetbrains.dokka.base.translators.isDirectlyAnException
import org.jetbrains.dokka.base.translators.psi.parsers.JavaDocumentationParser
import org.jetbrains.dokka.base.translators.psi.parsers.JavadocParser
import org.jetbrains.dokka.base.translators.unquotedValue
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.links.nextTarget
-import org.jetbrains.dokka.links.withClass
+import org.jetbrains.dokka.links.*
import org.jetbrains.dokka.model.*
import org.jetbrains.dokka.model.AnnotationTarget
+import org.jetbrains.dokka.model.Nullable
+import org.jetbrains.dokka.model.TypeConstructor
import org.jetbrains.dokka.model.doc.DocumentationNode
import org.jetbrains.dokka.model.doc.Param
import org.jetbrains.dokka.model.properties.PropertyContainer
@@ -269,7 +269,7 @@ class DefaultPsiToDocumentableTranslator(
name.orEmpty(),
fields.filterIsInstance<PsiEnumConstant>().map { entry ->
DEnumEntry(
- dri.withClass(entry.name),
+ dri.withClass(entry.name).withEnumEntryExtra(),
entry.name,
javadocParser.parseDocumentation(entry).toSourceSetDependent(),
null,
diff --git a/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt b/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt
index f9f591b2..fd8a49c8 100644
--- a/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/parsers/JavadocParser.kt
@@ -326,7 +326,7 @@ class JavadocParser(
dri.toString()
} ?: UNRESOLVED_PSI_ELEMENT
- return """<a data-dri="$dri">${label.ifBlank{ defaultLabel().text }}</a>"""
+ return """<a data-dri="${dri.htmlEscape()}">${label.ifBlank{ defaultLabel().text }}</a>"""
}
private fun convertInlineDocTag(
diff --git a/plugins/base/src/test/kotlin/enums/EnumsTest.kt b/plugins/base/src/test/kotlin/enums/EnumsTest.kt
index 59a4c6f2..bfdfa73b 100644
--- a/plugins/base/src/test/kotlin/enums/EnumsTest.kt
+++ b/plugins/base/src/test/kotlin/enums/EnumsTest.kt
@@ -125,7 +125,7 @@ class EnumsTest : BaseAbstractTest() {
pagesGenerationStage = { module ->
val entryPage = module.dfs { it.name == "E1" } as ClasslikePageNode
val signaturePart = (entryPage.content.dfs {
- it is ContentGroup && it.dci.toString() == "[enums/Test.E1///PointingToDeclaration/][Symbol]"
+ it is ContentGroup && it.dci.toString() == "[enums/Test.E1///PointingToDeclaration/{\"org.jetbrains.dokka.links.EnumEntryDRIExtra\":{\"key\":\"org.jetbrains.dokka.links.EnumEntryDRIExtra\"}}][Symbol]"
} as ContentGroup)
assertEquals("(\"e1\", 1, true)", signaturePart.constructorSignature())
}
@@ -202,7 +202,7 @@ class EnumsTest : BaseAbstractTest() {
) {
pagesTransformationStage = { m ->
val entryNode = m.children.first { it.name == "enums" }.children.first { it.name == "Test" }.children.firstIsInstance<ClasslikePageNode>()
- val signature = (entryNode.content as ContentGroup).dfs { it is ContentGroup && it.dci.toString() == "[enums/Test.E1///PointingToDeclaration/][Cover]" } as ContentGroup
+ val signature = (entryNode.content as ContentGroup).dfs { it is ContentGroup && it.dci.toString() == "[enums/Test.E1///PointingToDeclaration/{\"org.jetbrains.dokka.links.EnumEntryDRIExtra\":{\"key\":\"org.jetbrains.dokka.links.EnumEntryDRIExtra\"}}][Cover]" } as ContentGroup
signature.assertNode {
header(1) { +"E1" }
diff --git a/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt b/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt
new file mode 100644
index 00000000..29e705fd
--- /dev/null
+++ b/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt
@@ -0,0 +1,117 @@
+package linking
+
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jetbrains.dokka.links.DRIExtraContainer
+import org.jetbrains.dokka.links.EnumEntryDRIExtra
+import org.jetbrains.dokka.model.dfs
+import org.jetbrains.dokka.model.doc.DocumentationLink
+import org.jetbrains.dokka.pages.ContentDRILink
+import org.jetbrains.dokka.pages.ContentPage
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+import org.jsoup.Jsoup
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.Test
+import java.nio.file.Paths
+import utils.TestOutputWriterPlugin
+import java.lang.AssertionError
+
+class EnumValuesLinkingTest : BaseAbstractTest() {
+
+ @Test
+ fun `check if enum values are correctly linked`() {
+ val writerPlugin = TestOutputWriterPlugin()
+ val testDataDir = getTestDataDir("linking").toAbsolutePath()
+ testFromData(
+ dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf(Paths.get("$testDataDir/jvmMain/kotlin").toString())
+ analysisPlatform = "jvm"
+ name = "jvm"
+ }
+ }
+ },
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ documentablesTransformationStage = {
+ val classlikes = it.packages.single().children
+ assertEquals(4, classlikes.size)
+
+ val javaLinker = classlikes.single { it.name == "JavaLinker" }
+ javaLinker.documentation.values.single().children.run {
+ when (val kotlinLink = this[0].children[1].children[1]) {
+ is DocumentationLink -> kotlinLink.dri.run {
+ assertEquals("KotlinEnum.ON_CREATE", this.classNames)
+ assertEquals(null, this.callable)
+ assertNotNull(DRIExtraContainer(extra)[EnumEntryDRIExtra])
+ }
+ else -> throw AssertionError("Link node is not DocumentationLink type")
+ }
+
+ when (val javaLink = this[0].children[2].children[1]) {
+ is DocumentationLink -> javaLink.dri.run {
+ assertEquals("JavaEnum.ON_DECEIT", this.classNames)
+ assertEquals(null, this.callable)
+ assertNotNull(DRIExtraContainer(extra)[EnumEntryDRIExtra])
+ }
+ else -> throw AssertionError("Link node is not DocumentationLink type")
+ }
+ }
+
+ val kotlinLinker = classlikes.single { it.name == "KotlinLinker" }
+ kotlinLinker.documentation.values.single().children.run {
+ when (val kotlinLink = this[0].children[0].children[5]) {
+ is DocumentationLink -> kotlinLink.dri.run {
+ assertEquals("KotlinEnum.ON_CREATE", this.classNames)
+ assertEquals(null, this.callable)
+ assertNotNull(DRIExtraContainer(extra)[EnumEntryDRIExtra])
+ }
+ else -> throw AssertionError("Link node is not DocumentationLink type")
+ }
+
+ when (val javaLink = this[0].children[0].children[9]) {
+ is DocumentationLink -> javaLink.dri.run {
+ assertEquals("JavaEnum.ON_DECEIT", this.classNames)
+ assertEquals(null, this.callable)
+ assertNotNull(DRIExtraContainer(extra)[EnumEntryDRIExtra])
+ }
+ else -> throw AssertionError("Link node is not DocumentationLink type")
+ }
+ }
+
+ assertEquals(
+ javaLinker.documentation.values.single().children[0].children[1].children[1].safeAs<DocumentationLink>()?.dri,
+ kotlinLinker.documentation.values.single().children[0].children[0].children[5].safeAs<DocumentationLink>()?.dri
+ )
+
+ assertEquals(
+ javaLinker.documentation.values.single().children[0].children[2].children[1].safeAs<DocumentationLink>()?.dri,
+ kotlinLinker.documentation.values.single().children[0].children[0].children[9].safeAs<DocumentationLink>()?.dri
+ )
+ }
+
+ renderingStage = { rootPageNode, _ ->
+ val classlikes = rootPageNode.children.single().children
+ assertEquals(4, classlikes.size)
+
+ val javaLinker = classlikes.single { it.name == "JavaLinker" }
+ (javaLinker as ContentPage).run {
+ assertNotNull(content.dfs { it is ContentDRILink && it.address.classNames == "KotlinEnum.ON_CREATE" })
+ assertNotNull(content.dfs { it is ContentDRILink && it.address.classNames == "JavaEnum.ON_DECEIT" })
+ }
+
+ val kotlinLinker = classlikes.single { it.name == "KotlinLinker" }
+ (kotlinLinker as ContentPage).run {
+ assertNotNull(content.dfs { it is ContentDRILink && it.address.classNames == "KotlinEnum.ON_CREATE" })
+ assertNotNull(content.dfs { it is ContentDRILink && it.address.classNames == "JavaEnum.ON_DECEIT" })
+ }
+
+ // single method will throw an exception if there is no single element (0 or 2+)
+ Jsoup.parse(writerPlugin.writer.contents["root/linking.source/-java-linker/index.html"]).select("a[href=\"../-kotlin-enum/-o-n_-c-r-e-a-t-e/index.html\"]").single()
+ Jsoup.parse(writerPlugin.writer.contents["root/linking.source/-java-linker/index.html"]).select("a[href=\"../-java-enum/-o-n_-d-e-c-e-i-t/index.html\"]").single()
+ Jsoup.parse(writerPlugin.writer.contents["root/linking.source/-kotlin-linker/index.html"]).select("a[href=\"../-kotlin-enum/-o-n_-c-r-e-a-t-e/index.html\"]").single()
+ Jsoup.parse(writerPlugin.writer.contents["root/linking.source/-kotlin-linker/index.html"]).select("a[href=\"../-java-enum/-o-n_-d-e-c-e-i-t/index.html\"]").single()
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/locationProvider/JavadocExternalLocationProviderTest.kt b/plugins/base/src/test/kotlin/locationProvider/JavadocExternalLocationProviderTest.kt
index cb2b0331..95179e22 100644
--- a/plugins/base/src/test/kotlin/locationProvider/JavadocExternalLocationProviderTest.kt
+++ b/plugins/base/src/test/kotlin/locationProvider/JavadocExternalLocationProviderTest.kt
@@ -45,8 +45,8 @@ class JavadocExternalLocationProviderTest : BaseAbstractTest() {
)
val javaDri = DRI(
"java.nio.file",
- "StandardOpenOption",
- Callable("CREATE", null, emptyList()),
+ "StandardOpenOption.CREATE",
+ null,
PointingToDeclaration,
DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode()
)
diff --git a/plugins/base/src/test/kotlin/model/JavaTest.kt b/plugins/base/src/test/kotlin/model/JavaTest.kt
index 886aa0be..aa132f6e 100644
--- a/plugins/base/src/test/kotlin/model/JavaTest.kt
+++ b/plugins/base/src/test/kotlin/model/JavaTest.kt
@@ -391,8 +391,8 @@ class JavaTest : AbstractModelTest("/src/main/kotlin/java/Test.java", "java") {
"RUNTIME",
DRI(
"java.lang.annotation",
- "RetentionPolicy",
- DRICallable("RUNTIME", null, emptyList()),
+ "RetentionPolicy.RUNTIME",
+ null,
PointingToDeclaration,
DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode()
)
diff --git a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaEnum.java b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaEnum.java
new file mode 100644
index 00000000..016365a7
--- /dev/null
+++ b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaEnum.java
@@ -0,0 +1,5 @@
+package linking.source;
+
+public enum JavaEnum {
+ ON_DECEIT, ON_DESTROY;
+}
diff --git a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaLinker.java b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaLinker.java
new file mode 100644
index 00000000..ac416530
--- /dev/null
+++ b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaLinker.java
@@ -0,0 +1,8 @@
+package linking.source;
+
+/**
+ * Reference link {@link linking.source.KotlinEnum} should resolve <p>
+ * sjuff sjuff {@link linking.source.KotlinEnum#ON_CREATE} should resolve <p>
+ * sjujj sjujj {@link linking.source.JavaEnum#ON_DECEIT} should resolve
+ */
+public class JavaLinker {}
diff --git a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinEnum.kt b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinEnum.kt
new file mode 100644
index 00000000..a03316b1
--- /dev/null
+++ b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinEnum.kt
@@ -0,0 +1,5 @@
+package linking.source
+
+enum class KotlinEnum {
+ ON_CREATE, ON_CATASTROPHE
+}
diff --git a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinLinker.kt b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinLinker.kt
new file mode 100644
index 00000000..45afc3d5
--- /dev/null
+++ b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinLinker.kt
@@ -0,0 +1,8 @@
+package linking.source
+
+/**
+ * Reference link [KotlinEnum] should resolve <p>
+ * stuff stuff [KotlinEnum.ON_CREATE] should resolve <p>
+ * stuff stuff [JavaEnum.ON_DECEIT] should resolve
+ */
+class KotlinLinker {}
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
index 19ef6ae7..10240a3f 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
@@ -149,13 +149,13 @@ internal class JavadocClasslikeTemplateMapTest : AbstractJavadocTemplateMapTest(
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"])
+ assertEquals("@<a href=Author.html>Author</a>(name = &quot;Benjamin Franklin&quot;)", signature["annotations"])
val methods = assertIsInstance<Map<Any, Any?>>(map["methods"])
val ownMethods = assertIsInstance<List<*>>(methods["own"])
val method = assertIsInstance<Map<String, Any?>>(ownMethods.single())
val methodSignature = assertIsInstance<Map<String, Any?>>(method["signature"])
- assertEquals("@<a href=Author.html>Author</a>(name = \"Franklin D. Roosevelt\")", methodSignature["annotations"])
+ assertEquals("@<a href=Author.html>Author</a>(name = &quot;Franklin D. Roosevelt&quot;)", methodSignature["annotations"])
}
}