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