diff options
author | Dmitry Jemerov <yole@jetbrains.com> | 2015-02-20 17:01:26 +0100 |
---|---|---|
committer | Dmitry Jemerov <yole@jetbrains.com> | 2015-02-20 17:01:26 +0100 |
commit | bfe53b9ea3359baee1785c2f6291bb5408597e28 (patch) | |
tree | 07678730112e424224b7be8ca2758cb382fc2028 /src/Kotlin | |
parent | 69c3638e173d1b08e02af0d7723c27cb025cea7d (diff) | |
download | dokka-bfe53b9ea3359baee1785c2f6291bb5408597e28.tar.gz dokka-bfe53b9ea3359baee1785c2f6291bb5408597e28.tar.bz2 dokka-bfe53b9ea3359baee1785c2f6291bb5408597e28.zip |
resolve content links to declaration descriptors immediately during markdown to content tree conversion; remove separate phase for resolving links in content
Diffstat (limited to 'src/Kotlin')
-rw-r--r-- | src/Kotlin/ContentBuilder.kt | 12 | ||||
-rw-r--r-- | src/Kotlin/DocumentationBuilder.kt | 73 |
2 files changed, 26 insertions, 59 deletions
diff --git a/src/Kotlin/ContentBuilder.kt b/src/Kotlin/ContentBuilder.kt index 6bb32f31..de5ac956 100644 --- a/src/Kotlin/ContentBuilder.kt +++ b/src/Kotlin/ContentBuilder.kt @@ -10,13 +10,13 @@ import org.intellij.markdown.* import org.jetbrains.kotlin.psi.JetDeclarationWithBody import org.jetbrains.kotlin.psi.JetBlockExpression -public fun buildContent(tree: MarkdownNode): Content { +public fun buildContent(tree: MarkdownNode, linkResolver: (String) -> ContentBlock): Content { val result = Content() - buildContentTo(tree, result) + buildContentTo(tree, result, linkResolver) return result } -public fun buildContentTo(tree: MarkdownNode, target: ContentBlock) { +public fun buildContentTo(tree: MarkdownNode, target: ContentBlock, linkResolver: (String) -> ContentBlock) { // println(tree.toTestString()) val nodeStack = ArrayDeque<ContentBlock>() nodeStack.push(target) @@ -77,7 +77,7 @@ public fun buildContentTo(tree: MarkdownNode, target: ContentBlock) { MarkdownElementTypes.SHORT_REFERENCE_LINK -> { val label = node.child(MarkdownElementTypes.LINK_LABEL)?.child(MarkdownTokenTypes.TEXT) if (label != null) { - val link = ContentExternalLink(label.text) + val link = linkResolver(label.text) link.append(ContentText(label.text)) parent.append(link) } @@ -123,10 +123,10 @@ public fun buildContentTo(tree: MarkdownNode, target: ContentBlock) { private fun keepWhitespace(node: ContentNode) = node is ContentParagraph || node is ContentSection -public fun buildInlineContentTo(tree: MarkdownNode, target: ContentBlock) { +public fun buildInlineContentTo(tree: MarkdownNode, target: ContentBlock, linkResolver: (String) -> ContentBlock) { val inlineContent = tree.children.singleOrNull { it.type == MarkdownElementTypes.PARAGRAPH }?.children ?: listOf(tree) inlineContent.forEach { - buildContentTo(it, target) + buildContentTo(it, target, linkResolver) } } diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index e02b57db..5d9857a7 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -40,7 +40,6 @@ class PendingLink(val lazyNodeFrom: () -> DocumentationNode?, class DocumentationBuilder(val session: ResolveSession, val options: DocumentationOptions, val logger: DokkaLogger) { val visibleToDocumentation = setOf(Visibilities.INTERNAL, Visibilities.PROTECTED, Visibilities.PUBLIC) val descriptorToNode = hashMapOf<DeclarationDescriptor, DocumentationNode>() - val nodeToDescriptor = hashMapOf<DocumentationNode, DeclarationDescriptor>() val links = arrayListOf<PendingLink>() fun parseDocumentation(descriptor: DeclarationDescriptor): Content { @@ -55,7 +54,7 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati } val tree = parseMarkdown(kdocText) //println(tree.toTestString()) - val content = buildContent(tree) + val content = buildContent(tree, { href -> resolveContentLink(descriptor, href) }) if (kdoc is KDocSection) { val tags = kdoc.getTags() tags.forEach { @@ -63,12 +62,12 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati "sample" -> content.append(functionBody(descriptor, it.getSubjectName())) "see" -> - content.addTagToSeeAlso(it) + content.addTagToSeeAlso(descriptor, it) else -> { val section = content.addSection(javadocSectionDisplayName(it.getName()), it.getSubjectName()) val sectionContent = it.getContent() val markdownNode = parseMarkdown(sectionContent) - buildInlineContentTo(markdownNode, section) + buildInlineContentTo(markdownNode, section, { href -> resolveContentLink(descriptor, href) }) } } } @@ -76,13 +75,27 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati return content } + fun resolveContentLink(descriptor: DeclarationDescriptor, href: String): ContentBlock { + val symbols = resolveKDocLink(session, descriptor, null, href.split('.').toList()) + // don't include unresolved links in generated doc + // assume that if an href doesn't contain '/', it's not an attempt to reference an external file + if (symbols.isNotEmpty()) { + val symbol = symbols.first() + return ContentNodeLazyLink(href, {() -> descriptorToNode[symbol] }) + } + if ("/" in href) { + return ContentExternalLink(href) + } + return ContentExternalLink("#") + } + fun KDocSection.getTags(): Array<KDocTag> = PsiTreeUtil.getChildrenOfType(this, javaClass<KDocTag>()) ?: array() - private fun Content.addTagToSeeAlso(seeTag: KDocTag) { + private fun Content.addTagToSeeAlso(descriptor: DeclarationDescriptor, seeTag: KDocTag) { val subjectName = seeTag.getSubjectName() if (subjectName != null) { val seeSection = findSectionByTag("See Also") ?: addSection("See Also", null) - val link = ContentExternalLink(subjectName) + val link = resolveContentLink(descriptor, subjectName) link.append(ContentText(subjectName)) val para = ContentParagraph() para.append(link) @@ -102,7 +115,6 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati fun register(descriptor: DeclarationDescriptor, node: DocumentationNode) { descriptorToNode.put(descriptor, node) - nodeToDescriptor.put(node, descriptor) } fun DocumentationNode<T>(descriptor: T, kind: Kind): DocumentationNode where T : DeclarationDescriptor, T : Named { @@ -484,7 +496,7 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati * $receiver: [DocumentationContext] for node/descriptor resolutions * $node: [DocumentationNode] to visit */ - public fun resolveReferences(node: DocumentationModule) { + public fun resolveReferences() { for (link in links) { val fromNode = link.lazyNodeFrom() val toNode = link.lazyNodeTo() @@ -492,50 +504,5 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati fromNode.addReferenceTo(toNode, link.kind) } } - resolveContentReferences(node) - } - - private fun resolveContentReferences(node: DocumentationNode) { - resolveContentLinks(node, node.content) - for (section in node.content.sections) { - resolveContentLinks(node, section) - } - - for (child in node.members) { - resolveContentReferences(child) - } - for (child in node.details) { - resolveContentReferences(child) - } - } - - fun getDescriptorForNode(node: DocumentationNode): DeclarationDescriptor { - val descriptor = nodeToDescriptor[node] ?: throw IllegalArgumentException("Node is not known to this context") - return descriptor - } - - fun resolveContentLinks(node: DocumentationNode, content: ContentBlock) { - val resolvedContentChildren = content.children.map { resolveContentLink(node, it) } - content.children.clear() - content.children.addAll(resolvedContentChildren) - } - - private fun resolveContentLink(node: DocumentationNode, content: ContentNode): ContentNode { - if (content is ContentExternalLink) { - val referenceText = content.href - val symbols = resolveKDocLink(session, getDescriptorForNode(node), null, referenceText.split('.').toList()) - // don't include unresolved links in generated doc - // assume that if an href doesn't contain '/', it's not an attempt to reference an external file - if (symbols.isNotEmpty() || "/" !in referenceText) { - val targetNode = if (symbols.isEmpty()) null else descriptorToNode[symbols.first()] - val contentLink = if (targetNode != null) ContentNodeLink(targetNode) else ContentExternalLink("#") - contentLink.children.addAll(content.children.map { resolveContentLink(node, it) }) - return contentLink - } - } - if (content is ContentBlock) { - resolveContentLinks(node, content) - } - return content } } |