KT-22815: Render sections properly

This commit is contained in:
Simon Ogorodnik
2018-06-06 20:33:32 +03:00
parent 39e72f4041
commit 263ed47aac
2 changed files with 68 additions and 69 deletions
@@ -311,9 +311,7 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() {
var renderedHtml: String var renderedHtml: String
//if (!quickNavigation) {
renderedHtml = "${DocumentationMarkup.DEFINITION_START}$declaration${DocumentationMarkup.DEFINITION_END}" renderedHtml = "${DocumentationMarkup.DEFINITION_START}$declaration${DocumentationMarkup.DEFINITION_END}"
//}
val deprecationProvider = ktElement.getResolutionFacade().frontendService<DeprecationResolver>() val deprecationProvider = ktElement.getResolutionFacade().frontendService<DeprecationResolver>()
renderedHtml += renderDeprecationInfo(declarationDescriptor, deprecationProvider) renderedHtml += renderDeprecationInfo(declarationDescriptor, deprecationProvider)
@@ -322,13 +320,7 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() {
val comment = declarationDescriptor.findKDoc { DescriptorToSourceUtilsIde.getAnyDeclaration(ktElement.project, it) } val comment = declarationDescriptor.findKDoc { DescriptorToSourceUtilsIde.getAnyDeclaration(ktElement.project, it) }
if (comment != null) { if (comment != null) {
val renderedComment = KDocRenderer.renderKDoc(comment) val renderedComment = KDocRenderer.renderKDoc(comment)
renderedHtml += "${DocumentationMarkup.CONTENT_START}$renderedComment${DocumentationMarkup.CONTENT_END}" renderedHtml += "${DocumentationMarkup.CONTENT_START}$renderedComment"
// if (renderedComment.startsWith("<p>")) {
// renderedHtml += renderedComment
// }
// else {
// renderedHtml = "$renderedHtml<br/>$renderedComment"
// }
} else { } else {
if (declarationDescriptor is CallableDescriptor) { // If we couldn't find KDoc, try to find javadoc in one of super's if (declarationDescriptor is CallableDescriptor) { // If we couldn't find KDoc, try to find javadoc in one of super's
val psi = declarationDescriptor.findPsi() as? KtFunction val psi = declarationDescriptor.findPsi() as? KtFunction
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.kdoc package org.jetbrains.kotlin.idea.kdoc
import com.intellij.codeInsight.documentation.DocumentationManagerUtil import com.intellij.codeInsight.documentation.DocumentationManagerUtil
import com.intellij.lang.documentation.DocumentationMarkup.*
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.intellij.markdown.IElementType import org.intellij.markdown.IElementType
import org.intellij.markdown.MarkdownElementTypes import org.intellij.markdown.MarkdownElementTypes
@@ -36,30 +37,35 @@ import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
object KDocRenderer { object KDocRenderer {
fun renderKDoc(docComment: KDocTag): String { fun renderKDoc(docComment: KDocTag): String {
val content = docComment.getContent() return if (docComment is KDocSection) {
val result = StringBuilder() renderKDocSection(docComment)
result.append(markdownToHtml(content, allowSingleParagraph = true)) } else {
if (docComment is KDocSection) { markdownToHtml(docComment.getContent(), allowSingleParagraph = true)
result.append("\n")
renderTag(docComment.findTagByName("receiver"), "Receiver", result)
val paramTags = docComment.findTagsByName("param").filter { it.getSubjectName() != null }
renderTagList(paramTags, "Parameters", result)
renderTag(docComment.findTagByName("return"), "Returns", result)
val throwsTags = (docComment.findTagsByName("exception").union(docComment.findTagsByName("throws")))
.filter { it.getSubjectName() != null }
renderTagList(throwsTags, "Throws", result)
renderTag(docComment.findTagByName("author"), "Author", result)
renderTag(docComment.findTagByName("since"), "Since", result)
renderSeeAlso(docComment, result)
val sampleTags = docComment.findTagsByName("sample").filter { it.getSubjectLink() != null }
renderSamplesList(sampleTags, result)
} }
return result.toString() }
fun renderKDocSection(section: KDocSection): String = buildString {
append(markdownToHtml(section.getContent(), allowSingleParagraph = true))
append(CONTENT_END)
append(SECTIONS_START)
renderTag(section.findTagByName("receiver"), "Receiver", this)
val paramTags = section.findTagsByName("param").filter { it.getSubjectName() != null }
renderTagList(paramTags, "Parameters", this)
renderTag(section.findTagByName("return"), "Returns", this)
val throwsTags = (section.findTagsByName("exception").union(section.findTagsByName("throws")))
.filter { it.getSubjectName() != null }
renderTagList(throwsTags, "Throws", this)
renderTag(section.findTagByName("author"), "Author", this)
renderTag(section.findTagByName("since"), "Since", this)
renderSeeAlso(section, this)
val sampleTags = section.findTagsByName("sample").filter { it.getSubjectLink() != null }
renderSamplesList(sampleTags, this)
append(SECTIONS_END)
} }
private fun KDocLink.createHyperlink(to: StringBuilder) { private fun KDocLink.createHyperlink(to: StringBuilder) {
@@ -89,25 +95,27 @@ object KDocRenderer {
return lines.joinToString("\n") { it.drop(minIndent) } return lines.joinToString("\n") { it.drop(minIndent) }
} }
private fun StringBuilder.renderSection(title: String, content: StringBuilder.() -> Unit) {
append(SECTION_HEADER_START, title, SECTION_SEPARATOR)
content()
append(SECTION_END)
}
private fun renderSamplesList(sampleTags: List<KDocTag>, to: StringBuilder) { private fun renderSamplesList(sampleTags: List<KDocTag>, to: StringBuilder) {
if (sampleTags.isEmpty()) return if (sampleTags.isEmpty()) return
to.apply {
wrapTag("dl") { to.renderSection("Samples") {
append("<dt><b>Samples:</b></dt>") sampleTags.forEach {
sampleTags.forEach { it.getSubjectLink()?.let { subjectLink ->
wrapTag("dd") { append("<p>")
it.getSubjectLink()?.let { subjectLink -> subjectLink.createHyperlink(to)
subjectLink.createHyperlink(to) val target = subjectLink.getTargetElement()
val target = subjectLink.getTargetElement() wrapTag("pre") {
wrapTag("pre") { wrapTag("code") {
wrapTag("code") { if (target == null)
if (target == null) to.append("// Unresolved")
to.append("// Unresolved") else {
else { to.append(trimCommonIndent(target.extractExampleText()))
to.append(trimCommonIndent(target.extractExampleText()))
}
}
} }
} }
} }
@@ -119,40 +127,39 @@ object KDocRenderer {
private fun renderSeeAlso(docComment: KDocSection, to: StringBuilder) { private fun renderSeeAlso(docComment: KDocSection, to: StringBuilder) {
val seeTags = docComment.findTagsByName("see") val seeTags = docComment.findTagsByName("see")
if (seeTags.isEmpty()) return if (seeTags.isEmpty()) return
to.append("<DD><DL>")
to.append("<DT><b>").append("See Also:").append("</b>") to.renderSection("See Also") {
to.append("<DD>") seeTags.forEachIndexed { index, tag ->
seeTags.forEachIndexed { index, tag -> val subjectName = tag.getSubjectName()
val subjectName = tag.getSubjectName() if (subjectName != null) {
if (subjectName != null) { DocumentationManagerUtil.createHyperlink(this, subjectName, subjectName, false)
DocumentationManagerUtil.createHyperlink(to, subjectName, subjectName, false) }
} else {
else { append(tag.getContent())
to.append(tag.getContent()) }
} if (index < seeTags.size - 1) {
if (index < seeTags.size - 1) { append(", ")
to.append(", ") }
} }
} }
to.append("</DD></DL></DD>")
} }
private fun renderTagList(tags: List<KDocTag>, title: String, to: StringBuilder) { private fun renderTagList(tags: List<KDocTag>, title: String, to: StringBuilder) {
if (tags.isEmpty()) { if (tags.isEmpty()) {
return return
} }
to.append("<dl><dt><b>$title:</b></dt>") to.renderSection(title) {
tags.forEach { tags.forEach {
to.append("<dd><code>${it.getSubjectName()}</code> - ${markdownToHtml(it.getContent().trimStart())}</dd>") append("<p><code>${it.getSubjectName()}</code> - ${markdownToHtml(it.getContent().trimStart())}")
}
} }
to.append("</dl>\n")
} }
private fun renderTag(tag: KDocTag?, title: String, to: StringBuilder) { private fun renderTag(tag: KDocTag?, title: String, to: StringBuilder) {
if (tag != null) { if (tag != null) {
to.append("<dl><dt><b>$title:</b></dt>") to.renderSection(title) {
to.append("<dd>${markdownToHtml(tag.getContent())}</dd>") markdownToHtml(tag.getContent())
to.append("</dl>\n") }
} }
} }