• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download

<lambda>null1 package org.jetbrains.dokka
2 
3 import com.google.inject.Inject
4 import com.intellij.openapi.util.text.StringUtil
5 import com.intellij.psi.PsiField
6 import com.intellij.psi.PsiJavaFile
7 import org.jetbrains.dokka.DokkaConfiguration.*
8 import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser
9 import org.jetbrains.kotlin.builtins.KotlinBuiltIns
10 import org.jetbrains.kotlin.descriptors.*
11 import org.jetbrains.kotlin.descriptors.annotations.Annotated
12 import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
13 import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
14 import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
15 import org.jetbrains.kotlin.idea.kdoc.findKDoc
16 import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
17 import org.jetbrains.kotlin.idea.util.makeNotNullable
18 import org.jetbrains.kotlin.idea.util.toFuzzyType
19 import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
20 import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
21 import org.jetbrains.kotlin.lexer.KtTokens
22 import org.jetbrains.kotlin.name.ClassId
23 import org.jetbrains.kotlin.name.FqName
24 import org.jetbrains.kotlin.name.Name
25 import org.jetbrains.kotlin.psi.KtModifierListOwner
26 import org.jetbrains.kotlin.psi.KtParameter
27 import org.jetbrains.kotlin.psi.KtVariableDeclaration
28 import org.jetbrains.kotlin.resolve.DescriptorUtils
29 import org.jetbrains.kotlin.resolve.constants.ConstantValue
30 import org.jetbrains.kotlin.resolve.descriptorUtil.*
31 import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors
32 import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
33 import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
34 import org.jetbrains.kotlin.resolve.source.PsiSourceElement
35 import org.jetbrains.kotlin.resolve.source.getPsi
36 import org.jetbrains.kotlin.types.*
37 import org.jetbrains.kotlin.types.typeUtil.supertypes
38 import org.jetbrains.kotlin.util.supertypesWithAny
39 import java.io.File
40 import java.nio.file.Path
41 import java.nio.file.Paths
42 import com.google.inject.name.Named as GuiceNamed
43 
44 class DocumentationOptions(val outputDir: String,
45                            val outputFormat: String,
46                            includeNonPublic: Boolean = false,
47                            val includeRootPackage: Boolean = false,
48                            reportUndocumented: Boolean = true,
49                            val skipEmptyPackages: Boolean = true,
50                            skipDeprecated: Boolean = false,
51                            jdkVersion: Int = 6,
52                            val generateClassIndexPage: Boolean = true,
53                            val generatePackageIndexPage: Boolean = true,
54                            val sourceLinks: List<SourceLinkDefinition> = emptyList(),
55                            val impliedPlatforms: List<String> = emptyList(),
56                            // Sorted by pattern length
57                            perPackageOptions: List<PackageOptions> = emptyList(),
58                            externalDocumentationLinks: List<ExternalDocumentationLink> = emptyList(),
59                            noStdlibLink: Boolean,
60                            noJdkLink: Boolean = false,
61                            val languageVersion: String?,
62                            val apiVersion: String?,
63                            cacheRoot: String? = null,
64                            val suppressedFiles: Set<File> = emptySet(),
65                            val collectInheritedExtensionsFromLibraries: Boolean = false,
66                            val outlineRoot: String = "",
67                            val dacRoot: String = "") {
68     init {
69         if (perPackageOptions.any { it.prefix == "" })
70             throw IllegalArgumentException("Please do not register packageOptions with all match pattern, use global settings instead")
71     }
72 
73     val perPackageOptions = perPackageOptions.sortedByDescending { it.prefix.length }
74     val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated)
75 
76     fun effectivePackageOptions(pack: String): PackageOptions = perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions
77     fun effectivePackageOptions(pack: FqName): PackageOptions = effectivePackageOptions(pack.asString())
78 
79     val defaultLinks = run {
80         val links = mutableListOf<ExternalDocumentationLink>()
81         //links += ExternalDocumentationLink.Builder("https://developer.android.com/reference/").build()
82         if (!noJdkLink)
83             links += ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build()
84 
85         if (!noStdlibLink)
86             links += ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build()
87         links
88     }
89 
90     val externalDocumentationLinks = defaultLinks + externalDocumentationLinks
91 
92     val cacheRoot: Path? = when {
93         cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka")
94         cacheRoot != null -> Paths.get(cacheRoot)
95         else -> null
96     }
97 }
98 
isExtensionForExternalClassnull99 private fun isExtensionForExternalClass(extensionFunctionDescriptor: DeclarationDescriptor,
100                                         extensionReceiverDescriptor: DeclarationDescriptor,
101                                         allFqNames: Collection<FqName>): Boolean {
102     val extensionFunctionPackage = DescriptorUtils.getParentOfType(extensionFunctionDescriptor, PackageFragmentDescriptor::class.java)
103     val extensionReceiverPackage = DescriptorUtils.getParentOfType(extensionReceiverDescriptor, PackageFragmentDescriptor::class.java)
104     return extensionFunctionPackage != null && extensionReceiverPackage != null &&
105             extensionFunctionPackage.fqName != extensionReceiverPackage.fqName &&
106             extensionReceiverPackage.fqName !in allFqNames
107 }
108 
109 interface PackageDocumentationBuilder {
buildPackageDocumentationnull110     fun buildPackageDocumentation(documentationBuilder: DocumentationBuilder,
111                                   packageName: FqName,
112                                   packageNode: DocumentationNode,
113                                   declarations: List<DeclarationDescriptor>,
114                                   allFqNames: Collection<FqName>)
115 }
116 
117 interface DefaultPlatformsProvider {
118     fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List<String>
119 }
120 
121 val ignoredSupertypes = setOf(
122     "kotlin.Annotation", "kotlin.Enum", "kotlin.Any"
123 )
124 
125 class DocumentationBuilder
126 @Inject constructor(val resolutionFacade: DokkaResolutionFacade,
127                     val descriptorDocumentationParser: DescriptorDocumentationParser,
128                     val options: DocumentationOptions,
129                     val refGraph: NodeReferenceGraph,
130                     val platformNodeRegistry: PlatformNodeRegistry,
131                     val logger: DokkaLogger,
132                     val linkResolver: DeclarationLinkResolver,
133                     val defaultPlatformsProvider: DefaultPlatformsProvider) {
134     val boringBuiltinClasses = setOf(
135             "kotlin.Unit", "kotlin.Byte", "kotlin.Short", "kotlin.Int", "kotlin.Long", "kotlin.Char", "kotlin.Boolean",
136             "kotlin.Float", "kotlin.Double", "kotlin.String", "kotlin.Array", "kotlin.Any")
137     val knownModifiers = setOf(
138             KtTokens.PUBLIC_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.INTERNAL_KEYWORD, KtTokens.PRIVATE_KEYWORD,
139             KtTokens.OPEN_KEYWORD, KtTokens.FINAL_KEYWORD, KtTokens.ABSTRACT_KEYWORD, KtTokens.SEALED_KEYWORD,
140             KtTokens.OVERRIDE_KEYWORD)
141 
linknull142     fun link(node: DocumentationNode, descriptor: DeclarationDescriptor, kind: RefKind) {
143         refGraph.link(node, descriptor.signature(), kind)
144     }
145 
linknull146     fun link(fromDescriptor: DeclarationDescriptor?, toDescriptor: DeclarationDescriptor?, kind: RefKind) {
147         if (fromDescriptor != null && toDescriptor != null) {
148             refGraph.link(fromDescriptor.signature(), toDescriptor.signature(), kind)
149         }
150     }
151 
registernull152     fun register(descriptor: DeclarationDescriptor, node: DocumentationNode) {
153         refGraph.register(descriptor.signature(), node)
154     }
155 
nodeForDescriptornull156     fun <T> nodeForDescriptor(
157         descriptor: T,
158         kind: NodeKind,
159         external: Boolean = false
160     ): DocumentationNode where T : DeclarationDescriptor, T : Named {
161         val (doc, callback) =
162                 if (external) {
163                     Content.Empty to { node -> }
164                 } else {
165                     descriptorDocumentationParser.parseDocumentationAndDetails(
166                         descriptor,
167                         kind == NodeKind.Parameter
168                     )
169                 }
170         val node = DocumentationNode(descriptor.name.asString(), doc, kind).withModifiers(descriptor)
171         node.appendSignature(descriptor)
172         callback(node)
173         return node
174     }
175 
withModifiersnull176     private fun DocumentationNode.withModifiers(descriptor: DeclarationDescriptor): DocumentationNode {
177         if (descriptor is MemberDescriptor) {
178             appendVisibility(descriptor)
179             if (descriptor !is ConstructorDescriptor) {
180                 appendModality(descriptor)
181             }
182         }
183         return this
184     }
185 
appendModalitynull186     fun DocumentationNode.appendModality(descriptor: MemberDescriptor) {
187         var modality = descriptor.modality
188         if (modality == Modality.OPEN) {
189             val containingClass = descriptor.containingDeclaration as? ClassDescriptor
190             if (containingClass?.modality == Modality.FINAL) {
191                 modality = Modality.FINAL
192             }
193         }
194         val modifier = modality.name.toLowerCase()
195         appendTextNode(modifier, NodeKind.Modifier)
196     }
197 
appendVisibilitynull198     fun DocumentationNode.appendVisibility(descriptor: DeclarationDescriptorWithVisibility) {
199         val modifier = descriptor.visibility.normalize().displayName
200         appendTextNode(modifier, NodeKind.Modifier)
201     }
202 
appendSupertypenull203     fun DocumentationNode.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType, backref: Boolean) {
204         val unwrappedType = superType.unwrap()
205         if (unwrappedType is AbbreviatedType) {
206             appendSupertype(descriptor, unwrappedType.abbreviation, backref)
207         } else {
208             appendType(unwrappedType, NodeKind.Supertype)
209             val superclass = unwrappedType.constructor.declarationDescriptor
210             if (backref) {
211                 link(superclass, descriptor, RefKind.Inheritor)
212             }
213             link(descriptor, superclass, RefKind.Superclass)
214         }
215     }
216 
appendProjectionnull217     fun DocumentationNode.appendProjection(projection: TypeProjection, kind: NodeKind = NodeKind.Type) {
218         if (projection.isStarProjection) {
219             appendTextNode("*", NodeKind.Type)
220         } else {
221             appendType(projection.type, kind, projection.projectionKind.label)
222         }
223     }
224 
DocumentationNodenull225     fun DocumentationNode.appendType(kotlinType: KotlinType?, kind: NodeKind = NodeKind.Type, prefix: String = "") {
226         if (kotlinType == null)
227             return
228         (kotlinType.unwrap() as? AbbreviatedType)?.let {
229             return appendType(it.abbreviation)
230         }
231 
232         if (kotlinType.isDynamic()) {
233             append(DocumentationNode("dynamic", Content.Empty, kind), RefKind.Detail)
234             return
235         }
236 
237         val classifierDescriptor = kotlinType.constructor.declarationDescriptor
238         val name = when (classifierDescriptor) {
239             is ClassDescriptor -> {
240                 if (classifierDescriptor.isCompanionObject) {
241                     classifierDescriptor.containingDeclaration.name.asString() +
242                             "." + classifierDescriptor.name.asString()
243                 } else {
244                     classifierDescriptor.name.asString()
245                 }
246             }
247             is Named -> classifierDescriptor.name.asString()
248             else -> "<anonymous>"
249         }
250         val node = DocumentationNode(name, Content.Empty, kind)
251         if (prefix != "") {
252             node.appendTextNode(prefix, NodeKind.Modifier)
253         }
254         if (kotlinType.isNullabilityFlexible()) {
255             node.appendTextNode("!", NodeKind.NullabilityModifier)
256         } else if (kotlinType.isMarkedNullable) {
257             node.appendTextNode("?", NodeKind.NullabilityModifier)
258         }
259         if (classifierDescriptor != null) {
260             val externalLink =
261                 linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor)
262             if (externalLink != null) {
263                 if (classifierDescriptor !is TypeParameterDescriptor) {
264                     val targetNode =
265                         refGraph.lookup(classifierDescriptor.signature()) ?: classifierDescriptor.build(true)
266                     node.append(targetNode, RefKind.ExternalType)
267                     node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
268                 }
269             }
270             link(
271                 node, classifierDescriptor,
272                 if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link
273             )
274             if (classifierDescriptor !is TypeParameterDescriptor) {
275                 node.append(
276                     DocumentationNode(
277                         classifierDescriptor.fqNameUnsafe.asString(),
278                         Content.Empty,
279                         NodeKind.QualifiedName
280                     ), RefKind.Detail
281                 )
282             }
283         }
284 
285 
286         append(node, RefKind.Detail)
287         node.appendAnnotations(kotlinType)
288         for (typeArgument in kotlinType.arguments) {
289             node.appendProjection(typeArgument)
290         }
291     }
292 
ClassifierDescriptornull293     fun ClassifierDescriptor.isBoringBuiltinClass(): Boolean =
294             DescriptorUtils.getFqName(this).asString() in boringBuiltinClasses
295 
296     fun DocumentationNode.appendAnnotations(annotated: Annotated) {
297         annotated.annotations.forEach {
298             it.build()?.let { annotationNode ->
299                 if (annotationNode.isSinceKotlin()) {
300                     appendSinceKotlin(annotationNode)
301                 }
302                 else {
303                     val refKind = when {
304                         it.isDocumented() ->
305                             when {
306                                 annotationNode.isDeprecation() -> RefKind.Deprecation
307                                 else -> RefKind.Annotation
308                             }
309                         it.isHiddenInDocumentation() -> RefKind.HiddenAnnotation
310                         else -> return@forEach
311                     }
312                     append(annotationNode, refKind)
313                     if (refKind == RefKind.Deprecation) annotationNode.convertDeprecationDetailsToChildren()
314                 }
315             }
316         }
317     }
318 
DocumentationNodenull319     fun DocumentationNode.appendExternalLink(externalLink: String) {
320         append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
321     }
322 
DocumentationNodenull323     fun DocumentationNode.appendExternalLink(descriptor: DeclarationDescriptor) {
324         val target = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(descriptor)
325         if (target != null) {
326             appendExternalLink(target)
327         }
328     }
329 
appendSinceKotlinnull330     fun DocumentationNode.appendSinceKotlin(annotation: DocumentationNode) {
331         val kotlinVersion = annotation
332                 .detail(NodeKind.Parameter)
333                 .detail(NodeKind.Value)
334                 .name.removeSurrounding("\"")
335 
336         append(platformNodeRegistry["Kotlin " + kotlinVersion], RefKind.Platform)
337     }
338 
appendModifiersnull339     fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) {
340         val psi = (descriptor as DeclarationDescriptorWithSource).source.getPsi() as? KtModifierListOwner ?: return
341         KtTokens.MODIFIER_KEYWORDS_ARRAY.filter { it !in knownModifiers }.forEach {
342             if (psi.hasModifier(it)) {
343                 appendTextNode(it.value, NodeKind.Modifier)
344             }
345         }
346     }
347 
appendDefaultPlatformsnull348     fun DocumentationNode.appendDefaultPlatforms(descriptor: DeclarationDescriptor) {
349         for (platform in defaultPlatformsProvider.getDefaultPlatforms(descriptor)) {
350             append(platformNodeRegistry[platform], RefKind.Platform)
351         }
352     }
353 
isDeprecationnull354     fun DocumentationNode.isDeprecation() = name == "Deprecated" || name == "deprecated"
355 
356     fun DocumentationNode.isSinceKotlin() = name == "SinceKotlin" && kind == NodeKind.Annotation
357 
358     fun DocumentationNode.appendSourceLink(sourceElement: SourceElement) {
359         appendSourceLink(sourceElement.getPsi(), options.sourceLinks)
360     }
361 
appendSignaturenull362     fun DocumentationNode.appendSignature(descriptor: DeclarationDescriptor) {
363         appendTextNode(descriptor.signature(), NodeKind.Signature, RefKind.Detail)
364     }
365 
appendChildnull366     fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: RefKind): DocumentationNode? {
367         if (!descriptor.isGenerated() && descriptor.isDocumented(options)) {
368             val node = descriptor.build()
369             append(node, kind)
370             return node
371         }
372         return null
373     }
374 
<lambda>null375     fun createGroupNode(signature: String, nodes: List<DocumentationNode>) = (nodes.find { it.kind == NodeKind.GroupNode } ?:
<lambda>null376             DocumentationNode(nodes.first().name, Content.Empty, NodeKind.GroupNode).apply {
377                 appendTextNode(signature, NodeKind.Signature, RefKind.Detail)
378             })
groupNodenull379             .also { groupNode ->
380                 nodes.forEach { node ->
381                     if (node != groupNode) {
382                         node.owner?.let { owner ->
383                             node.dropReferences { it.to == owner && it.kind == RefKind.Owner }
384                             owner.dropReferences { it.to == node && it.kind == RefKind.Member }
385                             owner.append(groupNode, RefKind.Member)
386                         }
387                         groupNode.append(node, RefKind.Member)
388                     }
389                 }
390             }
391 
392 
DocumentationNodenull393     fun DocumentationNode.appendOrUpdateMember(descriptor: DeclarationDescriptor) {
394         if (descriptor.isGenerated() || !descriptor.isDocumented(options)) return
395 
396         val existingNode = refGraph.lookup(descriptor.signature())
397         if (existingNode != null) {
398             if (existingNode.kind == NodeKind.TypeAlias && descriptor is ClassDescriptor
399                     || existingNode.kind == NodeKind.Class && descriptor is TypeAliasDescriptor) {
400                 val node = createGroupNode(descriptor.signature(), listOf(existingNode, descriptor.build()))
401                 register(descriptor, node)
402                 return
403             }
404 
405             existingNode.updatePlatforms(descriptor)
406 
407             if (descriptor is ClassDescriptor) {
408                 val membersToDocument = descriptor.collectMembersToDocument()
409                 for ((memberDescriptor, inheritedLinkKind, extraModifier) in membersToDocument) {
410                     if (memberDescriptor is ClassDescriptor) {
411                         existingNode.appendOrUpdateMember(memberDescriptor)   // recurse into nested classes
412                     }
413                     else {
414                         val existingMemberNode = refGraph.lookup(memberDescriptor.signature())
415                         if (existingMemberNode != null) {
416                             existingMemberNode.updatePlatforms(memberDescriptor)
417                         }
418                         else {
419                             existingNode.appendClassMember(memberDescriptor, inheritedLinkKind, extraModifier)
420                         }
421                     }
422                 }
423             }
424         }
425         else {
426             appendChild(descriptor, RefKind.Member)
427         }
428     }
429 
updatePlatformsnull430     private fun DocumentationNode.updatePlatforms(descriptor: DeclarationDescriptor) {
431         for (platform in defaultPlatformsProvider.getDefaultPlatforms(descriptor) - platforms) {
432             append(platformNodeRegistry[platform], RefKind.Platform)
433         }
434     }
435 
appendClassMembernull436     fun DocumentationNode.appendClassMember(descriptor: DeclarationDescriptor,
437                                             inheritedLinkKind: RefKind = RefKind.InheritedMember,
438                                             extraModifier: String?) {
439         if (descriptor is CallableMemberDescriptor && descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
440             val baseDescriptor = descriptor.overriddenDescriptors.firstOrNull()
441             if (baseDescriptor != null) {
442                 link(this, baseDescriptor, inheritedLinkKind)
443             }
444         } else {
445             val descriptorToUse = if (descriptor is ConstructorDescriptor) descriptor else descriptor.original
446             val child = appendChild(descriptorToUse, RefKind.Member)
447             if (extraModifier != null) {
448                 child?.appendTextNode("static", NodeKind.Modifier)
449             }
450         }
451     }
452 
appendInPageChildrennull453     fun DocumentationNode.appendInPageChildren(descriptors: Iterable<DeclarationDescriptor>, kind: RefKind) {
454         descriptors.forEach { descriptor ->
455             val node = appendChild(descriptor, kind)
456             node?.addReferenceTo(this, RefKind.TopLevelPage)
457         }
458     }
459 
DocumentationModulenull460     fun DocumentationModule.appendFragments(fragments: Collection<PackageFragmentDescriptor>,
461                                             packageContent: Map<String, Content>,
462                                             packageDocumentationBuilder: PackageDocumentationBuilder) {
463         val allFqNames = fragments.map { it.fqName }.distinct()
464 
465         for (packageName in allFqNames) {
466             if (packageName.isRoot && !options.includeRootPackage) continue
467             val declarations = fragments.filter { it.fqName == packageName }.flatMap { it.getMemberScope().getContributedDescriptors() }
468 
469             if (options.skipEmptyPackages && declarations.none { it.isDocumented(options) }) continue
470             logger.info("  package $packageName: ${declarations.count()} declarations")
471             val packageNode = findOrCreatePackageNode(this, packageName.asString(), packageContent, this@DocumentationBuilder.refGraph)
472             packageDocumentationBuilder.buildPackageDocumentation(this@DocumentationBuilder, packageName, packageNode,
473                     declarations, allFqNames)
474         }
475 
476     }
477 
propagateExtensionFunctionsToSubclassesnull478     fun propagateExtensionFunctionsToSubclasses(
479         fragments: Collection<PackageFragmentDescriptor>,
480         resolutionFacade: DokkaResolutionFacade
481     ) {
482 
483         val moduleDescriptor = resolutionFacade.moduleDescriptor
484 
485         // Wide-collect all view descriptors
486         val allPackageViewDescriptors = generateSequence(listOf(moduleDescriptor.getPackage(FqName.ROOT))) { packages ->
487             packages
488                 .flatMap { pkg ->
489                     moduleDescriptor.getSubPackagesOf(pkg.fqName) { true }
490                 }.map { fqName ->
491                     moduleDescriptor.getPackage(fqName)
492                 }.takeUnless { it.isEmpty() }
493         }.flatten()
494 
495         val allDescriptors =
496             if (options.collectInheritedExtensionsFromLibraries) {
497                 allPackageViewDescriptors.map { it.memberScope }
498             } else {
499                 fragments.asSequence().map { it.getMemberScope() }
500             }.flatMap {
501                 it.getDescriptorsFiltered(
502                     DescriptorKindFilter.CALLABLES
503                 ).asSequence()
504             }
505 
506 
507         val documentingDescriptors = fragments.flatMap { it.getMemberScope().getContributedDescriptors() }
508         val documentingClasses = documentingDescriptors.filterIsInstance<ClassDescriptor>()
509 
510         val classHierarchy = buildClassHierarchy(documentingClasses)
511 
512         val allExtensionFunctions =
513             allDescriptors
514                 .filterIsInstance<CallableMemberDescriptor>()
515                 .filter { it.extensionReceiverParameter != null }
516         val extensionFunctionsByName = allExtensionFunctions.groupBy { it.name }
517 
518         for (extensionFunction in allExtensionFunctions) {
519             if (extensionFunction.dispatchReceiverParameter != null) continue
520             val possiblyShadowingFunctions = extensionFunctionsByName[extensionFunction.name]
521                 ?.filter { fn -> fn.canShadow(extensionFunction) }
522                     ?: emptyList()
523 
524             if (extensionFunction.extensionReceiverParameter?.type?.isDynamic() == true) continue
525             val subclasses =
526                 classHierarchy.filter { (key) -> key.isExtensionApplicable(extensionFunction) }
527             if (subclasses.isEmpty()) continue
528             subclasses.values.flatten().forEach { subclass ->
529                 if (subclass.isExtensionApplicable(extensionFunction) &&
530                     possiblyShadowingFunctions.none { subclass.isExtensionApplicable(it) }) {
531 
532                     val hasExternalLink =
533                         linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(
534                             extensionFunction
535                         ) != null
536                     if (hasExternalLink) {
537                         val containerDesc =
538                             extensionFunction.containingDeclaration as? PackageFragmentDescriptor
539                         if (containerDesc != null) {
540                             val container = refGraph.lookup(containerDesc.signature())
541                                     ?: containerDesc.buildExternal()
542                             container.append(extensionFunction.buildExternal(), RefKind.Member)
543                         }
544                     }
545 
546                     refGraph.link(subclass.signature(), extensionFunction.signature(), RefKind.Extension)
547                 }
548             }
549         }
550     }
551 
ClassDescriptornull552     private fun ClassDescriptor.isExtensionApplicable(extensionFunction: CallableMemberDescriptor): Boolean {
553         val receiverType = extensionFunction.fuzzyExtensionReceiverType()?.makeNotNullable()
554         val classType = defaultType.toFuzzyType(declaredTypeParameters)
555         return receiverType != null && classType.checkIsSubtypeOf(receiverType) != null
556     }
557 
buildClassHierarchynull558     private fun buildClassHierarchy(classes: List<ClassDescriptor>): Map<ClassDescriptor, List<ClassDescriptor>> {
559         val result = hashMapOf<ClassDescriptor, MutableList<ClassDescriptor>>()
560         classes.forEach { cls ->
561             TypeUtils.getAllSupertypes(cls.defaultType).forEach { supertype ->
562                 val classDescriptor = supertype.constructor.declarationDescriptor as? ClassDescriptor
563                 if (classDescriptor != null) {
564                     val subtypesList = result.getOrPut(classDescriptor) { arrayListOf() }
565                     subtypesList.add(cls)
566                 }
567             }
568         }
569         return result
570     }
571 
CallableMemberDescriptornull572     private fun CallableMemberDescriptor.canShadow(other: CallableMemberDescriptor): Boolean {
573         if (this == other) return false
574         if (this is PropertyDescriptor && other is PropertyDescriptor) {
575             return true
576         }
577         if (this is FunctionDescriptor && other is FunctionDescriptor) {
578             val parameters1 = valueParameters
579             val parameters2 = other.valueParameters
580             if (parameters1.size != parameters2.size) {
581                 return false
582             }
583             for ((p1, p2) in parameters1 zip parameters2) {
584                 if (p1.type != p2.type) {
585                     return false
586                 }
587             }
588             return true
589         }
590         return false
591     }
592 
buildnull593     fun DeclarationDescriptor.build(): DocumentationNode = when (this) {
594         is ClassifierDescriptor -> build()
595         is ConstructorDescriptor -> build()
596         is PropertyDescriptor -> build()
597         is FunctionDescriptor -> build()
598         is ValueParameterDescriptor -> build()
599         is ReceiverParameterDescriptor -> build()
600         else -> throw IllegalStateException("Descriptor $this is not known")
601     }
602 
buildExternalnull603     fun PackageFragmentDescriptor.buildExternal(): DocumentationNode {
604         val node = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.Package)
605 
606         val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(this)
607         if (externalLink != null) {
608             node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
609         }
610         register(this, node)
611         return node
612     }
613 
buildExternalnull614     fun CallableDescriptor.buildExternal(): DocumentationNode = when(this) {
615         is FunctionDescriptor -> build(true)
616         is PropertyDescriptor -> build(true)
617         else -> throw IllegalStateException("Descriptor $this is not known")
618     }
619 
620 
buildnull621     fun ClassifierDescriptor.build(external: Boolean = false): DocumentationNode = when (this) {
622         is ClassDescriptor -> build(external)
623         is TypeAliasDescriptor -> build(external)
624         is TypeParameterDescriptor -> build()
625         else -> throw IllegalStateException("Descriptor $this is not known")
626     }
627 
TypeAliasDescriptornull628     fun TypeAliasDescriptor.build(external: Boolean = false): DocumentationNode {
629         val node = nodeForDescriptor(this, NodeKind.TypeAlias)
630 
631         if (!external) {
632             node.appendAnnotations(this)
633         }
634         node.appendModifiers(this)
635         node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail)
636 
637         node.appendType(underlyingType, NodeKind.TypeAliasUnderlyingType)
638 
639         if (!external) {
640             node.appendSourceLink(source)
641             node.appendDefaultPlatforms(this)
642         }
643         register(this, node)
644         return node
645     }
646 
ClassDescriptornull647     fun ClassDescriptor.build(external: Boolean = false): DocumentationNode {
648         val kind = when {
649             kind == ClassKind.OBJECT -> NodeKind.Object
650             kind == ClassKind.INTERFACE -> NodeKind.Interface
651             kind == ClassKind.ENUM_CLASS -> NodeKind.Enum
652             kind == ClassKind.ANNOTATION_CLASS -> NodeKind.AnnotationClass
653             kind == ClassKind.ENUM_ENTRY -> NodeKind.EnumItem
654             isSubclassOfThrowable() -> NodeKind.Exception
655             else -> NodeKind.Class
656         }
657         val node = nodeForDescriptor(this, kind, external)
658         register(this, node)
659         supertypesWithAnyPrecise().forEach {
660             node.appendSupertype(this, it, !external)
661         }
662         if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) {
663             node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail)
664         }
665         if (!external) {
666             for ((descriptor, inheritedLinkKind, extraModifier) in collectMembersToDocument()) {
667                 node.appendClassMember(descriptor, inheritedLinkKind, extraModifier)
668             }
669             node.appendAnnotations(this)
670         }
671         node.appendModifiers(this)
672         if (!external) {
673             node.appendSourceLink(source)
674             node.appendDefaultPlatforms(this)
675         }
676         return node
677     }
678 
679     data class ClassMember(val descriptor: DeclarationDescriptor,
680                            val inheritedLinkKind: RefKind = RefKind.InheritedMember,
681                            val extraModifier: String? = null)
682 
ClassDescriptornull683     fun ClassDescriptor.collectMembersToDocument(): List<ClassMember> {
684         val result = arrayListOf<ClassMember>()
685         if (kind != ClassKind.OBJECT && kind != ClassKind.ENUM_ENTRY) {
686             val constructorsToDocument = if (kind == ClassKind.ENUM_CLASS)
687                 constructors.filter { it.valueParameters.size > 0 }
688             else
689                 constructors
690             constructorsToDocument.mapTo(result) { ClassMember(it) }
691         }
692 
693         defaultType.memberScope.getContributedDescriptors()
694                 .filter { it != companionObjectDescriptor }
695                 .mapTo(result) { ClassMember(it) }
696 
697         staticScope.getContributedDescriptors()
698                 .mapTo(result) { ClassMember(it, extraModifier = "static") }
699 
700         val companionObjectDescriptor = companionObjectDescriptor
701         if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(options)) {
702             val descriptors = companionObjectDescriptor.defaultType.memberScope.getContributedDescriptors()
703             val descriptorsToDocument = descriptors.filter { it !is CallableDescriptor || !it.isInheritedFromAny() }
704             descriptorsToDocument.mapTo(result) {
705                 ClassMember(it, inheritedLinkKind = RefKind.InheritedCompanionObjectMember)
706             }
707 
708             if (companionObjectDescriptor.getAllSuperclassesWithoutAny().isNotEmpty()
709                     || companionObjectDescriptor.getSuperInterfaces().isNotEmpty()) {
710                 result += ClassMember(companionObjectDescriptor)
711             }
712         }
713         return result
714     }
715 
isInheritedFromAnynull716     fun CallableDescriptor.isInheritedFromAny(): Boolean {
717         return findTopMostOverriddenDescriptors().any {
718             DescriptorUtils.getFqNameSafe(it.containingDeclaration).asString() == "kotlin.Any"
719         }
720     }
721 
ClassDescriptornull722     fun ClassDescriptor.isSubclassOfThrowable(): Boolean =
723             defaultType.supertypes().any { it.constructor.declarationDescriptor == builtIns.throwable }
724 
buildnull725     fun ConstructorDescriptor.build(): DocumentationNode {
726         val node = nodeForDescriptor(this, NodeKind.Constructor)
727         node.appendInPageChildren(valueParameters, RefKind.Detail)
728         node.appendDefaultPlatforms(this)
729         register(this, node)
730         return node
731     }
732 
inCompanionObjectnull733     private fun CallableMemberDescriptor.inCompanionObject(): Boolean {
734         val containingDeclaration = containingDeclaration
735         if ((containingDeclaration as? ClassDescriptor)?.isCompanionObject ?: false) {
736             return true
737         }
738         val receiver = extensionReceiverParameter
739         return (receiver?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.isCompanionObject ?: false
740     }
741 
buildnull742     fun FunctionDescriptor.build(external: Boolean = false): DocumentationNode {
743         if (ErrorUtils.containsErrorTypeInParameters(this) || ErrorUtils.containsErrorType(this.returnType)) {
744             logger.warn("Found an unresolved type in ${signatureWithSourceLocation()}")
745         }
746 
747         val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectFunction else NodeKind.Function, external)
748 
749         node.appendInPageChildren(typeParameters, RefKind.Detail)
750         extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) }
751         node.appendInPageChildren(valueParameters, RefKind.Detail)
752         node.appendType(returnType)
753         node.appendAnnotations(this)
754         node.appendModifiers(this)
755         if (!external) {
756             node.appendSourceLink(source)
757             node.appendDefaultPlatforms(this)
758         } else {
759             node.appendExternalLink(this)
760         }
761 
762         overriddenDescriptors.forEach {
763             addOverrideLink(it, this)
764         }
765 
766         register(this, node)
767         return node
768     }
769 
addOverrideLinknull770     fun addOverrideLink(baseClassFunction: CallableMemberDescriptor, overridingFunction: CallableMemberDescriptor) {
771         val source = baseClassFunction.original.source.getPsi()
772         if (source != null) {
773             link(overridingFunction, baseClassFunction, RefKind.Override)
774         } else {
775             baseClassFunction.overriddenDescriptors.forEach {
776                 addOverrideLink(it, overridingFunction)
777             }
778         }
779     }
780 
PropertyDescriptornull781     fun PropertyDescriptor.build(external: Boolean = false): DocumentationNode {
782         val node = nodeForDescriptor(
783             this,
784             if (inCompanionObject()) NodeKind.CompanionObjectProperty else NodeKind.Property,
785             external
786         )
787         node.appendInPageChildren(typeParameters, RefKind.Detail)
788         extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) }
789         node.appendType(returnType)
790         node.appendAnnotations(this)
791         node.appendModifiers(this)
792         if (!external) {
793             node.appendSourceLink(source)
794             if (isVar) {
795                 node.appendTextNode("var", NodeKind.Modifier)
796             }
797 
798             if (isConst) {
799                 val psi = sourcePsi()
800                 val valueText = when (psi) {
801                     is KtVariableDeclaration -> psi.initializer?.text
802                     is PsiField -> psi.initializer?.text
803                     else -> null
804                 }
805                 valueText?.let { node.appendTextNode(it, NodeKind.Value) }
806             }
807 
808 
809             getter?.let {
810                 if (!it.isDefault) {
811                     node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Getter")
812                 }
813             }
814             setter?.let {
815                 if (!it.isDefault) {
816                     node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Setter")
817                 }
818             }
819             node.appendDefaultPlatforms(this)
820         }
821         if (external) {
822             node.appendExternalLink(this)
823         }
824 
825         overriddenDescriptors.forEach {
826             addOverrideLink(it, this)
827         }
828 
829         register(this, node)
830         return node
831     }
832 
addAccessorDocumentationnull833     fun DocumentationNode.addAccessorDocumentation(documentation: Content, prefix: String) {
834         if (documentation == Content.Empty) return
835         updateContent {
836             if (!documentation.children.isEmpty()) {
837                 val section = addSection(prefix, null)
838                 documentation.children.forEach { section.append(it) }
839             }
840             documentation.sections.forEach {
841                 val section = addSection("$prefix ${it.tag}", it.subjectName)
842                 it.children.forEach { section.append(it) }
843             }
844         }
845     }
846 
buildnull847     fun ValueParameterDescriptor.build(): DocumentationNode {
848         val node = nodeForDescriptor(this, NodeKind.Parameter)
849         node.appendType(varargElementType ?: type)
850         if (declaresDefaultValue()) {
851             val psi = source.getPsi() as? KtParameter
852             if (psi != null) {
853                 val defaultValueText = psi.defaultValue?.text
854                 if (defaultValueText != null) {
855                     node.appendTextNode(defaultValueText, NodeKind.Value)
856                 }
857             }
858         }
859         node.appendAnnotations(this)
860         node.appendModifiers(this)
861         if (varargElementType != null && node.details(NodeKind.Modifier).none { it.name == "vararg" }) {
862             node.appendTextNode("vararg", NodeKind.Modifier)
863         }
864         register(this, node)
865         return node
866     }
867 
TypeParameterDescriptornull868     fun TypeParameterDescriptor.build(): DocumentationNode {
869         val doc = descriptorDocumentationParser.parseDocumentation(this)
870         val name = name.asString()
871         val prefix = variance.label
872 
873         val node = DocumentationNode(name, doc, NodeKind.TypeParameter)
874         if (prefix != "") {
875             node.appendTextNode(prefix, NodeKind.Modifier)
876         }
877         if (isReified) {
878             node.appendTextNode("reified", NodeKind.Modifier)
879         }
880 
881         for (constraint in upperBounds) {
882             if (KotlinBuiltIns.isDefaultBound(constraint)) {
883                 continue
884             }
885             node.appendType(constraint, NodeKind.UpperBound)
886         }
887         register(this, node)
888         return node
889     }
890 
buildnull891     fun ReceiverParameterDescriptor.build(): DocumentationNode {
892         var receiverClass: DeclarationDescriptor = type.constructor.declarationDescriptor!!
893         if ((receiverClass as? ClassDescriptor)?.isCompanionObject ?: false) {
894             receiverClass = receiverClass.containingDeclaration!!
895         } else if (receiverClass is TypeParameterDescriptor) {
896             val upperBoundClass = receiverClass.upperBounds.singleOrNull()?.constructor?.declarationDescriptor
897             if (upperBoundClass != null) {
898                 receiverClass = upperBoundClass
899             }
900         }
901 
902         if ((containingDeclaration as? FunctionDescriptor)?.dispatchReceiverParameter == null) {
903             link(receiverClass, containingDeclaration, RefKind.Extension)
904         }
905 
906         val node = DocumentationNode(name.asString(), Content.Empty, NodeKind.Receiver)
907         node.appendType(type)
908         register(this, node)
909         return node
910     }
911 
AnnotationDescriptornull912     fun AnnotationDescriptor.build(isWithinReplaceWith: Boolean = false): DocumentationNode? {
913         val annotationClass = type.constructor.declarationDescriptor
914         if (annotationClass == null || ErrorUtils.isError(annotationClass)) {
915             return null
916         }
917         val node = DocumentationNode(annotationClass.name.asString(), Content.Empty, NodeKind.Annotation)
918         allValueArguments.forEach foreach@{ (name, value) ->
919             if (name.toString() == "imports" && value.toString() == "[]") return@foreach
920             var valueNode: DocumentationNode? = null
921             if (value.toString() == "@kotlin.ReplaceWith") {
922                 valueNode = (value.value as AnnotationDescriptor).build(true)
923             }
924             else valueNode = value.toDocumentationNode(isWithinReplaceWith)
925             if (valueNode != null) {
926                 val paramNode = DocumentationNode(name.asString(), Content.Empty, NodeKind.Parameter)
927                 paramNode.append(valueNode, RefKind.Detail)
928                 node.append(paramNode, RefKind.Detail)
929             }
930         }
931         return node
932     }
933 
toDocumentationNodenull934     fun ConstantValue<*>.toDocumentationNode(isWithinReplaceWith: Boolean = false): DocumentationNode? = value?.let { value ->
935         when (value) {
936             is String ->
937                 (if (isWithinReplaceWith) "Replace with: " else "") + "\"" + StringUtil.escapeStringCharacters(value) + "\""
938             is EnumEntrySyntheticClassDescriptor ->
939                 value.containingDeclaration.name.asString() + "." + value.name.asString()
940             is Pair<*, *> -> {
941                 val (classId, name) = value
942                 if (classId is ClassId && name is Name) {
943                     classId.shortClassName.asString() + "." + name.asString()
944                 } else {
945                     value.toString()
946                 }
947             }
948             else -> value.toString()
949         }.let { valueString ->
950             DocumentationNode(valueString, Content.Empty, NodeKind.Value)
951         }
952     }
953 
954 
getParentForPackageMembernull955     fun DocumentationNode.getParentForPackageMember(descriptor: DeclarationDescriptor,
956                                                     externalClassNodes: MutableMap<FqName, DocumentationNode>,
957                                                     allFqNames: Collection<FqName>): DocumentationNode {
958         if (descriptor is CallableMemberDescriptor) {
959             val extensionClassDescriptor = descriptor.getExtensionClassDescriptor()
960             if (extensionClassDescriptor != null && isExtensionForExternalClass(descriptor, extensionClassDescriptor, allFqNames) &&
961                 !ErrorUtils.isError(extensionClassDescriptor)) {
962                 val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor)
963                 return externalClassNodes.getOrPut(fqName, {
964                     val newNode = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.ExternalClass)
965                     val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(extensionClassDescriptor)
966                     if (externalLink != null) {
967                         newNode.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
968                     }
969                     append(newNode, RefKind.Member)
970                     newNode
971                 })
972             }
973         }
974         return this
975     }
976 
977 }
978 
isDocumentednull979 fun DeclarationDescriptor.isDocumented(options: DocumentationOptions): Boolean {
980     return (options.effectivePackageOptions(fqNameSafe).includeNonPublic
981             || this !is MemberDescriptor
982             || this.visibility.isPublicAPI)
983             && !isDocumentationSuppressed(options)
984             && (!options.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated())
985 }
986 
isGeneratednull987 private fun DeclarationDescriptor.isGenerated() = this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION
988 
989 class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder {
990     override fun buildPackageDocumentation(documentationBuilder: DocumentationBuilder,
991                                            packageName: FqName,
992                                            packageNode: DocumentationNode,
993                                            declarations: List<DeclarationDescriptor>,
994                                            allFqNames: Collection<FqName>) {
995         val externalClassNodes = hashMapOf<FqName, DocumentationNode>()
996         declarations.forEach { descriptor ->
997             with(documentationBuilder) {
998                 if (descriptor.isDocumented(options)) {
999                     val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes, allFqNames)
1000                     parent.appendOrUpdateMember(descriptor)
1001                 }
1002             }
1003         }
1004     }
1005 }
1006 
1007 class KotlinJavaDocumentationBuilder
1008 @Inject constructor(val resolutionFacade: DokkaResolutionFacade,
1009                     val documentationBuilder: DocumentationBuilder,
1010                     val options: DocumentationOptions,
1011                     val logger: DokkaLogger) : JavaDocumentationBuilder {
appendFilenull1012     override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) {
1013         val classDescriptors = file.classes.map {
1014             it.getJavaClassDescriptor(resolutionFacade)
1015         }
1016 
1017         if (classDescriptors.any { it != null && it.isDocumented(options) }) {
1018             val packageNode = findOrCreatePackageNode(module, file.packageName, packageContent, documentationBuilder.refGraph)
1019 
1020             for (descriptor in classDescriptors.filterNotNull()) {
1021                 with(documentationBuilder) {
1022                     packageNode.appendChild(descriptor, RefKind.Member)
1023                 }
1024             }
1025         }
1026     }
1027 }
1028 
1029 private val hiddenAnnotations = setOf(
1030         KotlinBuiltIns.FQ_NAMES.parameterName.asString()
1031 )
1032 
AnnotationDescriptornull1033 private fun AnnotationDescriptor.isHiddenInDocumentation() =
1034         type.constructor.declarationDescriptor?.fqNameSafe?.asString() in hiddenAnnotations
1035 
1036 private fun AnnotationDescriptor.isDocumented(): Boolean {
1037     if (source.getPsi() != null && mustBeDocumented()) return true
1038     val annotationClassName = type.constructor.declarationDescriptor?.fqNameSafe?.asString()
1039     return annotationClassName == KotlinBuiltIns.FQ_NAMES.extensionFunctionType.asString()
1040 }
1041 
AnnotationDescriptornull1042 fun AnnotationDescriptor.mustBeDocumented(): Boolean {
1043     val annotationClass = type.constructor.declarationDescriptor as? Annotated ?: return false
1044     return annotationClass.isDocumentedAnnotation()
1045 }
1046 
isDocumentationSuppressednull1047 fun DeclarationDescriptor.isDocumentationSuppressed(options: DocumentationOptions): Boolean {
1048 
1049     if (options.effectivePackageOptions(fqNameSafe).suppress) return true
1050 
1051     val path = this.findPsi()?.containingFile?.virtualFile?.path
1052     if (path != null) {
1053         if (File(path).absoluteFile in options.suppressedFiles) return true
1054     }
1055 
1056     val doc = findKDoc()
1057     if (doc is KDocSection && doc.findTagByName("suppress") != null) return true
1058 
1059     return hasSuppressDocTag(sourcePsi()) || hasHideAnnotation(sourcePsi())
1060 }
1061 
DeclarationDescriptornull1062 fun DeclarationDescriptor.sourcePsi() =
1063         ((original as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi
1064 
1065 fun DeclarationDescriptor.isDeprecated(): Boolean = annotations.any {
1066     DescriptorUtils.getFqName(it.type.constructor.declarationDescriptor!!).asString() == "kotlin.Deprecated"
1067 } || (this is ConstructorDescriptor && containingDeclaration.isDeprecated())
1068 
getExtensionClassDescriptornull1069 fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor? {
1070     val extensionReceiver = extensionReceiverParameter
1071     if (extensionReceiver != null) {
1072         val type = extensionReceiver.type
1073         val receiverClass = type.constructor.declarationDescriptor as? ClassDescriptor
1074         if (receiverClass?.isCompanionObject ?: false) {
1075             return receiverClass?.containingDeclaration as? ClassifierDescriptor
1076         }
1077         return receiverClass
1078     }
1079     return null
1080 }
1081 
signaturenull1082 fun DeclarationDescriptor.signature(): String {
1083     if (this != original) return original.signature()
1084     return when (this) {
1085         is ClassDescriptor,
1086         is PackageFragmentDescriptor,
1087         is PackageViewDescriptor,
1088         is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString()
1089 
1090         is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature()
1091         is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature()
1092         is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name
1093         is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name
1094         is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name
1095         else -> throw UnsupportedOperationException("Don't know how to calculate signature for $this")
1096     }
1097 }
1098 
receiverSignaturenull1099 fun PropertyDescriptor.receiverSignature(): String {
1100     val receiver = extensionReceiverParameter
1101     if (receiver != null) {
1102         return "#" + receiver.type.signature()
1103     }
1104     return ""
1105 }
1106 
parameterSignaturenull1107 fun CallableMemberDescriptor.parameterSignature(): String {
1108     val params = valueParameters.map { it.type }.toMutableList()
1109     val extensionReceiver = extensionReceiverParameter
1110     if (extensionReceiver != null) {
1111         params.add(0, extensionReceiver.type)
1112     }
1113     return params.joinToString(prefix = "(", postfix = ")") { it.signature() }
1114 }
1115 
signaturenull1116 fun KotlinType.signature(): String {
1117     val visited = hashSetOf<KotlinType>()
1118 
1119     fun KotlinType.signatureRecursive(): String {
1120         if (this in visited) {
1121             return ""
1122         }
1123         visited.add(this)
1124 
1125         val declarationDescriptor = constructor.declarationDescriptor ?: return "<null>"
1126         val typeName = DescriptorUtils.getFqName(declarationDescriptor).asString()
1127         if (arguments.isEmpty()) {
1128             return typeName
1129         }
1130         return typeName + arguments.joinToString(prefix = "((", postfix = "))") { it.type.signatureRecursive() }
1131     }
1132 
1133     return signatureRecursive()
1134 }
1135 
signatureWithSourceLocationnull1136 fun DeclarationDescriptor.signatureWithSourceLocation(): String {
1137     val signature = signature()
1138     val sourceLocation = sourceLocation()
1139     return if (sourceLocation != null) "$signature ($sourceLocation)" else signature
1140 }
1141 
DeclarationDescriptornull1142 fun DeclarationDescriptor.sourceLocation(): String? {
1143     val psi = sourcePsi()
1144     if (psi != null) {
1145         val fileName = psi.containingFile.name
1146         val lineNumber = psi.lineNumber()
1147         return if (lineNumber != null) "$fileName:$lineNumber" else fileName
1148     }
1149     return null
1150 }
1151 
DocumentationModulenull1152 fun DocumentationModule.prepareForGeneration(options: DocumentationOptions) {
1153     if (options.generateClassIndexPage) {
1154         generateAllTypesNode()
1155     }
1156     nodeRefGraph.resolveReferences()
1157 }
1158 
generateAllTypesNodenull1159 fun DocumentationNode.generateAllTypesNode() {
1160     val allTypes = members(NodeKind.Package)
1161             .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass } }
1162             .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.').toLowerCase() else it.name.toLowerCase() }
1163 
1164     val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes)
1165     for (typeNode in allTypes) {
1166         allTypesNode.addReferenceTo(typeNode, RefKind.Member)
1167     }
1168 
1169     append(allTypesNode, RefKind.Member)
1170 }
1171 
ClassDescriptornull1172 fun ClassDescriptor.supertypesWithAnyPrecise(): Collection<KotlinType> {
1173     if (KotlinBuiltIns.isAny(this)) {
1174         return emptyList()
1175     }
1176     return typeConstructor.supertypesWithAny()
1177 }