From 72541d1f1717e79534d9f24cbc7263bebde24885 Mon Sep 17 00:00:00 2001 From: Ignat Beresnev Date: Mon, 17 Jul 2023 11:22:35 +0200 Subject: Hardcode documentation for the synthetic Enum.entries property (#3071) --- .../DefaultDescriptorToDocumentableTranslator.kt | 24 +++++++------ .../SyntheticDescriptorDocumentationProvider.kt | 42 +++++++++++++++++++--- 2 files changed, 50 insertions(+), 16 deletions(-) (limited to 'subprojects') 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() - - 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(), + functions = descriptorsWithKind.functions + contributedDescriptors.filterIsInstance() + ) } 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 { - val isSynthesized = this.kind == CallableMemberDescriptor.Kind.SYNTHESIZED + private fun DeclarationDescriptor.getDocumentation(): SourceSetDependent { + 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 = - 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 } } -- cgit