<lambda>null1 package org.jetbrains.dokka
2
3 import com.google.inject.Inject
4 import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
5 import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
6 import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
7 import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink
8
9 class DeclarationLinkResolver
10 @Inject constructor(val resolutionFacade: DokkaResolutionFacade,
11 val refGraph: NodeReferenceGraph,
12 val logger: DokkaLogger,
13 val options: DocumentationOptions,
14 val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver,
15 val elementSignatureProvider: ElementSignatureProvider) {
16
17
18 fun tryResolveContentLink(fromDescriptor: DeclarationDescriptor, href: String): ContentBlock? {
19 val symbol = try {
20 val symbols = resolveKDocLink(resolutionFacade.resolveSession.bindingContext,
21 resolutionFacade, fromDescriptor, null, href.split('.').toList())
22 findTargetSymbol(symbols)
23 } catch(e: Exception) {
24 null
25 }
26
27 // don't include unresolved links in generated doc
28 // assume that if an href doesn't contain '/', it's not an attempt to reference an external file
29 if (symbol != null) {
30 val externalHref = externalDocumentationLinkResolver.buildExternalDocumentationLink(symbol)
31 if (externalHref != null) {
32 return ContentExternalLink(externalHref)
33 }
34 val signature = elementSignatureProvider.signature(symbol)
35 val referencedAt = fromDescriptor.signatureWithSourceLocation()
36
37 return ContentNodeLazyLink(href, { ->
38 val target = refGraph.lookup(signature)
39
40 if (target == null) {
41 logger.warn("Can't find node by signature `$signature`, referenced at $referencedAt")
42 }
43 target
44 })
45 }
46 if ("/" in href) {
47 return ContentExternalLink(href)
48 }
49 return null
50 }
51
52 fun resolveContentLink(fromDescriptor: DeclarationDescriptor, href: String) =
53 tryResolveContentLink(fromDescriptor, href) ?: run {
54 logger.warn("Unresolved link to $href in doc comment of ${fromDescriptor.signatureWithSourceLocation()}")
55 ContentExternalLink("#")
56 }
57
58 fun findTargetSymbol(symbols: Collection<DeclarationDescriptor>): DeclarationDescriptor? {
59 if (symbols.isEmpty()) {
60 return null
61 }
62 val symbol = symbols.first()
63 if (symbol is CallableMemberDescriptor && symbol.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
64 return symbol.overriddenDescriptors.firstOrNull()
65 }
66 if (symbol is TypeAliasDescriptor && !symbol.isDocumented(options)) {
67 return symbol.classDescriptor
68 }
69 return symbol
70 }
71
72 }
73