aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/base/src/main/kotlin')
-rw-r--r--plugins/base/src/main/kotlin/DokkaBase.kt21
-rw-r--r--plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt2
-rw-r--r--plugins/base/src/main/kotlin/parsers/HtmlParser.kt89
-rw-r--r--plugins/base/src/main/kotlin/parsers/MarkdownParser.kt419
-rw-r--r--plugins/base/src/main/kotlin/parsers/Parser.kt42
-rw-r--r--plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt43
-rw-r--r--plugins/base/src/main/kotlin/parsers/factories/DocTagsFromStringFactory.kt77
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt20
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt1
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt41
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt4
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt13
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt23
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt1
14 files changed, 754 insertions, 42 deletions
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt
index cf4ad88f..f1b0d969 100644
--- a/plugins/base/src/main/kotlin/DokkaBase.kt
+++ b/plugins/base/src/main/kotlin/DokkaBase.kt
@@ -1,6 +1,9 @@
+@file:Suppress("unused")
+
package org.jetbrains.dokka.base
import org.jetbrains.dokka.CoreExtensions
+import org.jetbrains.dokka.analysis.KotlinAnalysis
import org.jetbrains.dokka.base.allModulePage.MultimodulePageCreator
import org.jetbrains.dokka.base.renderers.*
import org.jetbrains.dokka.base.renderers.html.*
@@ -37,13 +40,19 @@ class DokkaBase : DokkaPlugin() {
val externalLocationProviderFactory by extensionPoint<ExternalLocationProviderFactory>()
val outputWriter by extensionPoint<OutputWriter>()
val htmlPreprocessors by extensionPoint<PageTransformer>()
+ val kotlinAnalysis by extensionPoint<KotlinAnalysis>()
+
val descriptorToDocumentableTranslator by extending {
- CoreExtensions.sourceToDocumentableTranslator with DefaultDescriptorToDocumentableTranslator
+ CoreExtensions.sourceToDocumentableTranslator providing { ctx ->
+ DefaultDescriptorToDocumentableTranslator(ctx.single(kotlinAnalysis))
+ }
}
val psiToDocumentableTranslator by extending {
- CoreExtensions.sourceToDocumentableTranslator with DefaultPsiToDocumentableTranslator
+ CoreExtensions.sourceToDocumentableTranslator providing { ctx ->
+ DefaultPsiToDocumentableTranslator(ctx.single(kotlinAnalysis))
+ }
}
val documentableMerger by extending(isFallback = true) {
@@ -69,7 +78,9 @@ class DokkaBase : DokkaPlugin() {
}
val modulesAndPackagesDocumentation by extending(isFallback = true) {
- CoreExtensions.preMergeDocumentableTransformer providing ::ModuleAndPackageDocumentationTransformer
+ CoreExtensions.preMergeDocumentableTransformer providing { ctx ->
+ ModuleAndPackageDocumentationTransformer(ctx, ctx.single(kotlinAnalysis))
+ }
}
val kotlinSignatureProvider by extending(isFallback = true) {
@@ -124,6 +135,10 @@ class DokkaBase : DokkaPlugin() {
CoreExtensions.renderer providing ::HtmlRenderer applyIf { format == "html" }
}
+ val defaultKotlinAnalysis by extending(isFallback = true) {
+ kotlinAnalysis providing { ctx -> KotlinAnalysis(ctx) }
+ }
+
val locationProvider by extending(isFallback = true) {
locationProviderFactory providing ::DefaultLocationProviderFactory
}
diff --git a/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt b/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt
index ea1d8510..cdaa0274 100644
--- a/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt
+++ b/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt
@@ -9,7 +9,7 @@ import org.jetbrains.dokka.model.SourceSetData
import org.jetbrains.dokka.model.doc.DocumentationNode
import org.jetbrains.dokka.model.doc.P
import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.parsers.MarkdownParser
+import org.jetbrains.dokka.base.parsers.MarkdownParser
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.querySingle
import org.jetbrains.dokka.transformers.pages.PageCreator
diff --git a/plugins/base/src/main/kotlin/parsers/HtmlParser.kt b/plugins/base/src/main/kotlin/parsers/HtmlParser.kt
new file mode 100644
index 00000000..ece3cf24
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/HtmlParser.kt
@@ -0,0 +1,89 @@
+package org.jetbrains.dokka.base.parsers
+
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.base.parsers.factories.DocTagsFromStringFactory
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Node
+import org.jsoup.select.NodeFilter
+import org.jsoup.select.NodeTraversor
+
+class HtmlParser : Parser() {
+
+ inner class NodeFilterImpl : NodeFilter {
+
+ private val nodesCache: MutableMap<Int, MutableList<DocTag>> = mutableMapOf()
+ private var currentDepth = 0
+
+ fun collect(): DocTag = nodesCache[currentDepth]!![0]
+
+ override fun tail(node: Node?, depth: Int): NodeFilter.FilterResult {
+ val nodeName = node!!.nodeName()
+ val nodeAttributes = node.attributes()
+
+ if(nodeName in listOf("#document", "html", "head"))
+ return NodeFilter.FilterResult.CONTINUE
+
+ val body: String
+ val params: Map<String, String>
+
+
+ if(nodeName != "#text") {
+ body = ""
+ params = nodeAttributes.map { it.key to it.value }.toMap()
+ } else {
+ body = nodeAttributes["#text"]
+ params = emptyMap()
+ }
+
+ val docNode = if(depth < currentDepth) {
+ DocTagsFromStringFactory.getInstance(nodeName, nodesCache.getOrDefault(currentDepth, mutableListOf()).toList(), params, body).also {
+ nodesCache[currentDepth] = mutableListOf()
+ currentDepth = depth
+ }
+ } else {
+ DocTagsFromStringFactory.getInstance(nodeName, emptyList(), params, body)
+ }
+
+ nodesCache.getOrDefault(depth, mutableListOf()) += docNode
+ return NodeFilter.FilterResult.CONTINUE
+ }
+
+ override fun head(node: Node?, depth: Int): NodeFilter.FilterResult {
+
+ val nodeName = node!!.nodeName()
+
+ if(currentDepth < depth) {
+ currentDepth = depth
+ nodesCache[currentDepth] = mutableListOf()
+ }
+
+ if(nodeName in listOf("#document", "html", "head"))
+ return NodeFilter.FilterResult.CONTINUE
+
+ return NodeFilter.FilterResult.CONTINUE
+ }
+ }
+
+
+ private fun htmlToDocNode(string: String): DocTag {
+ val document = Jsoup.parse(string)
+ val nodeFilterImpl = NodeFilterImpl()
+ NodeTraversor.filter(nodeFilterImpl, document.root())
+ return nodeFilterImpl.collect()
+ }
+
+ private fun replaceLinksWithHrefs(javadoc: String): String = Regex("\\{@link .*?}").replace(javadoc) {
+ val split = it.value.dropLast(1).split(" ")
+ if(split.size !in listOf(2, 3))
+ return@replace it.value
+ if(split.size == 3)
+ return@replace "<documentationlink href=\"${split[1]}\">${split[2]}</documentationlink>"
+ else
+ return@replace "<documentationlink href=\"${split[1]}\">${split[1]}</documentationlink>"
+ }
+
+ override fun parseStringToDocNode(extractedString: String) = htmlToDocNode(extractedString)
+ override fun preparse(text: String) = replaceLinksWithHrefs(text)
+}
+
+
diff --git a/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt b/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt
new file mode 100644
index 00000000..6075ef73
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt
@@ -0,0 +1,419 @@
+package org.jetbrains.dokka.base.parsers
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.dokka.model.doc.*
+import org.intellij.markdown.MarkdownElementTypes
+import org.intellij.markdown.MarkdownTokenTypes
+import org.intellij.markdown.ast.ASTNode
+import org.intellij.markdown.ast.CompositeASTNode
+import org.intellij.markdown.ast.LeafASTNode
+import org.intellij.markdown.ast.impl.ListItemCompositeNode
+import org.intellij.markdown.flavours.gfm.GFMElementTypes
+import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
+import org.intellij.markdown.flavours.gfm.GFMTokenTypes
+import org.jetbrains.dokka.analysis.DokkaResolutionFacade
+import org.jetbrains.dokka.analysis.from
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.base.parsers.factories.DocTagsFromIElementFactory
+import org.jetbrains.dokka.utilities.DokkaLogger
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink
+import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
+import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
+import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
+import java.net.MalformedURLException
+import org.intellij.markdown.parser.MarkdownParser as IntellijMarkdownParser
+
+class MarkdownParser(
+ private val resolutionFacade: DokkaResolutionFacade? = null,
+ private val declarationDescriptor: DeclarationDescriptor? = null,
+ private val logger: DokkaLogger
+) : Parser() {
+
+ inner class MarkdownVisitor(val text: String, val destinationLinksMap: Map<String, String>) {
+
+ private fun headersHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type,
+ visitNode(node.children.find { it.type == MarkdownTokenTypes.ATX_CONTENT }
+ ?: throw IllegalStateException("Wrong AST Tree. ATX Header does not contain expected content")).children
+ )
+
+ private fun horizontalRulesHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(MarkdownTokenTypes.HORIZONTAL_RULE)
+
+ private fun emphasisHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type,
+ children = listOf(visitNode(node.children[node.children.size / 2]))
+ )
+
+ private fun blockquotesHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type, children = node.children
+ .filterIsInstance<CompositeASTNode>()
+ .evaluateChildren()
+ )
+
+ private fun listsHandler(node: ASTNode): DocTag {
+
+ val children = node.children.filterIsInstance<ListItemCompositeNode>().flatMap {
+ if (it.children.last().type in listOf(
+ MarkdownElementTypes.ORDERED_LIST,
+ MarkdownElementTypes.UNORDERED_LIST
+ )
+ ) {
+ val nestedList = it.children.last()
+ (it.children as MutableList).removeAt(it.children.lastIndex)
+ listOf(it, nestedList)
+ } else
+ listOf(it)
+ }
+
+ return DocTagsFromIElementFactory.getInstance(
+ node.type,
+ children =
+ children
+ .map {
+ if (it.type == MarkdownElementTypes.LIST_ITEM)
+ DocTagsFromIElementFactory.getInstance(
+ it.type,
+ children = it
+ .children
+ .filterIsInstance<CompositeASTNode>()
+ .evaluateChildren()
+ )
+ else
+ visitNode(it)
+ },
+ params =
+ if (node.type == MarkdownElementTypes.ORDERED_LIST) {
+ val listNumberNode = node.children.first().children.first()
+ mapOf(
+ "start" to text.substring(
+ listNumberNode.startOffset,
+ listNumberNode.endOffset
+ ).trim().dropLast(1)
+ )
+ } else
+ emptyMap()
+ )
+ }
+
+ private fun resolveDRI(mdLink: String): DRI? =
+ mdLink
+ .removePrefix("[")
+ .removeSuffix("]")
+ .let { link ->
+ try {
+ java.net.URL(link)
+ null
+ } catch (e: MalformedURLException) {
+ try {
+ if (resolutionFacade != null && declarationDescriptor != null) {
+ resolveKDocLink(
+ resolutionFacade.resolveSession.bindingContext,
+ resolutionFacade,
+ declarationDescriptor,
+ null,
+ link.split('.')
+ ).minBy { it is ClassDescriptor }?.let { DRI.from(it) }
+ } else null
+ } catch (e1: IllegalArgumentException) {
+ null
+ }
+ }
+ }
+
+ private fun referenceLinksHandler(node: ASTNode): DocTag {
+ val linkLabel = node.children.find { it.type == MarkdownElementTypes.LINK_LABEL }
+ ?: throw IllegalStateException("Wrong AST Tree. Reference link does not contain expected content")
+ val linkText = node.children.findLast { it.type == MarkdownElementTypes.LINK_TEXT } ?: linkLabel
+
+ val linkKey = text.substring(linkLabel.startOffset, linkLabel.endOffset)
+
+ val link = destinationLinksMap[linkKey.toLowerCase()] ?: linkKey
+
+ return linksHandler(linkText, link)
+ }
+
+ private fun inlineLinksHandler(node: ASTNode): DocTag {
+ val linkText = node.children.find { it.type == MarkdownElementTypes.LINK_TEXT }
+ ?: throw IllegalStateException("Wrong AST Tree. Inline link does not contain expected content")
+ val linkDestination = node.children.find { it.type == MarkdownElementTypes.LINK_DESTINATION }
+ ?: throw IllegalStateException("Wrong AST Tree. Inline link does not contain expected content")
+ val linkTitle = node.children.find { it.type == MarkdownElementTypes.LINK_TITLE }
+
+ val link = text.substring(linkDestination.startOffset, linkDestination.endOffset)
+
+ return linksHandler(linkText, link, linkTitle)
+ }
+
+ private fun autoLinksHandler(node: ASTNode): DocTag {
+ val link = text.substring(node.startOffset + 1, node.endOffset - 1)
+
+ return linksHandler(node, link)
+ }
+
+ private fun linksHandler(linkText: ASTNode, link: String, linkTitle: ASTNode? = null): DocTag {
+ val dri: DRI? = resolveDRI(link)
+ val params = if (linkTitle == null)
+ mapOf("href" to link)
+ else
+ mapOf("href" to link, "title" to text.substring(linkTitle.startOffset + 1, linkTitle.endOffset - 1))
+
+ return DocTagsFromIElementFactory.getInstance(
+ MarkdownElementTypes.INLINE_LINK,
+ params = params,
+ children = linkText.children.drop(1).dropLast(1).evaluateChildren(),
+ dri = dri
+ )
+ }
+
+ private fun imagesHandler(node: ASTNode): DocTag {
+ val linkNode =
+ node.children.last().children.find { it.type == MarkdownElementTypes.LINK_LABEL }!!.children[1]
+ val link = text.substring(linkNode.startOffset, linkNode.endOffset)
+ val src = mapOf("src" to link)
+ return DocTagsFromIElementFactory.getInstance(
+ node.type,
+ params = src,
+ children = listOf(visitNode(node.children.last().children.find { it.type == MarkdownElementTypes.LINK_TEXT }!!))
+ )
+ }
+
+ private fun codeSpansHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type,
+ children = listOf(
+ DocTagsFromIElementFactory.getInstance(
+ MarkdownTokenTypes.TEXT,
+ body = text.substring(node.startOffset + 1, node.endOffset - 1).replace('\n', ' ').trimIndent()
+ )
+
+ )
+ )
+
+ private fun codeFencesHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type,
+ children = node
+ .children
+ .dropWhile { it.type != MarkdownTokenTypes.CODE_FENCE_CONTENT }
+ .dropLastWhile { it.type != MarkdownTokenTypes.CODE_FENCE_CONTENT }
+ .map {
+ if (it.type == MarkdownTokenTypes.EOL)
+ LeafASTNode(MarkdownTokenTypes.HARD_LINE_BREAK, 0, 0)
+ else
+ it
+ }.evaluateChildren(),
+ params = node
+ .children
+ .find { it.type == MarkdownTokenTypes.FENCE_LANG }
+ ?.let { mapOf("lang" to text.substring(it.startOffset, it.endOffset)) }
+ ?: emptyMap()
+ )
+
+ private fun codeBlocksHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(node.type, children = node.children.evaluateChildren())
+
+ private fun defaultHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ MarkdownElementTypes.PARAGRAPH,
+ children = node.children.evaluateChildren()
+ )
+
+ fun visitNode(node: ASTNode): DocTag =
+ when (node.type) {
+ MarkdownElementTypes.ATX_1,
+ MarkdownElementTypes.ATX_2,
+ MarkdownElementTypes.ATX_3,
+ MarkdownElementTypes.ATX_4,
+ MarkdownElementTypes.ATX_5,
+ MarkdownElementTypes.ATX_6 -> headersHandler(node)
+ MarkdownTokenTypes.HORIZONTAL_RULE -> horizontalRulesHandler(node)
+ MarkdownElementTypes.STRONG,
+ MarkdownElementTypes.EMPH -> emphasisHandler(node)
+ MarkdownElementTypes.FULL_REFERENCE_LINK,
+ MarkdownElementTypes.SHORT_REFERENCE_LINK -> referenceLinksHandler(node)
+ MarkdownElementTypes.INLINE_LINK -> inlineLinksHandler(node)
+ MarkdownElementTypes.AUTOLINK -> autoLinksHandler(node)
+ MarkdownElementTypes.BLOCK_QUOTE -> blockquotesHandler(node)
+ MarkdownElementTypes.UNORDERED_LIST,
+ MarkdownElementTypes.ORDERED_LIST -> listsHandler(node)
+ MarkdownElementTypes.CODE_BLOCK -> codeBlocksHandler(node)
+ MarkdownElementTypes.CODE_FENCE -> codeFencesHandler(node)
+ MarkdownElementTypes.CODE_SPAN -> codeSpansHandler(node)
+ MarkdownElementTypes.IMAGE -> imagesHandler(node)
+ MarkdownTokenTypes.HARD_LINE_BREAK -> DocTagsFromIElementFactory.getInstance(node.type)
+ MarkdownTokenTypes.CODE_FENCE_CONTENT,
+ MarkdownTokenTypes.CODE_LINE,
+ MarkdownTokenTypes.TEXT -> DocTagsFromIElementFactory.getInstance(
+ MarkdownTokenTypes.TEXT,
+ body = text
+ .substring(node.startOffset, node.endOffset).transform()
+ )
+ MarkdownElementTypes.MARKDOWN_FILE -> if (node.children.size == 1) visitNode(node.children.first()) else defaultHandler(
+ node
+ )
+ GFMElementTypes.STRIKETHROUGH -> DocTagsFromIElementFactory.getInstance(
+ GFMElementTypes.STRIKETHROUGH,
+ body = text
+ .substring(node.startOffset, node.endOffset).transform()
+ )
+ GFMElementTypes.TABLE -> DocTagsFromIElementFactory.getInstance(
+ GFMElementTypes.TABLE,
+ children = node.children.filterTabSeparators().evaluateChildren()
+ )
+ GFMElementTypes.HEADER -> DocTagsFromIElementFactory.getInstance(
+ GFMElementTypes.HEADER,
+ children = node.children.filterTabSeparators().evaluateChildren()
+ )
+ GFMElementTypes.ROW -> DocTagsFromIElementFactory.getInstance(
+ GFMElementTypes.ROW,
+ children = node.children.filterTabSeparators().evaluateChildren()
+ )
+ else -> defaultHandler(node)
+ }
+
+ private fun List<ASTNode>.filterTabSeparators() =
+ this.filterNot { it.type == GFMTokenTypes.TABLE_SEPARATOR }
+
+ private fun List<ASTNode>.evaluateChildren(): List<DocTag> =
+ this.removeUselessTokens().mergeLeafASTNodes().map { visitNode(it) }
+
+ private fun List<ASTNode>.removeUselessTokens(): List<ASTNode> =
+ this.filterIndexed { index, node ->
+ !(node.type == MarkdownElementTypes.LINK_DEFINITION || (
+ node.type == MarkdownTokenTypes.EOL &&
+ this.getOrNull(index - 1)?.type == MarkdownTokenTypes.HARD_LINE_BREAK
+ ))
+ }
+
+ private val notLeafNodes = listOf(MarkdownTokenTypes.HORIZONTAL_RULE, MarkdownTokenTypes.HARD_LINE_BREAK)
+
+ private fun List<ASTNode>.isNotLeaf(index: Int): Boolean =
+ if (index in 0..this.lastIndex)
+ (this[index] is CompositeASTNode) || this[index].type in notLeafNodes
+ else
+ false
+
+ private fun List<ASTNode>.mergeLeafASTNodes(): List<ASTNode> {
+ val children: MutableList<ASTNode> = mutableListOf()
+ var index = 0
+ while (index <= this.lastIndex) {
+ if (this.isNotLeaf(index)) {
+ children += this[index]
+ } else {
+ val startOffset = this[index].startOffset
+ while (index < this.lastIndex) {
+ if (this.isNotLeaf(index + 1) || this[index + 1].startOffset != this[index].endOffset) {
+ val endOffset = this[index].endOffset
+ if (text.substring(startOffset, endOffset).transform().trim().isNotEmpty())
+ children += LeafASTNode(MarkdownTokenTypes.TEXT, startOffset, endOffset)
+ break
+ }
+ index++
+ }
+ if (index == this.lastIndex) {
+ val endOffset = this[index].endOffset
+ if (text.substring(startOffset, endOffset).transform().trim().isNotEmpty())
+ children += LeafASTNode(MarkdownTokenTypes.TEXT, startOffset, endOffset)
+ }
+ }
+ index++
+ }
+ return children
+ }
+
+ private fun String.transform() = this
+ .replace(Regex("\n\n+"), "") // Squashing new lines between paragraphs
+ .replace(Regex("\n"), " ")
+ .replace(Regex(" >+ +"), " ") // Replacement used in blockquotes, get rid of garbage
+ }
+
+
+ private fun getAllDestinationLinks(text: String, node: ASTNode): List<Pair<String, String>> =
+ node.children
+ .filter { it.type == MarkdownElementTypes.LINK_DEFINITION }
+ .map {
+ text.substring(it.children[0].startOffset, it.children[0].endOffset).toLowerCase() to
+ text.substring(it.children[2].startOffset, it.children[2].endOffset)
+ } +
+ node.children.filterIsInstance<CompositeASTNode>().flatMap { getAllDestinationLinks(text, it) }
+
+
+ private fun markdownToDocNode(text: String): DocTag {
+
+ val flavourDescriptor = GFMFlavourDescriptor()
+ val markdownAstRoot: ASTNode = IntellijMarkdownParser(flavourDescriptor).buildMarkdownTreeFromString(text)
+
+ return MarkdownVisitor(text, getAllDestinationLinks(text, markdownAstRoot).toMap()).visitNode(markdownAstRoot)
+ }
+
+ override fun parseStringToDocNode(extractedString: String) = markdownToDocNode(extractedString)
+ override fun preparse(text: String) = text
+
+ private fun findParent(kDoc: PsiElement): PsiElement =
+ if (kDoc is KDocSection) findParent(kDoc.parent) else kDoc
+
+ private fun getAllKDocTags(kDocImpl: PsiElement): List<KDocTag> =
+ kDocImpl.children.filterIsInstance<KDocTag>().filterNot { it is KDocSection } + kDocImpl.children.flatMap {
+ getAllKDocTags(
+ it
+ )
+ }
+
+ fun parseFromKDocTag(kDocTag: KDocTag?): DocumentationNode {
+ return if (kDocTag == null)
+ DocumentationNode(emptyList())
+ else
+ DocumentationNode(
+ (listOf(kDocTag) + getAllKDocTags(findParent(kDocTag))).map {
+ when (it.knownTag) {
+ null -> if (it.name == null) Description(parseStringToDocNode(it.getContent())) else CustomTagWrapper(
+ parseStringToDocNode(it.getContent()),
+ it.name!!
+ )
+ KDocKnownTag.AUTHOR -> Author(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.THROWS -> Throws(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.EXCEPTION -> Throws(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.PARAM -> Param(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.RECEIVER -> Receiver(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.RETURN -> Return(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.SEE -> See(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty(),
+ parseStringToDocNode("[${it.getSubjectName()}]")
+ .let {
+ val link = it.children[0]
+ if (link is DocumentationLink) link.dri
+ else null
+ }
+ )
+ KDocKnownTag.SINCE -> Since(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.CONSTRUCTOR -> Constructor(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.PROPERTY -> Property(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.SAMPLE -> Sample(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.SUPPRESS -> Suppress(parseStringToDocNode(it.getContent()))
+ }
+ }
+ )
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/parsers/Parser.kt b/plugins/base/src/main/kotlin/parsers/Parser.kt
new file mode 100644
index 00000000..1dd0c34a
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/Parser.kt
@@ -0,0 +1,42 @@
+package org.jetbrains.dokka.base.parsers
+
+import org.jetbrains.dokka.model.doc.*
+
+abstract class Parser {
+
+ abstract fun parseStringToDocNode(extractedString: String): DocTag
+ abstract fun preparse(text: String): String
+
+ fun parse(text: String): DocumentationNode {
+
+ val list = jkdocToListOfPairs(preparse(text))
+
+ val mappedList: List<TagWrapper> = list.map {
+ when(it.first) {
+ "description" -> Description(parseStringToDocNode(it.second))
+ "author" -> Author(parseStringToDocNode(it.second))
+ "version" -> Version(parseStringToDocNode(it.second))
+ "since" -> Since(parseStringToDocNode(it.second))
+ "see" -> See(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '), null)
+ "param" -> Param(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '))
+ "property" -> Property(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '))
+ "return" -> Return(parseStringToDocNode(it.second))
+ "constructor" -> Constructor(parseStringToDocNode(it.second))
+ "receiver" -> Receiver(parseStringToDocNode(it.second))
+ "throws", "exception" -> Throws(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '))
+ "deprecated" -> Deprecated(parseStringToDocNode(it.second))
+ "sample" -> Sample(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '))
+ "suppress" -> Suppress(parseStringToDocNode(it.second))
+ else -> CustomTagWrapper(parseStringToDocNode(it.second), it.first)
+ }
+ }
+ return DocumentationNode(mappedList)
+ }
+
+ private fun jkdocToListOfPairs(javadoc: String): List<Pair<String, String>> =
+ "description $javadoc"
+ .split("\n@")
+ .map {
+ it.substringBefore(' ') to it.substringAfter(' ')
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt
new file mode 100644
index 00000000..e81eb513
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt
@@ -0,0 +1,43 @@
+package org.jetbrains.dokka.base.parsers.factories
+
+import org.jetbrains.dokka.model.doc.*
+import org.intellij.markdown.IElementType
+import org.intellij.markdown.MarkdownElementTypes
+import org.intellij.markdown.MarkdownTokenTypes
+import org.intellij.markdown.flavours.gfm.GFMElementTypes
+import org.jetbrains.dokka.links.DRI
+import java.lang.NullPointerException
+
+object DocTagsFromIElementFactory {
+ fun getInstance(type: IElementType, children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap(), body: String? = null, dri: DRI? = null) =
+ when(type) {
+ MarkdownElementTypes.SHORT_REFERENCE_LINK,
+ MarkdownElementTypes.FULL_REFERENCE_LINK,
+ MarkdownElementTypes.INLINE_LINK -> if(dri == null) A(children, params) else DocumentationLink(dri, children, params)
+ MarkdownElementTypes.STRONG -> B(children, params)
+ MarkdownElementTypes.BLOCK_QUOTE -> BlockQuote(children, params)
+ MarkdownElementTypes.CODE_SPAN,
+ MarkdownElementTypes.CODE_BLOCK,
+ MarkdownElementTypes.CODE_FENCE -> Code(children, params)
+ MarkdownElementTypes.ATX_1 -> H1(children, params)
+ MarkdownElementTypes.ATX_2 -> H2(children, params)
+ MarkdownElementTypes.ATX_3 -> H3(children, params)
+ MarkdownElementTypes.ATX_4 -> H4(children, params)
+ MarkdownElementTypes.ATX_5 -> H5(children, params)
+ MarkdownElementTypes.ATX_6 -> H6(children, params)
+ MarkdownElementTypes.EMPH -> I(children, params)
+ MarkdownElementTypes.IMAGE -> Img(children, params)
+ MarkdownElementTypes.LIST_ITEM -> Li(children, params)
+ MarkdownElementTypes.ORDERED_LIST -> Ol(children, params)
+ MarkdownElementTypes.UNORDERED_LIST -> Ul(children, params)
+ MarkdownElementTypes.PARAGRAPH -> P(children, params)
+ MarkdownTokenTypes.TEXT -> Text(body ?: throw NullPointerException("Text body should be at least empty string passed to DocNodes factory!"), children, params )
+ MarkdownTokenTypes.HORIZONTAL_RULE -> HorizontalRule
+ MarkdownTokenTypes.HARD_LINE_BREAK -> Br
+ GFMElementTypes.STRIKETHROUGH -> Strikethrough(children, params)
+ GFMElementTypes.TABLE -> Table(children, params)
+ GFMElementTypes.HEADER -> Th(children, params)
+ GFMElementTypes.ROW -> Tr(children, params)
+ else -> CustomDocTag(children, params)
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromStringFactory.kt b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromStringFactory.kt
new file mode 100644
index 00000000..de7c3cad
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromStringFactory.kt
@@ -0,0 +1,77 @@
+package org.jetbrains.dokka.base.parsers.factories
+
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.links.DRI
+import java.lang.NullPointerException
+
+object DocTagsFromStringFactory {
+ fun getInstance(name: String, children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap(), body: String? = null, dri: DRI? = null) =
+ when(name) {
+ "a" -> A(children, params)
+ "big" -> Big(children, params)
+ "b" -> B(children, params)
+ "blockquote" -> BlockQuote(children, params)
+ "br" -> Br
+ "cite" -> Cite(children, params)
+ "code" -> Code(children, params)
+ "dd" -> Dd(children, params)
+ "dfn" -> Dfn(children, params)
+ "dir" -> Dir(children, params)
+ "div" -> Div(children, params)
+ "dl" -> Dl(children, params)
+ "dt" -> Dt(children, params)
+ "Em" -> Em(children, params)
+ "font" -> Font(children, params)
+ "footer" -> Footer(children, params)
+ "frame" -> Frame(children, params)
+ "frameset" -> FrameSet(children, params)
+ "h1" -> H1(children, params)
+ "h2" -> H2(children, params)
+ "h3" -> H3(children, params)
+ "h4" -> H4(children, params)
+ "h5" -> H5(children, params)
+ "h6" -> H6(children, params)
+ "head" -> Head(children, params)
+ "header" -> Header(children, params)
+ "html" -> Html(children, params)
+ "i" -> I(children, params)
+ "iframe" -> IFrame(children, params)
+ "img" -> Img(children, params)
+ "input" -> Input(children, params)
+ "li" -> Li(children, params)
+ "link" -> Link(children, params)
+ "listing" -> Listing(children, params)
+ "main" -> Main(children, params)
+ "menu" -> Menu(children, params)
+ "meta" -> Meta(children, params)
+ "nav" -> Nav(children, params)
+ "noframes" -> NoFrames(children, params)
+ "noscript" -> NoScript(children, params)
+ "ol" -> Ol(children, params)
+ "p" -> P(children, params)
+ "pre" -> Pre(children, params)
+ "script" -> Script(children, params)
+ "section" -> Section(children, params)
+ "small" -> Small(children, params)
+ "span" -> Span(children, params)
+ "strong" -> Strong(children, params)
+ "sub" -> Sub(children, params)
+ "sup" -> Sup(children, params)
+ "table" -> Table(children, params)
+ "#text" -> Text(body ?: throw NullPointerException("Text body should be at least empty string passed to DocNodes factory!"), children, params)
+ "tBody" -> TBody(children, params)
+ "td" -> Td(children, params)
+ "tFoot" -> TFoot(children, params)
+ "th" -> Th(children, params)
+ "tHead" -> THead(children, params)
+ "title" -> Title(children, params)
+ "tr" -> Tr(children, params)
+ "tt" -> Tt(children, params)
+ "u" -> U(children, params)
+ "ul" -> Ul(children, params)
+ "var" -> Var(children, params)
+ "documentationlink" -> DocumentationLink(dri ?: throw NullPointerException("DRI cannot be passed null while constructing documentation link!"), children, params)
+ "hr" -> HorizontalRule
+ else -> CustomDocTag(children, params)
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
index 2aab6018..63232793 100644
--- a/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
+++ b/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
@@ -1,10 +1,13 @@
package org.jetbrains.dokka.base.transformers.documentables
+import org.jetbrains.dokka.analysis.EnvironmentAndFacade
+import org.jetbrains.dokka.analysis.KotlinAnalysis
import org.jetbrains.dokka.model.DModule
import org.jetbrains.dokka.model.SourceSetData
import org.jetbrains.dokka.model.doc.DocumentationNode
import org.jetbrains.dokka.model.sourceSet
-import org.jetbrains.dokka.parsers.MarkdownParser
+import org.jetbrains.dokka.base.parsers.MarkdownParser
+import org.jetbrains.dokka.model.SourceSetDependent
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
import org.jetbrains.kotlin.name.FqName
@@ -12,9 +15,12 @@ import java.nio.file.Files
import java.nio.file.Paths
-internal class ModuleAndPackageDocumentationTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer {
+internal class ModuleAndPackageDocumentationTransformer(
+ private val context: DokkaContext,
+ private val kotlinAnalysis: KotlinAnalysis
+) : PreMergeDocumentableTransformer {
- override fun invoke(original: List<DModule>): List<DModule> {
+ override fun invoke(modules: List<DModule>): List<DModule> {
val modulesAndPackagesDocumentation =
context.configuration.passesConfigurations
@@ -47,13 +53,12 @@ internal class ModuleAndPackageDocumentationTransformer(val context: DokkaContex
}
}.toMap()
- return original.map { module ->
+ return modules.map { module ->
val moduleDocumentation =
module.sourceSets.mapNotNull { pd ->
val doc = modulesAndPackagesDocumentation[Pair(module.name, pd)]
- val facade = context.platforms[pd]?.facade
- ?: return@mapNotNull null.also { context.logger.warn("Could not find platform data for ${pd.moduleName}/${pd.sourceSetID}") }
+ val facade = kotlinAnalysis[pd].facade
try {
doc?.get("Module")?.get(module.name)?.run {
pd to MarkdownParser(
@@ -71,8 +76,7 @@ internal class ModuleAndPackageDocumentationTransformer(val context: DokkaContex
val packagesDocumentation = module.packages.map {
it.name to it.sourceSets.mapNotNull { pd ->
val doc = modulesAndPackagesDocumentation[Pair(module.name, pd)]
- val facade = context.platforms[pd]?.facade
- ?: return@mapNotNull null.also { context.logger.warn("Could not find platform data for ${pd.moduleName}/${pd.sourceSetID}") }
+ val facade = kotlinAnalysis[pd].facade
val descriptor = facade.moduleDescriptor.getPackage(FqName(it.name.let { if(it == "[JS root]") "" else it }))
doc?.get("Package")?.get(it.name)?.run {
pd to MarkdownParser(
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt
index 7d475571..0b47345d 100644
--- a/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt
+++ b/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt
@@ -2,6 +2,7 @@ package org.jetbrains.dokka.base.transformers.documentables
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.DokkaConfiguration.PassConfiguration
+import org.jetbrains.dokka.analysis.DescriptorDocumentableSource
import org.jetbrains.dokka.model.*
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
diff --git a/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt
index 57655a9d..0d133a65 100644
--- a/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt
+++ b/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt
@@ -1,11 +1,11 @@
package org.jetbrains.dokka.base.transformers.pages.samples
import com.intellij.psi.PsiElement
-import org.jetbrains.dokka.DokkaGenerator
-import org.jetbrains.dokka.EnvironmentAndFacade
import org.jetbrains.dokka.Platform
import org.jetbrains.dokka.analysis.AnalysisEnvironment
+import org.jetbrains.dokka.analysis.DokkaMessageCollector
import org.jetbrains.dokka.analysis.DokkaResolutionFacade
+import org.jetbrains.dokka.analysis.EnvironmentAndFacade
import org.jetbrains.dokka.base.renderers.platforms
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.model.SourceSetData
@@ -41,7 +41,7 @@ abstract class SamplesTransformer(val context: DokkaContext) : PageTransformer {
}
private fun setUpAnalysis(context: DokkaContext) = context.configuration.passesConfigurations.map {
- context.sourceSet(it) to AnalysisEnvironment(DokkaGenerator.DokkaMessageCollector(context.logger), it.analysisPlatform).run {
+ context.sourceSet(it) to AnalysisEnvironment(DokkaMessageCollector(context.logger), it.analysisPlatform).run {
if (analysisPlatform == Platform.jvm) {
addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
}
@@ -57,11 +57,16 @@ abstract class SamplesTransformer(val context: DokkaContext) : PageTransformer {
}
}.toMap()
- private fun ContentNode.addSample(contentPage: ContentPage, platform: SourceSetData, fqName: String, analysis: Map<SourceSetData, EnvironmentAndFacade>): ContentNode {
- val facade = analysis[platform]?.facade ?:
- return this.also { context.logger.warn("Cannot resolve facade for platform ${platform.moduleName}")}
- val psiElement = fqNameToPsiElement(facade, fqName) ?:
- return this.also { context.logger.warn("Cannot find PsiElement corresponding to $fqName") }
+ private fun ContentNode.addSample(
+ contentPage: ContentPage,
+ platform: SourceSetData,
+ fqName: String,
+ analysis: Map<SourceSetData, EnvironmentAndFacade>
+ ): ContentNode {
+ val facade = analysis[platform]?.facade
+ ?: return this.also { context.logger.warn("Cannot resolve facade for platform ${platform.moduleName}") }
+ val psiElement = fqNameToPsiElement(facade, fqName)
+ ?: return this.also { context.logger.warn("Cannot find PsiElement corresponding to $fqName") }
val imports = processImports(psiElement) // TODO: Process somehow imports. Maybe just attach them at the top of each body
val body = processBody(psiElement)
val node = contentCode(contentPage.platforms(), contentPage.dri, body, "kotlin")
@@ -70,10 +75,14 @@ abstract class SamplesTransformer(val context: DokkaContext) : PageTransformer {
}
private fun ContentNode.dfs(fqName: String, node: ContentCode): ContentNode {
- return when(this) {
+ return when (this) {
is ContentHeader -> copy(children.map { it.dfs(fqName, node) })
is ContentDivergentGroup -> copy(children.map { it.dfs(fqName, node) } as List<ContentDivergentInstance>)
- is ContentDivergentInstance -> copy(before.let { it?.dfs(fqName, node) }, divergent.let { it.dfs(fqName, node) }, after.let { it?.dfs(fqName, node) })
+ is ContentDivergentInstance -> copy(
+ before.let { it?.dfs(fqName, node) },
+ divergent.dfs(fqName, node),
+ after.let { it?.dfs(fqName, node) }
+ )
is ContentCode -> copy(children.map { it.dfs(fqName, node) })
is ContentDRILink -> copy(children.map { it.dfs(fqName, node) })
is ContentResolvedLink -> copy(children.map { it.dfs(fqName, node) })
@@ -90,10 +99,14 @@ abstract class SamplesTransformer(val context: DokkaContext) : PageTransformer {
private fun fqNameToPsiElement(resolutionFacade: DokkaResolutionFacade, functionName: String): PsiElement? {
val packageName = functionName.takeWhile { it != '.' }
- val descriptor = resolutionFacade.resolveSession.getPackageFragment(FqName(packageName)) ?:
- return null.also { context.logger.warn("Cannot find descriptor for package $packageName") }
- val symbol = resolveKDocSampleLink(BindingContext.EMPTY, resolutionFacade, descriptor, functionName.split(".")).firstOrNull() ?:
- return null.also { context.logger.warn("Unresolved function $functionName in @sample") }
+ val descriptor = resolutionFacade.resolveSession.getPackageFragment(FqName(packageName))
+ ?: return null.also { context.logger.warn("Cannot find descriptor for package $packageName") }
+ val symbol = resolveKDocSampleLink(
+ BindingContext.EMPTY,
+ resolutionFacade,
+ descriptor,
+ functionName.split(".")
+ ).firstOrNull() ?: return null.also { context.logger.warn("Unresolved function $functionName in @sample") }
return DescriptorToSourceUtils.descriptorToDeclaration(symbol)
}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
index 8113d277..7603c80b 100644
--- a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
+++ b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
@@ -3,11 +3,11 @@ package org.jetbrains.dokka.base.transformers.pages.sourcelinks
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiDocumentManager
import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.analysis.DescriptorDocumentableSource
+import org.jetbrains.dokka.analysis.PsiDocumentableSource
import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
-import org.jetbrains.dokka.model.DescriptorDocumentableSource
import org.jetbrains.dokka.model.SourceSetData
import org.jetbrains.dokka.model.DocumentableSource
-import org.jetbrains.dokka.model.PsiDocumentableSource
import org.jetbrains.dokka.model.WithExpectActual
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.plugability.DokkaContext
diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
index 49d8ae0f..cefea4ec 100644
--- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -1,6 +1,6 @@
package org.jetbrains.dokka.base.translators.descriptors
-import org.jetbrains.dokka.analysis.DokkaResolutionFacade
+import org.jetbrains.dokka.analysis.*
import org.jetbrains.dokka.links.*
import org.jetbrains.dokka.links.Callable
import org.jetbrains.dokka.model.*
@@ -8,7 +8,7 @@ import org.jetbrains.dokka.model.Nullable
import org.jetbrains.dokka.model.TypeConstructor
import org.jetbrains.dokka.model.doc.*
import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.parsers.MarkdownParser
+import org.jetbrains.dokka.base.parsers.MarkdownParser
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator
import org.jetbrains.dokka.utilities.DokkaLogger
@@ -52,18 +52,19 @@ import org.jetbrains.kotlin.resolve.constants.EnumValue as ConstantsEnumValue
import org.jetbrains.kotlin.resolve.constants.KClassValue as ConstantsKtClassValue
import kotlin.IllegalArgumentException
-object DefaultDescriptorToDocumentableTranslator : SourceToDocumentableTranslator {
+class DefaultDescriptorToDocumentableTranslator(
+ private val kotlinAnalysis: KotlinAnalysis
+) : SourceToDocumentableTranslator {
override fun invoke(sourceSet: SourceSetData, context: DokkaContext): DModule {
-
- val (environment, facade) = context.platforms.getValue(sourceSet)
+ val (environment, facade) = kotlinAnalysis[sourceSet]
val packageFragments = environment.getSourceFiles().asSequence()
.map { it.packageFqName }
.distinct()
.mapNotNull { facade.resolveSession.getPackageFragment(it) }
.toList()
- return DokkaDescriptorVisitor(sourceSet, context.platforms.getValue(sourceSet).facade, context.logger).run {
+ return DokkaDescriptorVisitor(sourceSet, kotlinAnalysis[sourceSet].facade, context.logger).run {
packageFragments.mapNotNull { it.safeAs<PackageFragmentDescriptor>() }.map {
visitPackageFragmentDescriptor(
it,
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index a5117b09..e71d936a 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -7,6 +7,10 @@ import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiClassReferenceType
import com.intellij.psi.impl.source.PsiImmediateClassType
+import org.jetbrains.dokka.analysis.KotlinAnalysis
+import org.jetbrains.dokka.analysis.PsiDocumentableSource
+import org.jetbrains.dokka.analysis.from
+import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.links.nextTarget
import org.jetbrains.dokka.links.withClass
@@ -17,6 +21,7 @@ import org.jetbrains.dokka.model.doc.Param
import org.jetbrains.dokka.model.doc.Text
import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.DokkaPlugin
import org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator
import org.jetbrains.dokka.utilities.DokkaLogger
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
@@ -33,15 +38,17 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.io.File
-object DefaultPsiToDocumentableTranslator : SourceToDocumentableTranslator {
+class DefaultPsiToDocumentableTranslator(
+ private val kotlinAnalysis: KotlinAnalysis
+) : SourceToDocumentableTranslator {
- override fun invoke(sourceSetData: SourceSetData, context: DokkaContext): DModule {
+ override fun invoke(sourceSet: SourceSetData, context: DokkaContext): DModule {
fun isFileInSourceRoots(file: File): Boolean {
- return sourceSetData.sourceRoots.any { root -> file.path.startsWith(File(root.path).absolutePath) }
+ return sourceSet.sourceRoots.any { root -> file.path.startsWith(File(root.path).absolutePath) }
}
- val (environment, _) = context.platforms.getValue(sourceSetData)
+ val (environment, _) = kotlinAnalysis[sourceSet]
val sourceRoots = environment.configuration.get(CLIConfigurationKeys.CONTENT_ROOTS)
?.filterIsInstance<JavaSourceRoot>()
@@ -59,11 +66,11 @@ object DefaultPsiToDocumentableTranslator : SourceToDocumentableTranslator {
val docParser =
DokkaPsiParser(
- sourceSetData,
+ sourceSet,
context.logger
)
return DModule(
- sourceSetData.moduleName,
+ sourceSet.moduleName,
psiFiles.mapNotNull { it.safeAs<PsiJavaFile>() }.groupBy { it.packageName }.map { (packageName, psiFiles) ->
val dri = DRI(packageName = packageName)
DPackage(
@@ -76,12 +83,12 @@ object DefaultPsiToDocumentableTranslator : SourceToDocumentableTranslator {
emptyList(),
emptyMap(),
null,
- setOf(sourceSetData)
+ setOf(sourceSet)
)
},
emptyMap(),
null,
- setOf(sourceSetData)
+ setOf(sourceSet)
)
}
diff --git a/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt b/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt
index d8130974..7119ba68 100644
--- a/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt
@@ -6,6 +6,7 @@ import com.intellij.psi.impl.source.tree.JavaDocElementType
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.javadoc.*
import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.dokka.analysis.from
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.model.doc.*
import org.jetbrains.dokka.model.doc.Deprecated