aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/Kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/kotlin/Kotlin')
-rw-r--r--core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt188
-rw-r--r--core/src/main/kotlin/Kotlin/DocumentationBuilder.kt534
-rw-r--r--core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt33
-rw-r--r--core/src/main/kotlin/Kotlin/KotlinLanguageService.kt473
4 files changed, 0 insertions, 1228 deletions
diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
deleted file mode 100644
index 7c9f2d15..00000000
--- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
+++ /dev/null
@@ -1,188 +0,0 @@
-package org.jetbrains.dokka.Kotlin
-
-import com.google.inject.Inject
-import com.intellij.psi.PsiDocCommentOwner
-import com.intellij.psi.PsiNamedElement
-import com.intellij.psi.util.PsiTreeUtil
-import org.intellij.markdown.parser.LinkMap
-import org.jetbrains.dokka.*
-import org.jetbrains.dokka.Samples.SampleProcessingService
-import org.jetbrains.kotlin.descriptors.*
-import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
-import org.jetbrains.kotlin.idea.kdoc.findKDoc
-import org.jetbrains.kotlin.incremental.components.NoLookupLocation
-import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
-import org.jetbrains.kotlin.kdoc.psi.api.KDoc
-import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
-import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
-import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
-import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.psi.KtDeclaration
-import org.jetbrains.kotlin.psi.KtElement
-import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
-import org.jetbrains.kotlin.resolve.DescriptorUtils
-import org.jetbrains.kotlin.resolve.annotations.argumentValue
-import org.jetbrains.kotlin.resolve.constants.StringValue
-import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
-import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
-import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
-import org.jetbrains.kotlin.resolve.source.PsiSourceElement
-
-class DescriptorDocumentationParser
-@Inject constructor(
- val options: DokkaConfiguration.PassConfiguration,
- val logger: DokkaLogger,
- val linkResolver: DeclarationLinkResolver,
- val resolutionFacade: DokkaResolutionFacade,
- val refGraph: NodeReferenceGraph,
- val sampleService: SampleProcessingService,
- val signatureProvider: KotlinElementSignatureProvider,
- val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver
-) {
- fun parseDocumentation(
- descriptor: DeclarationDescriptor,
- inline: Boolean = false,
- isDefaultNoArgConstructor: Boolean = false
- ): Content =
- parseDocumentationAndDetails(descriptor, inline, isDefaultNoArgConstructor).first
-
- fun parseDocumentationAndDetails(
- descriptor: DeclarationDescriptor,
- inline: Boolean = false,
- isDefaultNoArgConstructor: Boolean = false
- ): Pair<Content, (DocumentationNode) -> Unit> {
- if (descriptor is JavaClassDescriptor || descriptor is JavaCallableMemberDescriptor) {
- return parseJavadoc(descriptor)
- }
-
- val kdoc = descriptor.findKDoc() ?: findStdlibKDoc(descriptor)
- if (kdoc == null) {
- if (options.effectivePackageOptions(descriptor.fqNameSafe).reportUndocumented && !descriptor.isDeprecated() &&
- descriptor !is ValueParameterDescriptor && descriptor !is TypeParameterDescriptor &&
- descriptor !is PropertyAccessorDescriptor && !descriptor.isSuppressWarning()) {
- logger.warn("No documentation for ${descriptor.signatureWithSourceLocation()}")
- }
- return Content.Empty to { node -> }
- }
-
- val contextDescriptor =
- (PsiTreeUtil.getParentOfType(kdoc, KDoc::class.java)?.context as? KtDeclaration)
- ?.takeIf { it != descriptor.original.sourcePsi() }
- ?.resolveToDescriptorIfAny()
- ?: descriptor
-
- var kdocText = if (isDefaultNoArgConstructor) {
- getConstructorTagContent(descriptor) ?: kdoc.getContent()
- } else kdoc.getContent()
-
- // workaround for code fence parsing problem in IJ markdown parser
- if (kdocText.endsWith("```") || kdocText.endsWith("~~~")) {
- kdocText += "\n"
- }
- val tree = parseMarkdown(kdocText)
- val linkMap = LinkMap.buildLinkMap(tree.node, kdocText)
- val content = buildContent(
- tree,
- LinkResolver(linkMap) { href -> linkResolver.resolveContentLink(contextDescriptor, href) },
- inline
- )
- if (kdoc is KDocSection) {
- val tags = kdoc.getTags()
- tags.forEach {
- when (it.knownTag) {
- KDocKnownTag.SAMPLE ->
- content.append(sampleService.resolveSample(contextDescriptor, it.getSubjectName(), it))
- KDocKnownTag.SEE ->
- content.addTagToSeeAlso(contextDescriptor, it)
- else -> {
- val section = content.addSection(javadocSectionDisplayName(it.name), it.getSubjectName())
- val sectionContent = it.getContent()
- val markdownNode = parseMarkdown(sectionContent)
- buildInlineContentTo(
- markdownNode,
- section,
- LinkResolver(linkMap) { href -> linkResolver.resolveContentLink(contextDescriptor, href) })
- }
- }
- }
- }
- return content to { node -> }
- }
-
- private fun getConstructorTagContent(descriptor: DeclarationDescriptor): String? {
- return ((DescriptorToSourceUtils.descriptorToDeclaration(descriptor)?.navigationElement as? KtElement) as KtDeclaration).docComment?.findSectionByTag(
- KDocKnownTag.CONSTRUCTOR
- )?.getContent()
- }
-
-
- private fun DeclarationDescriptor.isSuppressWarning(): Boolean {
- val suppressAnnotation = annotations.findAnnotation(FqName(Suppress::class.qualifiedName!!))
- return if (suppressAnnotation != null) {
- @Suppress("UNCHECKED_CAST")
- (suppressAnnotation.argumentValue("names")?.value as List<StringValue>).any { it.value == "NOT_DOCUMENTED" }
- } else containingDeclaration?.isSuppressWarning() ?: false
- }
-
- /**
- * Special case for generating stdlib documentation (the Any class to which the override chain will resolve
- * is not the same one as the Any class included in the source scope).
- */
- fun findStdlibKDoc(descriptor: DeclarationDescriptor): KDocTag? {
- if (descriptor !is CallableMemberDescriptor) {
- return null
- }
- val name = descriptor.name.asString()
- if (name == "equals" || name == "hashCode" || name == "toString") {
- var deepestDescriptor: CallableMemberDescriptor = descriptor
- while (!deepestDescriptor.overriddenDescriptors.isEmpty()) {
- deepestDescriptor = deepestDescriptor.overriddenDescriptors.first()
- }
- if (DescriptorUtils.getFqName(deepestDescriptor.containingDeclaration).asString() == "kotlin.Any") {
- val anyClassDescriptors = resolutionFacade.resolveSession.getTopLevelClassifierDescriptors(
- FqName.fromSegments(listOf("kotlin", "Any")), NoLookupLocation.FROM_IDE
- )
- anyClassDescriptors.forEach {
- val anyMethod = (it as ClassDescriptor).getMemberScope(listOf())
- .getDescriptorsFiltered(DescriptorKindFilter.FUNCTIONS) { it == descriptor.name }
- .single()
- val kdoc = anyMethod.findKDoc()
- if (kdoc != null) {
- return kdoc
- }
- }
- }
- }
- return null
- }
-
- fun parseJavadoc(descriptor: DeclarationDescriptor): Pair<Content, (DocumentationNode) -> Unit> {
- val psi = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi
- if (psi is PsiDocCommentOwner) {
- val parseResult = JavadocParser(
- refGraph,
- logger,
- signatureProvider,
- externalDocumentationLinkResolver
- ).parseDocumentation(psi as PsiNamedElement)
- return parseResult.content to { node -> }
- }
- return Content.Empty to { node -> }
- }
-
- fun KDocSection.getTags(): Array<KDocTag> = PsiTreeUtil.getChildrenOfType(this, KDocTag::class.java) ?: arrayOf()
-
- private fun MutableContent.addTagToSeeAlso(descriptor: DeclarationDescriptor, seeTag: KDocTag) {
- val subjectName = seeTag.getSubjectName()
- if (subjectName != null) {
- val seeSection = findSectionByTag("See Also") ?: addSection("See Also", null)
- val link = linkResolver.resolveContentLink(descriptor, subjectName)
- link.append(ContentText(subjectName))
- val para = ContentParagraph()
- para.append(link)
- seeSection.append(para)
- }
- }
-
-}
diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
deleted file mode 100644
index 6d258564..00000000
--- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
+++ /dev/null
@@ -1,534 +0,0 @@
-package org.jetbrains.dokka
-
-import com.google.inject.Inject
-import com.intellij.psi.PsiJavaFile
-import org.jetbrains.dokka.DokkaConfiguration.PassConfiguration
-import org.jetbrains.kotlin.builtins.KotlinBuiltIns
-import org.jetbrains.kotlin.descriptors.*
-import org.jetbrains.kotlin.idea.kdoc.findKDoc
-import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
-import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.resolve.DescriptorUtils
-import org.jetbrains.kotlin.resolve.descriptorUtil.*
-import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors
-import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
-import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
-import org.jetbrains.kotlin.resolve.source.PsiSourceElement
-import org.jetbrains.kotlin.types.*
-import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
-import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
-import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
-import org.jetbrains.kotlin.types.typeUtil.supertypes
-import org.jetbrains.kotlin.util.supertypesWithAny
-import kotlin.reflect.KClass
-import com.google.inject.name.Named as GuiceNamed
-
-private fun isExtensionForExternalClass(
- extensionFunctionDescriptor: DeclarationDescriptor,
- extensionReceiverDescriptor: DeclarationDescriptor,
- allFqNames: Collection<FqName>
-): Boolean {
- val extensionFunctionPackage =
- DescriptorUtils.getParentOfType(extensionFunctionDescriptor, PackageFragmentDescriptor::class.java)
- val extensionReceiverPackage =
- DescriptorUtils.getParentOfType(extensionReceiverDescriptor, PackageFragmentDescriptor::class.java)
- return extensionFunctionPackage != null && extensionReceiverPackage != null &&
- extensionFunctionPackage.fqName != extensionReceiverPackage.fqName &&
- extensionReceiverPackage.fqName !in allFqNames
-}
-
-interface PackageDocumentationBuilder {
- fun buildPackageDocumentation(
- documentationBuilder: DocumentationBuilder,
- packageName: FqName,
- packageNode: DocumentationNodes.Package,
- declarations: List<DeclarationDescriptor>,
- allFqNames: Collection<FqName>
- )
-}
-
-interface DefaultPlatformsProvider {
- fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List<String>
-}
-
-val ignoredSupertypes = setOf(
- "kotlin.Annotation", "kotlin.Enum", "kotlin.Any"
-)
-
-class DocumentationBuilder
-@Inject constructor(
- val resolutionFacade: DokkaResolutionFacade,
- val passConfiguration: DokkaConfiguration.PassConfiguration,
- val logger: DokkaLogger
-) {
-
- private fun DocumentationNodes.Class.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType, backref: Boolean) {
- val unwrappedType = superType.unwrap()
- if (unwrappedType is AbbreviatedType) {
- appendSupertype(descriptor, unwrappedType.abbreviation, backref)
- } else {
- appendType(unwrappedType, descriptor)
- }
- }
-
- private fun DocumentationNodes.Class.appendType(
- kotlinType: KotlinType?,
- descriptor: ClassDescriptor?
- ) {
- if (kotlinType == null)
- return
- (kotlinType.unwrap() as? AbbreviatedType)?.let {
- return appendType(it.abbreviation, descriptor)
- }
-
- if (kotlinType.isDynamic()) {
- append(kind.createNode("dynamic", descriptor), RefKind.Detail)
- return
- }
-
- val classifierDescriptor = kotlinType.constructor.declarationDescriptor
- val name = when (classifierDescriptor) {
- is ClassDescriptor -> {
- if (classifierDescriptor.isCompanionObject) {
- classifierDescriptor.containingDeclaration.name.asString() +
- "." + classifierDescriptor.name.asString()
- } else {
- classifierDescriptor.name.asString()
- }
- }
- is Named -> classifierDescriptor.name.asString()
- else -> "<anonymous>"
- }
- val node = kind.createNode(name, descriptor)
-
- append(node, RefKind.Detail)
- for (typeArgument in kotlinType.arguments) {
- node.appendProjection(typeArgument, null)
- }
- }
-
- fun DocumentationNode<*>.appendChild(descriptor: DeclarationDescriptor) {
- if (!descriptor.isGenerated() && descriptor.isDocumented(passConfiguration)) {
- val node = descriptor.build()
- append(node, kind)
- }
- }
-
- fun DocumentationNode.appendMember(descriptor: DeclarationDescriptor) {
- if (!descriptor.isGenerated() && descriptor.isDocumented(passConfiguration)) {
- val existingNode = members.firstOrNull { it.descriptor?.fqNameSafe == descriptor.fqNameSafe }
- if (existingNode != null) {
- if (descriptor is ClassDescriptor) {
- val membersToDocument = descriptor.collectMembersToDocument()
- for ((memberDescriptor, _, _) in membersToDocument) {
- if (memberDescriptor is ClassDescriptor) {
- existingNode.appendMember(memberDescriptor) // recurse into nested classes
- } else {
- if (members.any { it.descriptor?.fqNameSafe == memberDescriptor.fqNameSafe }) {
- existingNode.appendClassMember(memberDescriptor)
- }
- }
- }
- }
- } else {
- appendChild(descriptor, RefKind.Member)
- }
- }
- }
-
- private fun DocumentationNode.appendClassMember(descriptor: DeclarationDescriptor) {
- if (descriptor !is CallableMemberDescriptor || descriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
- val descriptorToUse = if (descriptor is ConstructorDescriptor) descriptor else descriptor.original
- appendChild(descriptorToUse, RefKind.Member)
- }
- }
-
- fun DocumentationNodes.Module.appendFragments(
- fragments: Collection<PackageFragmentDescriptor>,
- packageDocumentationBuilder: PackageDocumentationBuilder
- ) {
- val allFqNames = fragments.filter { it.isDocumented(passConfiguration) }.map { it.fqName }.distinct()
-
- for (packageName in allFqNames) {
- if (packageName.isRoot && !passConfiguration.includeRootPackage) continue
- val declarations = fragments.filter { it.fqName == packageName }
- .flatMap { it.getMemberScope().getContributedDescriptors() }
-
- if (passConfiguration.skipEmptyPackages && declarations.none { it.isDocumented(passConfiguration) }) continue
- logger.info(" package $packageName: ${declarations.count()} declarations")
- val packageNode = findOrCreatePackageNode(this, packageName.asString())
- packageDocumentationBuilder.buildPackageDocumentation(
- this@DocumentationBuilder, packageName, packageNode,
- declarations, allFqNames
- )
- }
- }
-
- fun findOrCreatePackageNode(
- module: DocumentationNodes.Module,
- packageName: String
- ): DocumentationNode<*> {
- val node = module?.member(DocumentationNodes.Package::class) ?: DocumentationNodes.Package(packageName)
- if (module != null && node !in module.members) {
- module.append(node, RefKind.Member)
- }
- return node
- }
-
- fun propagateExtensionFunctionsToSubclasses(
- fragments: Collection<PackageFragmentDescriptor>,
- resolutionFacade: DokkaResolutionFacade
- ) {
-
- val moduleDescriptor = resolutionFacade.moduleDescriptor
-
- // Wide-collect all view descriptors
- val allPackageViewDescriptors = generateSequence(listOf(moduleDescriptor.getPackage(FqName.ROOT))) { packages ->
- packages
- .flatMap { pkg ->
- moduleDescriptor.getSubPackagesOf(pkg.fqName) { true }
- }.map { fqName ->
- moduleDescriptor.getPackage(fqName)
- }.takeUnless { it.isEmpty() }
- }.flatten()
-
- val allDescriptors =
- if (passConfiguration.collectInheritedExtensionsFromLibraries) {
- allPackageViewDescriptors.map { it.memberScope }
- } else {
- fragments.asSequence().map { it.getMemberScope() }
- }.flatMap {
- it.getDescriptorsFiltered(
- DescriptorKindFilter.CALLABLES
- ).asSequence()
- }
-
- val allExtensionFunctions =
- allDescriptors
- .filterIsInstance<CallableMemberDescriptor>()
- .filter { it.extensionReceiverParameter != null }
- val extensionFunctionsByName = allExtensionFunctions.groupBy { it.name }
-
- fun isIgnoredReceiverType(type: KotlinType) =
- type.isDynamic() ||
- type.isAnyOrNullableAny() ||
- (type.isTypeParameter() && type.immediateSupertypes().all { it.isAnyOrNullableAny() })
-
-
- for (extensionFunction in allExtensionFunctions) {
- val extensionReceiverParameter = extensionFunction.extensionReceiverParameter!!
- if (extensionFunction.dispatchReceiverParameter != null) continue
- val possiblyShadowingFunctions = extensionFunctionsByName[extensionFunction.name]
- ?.filter { fn -> fn.canShadow(extensionFunction) }
- ?: emptyList()
-
- if (isIgnoredReceiverType(extensionReceiverParameter.type)) continue
- }
- }
-
- private fun CallableMemberDescriptor.canShadow(other: CallableMemberDescriptor): Boolean {
- if (this == other) return false
- if (this is PropertyDescriptor && other is PropertyDescriptor) {
- return true
- }
- if (this is FunctionDescriptor && other is FunctionDescriptor) {
- val parameters1 = valueParameters
- val parameters2 = other.valueParameters
- if (parameters1.size != parameters2.size) {
- return false
- }
- for ((p1, p2) in parameters1 zip parameters2) {
- if (p1.type != p2.type) {
- return false
- }
- }
- return true
- }
- return false
- }
-
- fun DeclarationDescriptor.build(): DocumentationNode = when (this) {
- is ClassifierDescriptor -> build()
- is ConstructorDescriptor -> build()
- is PropertyDescriptor -> build()
- is FunctionDescriptor -> build()
- is ValueParameterDescriptor -> build()
- is ReceiverParameterDescriptor -> build()
- else -> throw IllegalStateException("Descriptor $this is not known")
- }
-
- fun ClassifierDescriptor.build(external: Boolean = false): DocumentationNode = when (this) {
- is ClassDescriptor -> build(this, external)
- is TypeAliasDescriptor -> build()
- is TypeParameterDescriptor -> build()
- else -> throw IllegalStateException("Descriptor $this is not known")
- }
-
- fun TypeAliasDescriptor.build(): DocumentationNode {
- val node = DocumentationNodes.TypeAlias(name.asString(), this)
- node.appendType(underlyingType, this, DocumentationNodes.TypeAliasUnderlyingType::class)
- return node
- }
-
- fun ClassDescriptor.build(descriptor: DeclarationDescriptor, external: Boolean = false): DocumentationNode {
- val node = when {
- kind == ClassKind.OBJECT -> DocumentationNodes.Object(descriptor.name.asString(), descriptor)
- kind == ClassKind.INTERFACE -> DocumentationNodes.Interface(descriptor.name.asString(), descriptor)
- kind == ClassKind.ENUM_CLASS -> DocumentationNodes.Enum(descriptor.name.asString(), descriptor)
- kind == ClassKind.ANNOTATION_CLASS -> DocumentationNodes.AnnotationClass(descriptor.name.asString(), descriptor)
- kind == ClassKind.ENUM_ENTRY -> DocumentationNodes.EnumItem(descriptor.name.asString(), descriptor)
- isSubclassOfThrowable() -> DocumentationNodes.Exception(descriptor.name.asString(), descriptor)
- else -> DocumentationNodes.Class(descriptor.name.asString(), descriptor)
- }
- supertypesWithAnyPrecise().forEach {
- node.appendSupertype(this, it, !external)
- }
- if (!external) {
- for ((membersDescriptor, _, _) in collectMembersToDocument()) {
- node.appendClassMember(membersDescriptor)
- }
- }
- return node
- }
-
- data class ClassMember(
- val descriptor: DeclarationDescriptor,
- val inheritedLinkKind: RefKind = RefKind.InheritedMember,
- val extraModifier: String? = null
- )
-
- private fun ClassDescriptor.collectMembersToDocument(): List<ClassMember> {
- val result = arrayListOf<ClassMember>()
- if (kind != ClassKind.OBJECT && kind != ClassKind.ENUM_ENTRY) {
- val constructorsToDocument = if (kind == ClassKind.ENUM_CLASS)
- constructors.filter { it.valueParameters.size > 0 }
- else
- constructors
- constructorsToDocument.mapTo(result) { ClassMember(it) }
- }
-
- defaultType.memberScope.getContributedDescriptors()
- .filter { it != companionObjectDescriptor }
- .mapTo(result) { ClassMember(it) }
-
- staticScope.getContributedDescriptors()
- .mapTo(result) { ClassMember(it, extraModifier = "static") }
-
- val companionObjectDescriptor = companionObjectDescriptor
- if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(passConfiguration)) {
- val descriptors = companionObjectDescriptor.defaultType.memberScope.getContributedDescriptors()
- val descriptorsToDocument = descriptors.filter { it !is CallableDescriptor || !it.isInheritedFromAny() }
- descriptorsToDocument.mapTo(result) {
- ClassMember(it, inheritedLinkKind = RefKind.InheritedCompanionObjectMember)
- }
-
- if (companionObjectDescriptor.getAllSuperclassesWithoutAny().isNotEmpty()
- || companionObjectDescriptor.getSuperInterfaces().isNotEmpty()) {
- result += ClassMember(companionObjectDescriptor)
- }
- }
- return result
- }
-
- private fun CallableDescriptor.isInheritedFromAny(): Boolean {
- return findTopMostOverriddenDescriptors().any {
- DescriptorUtils.getFqNameSafe(it.containingDeclaration).asString() == "kotlin.Any"
- }
- }
-
- private fun ClassDescriptor.isSubclassOfThrowable(): Boolean =
- defaultType.supertypes().any { it.constructor.declarationDescriptor == builtIns.throwable }
-
- fun ConstructorDescriptor.build(): DocumentationNode =
- DocumentationNodes.Constructor(name.asString(), this)
-
- private fun CallableMemberDescriptor.inCompanionObject(): Boolean {
- val containingDeclaration = containingDeclaration
- if ((containingDeclaration as? ClassDescriptor)?.isCompanionObject == true) {
- return true
- }
- val receiver = extensionReceiverParameter
- return (receiver?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.isCompanionObject ?: false
- }
-
- fun FunctionDescriptor.build(): DocumentationNode =
- if (inCompanionObject())
- DocumentationNodes.CompanionObjectFunction(name.asString(),this)
- else
- DocumentationNodes.Function(name.asString(),this)
-
- fun PropertyDescriptor.build(): DocumentationNode =
- DocumentationNodes.Property(name.asString(), this)
-
- fun ValueParameterDescriptor.build(): DocumentationNode =
- DocumentationNodes.Parameter(name.asString(), this)
-
- fun TypeParameterDescriptor.build(): DocumentationNode =
- DocumentationNodes.TypeParameter(name.asString(), this)
-
- fun ReceiverParameterDescriptor.build(): DocumentationNode =
- DocumentationNodes.Receiver(name.asString(), this)
-}
-
-fun DeclarationDescriptor.isDocumented(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean {
- return (passConfiguration.effectivePackageOptions(fqNameSafe).includeNonPublic
- || this !is MemberDescriptor
- || this.visibility.isPublicAPI)
- && !isDocumentationSuppressed(passConfiguration)
- && (!passConfiguration.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated())
-}
-
-private fun DeclarationDescriptor.isGenerated() =
- this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION
-
-class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder {
-
- override fun buildPackageDocumentation(
- documentationBuilder: DocumentationBuilder,
- packageName: FqName,
- packageNode: DocumentationNode,
- declarations: List<DeclarationDescriptor>,
- allFqNames: Collection<FqName>
- ) {
- declarations.forEach { descriptor ->
- with(documentationBuilder) {
- if (descriptor.isDocumented(passConfiguration)) {
- packageNode.appendMember(descriptor)
- }
- }
- }
- }
-}
-
-class KotlinJavaDocumentationBuilder
-@Inject constructor(
- val resolutionFacade: DokkaResolutionFacade,
- val documentationBuilder: DocumentationBuilder,
- val passConfiguration: DokkaConfiguration.PassConfiguration,
- val logger: DokkaLogger
-) : JavaDocumentationBuilder {
- override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) {
- val classDescriptors = file.classes.map {
- it.getJavaClassDescriptor(resolutionFacade)
- }
-
- if (classDescriptors.any { it != null && it.isDocumented(passConfiguration) }) {
- val packageNode = documentationBuilder.findOrCreatePackageNode(module, file.packageName)
-
- for (descriptor in classDescriptors.filterNotNull()) {
- with(documentationBuilder) {
- packageNode.appendChild(descriptor, RefKind.Member)
- }
- }
- }
- }
-}
-
-fun DeclarationDescriptor.isDocumentationSuppressed(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean {
-
- if (passConfiguration.effectivePackageOptions(fqNameSafe).suppress) return true
-
- val path = this.findPsi()?.containingFile?.virtualFile?.path
- if (path != null) {
- if (path in passConfiguration.suppressedFiles) return true
- }
-
- val doc = findKDoc()
- if (doc is KDocSection && doc.findTagByName("suppress") != null) return true
-
- return hasSuppressDocTag(sourcePsi())
-}
-
-fun DeclarationDescriptor.sourcePsi() =
- ((original as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi
-
-fun DeclarationDescriptor.isDeprecated(): Boolean = annotations.any {
- DescriptorUtils.getFqName(it.type.constructor.declarationDescriptor!!).asString() == "kotlin.Deprecated"
-} || (this is ConstructorDescriptor && containingDeclaration.isDeprecated())
-
-fun DeclarationDescriptor.signature(): String {
- if (this != original) return original.signature()
- return when (this) {
- is ClassDescriptor,
- is PackageFragmentDescriptor,
- is PackageViewDescriptor,
- is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString()
-
- is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature()
- is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature()
- is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name
- is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name
- is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name
- else -> throw UnsupportedOperationException("Don't know how to calculate signature for $this")
- }
-}
-
-fun PropertyDescriptor.receiverSignature(): String {
- val receiver = extensionReceiverParameter
- if (receiver != null) {
- return "#" + receiver.type.signature()
- }
- return ""
-}
-
-fun CallableMemberDescriptor.parameterSignature(): String {
- val params = valueParameters.map { it.type }.toMutableList()
- val extensionReceiver = extensionReceiverParameter
- if (extensionReceiver != null) {
- params.add(0, extensionReceiver.type)
- }
- return params.joinToString(prefix = "(", postfix = ")") { it.signature() }
-}
-
-fun KotlinType.signature(): String {
- val visited = hashSetOf<KotlinType>()
-
- fun KotlinType.signatureRecursive(): String {
- if (this in visited) {
- return ""
- }
- visited.add(this)
-
- val declarationDescriptor = constructor.declarationDescriptor ?: return "<null>"
- val typeName = DescriptorUtils.getFqName(declarationDescriptor).asString()
- if (arguments.isEmpty()) {
- return typeName
- }
- return typeName + arguments.joinToString(prefix = "((", postfix = "))") { it.type.signatureRecursive() }
- }
-
- return signatureRecursive()
-}
-
-fun DeclarationDescriptor.signatureWithSourceLocation(): String {
- val signature = signature()
- val sourceLocation = sourceLocation()
- return if (sourceLocation != null) "$signature ($sourceLocation)" else signature
-}
-
-fun DeclarationDescriptor.sourceLocation(): String? {
- val psi = sourcePsi()
- if (psi != null) {
- val fileName = psi.containingFile.name
- val lineNumber = psi.lineNumber()
- return if (lineNumber != null) "$fileName:$lineNumber" else fileName
- }
- return null
-}
-
-fun ClassDescriptor.supertypesWithAnyPrecise(): Collection<KotlinType> {
- if (KotlinBuiltIns.isAny(this)) {
- return emptyList()
- }
- return typeConstructor.supertypesWithAny()
-}
-
-fun PassConfiguration.effectivePackageOptions(pack: String): DokkaConfiguration.PackageOptions {
- val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated, false)
- return perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions
-}
-
-fun PassConfiguration.effectivePackageOptions(pack: FqName): DokkaConfiguration.PackageOptions =
- effectivePackageOptions(pack.asString())
-
diff --git a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt
deleted file mode 100644
index c7187b23..00000000
--- a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.jetbrains.dokka
-
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiMember
-import com.intellij.psi.PsiPackage
-import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
-import org.jetbrains.kotlin.asJava.elements.KtLightElement
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.resolve.BindingContext
-import javax.inject.Inject
-
-class KotlinElementSignatureProvider @Inject constructor(
- val resolutionFacade: DokkaResolutionFacade
-) : ElementSignatureProvider {
- override fun signature(forPsi: PsiElement): String {
- return forPsi.extractDescriptor(resolutionFacade)
- ?.let { signature(it) }
- ?: run { "no desc for $forPsi in ${(forPsi as? PsiMember)?.containingClass}" }
- }
-
- override fun signature(forDesc: DeclarationDescriptor): String = forDesc.signature()
-}
-
-
-fun PsiElement.extractDescriptor(resolutionFacade: DokkaResolutionFacade): DeclarationDescriptor? =
- when (val forPsi = this) {
- is KtLightClassForFacade -> resolutionFacade.moduleDescriptor.getPackage(forPsi.fqName)
- is KtLightElement<*, *> -> (forPsi.kotlinOrigin!!).extractDescriptor(resolutionFacade)
- is PsiPackage -> resolutionFacade.moduleDescriptor.getPackage(FqName(forPsi.qualifiedName))
- is PsiMember -> forPsi.getJavaOrKotlinMemberDescriptor(resolutionFacade)
- else -> resolutionFacade.resolveSession.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, forPsi]
- }
diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt
deleted file mode 100644
index 7310610f..00000000
--- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt
+++ /dev/null
@@ -1,473 +0,0 @@
-package org.jetbrains.dokka
-
-import org.jetbrains.dokka.LanguageService.RenderMode
-
-/**
- * Implements [LanguageService] and provides rendering of symbols in Kotlin language
- */
-class KotlinLanguageService : CommonLanguageService() {
- override fun showModifierInSummary(node: DocumentationNode): Boolean {
- return node.name !in fullOnlyModifiers
- }
-
- private val fullOnlyModifiers =
- setOf("public", "protected", "private", "internal", "inline", "noinline", "crossinline", "reified")
-
- override fun render(node: DocumentationNode, renderMode: RenderMode): ContentNode {
- return content {
- when (node.kind) {
- NodeKind.Package -> if (renderMode == RenderMode.FULL) renderPackage(node)
- in NodeKind.classLike -> renderClass(node, renderMode)
-
- NodeKind.EnumItem,
- NodeKind.ExternalClass -> if (renderMode == RenderMode.FULL) identifier(node.name)
-
- NodeKind.Parameter -> renderParameter(node, renderMode)
- NodeKind.TypeParameter -> renderTypeParameter(node, renderMode)
- NodeKind.Type,
- NodeKind.UpperBound -> renderType(node, renderMode)
-
- NodeKind.Modifier -> renderModifier(this, node, renderMode)
- NodeKind.Constructor,
- NodeKind.Function,
- NodeKind.CompanionObjectFunction -> renderFunction(node, renderMode)
- NodeKind.Property,
- NodeKind.CompanionObjectProperty -> renderProperty(node, renderMode)
- else -> identifier(node.name)
- }
- }
- }
-
-
- override fun summarizeSignatures(nodes: List<DocumentationNode>): ContentNode? {
- if (nodes.size < 2) return null
- val receiverKind = nodes.getReceiverKind() ?: return null
- val functionWithTypeParameter = nodes.firstOrNull { it.details(NodeKind.TypeParameter).any() } ?: return null
- return content {
- val typeParameter = functionWithTypeParameter.details(NodeKind.TypeParameter).first()
- if (functionWithTypeParameter.kind == NodeKind.Function) {
- renderFunction(
- functionWithTypeParameter,
- RenderMode.SUMMARY,
- SummarizingMapper(receiverKind, typeParameter.name)
- )
- } else {
- renderProperty(
- functionWithTypeParameter,
- RenderMode.SUMMARY,
- SummarizingMapper(receiverKind, typeParameter.name)
- )
- }
- }
- }
-
- private fun List<DocumentationNode>.getReceiverKind(): ReceiverKind? {
- val qNames = mapNotNull { it.getReceiverQName() }
- if (qNames.size != size)
- return null
-
- return ReceiverKind.values().firstOrNull { kind -> qNames.all { it in kind.classes } }
- }
-
- private fun DocumentationNode.getReceiverQName(): String? {
- if (kind != NodeKind.Function && kind != NodeKind.Property) return null
- val receiver = details(NodeKind.Receiver).singleOrNull() ?: return null
- return receiver.detail(NodeKind.Type).qualifiedNameFromType()
- }
-
- companion object {
- private val arrayClasses = setOf(
- "kotlin.Array",
- "kotlin.BooleanArray",
- "kotlin.ByteArray",
- "kotlin.CharArray",
- "kotlin.ShortArray",
- "kotlin.IntArray",
- "kotlin.LongArray",
- "kotlin.FloatArray",
- "kotlin.DoubleArray"
- )
-
- private val arrayOrListClasses = setOf("kotlin.List") + arrayClasses
-
- private val iterableClasses = setOf(
- "kotlin.Collection",
- "kotlin.Sequence",
- "kotlin.Iterable",
- "kotlin.Map",
- "kotlin.String",
- "kotlin.CharSequence"
- ) + arrayOrListClasses
- }
-
- private enum class ReceiverKind(val receiverName: String, val classes: Collection<String>) {
- ARRAY("any_array", arrayClasses),
- ARRAY_OR_LIST("any_array_or_list", arrayOrListClasses),
- ITERABLE("any_iterable", iterableClasses),
- }
-
- interface SignatureMapper {
- fun renderReceiver(receiver: DocumentationNode, to: ContentBlock)
- }
-
- private class SummarizingMapper(val kind: ReceiverKind, val typeParameterName: String) : SignatureMapper {
- override fun renderReceiver(receiver: DocumentationNode, to: ContentBlock) {
- to.append(ContentIdentifier(kind.receiverName, IdentifierKind.SummarizedTypeName))
- to.text("<$typeParameterName>")
- }
- }
-
- private fun ContentBlock.renderFunctionalTypeParameterName(node: DocumentationNode, renderMode: RenderMode) {
- node.references(RefKind.HiddenAnnotation).map { it.to }
- .find { it.name == "ParameterName" }?.let {
- val parameterNameValue = it.detail(NodeKind.Parameter).detail(NodeKind.Value)
- identifier(parameterNameValue.name.removeSurrounding("\""), IdentifierKind.ParameterName)
- symbol(":")
- nbsp()
- }
- }
-
- private fun ContentBlock.renderFunctionalType(node: DocumentationNode, renderMode: RenderMode) {
- var typeArguments = node.details(NodeKind.Type)
-
- if (node.name.startsWith("Suspend")) {
- keyword("suspend ")
- }
-
- // lambda
- val isExtension = node.annotations.any { it.name == "ExtensionFunctionType" }
- if (isExtension) {
- renderType(typeArguments.first(), renderMode)
- symbol(".")
- typeArguments = typeArguments.drop(1)
- }
- symbol("(")
- renderList(typeArguments.take(typeArguments.size - 1), noWrap = true) {
- renderFunctionalTypeParameterName(it, renderMode)
- renderType(it, renderMode)
- }
- symbol(")")
- nbsp()
- symbol("->")
- nbsp()
- renderType(typeArguments.last(), renderMode)
-
- }
-
- private fun DocumentationNode.isFunctionalType(): Boolean {
- val typeArguments = details(NodeKind.Type)
- val functionalTypeName = "Function${typeArguments.count() - 1}"
- val suspendFunctionalTypeName = "Suspend$functionalTypeName"
- return name == functionalTypeName || name == suspendFunctionalTypeName
- }
-
- private fun ContentBlock.renderType(node: DocumentationNode, renderMode: RenderMode) {
- if (node.name == "dynamic") {
- keyword("dynamic")
- return
- }
-
- val nullabilityModifier = node.detailOrNull(NodeKind.NullabilityModifier)
-
- if (node.isFunctionalType()) {
- if (nullabilityModifier != null) {
- symbol("(")
- renderFunctionalType(node, renderMode)
- symbol(")")
- symbol(nullabilityModifier.name)
- } else {
- renderFunctionalType(node, renderMode)
- }
- return
- }
- if (renderMode == RenderMode.FULL) {
- renderAnnotationsForNode(node)
- }
- renderModifiersForNode(node, renderMode, true)
- renderLinked(this, node) {
- identifier(it.typeDeclarationClass?.classNodeNameWithOuterClass() ?: it.name, IdentifierKind.TypeName)
- }
- val typeArguments = node.details(NodeKind.Type)
- if (typeArguments.isNotEmpty()) {
- symbol("<")
- renderList(typeArguments, noWrap = true) {
- renderType(it, renderMode)
- }
- symbol(">")
- }
-
- nullabilityModifier ?.apply {
- symbol(nullabilityModifier.name)
- }
- }
-
- override fun renderModifier(
- block: ContentBlock,
- node: DocumentationNode,
- renderMode: RenderMode,
- nowrap: Boolean
- ) {
- when (node.name) {
- "final", "public", "var", "expect", "actual", "external" -> {
- }
- else -> {
- if (showModifierInSummary(node) || renderMode == RenderMode.FULL) {
- super.renderModifier(block, node, renderMode, nowrap)
- }
- }
- }
- }
-
- private fun ContentBlock.renderTypeParameter(node: DocumentationNode, renderMode: RenderMode) {
- renderModifiersForNode(node, renderMode, true)
-
- identifier(node.name)
-
- val constraints = node.details(NodeKind.UpperBound)
- if (constraints.size == 1) {
- nbsp()
- symbol(":")
- nbsp()
- renderList(constraints, noWrap = true) {
- renderType(it, renderMode)
- }
- }
- }
-
- private fun ContentBlock.renderParameter(node: DocumentationNode, renderMode: RenderMode) {
- if (renderMode == RenderMode.FULL) {
- renderAnnotationsForNode(node)
- }
- renderModifiersForNode(node, renderMode)
- identifier(node.name, IdentifierKind.ParameterName, node.detailOrNull(NodeKind.Signature)?.name)
- symbol(":")
- nbsp()
- val parameterType = node.detail(NodeKind.Type)
- renderType(parameterType, renderMode)
- val valueNode = node.details(NodeKind.Value).firstOrNull()
- if (valueNode != null) {
- nbsp()
- symbol("=")
- nbsp()
- text(valueNode.name)
- }
- }
-
- private fun ContentBlock.renderTypeParametersForNode(node: DocumentationNode, renderMode: RenderMode) {
- val typeParameters = node.details(NodeKind.TypeParameter)
- if (typeParameters.any()) {
- symbol("<")
- renderList(typeParameters) {
- renderTypeParameter(it, renderMode)
- }
- symbol(">")
- }
- }
-
- private fun ContentBlock.renderExtraTypeParameterConstraints(node: DocumentationNode, renderMode: RenderMode) {
- val parametersWithMultipleConstraints =
- node.details(NodeKind.TypeParameter).filter { it.details(NodeKind.UpperBound).size > 1 }
- val parametersWithConstraints = parametersWithMultipleConstraints
- .flatMap { parameter ->
- parameter.details(NodeKind.UpperBound).map { constraint -> parameter to constraint }
- }
- if (parametersWithMultipleConstraints.isNotEmpty()) {
- keyword(" where ")
- renderList(parametersWithConstraints) {
- identifier(it.first.name)
- nbsp()
- symbol(":")
- nbsp()
- renderType(it.second, renderMode)
- }
- }
- }
-
- private fun ContentBlock.renderSupertypesForNode(node: DocumentationNode, renderMode: RenderMode) {
- val supertypes = node.details(NodeKind.Supertype).filterNot { it.qualifiedNameFromType() in ignoredSupertypes }
- if (supertypes.any()) {
- nbsp()
- symbol(":")
- nbsp()
- renderList(supertypes) {
- indentedSoftLineBreak()
- renderType(it, renderMode)
- }
- }
- }
-
- private fun ContentBlock.renderAnnotationsForNode(node: DocumentationNode) {
- node.annotations.forEach {
- renderAnnotation(it)
- }
- }
-
- private fun ContentBlock.renderAnnotation(node: DocumentationNode) {
- identifier("@" + node.name, IdentifierKind.AnnotationName)
- val parameters = node.details(NodeKind.Parameter)
- if (!parameters.isEmpty()) {
- symbol("(")
- renderList(parameters) {
- text(it.detail(NodeKind.Value).name)
- }
- symbol(")")
- }
- text(" ")
- }
-
- private fun ContentBlock.renderClass(node: DocumentationNode, renderMode: RenderMode) {
- if (renderMode == RenderMode.FULL) {
- renderAnnotationsForNode(node)
- }
- renderModifiersForNode(node, renderMode)
- when (node.kind) {
- NodeKind.Class,
- NodeKind.AnnotationClass,
- NodeKind.Exception,
- NodeKind.Enum -> keyword("class ")
- NodeKind.Interface -> keyword("interface ")
- NodeKind.EnumItem -> keyword("enum val ")
- NodeKind.Object -> keyword("object ")
- NodeKind.TypeAlias -> keyword("typealias ")
- else -> throw IllegalArgumentException("Node $node is not a class-like object")
- }
-
- identifierOrDeprecated(node)
- renderTypeParametersForNode(node, renderMode)
- renderSupertypesForNode(node, renderMode)
- renderExtraTypeParameterConstraints(node, renderMode)
-
- if (node.kind == NodeKind.TypeAlias) {
- nbsp()
- symbol("=")
- nbsp()
- renderType(node.detail(NodeKind.TypeAliasUnderlyingType), renderMode)
- }
- }
-
- private fun ContentBlock.renderFunction(
- node: DocumentationNode,
- renderMode: RenderMode,
- signatureMapper: SignatureMapper? = null
- ) {
- if (renderMode == RenderMode.FULL) {
- renderAnnotationsForNode(node)
- }
- renderModifiersForNode(node, renderMode)
- when (node.kind) {
- NodeKind.Constructor -> identifier(node.owner!!.name)
- NodeKind.Function,
- NodeKind.CompanionObjectFunction -> keyword("fun ")
- else -> throw IllegalArgumentException("Node $node is not a function-like object")
- }
- renderTypeParametersForNode(node, renderMode)
- if (node.details(NodeKind.TypeParameter).any()) {
- text(" ")
- }
-
- renderReceiver(node, renderMode, signatureMapper)
-
- if (node.kind != NodeKind.Constructor)
- identifierOrDeprecated(node)
-
- symbol("(")
- val parameters = node.details(NodeKind.Parameter)
- renderList(parameters) {
- indentedSoftLineBreak()
- renderParameter(it, renderMode)
- }
- if (needReturnType(node)) {
- if (parameters.isNotEmpty()) {
- softLineBreak()
- }
- symbol(")")
- symbol(": ")
- renderType(node.detail(NodeKind.Type), renderMode)
- } else {
- symbol(")")
- }
- renderExtraTypeParameterConstraints(node, renderMode)
- }
-
- private fun ContentBlock.renderReceiver(
- node: DocumentationNode,
- renderMode: RenderMode,
- signatureMapper: SignatureMapper?
- ) {
- val receiver = node.details(NodeKind.Receiver).singleOrNull()
- if (receiver != null) {
- if (signatureMapper != null) {
- signatureMapper.renderReceiver(receiver, this)
- } else {
- val type = receiver.detail(NodeKind.Type)
-
- if (type.isFunctionalType()) {
- symbol("(")
- renderFunctionalType(type, renderMode)
- symbol(")")
- } else {
- renderType(type, renderMode)
- }
- }
- symbol(".")
- }
- }
-
- private fun needReturnType(node: DocumentationNode) = when (node.kind) {
- NodeKind.Constructor -> false
- else -> !node.isUnitReturnType()
- }
-
- fun DocumentationNode.isUnitReturnType(): Boolean =
- detail(NodeKind.Type).hiddenLinks.firstOrNull()?.qualifiedName() == "kotlin.Unit"
-
- private fun ContentBlock.renderProperty(
- node: DocumentationNode,
- renderMode: RenderMode,
- signatureMapper: SignatureMapper? = null
- ) {
- if (renderMode == RenderMode.FULL) {
- renderAnnotationsForNode(node)
- }
- renderModifiersForNode(node, renderMode)
- when (node.kind) {
- NodeKind.Property,
- NodeKind.CompanionObjectProperty -> keyword("${node.getPropertyKeyword()} ")
- else -> throw IllegalArgumentException("Node $node is not a property")
- }
- renderTypeParametersForNode(node, renderMode)
- if (node.details(NodeKind.TypeParameter).any()) {
- text(" ")
- }
-
- renderReceiver(node, renderMode, signatureMapper)
-
- identifierOrDeprecated(node)
- symbol(": ")
- renderType(node.detail(NodeKind.Type), renderMode)
- renderExtraTypeParameterConstraints(node, renderMode)
- }
-
- fun DocumentationNode.getPropertyKeyword() =
- if (details(NodeKind.Modifier).any { it.name == "var" }) "var" else "val"
-
- fun ContentBlock.identifierOrDeprecated(node: DocumentationNode) {
- if (node.deprecation != null) {
- val strike = ContentStrikethrough()
- strike.identifier(node.name)
- append(strike)
- } else {
- identifier(node.name)
- }
- }
-}
-
-fun DocumentationNode.qualifiedNameFromType(): String {
- return details.firstOrNull { it.kind == NodeKind.QualifiedName }?.name
- ?: (links.firstOrNull() ?: hiddenLinks.firstOrNull())?.qualifiedName()
- ?: name
-}
-
-
-val DocumentationNode.typeDeclarationClass
- get() = (links.firstOrNull { it.kind in NodeKind.classLike } ?: externalType)