Skip to content

Commit

Permalink
Fix resolving DRIs of Enum Entries
Browse files Browse the repository at this point in the history
  • Loading branch information
BarkingBad committed Jan 12, 2022
1 parent b8ffe63 commit 7a83e46
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 5 deletions.
Expand Up @@ -6,6 +6,8 @@ import org.jetbrains.dokka.links.Callable
import org.jetbrains.dokka.links.JavaClassReference
import org.jetbrains.dokka.links.TypeReference
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor

fun Callable.Companion.from(descriptor: CallableDescriptor, name: String? = null) = with(descriptor) {
Callable(
Expand All @@ -15,6 +17,18 @@ fun Callable.Companion.from(descriptor: CallableDescriptor, name: String? = null
)
}

fun Callable.Companion.from(descriptor: LazyClassDescriptor) = Callable(
descriptor.name.asString(),
null,
emptyList()
)

fun Callable.Companion.from(descriptor: EnumEntrySyntheticClassDescriptor) = Callable(
descriptor.name.asString(),
null,
emptyList()
)

fun Callable.Companion.from(psi: PsiMethod) = with(psi) {
Callable(
name,
Expand Down
Expand Up @@ -6,19 +6,29 @@ import org.jetbrains.kotlin.descriptors.*
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.resolve.lazy.descriptors.LazyClassDescriptor
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>()
val callable = parameter?.containingDeclaration ?: firstIsInstanceOrNull<CallableDescriptor>()

DRI(
packageName = firstIsInstanceOrNull<PackageFragmentDescriptor>()?.fqName?.asString() ?: "",
classNames = (filterIsInstance<ClassDescriptor>() + filterIsInstance<TypeAliasDescriptor>()).toList()
classNames = (filterIsInstance<ClassDescriptor>().map {
if (it.kind == ClassKind.ENUM_ENTRY)
it.name.asString().split(".").dropLast(1).joinToString(".")
else
it.name.asString()
} + filterIsInstance<TypeAliasDescriptor>().map { it.name.asString() }
).toList()
.filter { it.isNotBlank() }
.takeIf { it.isNotEmpty() }
?.asReversed()
?.joinToString(separator = ".") { it.name.asString() },
callable = callable?.let { Callable.from(it) },
?.joinToString(separator = "."),
callable = callable?.let { Callable.from(it) }
?: descriptor.safeAs<LazyClassDescriptor>().takeIf { it?.kind == ClassKind.ENUM_ENTRY }?.let { Callable.from(it) }
?: descriptor.safeAs<EnumEntrySyntheticClassDescriptor>()?.let { Callable.from(it) },
target = DriTarget.from(parameter ?: descriptor),
extra = if (descriptor is EnumEntrySyntheticClassDescriptor)
DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode()
Expand Down
Expand Up @@ -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.replace("\"", "&quot;")}">${label.ifBlank{ defaultLabel().text }}</a>"""
}

private fun convertInlineDocTag(
Expand Down
70 changes: 70 additions & 0 deletions plugins/base/src/test/kotlin/linking/EnumValuesLinking.kt
@@ -0,0 +1,70 @@
package linking

import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
import org.jetbrains.dokka.model.doc.DocumentationLink
import org.junit.jupiter.api.Test
import java.nio.file.Paths
import org.junit.jupiter.api.Assertions.assertEquals
import java.lang.AssertionError

class EnumValuesLinking : BaseAbstractTest() {

@Test
fun `check if enum values are correctly linked`() {
val testDataDir = getTestDataDir("linking").toAbsolutePath()
testFromData(
dokkaConfiguration {
sourceSets {
sourceSet {
sourceRoots = listOf(Paths.get("$testDataDir/jvmMain/kotlin").toString())
analysisPlatform = "jvm"
name = "jvm"
}
}
}
) {
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", this.classNames)
assertEquals("ON_CREATE", this.callable?.name)
}
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", this.classNames)
assertEquals("ON_DECEIT", this.callable?.name)
}
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", this.classNames)
assertEquals("ON_CREATE", this.callable?.name)
}
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", this.classNames)
assertEquals("ON_DECEIT", this.callable?.name)
}
else -> throw AssertionError("Link node is not DocumentationLink type")
}
}
}
}
}
}
@@ -0,0 +1,5 @@
package linking.source;

public enum JavaEnum {
ON_DECEIT, ON_DESTROY;
}
@@ -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 {}
@@ -0,0 +1,5 @@
package linking.source

enum class KotlinEnum {
ON_CREATE, ON_CATASTROPHE
}
@@ -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 {}

0 comments on commit 7a83e46

Please sign in to comment.