aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Jemerov <yole@jetbrains.com>2015-02-20 17:01:26 +0100
committerDmitry Jemerov <yole@jetbrains.com>2015-02-20 17:01:26 +0100
commitbfe53b9ea3359baee1785c2f6291bb5408597e28 (patch)
tree07678730112e424224b7be8ca2758cb382fc2028
parent69c3638e173d1b08e02af0d7723c27cb025cea7d (diff)
downloaddokka-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
-rw-r--r--src/Formats/HtmlFormatService.kt2
-rw-r--r--src/Kotlin/ContentBuilder.kt12
-rw-r--r--src/Kotlin/DocumentationBuilder.kt73
-rw-r--r--src/Model/Content.kt22
-rw-r--r--src/main.kt6
5 files changed, 48 insertions, 67 deletions
diff --git a/src/Formats/HtmlFormatService.kt b/src/Formats/HtmlFormatService.kt
index d5331422..751c5d5b 100644
--- a/src/Formats/HtmlFormatService.kt
+++ b/src/Formats/HtmlFormatService.kt
@@ -134,7 +134,7 @@ public open class HtmlFormatService(locationService: LocationService,
}
override fun appendOutlineHeader(location: Location, node: DocumentationNode, to: StringBuilder) {
- val link = ContentNodeLink(node)
+ val link = ContentNodeDirectLink(node)
link.append(languageService.render(node, LanguageService.RenderMode.FULL))
val signature = formatText(location, link)
to.appendln("<a href=\"${location.path}\">${signature}</a><br/>")
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
}
}
diff --git a/src/Model/Content.kt b/src/Model/Content.kt
index 9864ee42..01d7b206 100644
--- a/src/Model/Content.kt
+++ b/src/Model/Content.kt
@@ -38,12 +38,26 @@ public class ContentStrikethrough() : ContentBlock()
public class ContentCode() : ContentBlock()
public class ContentBlockCode() : ContentBlock()
-public class ContentNodeLink(val node : DocumentationNode) : ContentBlock() {
+public abstract class ContentNodeLink() : ContentBlock() {
+ abstract val node: DocumentationNode
+}
+
+public class ContentNodeDirectLink(override val node: DocumentationNode): ContentNodeLink() {
+ override fun equals(other: Any?): Boolean =
+ super.equals(other) && other is ContentNodeDirectLink && node.name == other.node.name
+
+ override fun hashCode(): Int =
+ children.hashCode() * 31 + node.name.hashCode()
+}
+
+public class ContentNodeLazyLink(val linkText: String, val lazyNode: () -> DocumentationNode): ContentNodeLink() {
+ override val node: DocumentationNode get() = lazyNode()
+
override fun equals(other: Any?): Boolean =
- super.equals(other) && other is ContentNodeLink && node.name == other.node.name
+ super.equals(other) && other is ContentNodeLazyLink && linkText == other.linkText
override fun hashCode(): Int =
- children.hashCode() * 31 + node.name.hashCode()
+ children.hashCode() * 31 + linkText.hashCode()
}
public class ContentExternalLink(val href : String) : ContentBlock() {
@@ -77,7 +91,7 @@ fun ContentBlock.symbol(value: String) = append(ContentSymbol(value))
fun ContentBlock.identifier(value: String) = append(ContentIdentifier(value))
fun ContentBlock.link(to: DocumentationNode, body: ContentBlock.() -> Unit) {
- val block = ContentNodeLink(to)
+ val block = ContentNodeDirectLink(to)
block.body()
append(block)
}
diff --git a/src/main.kt b/src/main.kt
index 63495d46..44c435d2 100644
--- a/src/main.kt
+++ b/src/main.kt
@@ -195,12 +195,13 @@ fun buildDocumentationModule(environment: AnalysisEnvironment,
val fragments = fragmentFiles.map { session.getPackageFragment(it.getPackageFqName()) }.filterNotNull().distinct()
val moduleContent = Content()
+ val documentationBuilder = DocumentationBuilder(session, options, logger)
for (include in includes) {
val file = File(include)
if (file.exists()) {
val text = file.readText()
val tree = parseMarkdown(text)
- val content = buildContent(tree)
+ val content = buildContent(tree, {href -> documentationBuilder.resolveContentLink(fragments.first(), href)})
moduleContent.children.addAll(content.children)
} else {
logger.warn("Include file $file was not found.")
@@ -208,10 +209,9 @@ fun buildDocumentationModule(environment: AnalysisEnvironment,
}
val documentationModule = DocumentationModule(moduleName, moduleContent)
- val documentationBuilder = DocumentationBuilder(session, options, logger)
with(documentationBuilder) {
documentationModule.appendFragments(fragments)
- documentationBuilder.resolveReferences(documentationModule)
+ documentationBuilder.resolveReferences()
}
val javaFiles = environment.getJavaSourceFiles().filter(filesToDocumentFilter)