aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorPaweł Marks <pmarks@virtuslab.com>2019-11-04 19:59:18 +0100
committerPaweł Marks <pmarks@virtuslab.com>2019-11-04 19:59:18 +0100
commit78ef161062eefe33633ad912817ad5c0e1555ed6 (patch)
tree1026a340548b8038038c8d40881869f098eafceb /core
parent93af17aba8858806f197a7e8b8383566a1debdeb (diff)
downloaddokka-78ef161062eefe33633ad912817ad5c0e1555ed6.tar.gz
dokka-78ef161062eefe33633ad912817ad5c0e1555ed6.tar.bz2
dokka-78ef161062eefe33633ad912817ad5c0e1555ed6.zip
Some parsing for markdown links
Diffstat (limited to 'core')
-rw-r--r--core/src/main/kotlin/DokkaGenerator.kt30
-rw-r--r--core/src/main/kotlin/links/DRI.kt17
-rw-r--r--core/src/main/kotlin/pages/MarkdownToContentConverter.kt82
-rw-r--r--core/src/main/kotlin/renderers/DefaultRenderer.kt3
-rw-r--r--core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt154
-rw-r--r--core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt2
-rw-r--r--core/src/test/kotlin/markdownParser/MarkdownParserTest.kt24
7 files changed, 189 insertions, 123 deletions
diff --git a/core/src/main/kotlin/DokkaGenerator.kt b/core/src/main/kotlin/DokkaGenerator.kt
index 5dd56624..2ac95812 100644
--- a/core/src/main/kotlin/DokkaGenerator.kt
+++ b/core/src/main/kotlin/DokkaGenerator.kt
@@ -3,6 +3,8 @@ package org.jetbrains.dokka
import org.jetbrains.dokka.Model.Module
import org.jetbrains.dokka.Utilities.pretty
import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.pages.MarkdownToContentConverter
+import org.jetbrains.dokka.pages.PageNode
import org.jetbrains.dokka.renderers.FileWriter
import org.jetbrains.dokka.renderers.HtmlRenderer
import org.jetbrains.dokka.resolvers.DefaultLocationProvider
@@ -35,24 +37,32 @@ class DokkaGenerator(
val environment = createCoreEnvironment()
val (facade, _) = createResolutionFacade(environment)
- environment.getSourceFiles().asSequence()
+ val markdownConverter = MarkdownToContentConverter(facade, logger)
+
+ val module = environment.getSourceFiles().asSequence()
.map { it.packageFqName }
.distinct()
.mapNotNull { facade.resolveSession.getPackageFragment(it) }
.map { DokkaDescriptorVisitor.visitPackageFragmentDescriptor(it, DRI.topLevel) }
.toList()
- .let { Pair(pass, Module(it)) }
- }.also { println("${pass.analysisPlatform}:\n${it.second.pretty()}\n\n") }
- }.let {
- DefaultDocumentationToPageTransformer().transform(it)
- }.also {
- HtmlRenderer(
- FileWriter(configuration.outputDir, ""),
- DefaultLocationProvider(it, configuration, ".${configuration.format}")
- ).render(it)
+ .let { Module(it) }
+ .also { println("${pass.analysisPlatform}:\n${it.pretty()}\n\n") }
+
+ DefaultDocumentationToPageTransformer(markdownConverter).transform(pass, module)
+ }
}
+ .merge()
+ .also {
+ HtmlRenderer(
+ FileWriter(configuration.outputDir, ""),
+ DefaultLocationProvider(it, configuration, ".${configuration.format}")
+ ).render(it)
+ }
}
}
+
+private fun Iterable<PageNode>.merge(): PageNode = first() // TODO: implement
+
private class DokkaMessageCollector(private val logger: DokkaLogger) : MessageCollector {
override fun clear() {
seenErrors = false
diff --git a/core/src/main/kotlin/links/DRI.kt b/core/src/main/kotlin/links/DRI.kt
index 7ab25444..fced7dde 100644
--- a/core/src/main/kotlin/links/DRI.kt
+++ b/core/src/main/kotlin/links/DRI.kt
@@ -1,7 +1,9 @@
package org.jetbrains.dokka.links
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.text.ParseException
/**
@@ -48,6 +50,19 @@ data class DRI(
throw ParseException(s, 0)
}
+ fun from(descriptor: DeclarationDescriptor) = descriptor.parentsWithSelf.run {
+ val callable = firstIsInstanceOrNull<CallableDescriptor>()
+ val params = callable?.let { listOfNotNull(it.extensionReceiverParameter) + it.valueParameters }.orEmpty()
+ DRI(
+ firstIsInstanceOrNull<PackageFragmentDescriptor>()?.fqName?.asString(),
+ filterIsInstance<ClassDescriptor>().toList().takeIf { it.isNotEmpty() }?.asReversed()
+ ?.joinToString(separator = ".") { it.name.asString() },
+ callable?.let { Callable.from(it) },
+ firstIsInstanceOrNull<ParameterDescriptor>()?.let { params.indexOf(it) },
+ null
+ )
+ }
+
val topLevel = DRI()
}
}
diff --git a/core/src/main/kotlin/pages/MarkdownToContentConverter.kt b/core/src/main/kotlin/pages/MarkdownToContentConverter.kt
index d541dc91..14b56226 100644
--- a/core/src/main/kotlin/pages/MarkdownToContentConverter.kt
+++ b/core/src/main/kotlin/pages/MarkdownToContentConverter.kt
@@ -2,13 +2,28 @@ package org.jetbrains.dokka.pages
import org.intellij.markdown.MarkdownElementTypes
import org.intellij.markdown.MarkdownTokenTypes
+import org.jetbrains.dokka.DokkaLogger
+import org.jetbrains.dokka.DokkaResolutionFacade
import org.jetbrains.dokka.MarkdownNode
-
-class MarkdownToContentConverter {
- fun buildContent(node: MarkdownNode, platforms: List<PlatformData>): List<ContentNode> {
+import org.jetbrains.dokka.Model.DocumentationNode
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.visit
+import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink
+
+class MarkdownToContentConverter(
+ private val resolutionFacade: DokkaResolutionFacade,
+ private val logger: DokkaLogger
+) {
+ fun buildContent(
+ node: MarkdownNode,
+ platforms: List<PlatformData>,
+ documentationNode: DocumentationNode<*>
+ ): List<ContentNode> {
// println(tree.toTestString())
- fun buildChildren(node: MarkdownNode) = node.children.flatMap { buildContent(it, platforms) }.coalesceText()
+ fun buildChildren(node: MarkdownNode) = node.children.flatMap {
+ buildContent(it, platforms, documentationNode)
+ }.coalesceText()
return when (node.type) {
MarkdownElementTypes.ATX_1 -> listOf(ContentHeader(buildChildren(node), 1, platforms))
@@ -47,7 +62,13 @@ class MarkdownToContentConverter {
val language = node.child(MarkdownTokenTypes.FENCE_LANG)?.text?.trim() ?: ""
listOf(ContentCode(buildChildren(node).toString(), language, platforms)) // TODO
}
- MarkdownElementTypes.PARAGRAPH -> listOf(ContentStyle(buildChildren(node), Style.Paragraph, platforms)) // TODO
+ MarkdownElementTypes.PARAGRAPH -> listOf(
+ ContentStyle(
+ buildChildren(node),
+ Style.Paragraph,
+ platforms
+ )
+ ) // TODO
MarkdownElementTypes.INLINE_LINK -> {
// val linkTextNode = node.child(MarkdownElementTypes.LINK_TEXT)
@@ -69,23 +90,27 @@ class MarkdownToContentConverter {
}
MarkdownElementTypes.SHORT_REFERENCE_LINK,
MarkdownElementTypes.FULL_REFERENCE_LINK -> {
-// val labelElement = node.child(MarkdownElementTypes.LINK_LABEL)
-// if (labelElement != null) {
-// val linkInfo = linkResolver.getLinkInfo(labelElement.text)
-// val labelText = labelElement.getLabelText()
-// val link =
-// linkInfo?.let { linkResolver.resolve(it.destination.toString()) } ?: linkResolver.resolve(
-// labelText
-// )
-// val linkText = node.child(MarkdownElementTypes.LINK_TEXT)
-// if (linkText != null) {
-// renderLinkTextTo(linkText, link, linkResolver)
-// } else {
-// link.append(ContentText(labelText))
-// }
-// parent.append(link)
-// }
- TODO()
+ val descriptor = documentationNode.descriptor
+ if (descriptor != null) {
+ val destinationNode = node.children.find { it.type == MarkdownElementTypes.LINK_DESTINATION }
+ ?: node.children.first { it.type == MarkdownElementTypes.LINK_LABEL }
+ val destination = destinationNode.children.find { it.type == MarkdownTokenTypes.TEXT }?.text
+ ?:destinationNode.text
+
+ resolveKDocLink(
+ resolutionFacade.resolveSession.bindingContext,
+ resolutionFacade,
+ descriptor,
+ null,
+ destination.split('.')
+ )
+ .firstOrNull()
+ ?.let { ContentLink(destination, DRI.from(it), platforms) }
+ .let(::listOfNotNull)
+ } else {
+ logger.error("Apparently descriptor for $documentationNode was needed in model")
+ emptyList()
+ }
}
MarkdownTokenTypes.WHITE_SPACE -> {
// Don't append first space if start of header (it is added during formatting later)
@@ -169,23 +194,28 @@ class MarkdownToContentConverter {
.sliceWhen { prev, next -> prev::class != next::class }
.flatMap { nodes ->
when (nodes.first()) {
- is ContentText -> listOf(ContentText(nodes.joinToString("") { (it as ContentText).text }, nodes.first().platforms))
+ is ContentText -> listOf(
+ ContentText(
+ nodes.joinToString("") { (it as ContentText).text },
+ nodes.first().platforms
+ )
+ )
else -> nodes
}
}
}
-fun <T> Collection<T>.sliceWhen(predicate: (before: T, after: T)->Boolean): Collection<Collection<T>> {
+fun <T> Collection<T>.sliceWhen(predicate: (before: T, after: T) -> Boolean): Collection<Collection<T>> {
val newCollection = mutableListOf<Collection<T>>()
var currentSlice = mutableListOf<T>()
for ((prev, next) in this.windowed(2, 1, false)) {
currentSlice.add(prev)
- if(predicate(prev, next)) {
+ if (predicate(prev, next)) {
newCollection.add(currentSlice)
currentSlice = mutableListOf<T>()
}
}
- if(this.isNotEmpty()) {
+ if (this.isNotEmpty()) {
currentSlice.add(this.last())
newCollection.add(currentSlice)
}
diff --git a/core/src/main/kotlin/renderers/DefaultRenderer.kt b/core/src/main/kotlin/renderers/DefaultRenderer.kt
index 5c6b3751..a2ca4131 100644
--- a/core/src/main/kotlin/renderers/DefaultRenderer.kt
+++ b/core/src/main/kotlin/renderers/DefaultRenderer.kt
@@ -19,7 +19,7 @@ abstract class DefaultRenderer(val fileWriter: FileWriter, val locationProvider:
protected open fun ContentNode.build(pageContext: PageNode): String = buildContentNode(this, pageContext)
- protected open fun buildContentNode(node: ContentNode, pageContext: PageNode) =
+ protected open fun buildContentNode(node: ContentNode, pageContext: PageNode): String =
when(node) {
is ContentText -> buildText(node.text)
is ContentComment -> buildComment(node.parts, pageContext)
@@ -29,6 +29,7 @@ abstract class DefaultRenderer(val fileWriter: FileWriter, val locationProvider:
is ContentLink -> buildLink(node.text, locationProvider.resolve(node.address, node.platforms, pageContext))
is ContentGroup -> buildGroup(node.children, pageContext)
is ContentHeader -> buildHeader(node.level, node.items, pageContext)
+ is ContentStyle -> node.items.joinToString(separator = "\n") { buildContentNode(it, pageContext) }
else -> ""
}
diff --git a/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt b/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt
index ce4691b6..54fd9a27 100644
--- a/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt
+++ b/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt
@@ -4,18 +4,22 @@ import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.Model.*
import org.jetbrains.dokka.Model.Function
import org.jetbrains.dokka.links.Callable
+import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.parseMarkdown
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
-class DefaultDocumentationToPageTransformer: DocumentationToPageTransformer {
- override fun transform(modules: Collection<Pair<DokkaConfiguration.PassConfiguration, Module>>): PageNode {
- val module = modules.first().second // TODO only one module for starters
- val platformData = modules.first().first.targets.map { PlatformData(it, modules.first().first.analysisPlatform) }
+class DefaultDocumentationToPageTransformer(
+ private val markdownConverter: MarkdownToContentConverter
+) : DocumentationToPageTransformer {
+ override fun transform(passConfiguration: DokkaConfiguration.PassConfiguration, module: Module): PageNode {
+ val platformData = passConfiguration.targets.map { PlatformData(it, passConfiguration.analysisPlatform) }
return PageBuilder(platformData).pageForModule(module)
}
- class PageBuilder(private val platformData: List<PlatformData>) {
+ private inner class PageBuilder(private val platformData: List<PlatformData>) {
fun pageForModule(m: Module) =
ModulePageNode("root", contentForModule(m), documentationNode = m).apply {
// TODO change name
@@ -44,62 +48,92 @@ class DefaultDocumentationToPageTransformer: DocumentationToPageTransformer {
else -> throw IllegalStateException("$m should not be present here")
}
- private fun contentForModule(m: Module) = listOf(
- ContentHeader(listOf(ContentText("root", platformData)), 1, platformData),
- ContentBlock("Packages", m.packages.map { ContentLink(it.name, it.dri, platformData) }, platformData),
- ContentText("Index", platformData),
- ContentText("Link to allpage here", platformData)
- )
-
- private fun contentForPackage(p: Package) = listOf(
- ContentHeader(listOf(ContentText("Package ${p.name}", platformData)), 1, platformData),
- ContentBlock("Types", p.classes.map { ContentGroup(
- listOf(
- ContentLink(it.name, it.dri, platformData),
- ContentText(it.briefDocstring, platformData),
- ContentText("signature for class", platformData)
- ), platformData)
- }, platformData),
- ContentBlock("Functions", p.functions.map { ContentGroup(
- listOf(
- ContentLink(it.name, it.dri, platformData),
- ContentText(it.briefDocstring, platformData),
- ContentText("signature for function", platformData)
- ), platformData)
- }, platformData)
- )
-
- private fun contentForClass(c: Class) = listOf(
- ContentHeader(listOf(ContentText(c.name, platformData)), 1, platformData),
- ContentText(c.rawDocstring, platformData),
- ContentBlock("Constructors", c.descriptor.constructors.map { ContentGroup(
- listOf(
- ContentLink(it.fqNameSafe.asString(), c.dri.copy(callable = Callable(it.fqNameSafe.asString() /* TODO: identifier for filename here */, "", "", it.valueParameters.map {it.fqNameSafe.asString()})), platformData),
- ContentText("message to Pawel from the future: you forgot about extracting constructors, didn't you?", platformData),
- ContentText("signature for constructor", platformData)
- ), platformData)
- }, platformData),
- ContentBlock("Functions", c.functions.map { ContentGroup(
- listOf(
- ContentLink(it.name, it.dri, platformData),
- ContentText(it.briefDocstring, platformData),
- ContentText("signature for function", platformData)
- ), platformData)
- }, platformData)
- )
-
- private fun contentForFunction(f: Function) = listOf(
- ContentHeader(listOf(ContentText(f.name, platformData)), 1, platformData),
- ContentText("signature for function", platformData),
- ContentText(f.rawDocstring, platformData),
- ContentBlock("Parameters", f.parameters.map { ContentGroup(
- listOf(
- ContentText(it.name ?: "?", platformData),
- ContentText(it.rawDocstring, platformData)
- ), platformData)
- }, platformData)
- )
+ private fun contentForModule(m: Module) = content(platformData) {
+ header(1) { text("root") }
+ block("Packages", m.packages) { link(it.name, it.dri) }
+ text("Index")
+ text("Link to allpage here")
+ }
+
+ private fun contentForPackage(p: Package) = content(platformData) {
+ header(1) { text("Package ${p.name}") }
+ block("Types", p.classes) {
+ link(it.name, it.dri)
+ text(it.briefDocstring)
+ text("signature for class")
+ }
+ block("Functions", p.functions) {
+ link(it.name, it.dri)
+ text(it.briefDocstring)
+ text("signature for function")
+ }
+ }
+
+ private fun contentForClass(c: Class) = content(platformData) {
+ header(1) { text(c.name) }
+ markdown(c.rawDocstring, c)
+ text("PING PAWEL TO ADD CONSTRUCTORS TO MODEL!!!")
+ block("Constructors", emptyList<Function>() /* TODO: CONSTRUCTORS*/) {
+ link(it.name, it.dri)
+ text(it.briefDocstring)
+ text("message to Pawel from the future: you forgot about extracting constructors, didn't you?")
+ }
+ block("Functions", c.functions) {
+ link(it.name, it.dri)
+ text(it.briefDocstring)
+ text("signature for function")
+ }
+ }
+
+ private fun contentForFunction(f: Function) = content(platformData) {
+ header(1) { text(f.name) }
+ text("signature for function")
+ markdown(f.rawDocstring, f)
+ block("Parameters", f.children) {
+ group {
+ text(it.name ?: "RECEIVER")
+ markdown(it.rawDocstring, it)
+ }
+ }
+ }
+ }
+
+ // TODO: Make some public builder or merge it with page builder, whateva
+ private inner class ContentBuilder(private val platformData: List<PlatformData>) {
+ private val contents = mutableListOf<ContentNode>()
+
+ fun build() = contents.toList()
+
+ fun header(level: Int, block: ContentBuilder.() -> Unit) {
+ contents += ContentHeader(content(block), level, platformData)
+ }
+
+ fun text(text: String) {
+ contents += ContentText(text, platformData)
+ }
+
+ fun <T> block(name: String, elements: Iterable<T>, block: ContentBuilder.(T) -> Unit) {
+ contents += ContentBlock(name, content { elements.forEach { block(it) } }, platformData)
+ }
+
+ fun group(block: ContentBuilder.() -> Unit) {
+ contents += ContentGroup(content(block), platformData)
+ }
+
+ fun link(text: String, address: DRI) {
+ contents += ContentLink(text, address, platformData)
+ }
+
+ fun markdown(raw: String, node: DocumentationNode<*>) {
+ contents += markdownConverter.buildContent(parseMarkdown(raw), platformData, node)
+ }
+
+ private fun content(block: ContentBuilder.() -> Unit): List<ContentNode> = content(platformData, block)
}
+
+ private fun content(platformData: List<PlatformData>, block: ContentBuilder.() -> Unit): List<ContentNode> =
+ ContentBuilder(platformData).apply(block).build()
+
}
fun DocumentationNode<*>.identifier(platformData: List<PlatformData>): List<ContentNode> {
diff --git a/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt b/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt
index f75f8d8e..c7859f73 100644
--- a/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt
+++ b/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt
@@ -6,5 +6,5 @@ import org.jetbrains.dokka.Model.Module
import org.jetbrains.dokka.pages.PageNode
interface DocumentationToPageTransformer {
- fun transform (modules: Collection<Pair<DokkaConfiguration.PassConfiguration, Module>>): PageNode // TODO refactor this
+ fun transform(passConfiguration: DokkaConfiguration.PassConfiguration, module: Module): PageNode // TODO refactor this... some more?
} \ No newline at end of file
diff --git a/core/src/test/kotlin/markdownParser/MarkdownParserTest.kt b/core/src/test/kotlin/markdownParser/MarkdownParserTest.kt
deleted file mode 100644
index 523819b4..00000000
--- a/core/src/test/kotlin/markdownParser/MarkdownParserTest.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.jetbrains.dokka.tests.markdownParser
-
-import org.jetbrains.dokka.pages.MarkdownToContentConverter
-import org.jetbrains.dokka.parseMarkdown
-import org.junit.Assert.assertTrue
-import org.junit.Test
-
-
-class MarkdownParserTest {
-
- @Test fun basicTest() {
- val markdown = """
- # Header 1 test
- this is some text
- more text
- let's say there are some parentheses, like ( and )
- """.trimIndent()
- val node = parseMarkdown(markdown)
- val content = MarkdownToContentConverter().buildContent(node, emptyList())
- assertTrue(content.isNotEmpty())
- }
-
-}
-