aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-07-17 11:22:35 +0200
committerGitHub <noreply@github.com>2023-07-17 11:22:35 +0200
commit72541d1f1717e79534d9f24cbc7263bebde24885 (patch)
treea6bba9bdbc1bc3cca169cab87bc0970571d672a5
parent20e06e878ebbe09865ff36d64ff113fd4cff8905 (diff)
downloaddokka-72541d1f1717e79534d9f24cbc7263bebde24885.tar.gz
dokka-72541d1f1717e79534d9f24cbc7263bebde24885.tar.bz2
dokka-72541d1f1717e79534d9f24cbc7263bebde24885.zip
Hardcode documentation for the synthetic Enum.entries property (#3071)
-rw-r--r--plugins/base/src/main/resources/dokka/docs/kdoc/EnumEntries.kt.template3
-rw-r--r--plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt63
-rw-r--r--subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt24
-rw-r--r--subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/SyntheticDescriptorDocumentationProvider.kt42
4 files changed, 116 insertions, 16 deletions
diff --git a/plugins/base/src/main/resources/dokka/docs/kdoc/EnumEntries.kt.template b/plugins/base/src/main/resources/dokka/docs/kdoc/EnumEntries.kt.template
new file mode 100644
index 00000000..20d16421
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/docs/kdoc/EnumEntries.kt.template
@@ -0,0 +1,3 @@
+Returns a representation of an immutable list of all enum entries, in the order they're declared.
+
+This method may be used to iterate over the enum entries.
diff --git a/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt b/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt
index c7e2bc21..9a96ad29 100644
--- a/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt
+++ b/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt
@@ -918,6 +918,69 @@ val soapXml = node("soap-env:Envelope", soapAttrs,
}
@Test
+ fun `should have documentation for synthetic Enum entries property`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/KotlinEnum.kt
+ |package test
+ |
+ |enum class KotlinEnum {
+ | FOO, BAR;
+ |}
+ """.trimIndent(),
+ configuration
+ ) {
+ documentablesMergingStage = { module ->
+ val kotlinEnum = module.packages.find { it.name == "test" }
+ ?.classlikes
+ ?.single { it.name == "KotlinEnum" }
+
+ checkNotNull(kotlinEnum)
+
+ val entriesProperty = kotlinEnum.properties.single { it.name == "entries" }
+ val expectedEntriesType = GenericTypeConstructor(
+ dri = DRI(
+ packageName = "kotlin.enums",
+ classNames = "EnumEntries"
+ ),
+ projections = listOf(
+ Invariance(
+ GenericTypeConstructor(
+ dri = DRI(
+ packageName = "test",
+ classNames = "KotlinEnum"
+ ),
+ projections = emptyList()
+ )
+ )
+ )
+ )
+ assertEquals(expectedEntriesType, entriesProperty.type)
+
+ val expectedDocumentation = DocumentationNode(listOf(
+ Description(
+ CustomDocTag(
+ children = listOf(
+ P(listOf(
+ Text(
+ "Returns a representation of an immutable list of all enum entries, " +
+ "in the order they're declared."
+ ),
+ )),
+ P(listOf(
+ Text("This method may be used to iterate over the enum entries.")
+ ))
+ ),
+ name = "MARKDOWN_FILE"
+ )
+ )
+ ))
+ assertEquals(expectedDocumentation, entriesProperty.documentation.values.single())
+ }
+ }
+ }
+
+ @Test
fun `should have documentation for synthetic Enum valueOf functions`() {
testInline(
"""
diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt
index 7633a93f..cb52236e 100644
--- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt
+++ b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt
@@ -319,11 +319,13 @@ private class DokkaDescriptorVisitor(
val descriptorsWithKind = this.unsubstitutedMemberScope.getDescriptorsWithKind()
val staticScopeForKotlinEnum = (this.staticScope as? StaticScopeForKotlinEnum) ?: return descriptorsWithKind
- // synthetic values() and valueOf() functions are not present among average class functions
- val enumSyntheticFunctions = staticScopeForKotlinEnum.getContributedDescriptors { true }
- .filterIsInstance<FunctionDescriptor>()
-
- return descriptorsWithKind.copy(functions = descriptorsWithKind.functions + enumSyntheticFunctions)
+ // synthetic declarations, such as `entries`, `values()` and `valueOf()`,
+ // are not present among real in-code declarationg
+ val contributedDescriptors = staticScopeForKotlinEnum.getContributedDescriptors { true }
+ return descriptorsWithKind.copy(
+ properties = descriptorsWithKind.properties + contributedDescriptors.filterIsInstance<PropertyDescriptor>(),
+ functions = descriptorsWithKind.functions + contributedDescriptors.filterIsInstance<FunctionDescriptor>()
+ )
}
private suspend fun visitEnumEntryDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DEnumEntry {
@@ -507,7 +509,7 @@ private class DokkaDescriptorVisitor(
getter = getter,
setter = setter,
visibility = descriptor.getVisibility(implicitAccessors).toSourceSetDependent(),
- documentation = descriptor.resolveDescriptorData(),
+ documentation = descriptor.getDocumentation(),
modifier = descriptor.modifier().toSourceSetDependent(),
type = descriptor.returnType!!.toBound(),
expectPresentInSet = sourceSet.takeIf { isExpect },
@@ -609,8 +611,8 @@ private class DokkaDescriptorVisitor(
}
}
- private fun FunctionDescriptor.getDocumentation(): SourceSetDependent<DocumentationNode> {
- val isSynthesized = this.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
+ private fun DeclarationDescriptor.getDocumentation(): SourceSetDependent<DocumentationNode> {
+ val isSynthesized = this is CallableMemberDescriptor && this.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
return if (isSynthesized) {
syntheticDocProvider.getDocumentation(this)?.toSourceSetDependent() ?: emptyMap()
} else {
@@ -914,7 +916,7 @@ private class DokkaDescriptorVisitor(
coroutineScope { parallelMap { visitEnumEntryDescriptor(it, parent) } }
private fun DeclarationDescriptor.resolveDescriptorData(): SourceSetDependent<DocumentationNode> =
- getDocumentation()?.toSourceSetDependent() ?: emptyMap()
+ resolveDocumentation()?.toSourceSetDependent() ?: emptyMap()
private suspend fun toTypeConstructor(kt: KotlinType) =
@@ -1038,7 +1040,7 @@ private class DokkaDescriptorVisitor(
return effectiveReferencedDescriptors.firstOrNull()?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) }
}
- private fun DeclarationDescriptor.getDocumentation(): DocumentationNode? {
+ private fun DeclarationDescriptor.resolveDocumentation(): DocumentationNode? {
val find = with(kDocFinder) {
find(::descriptorToAnyDeclaration)
}
@@ -1050,7 +1052,7 @@ private class DokkaDescriptorVisitor(
try {
val kdocLink = with(kDocFinder) {
resolveKDocLink(
- fromDescriptor = this@getDocumentation,
+ fromDescriptor = this@resolveDocumentation,
qualifiedName = link,
sourceSet = sourceSet
)
diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/SyntheticDescriptorDocumentationProvider.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/SyntheticDescriptorDocumentationProvider.kt
index 3b21f771..b844ddd8 100644
--- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/SyntheticDescriptorDocumentationProvider.kt
+++ b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/SyntheticDescriptorDocumentationProvider.kt
@@ -6,10 +6,15 @@ import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.fr
import org.jetbrains.dokka.analysis.markdown.jb.MarkdownParser
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.model.doc.DocumentationNode
+import org.jetbrains.kotlin.builtins.StandardNames
+import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.resolve.DescriptorFactory
+import org.jetbrains.kotlin.resolve.DescriptorUtils
+private const val ENUM_ENTRIES_TEMPLATE_PATH = "/dokka/docs/kdoc/EnumEntries.kt.template"
private const val ENUM_VALUEOF_TEMPLATE_PATH = "/dokka/docs/kdoc/EnumValueOf.kt.template"
private const val ENUM_VALUES_TEMPLATE_PATH = "/dokka/docs/kdoc/EnumValues.kt.template"
@@ -17,14 +22,41 @@ internal class SyntheticDescriptorDocumentationProvider(
private val kDocFinder: KDocFinder,
private val sourceSet: DokkaConfiguration.DokkaSourceSet
) {
- fun isDocumented(descriptor: DeclarationDescriptor): Boolean = descriptor is FunctionDescriptor
- && (DescriptorFactory.isEnumValuesMethod(descriptor) || DescriptorFactory.isEnumValueOfMethod(descriptor))
+ fun isDocumented(descriptor: DeclarationDescriptor): Boolean {
+ return when(descriptor) {
+ is PropertyDescriptor -> descriptor.isEnumEntries()
+ is FunctionDescriptor -> {
+ DescriptorFactory.isEnumValuesMethod(descriptor) || DescriptorFactory.isEnumValueOfMethod(descriptor)
+ }
+ else -> false
+ }
+ }
+
+ private fun PropertyDescriptor.isEnumEntries(): Boolean {
+ return this.name == StandardNames.ENUM_ENTRIES
+ && this.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
+ && DescriptorUtils.isEnumClass(this.containingDeclaration)
+ }
fun getDocumentation(descriptor: DeclarationDescriptor): DocumentationNode? {
- val function = descriptor as? FunctionDescriptor ?: return null
+ return when(descriptor) {
+ is PropertyDescriptor -> descriptor.getDocumentation()
+ is FunctionDescriptor -> descriptor.getDocumentation()
+ else -> null
+ }
+ }
+
+ private fun PropertyDescriptor.getDocumentation(): DocumentationNode? {
+ return when {
+ this.isEnumEntries() -> loadTemplate(this, ENUM_ENTRIES_TEMPLATE_PATH)
+ else -> null
+ }
+ }
+
+ private fun FunctionDescriptor.getDocumentation(): DocumentationNode? {
return when {
- DescriptorFactory.isEnumValuesMethod(function) -> loadTemplate(descriptor, ENUM_VALUES_TEMPLATE_PATH)
- DescriptorFactory.isEnumValueOfMethod(function) -> loadTemplate(descriptor, ENUM_VALUEOF_TEMPLATE_PATH)
+ DescriptorFactory.isEnumValuesMethod(this) -> loadTemplate(this, ENUM_VALUES_TEMPLATE_PATH)
+ DescriptorFactory.isEnumValueOfMethod(this) -> loadTemplate(this, ENUM_VALUEOF_TEMPLATE_PATH)
else -> null
}
}