aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/kotlin')
-rw-r--r--core/src/main/kotlin/CoreExtensions.kt35
-rw-r--r--core/src/main/kotlin/DokkaGenerator.kt183
-rw-r--r--core/src/main/kotlin/Model/DocumentationNode.kt2
-rw-r--r--core/src/main/kotlin/Model/transformers/DocumentationNodeTransformer.kt8
-rw-r--r--core/src/main/kotlin/pages/DefaultMarkdownToContentConverter.kt229
-rw-r--r--core/src/main/kotlin/pages/MarkdownToContentConverter.kt219
-rw-r--r--core/src/main/kotlin/pages/transformers/PageNodeTransformer.kt7
-rw-r--r--core/src/main/kotlin/plugability/DefaultExtensions.kt25
-rw-r--r--core/src/main/kotlin/plugability/DokkaContext.kt61
-rw-r--r--core/src/main/kotlin/plugability/extensions.kt2
-rw-r--r--core/src/main/kotlin/renderers/DefaultRenderer.kt7
-rw-r--r--core/src/main/kotlin/renderers/HtmlRenderer.kt7
-rw-r--r--core/src/main/kotlin/renderers/Renderer.kt1
-rw-r--r--core/src/main/kotlin/resolvers/DefaultLocationProvider.kt11
-rw-r--r--core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt20
-rw-r--r--core/src/main/kotlin/transformers/PageNodeTransformer.kt8
-rw-r--r--core/src/main/kotlin/transformers/descriptors/DefaultDescriptorToDocumentationTranslator.kt (renamed from core/src/main/kotlin/DokkaDescriptorVisitor.kt)21
-rw-r--r--core/src/main/kotlin/transformers/descriptors/DescriptorToDocumentationTranslator.kt15
-rw-r--r--core/src/main/kotlin/transformers/documentation/DefaultDocumentationNodeMerger.kt (renamed from core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt)24
-rw-r--r--core/src/main/kotlin/transformers/documentation/DefaultDocumentationToPageTranslator.kt24
-rw-r--r--core/src/main/kotlin/transformers/documentation/DocumentationNodeMerger.kt8
-rw-r--r--core/src/main/kotlin/transformers/documentation/DocumentationNodeTransformer.kt8
-rw-r--r--core/src/main/kotlin/transformers/documentation/DocumentationToPageTranslator.kt (renamed from core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt)7
-rw-r--r--core/src/main/kotlin/transformers/pages/PageNodeTransformer.kt8
24 files changed, 580 insertions, 360 deletions
diff --git a/core/src/main/kotlin/CoreExtensions.kt b/core/src/main/kotlin/CoreExtensions.kt
index 6579cab2..f56cd854 100644
--- a/core/src/main/kotlin/CoreExtensions.kt
+++ b/core/src/main/kotlin/CoreExtensions.kt
@@ -1,14 +1,37 @@
package org.jetbrains.dokka
-import org.jetbrains.dokka.Model.transformers.DocumentationNodeTransformer
+import org.jetbrains.dokka.pages.MarkdownToContentConverter
+import org.jetbrains.dokka.pages.PageNode
+import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.ExtensionPoint
+import org.jetbrains.dokka.renderers.FileWriter
import org.jetbrains.dokka.renderers.Renderer
import org.jetbrains.dokka.resolvers.LocationProvider
-import org.jetbrains.dokka.transformers.PageNodeTransformer
+import org.jetbrains.dokka.transformers.descriptors.DescriptorToDocumentationTranslator
+import org.jetbrains.dokka.transformers.documentation.DocumentationNodeMerger
+import org.jetbrains.dokka.transformers.documentation.DocumentationNodeTransformer
+import org.jetbrains.dokka.transformers.documentation.DocumentationToPageTranslator
+import org.jetbrains.dokka.transformers.pages.PageNodeTransformer
+import kotlin.reflect.KProperty
+
+/**
+ * Extension points declared by dokka core.
+ * Default values are stored in [org.jetbrains.dokka.plugability.DefaultExtensions]
+ */
object CoreExtensions {
- val nodeTransformer = ExtensionPoint<DocumentationNodeTransformer>(this::class.qualifiedName!!, "nodeTransformer")
- val pageTransformer = ExtensionPoint<PageNodeTransformer>(this::class.qualifiedName!!, "pageTransformer")
- val renderer = ExtensionPoint<Renderer>(this::class.qualifiedName!!, "renderer")
- val locationProvider = ExtensionPoint<LocationProvider>(this::class.qualifiedName!!, "locationProvider")
+ val descriptorToDocumentationTranslator by coreExtension<DescriptorToDocumentationTranslator>()
+ val documentationMerger by coreExtension<DocumentationNodeMerger>()
+ val documentationTransformer by coreExtension<DocumentationNodeTransformer>()
+ val markdownToContentConverterFactory by coreExtension<(DokkaContext) -> MarkdownToContentConverter>()
+ val documentationToPageTranslator by coreExtension<DocumentationToPageTranslator>()
+ val pageTransformer by coreExtension<PageNodeTransformer>()
+ val renderer by coreExtension<(FileWriter, LocationProvider, DokkaContext) -> Renderer>()
+ val locationProvider by coreExtension<(root: PageNode, DokkaConfiguration, DokkaContext) -> LocationProvider>()
+ val fileExtension by coreExtension<String>()
+
+ private fun <T: Any> coreExtension() = object {
+ operator fun provideDelegate(thisRef: CoreExtensions, property: KProperty<*>): Lazy<ExtensionPoint<T>> =
+ lazy { ExtensionPoint<T>(thisRef::class.qualifiedName!!, property.name) }
+ }
} \ No newline at end of file
diff --git a/core/src/main/kotlin/DokkaGenerator.kt b/core/src/main/kotlin/DokkaGenerator.kt
index 05eb3054..b6bf7a73 100644
--- a/core/src/main/kotlin/DokkaGenerator.kt
+++ b/core/src/main/kotlin/DokkaGenerator.kt
@@ -1,20 +1,24 @@
package org.jetbrains.dokka
import org.jetbrains.dokka.Model.Module
-import org.jetbrains.dokka.Model.transformers.DocumentationNodesMerger
import org.jetbrains.dokka.Utilities.pretty
import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.pages.MarkdownToContentConverter
+import org.jetbrains.dokka.pages.DefaultMarkdownToContentConverter
import org.jetbrains.dokka.pages.PlatformData
import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.single
import org.jetbrains.dokka.renderers.FileWriter
import org.jetbrains.dokka.renderers.HtmlRenderer
import org.jetbrains.dokka.resolvers.DefaultLocationProvider
-import org.jetbrains.dokka.transformers.DefaultDocumentationToPageTransformer
+import org.jetbrains.dokka.resolvers.LocationProvider
+import org.jetbrains.dokka.transformers.documentation.DefaultDocumentationToPageTranslator
+import org.jetbrains.dokka.transformers.descriptors.DokkaDescriptorVisitor
+import org.jetbrains.dokka.transformers.documentation.DefaultDocumentationNodeMerger
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
+import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
@@ -22,56 +26,131 @@ class DokkaGenerator(
private val configuration: DokkaConfiguration,
private val logger: DokkaLogger
) {
- fun generate(): Unit {
+
+ fun generate() {
+ logger.debug("Setting up analysis environments")
+ val platforms: Map<PlatformData, EnvironmentAndFacade> = configuration.passesConfigurations.map {
+ PlatformData(it.analysisPlatform, it.targets) to createEnvironmentAndFacade(it)
+ }.toMap()
logger.debug("Initializing plugins")
- val context = DokkaContext.create(configuration.pluginsClasspath, logger)
-
- configuration.passesConfigurations.map { pass ->
- AnalysisEnvironment(DokkaMessageCollector(logger), pass.analysisPlatform).run {
- if (analysisPlatform == Platform.jvm) {
- addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
- }
- for (element in pass.classpath) {
- addClasspath(File(element))
- }
-
- addSources(pass.sourceRoots.map { it.path })
-
- loadLanguageVersionSettings(pass.languageVersion, pass.apiVersion)
-
- val environment = createCoreEnvironment()
- val (facade, _) = createResolutionFacade(environment)
-
- environment.getSourceFiles().asSequence()
- .map { it.packageFqName }
- .distinct()
- .mapNotNull { facade.resolveSession.getPackageFragment(it) }
- .map {
- DokkaDescriptorVisitor(
- PlatformData(pass.analysisPlatform, pass.targets),
- facade
- ).visitPackageFragmentDescriptor(
- it,
- DRI.topLevel
- )
- }
- .toList()
- .let { Module(it) }
- .let { DocumentationNodesMerger(it) }
- .also { println("${pass.analysisPlatform}:\n${it.pretty()}\n\n") }
+ val context = DokkaContext.create(configuration.pluginsClasspath, logger, platforms)
+
+ logger.debug("Creating documentation models")
+ val modulesFromPlatforms = platforms.map { (pdata, _) -> translateDescriptors(pdata, context) }
+
+ logger.debug("Merging documentation models")
+ val documentationModel = context.single(CoreExtensions.documentationMerger)
+ .invoke(modulesFromPlatforms, context)
+
+ logger.debug("Transforming documentation model")
+ val transformedDocumentation = context[CoreExtensions.documentationTransformer]
+ .fold(documentationModel) { acc, t -> t(acc, context) }
+
+ logger.debug("Creating pages")
+ val pages = context.single(CoreExtensions.documentationToPageTranslator)
+ .invoke(transformedDocumentation, context)
+
+ logger.debug("Transforming pages")
+ val transformedPages = context[CoreExtensions.pageTransformer]
+ .fold(pages) { acc, t -> t(acc, context) }
+
+ logger.debug("Rendering")
+ val fileWriter = FileWriter(configuration.outputDir, "")
+ val locationProvider = context.single(CoreExtensions.locationProvider)
+ .invoke(transformedPages, configuration, context)
+ val renderer = context.single(CoreExtensions.renderer)
+ .invoke(fileWriter, locationProvider, context)
+
+ renderer.render(transformedPages)
+ }
+
+// fun generate(int: Int) {
+//
+// logger.debug("Initializing plugins")
+// val context = DokkaContext.create(configuration.pluginsClasspath, logger, platforms)
+//
+// configuration.passesConfigurations.map { pass ->
+// AnalysisEnvironment(DokkaMessageCollector(logger), pass.analysisPlatform).run {
+// if (analysisPlatform == Platform.jvm) {
+// addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
+// }
+// for (element in pass.classpath) {
+// addClasspath(File(element))
+// }
+//
+// addSources(pass.sourceRoots.map { it.path })
+//
+// loadLanguageVersionSettings(pass.languageVersion, pass.apiVersion)
+//
+// val environment = createCoreEnvironment()
+// val (facade, _) = createResolutionFacade(environment)
+//
+// environment.getSourceFiles().asSequence()
+// .map { it.packageFqName }
+// .distinct()
+// .mapNotNull { facade.resolveSession.getPackageFragment(it) }
+// .map {
+// DokkaDescriptorVisitor(
+// PlatformData(
+// pass.analysisPlatform,
+// pass.targets
+// ), facade
+// )
+// .visitPackageFragmentDescriptor(it, DRI.topLevel)
+// }
+// .toList()
+// .let { Module(it) }
+// .let { DefaultDocumentationNodeMerger(it) }
+// .also { println("${pass.analysisPlatform}:\n${it.pretty()}\n\n") }
+// }
+// }.let {
+// val markdownConverter = DefaultMarkdownToContentConverter(logger)
+// DefaultDocumentationToPageTranslator(
+// markdownConverter,
+// logger
+// ).transform(
+// DefaultDocumentationNodeMerger(
+// it
+// )
+// )
+// }.let {
+// context[CoreExtensions.pageTransformer].fold(it) { pn, t -> t(pn, context) }
+// }.also {
+// HtmlRenderer(
+// FileWriter(configuration.outputDir, ""),
+// DefaultLocationProvider(it, configuration, ".${configuration.format}")
+// ).render(it)
+// }
+// }
+
+ private fun createEnvironmentAndFacade(pass: DokkaConfiguration.PassConfiguration): EnvironmentAndFacade =
+ AnalysisEnvironment(DokkaMessageCollector(logger), pass.analysisPlatform).run {
+ if (analysisPlatform == Platform.jvm) {
+ addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
}
- }.let {
- val markdownConverter = MarkdownToContentConverter(logger)
- DefaultDocumentationToPageTransformer(markdownConverter, logger).transform(DocumentationNodesMerger(it))
- }.let {
- context[CoreExtensions.pageTransformer].fold(it) { pn, t -> t.action.invoke(pn, context) }
- }.also {
- HtmlRenderer(
- FileWriter(configuration.outputDir, ""),
- DefaultLocationProvider(it, configuration, ".${configuration.format}")
- ).render(it)
+ pass.classpath.forEach { addClasspath(File(it)) }
+
+ addSources(pass.sourceRoots.map { it.path })
+
+ loadLanguageVersionSettings(pass.languageVersion, pass.apiVersion)
+
+ val environment = createCoreEnvironment()
+ val (facade, _) = createResolutionFacade(environment)
+ EnvironmentAndFacade(environment, facade)
}
+
+ private fun translateDescriptors(platformData: PlatformData, context: DokkaContext): Module {
+ val (environment, facade) = context.platforms.getValue(platformData)
+
+ val packageFragments = environment.getSourceFiles().asSequence()
+ .map { it.packageFqName }
+ .distinct()
+ .mapNotNull { facade.resolveSession.getPackageFragment(it) }
+ .toList()
+
+ return context.single(CoreExtensions.descriptorToDocumentationTranslator)
+ .invoke(packageFragments, platformData, context)
}
private class DokkaMessageCollector(private val logger: DokkaLogger) : MessageCollector {
@@ -90,4 +169,10 @@ class DokkaGenerator(
override fun hasErrors() = seenErrors
}
+}
+
+// It is not data class due to ill-defined equals
+class EnvironmentAndFacade(val environment: KotlinCoreEnvironment, val facade: DokkaResolutionFacade) {
+ operator fun component1() = environment
+ operator fun component2() = facade
} \ No newline at end of file
diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt
index 0adb37b5..b1d4be55 100644
--- a/core/src/main/kotlin/Model/DocumentationNode.kt
+++ b/core/src/main/kotlin/Model/DocumentationNode.kt
@@ -1,6 +1,6 @@
package org.jetbrains.dokka.Model
-import org.jetbrains.dokka.KotlinTypeWrapper
+import org.jetbrains.dokka.transformers.descriptors.KotlinTypeWrapper
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.pages.PlatformData
import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
diff --git a/core/src/main/kotlin/Model/transformers/DocumentationNodeTransformer.kt b/core/src/main/kotlin/Model/transformers/DocumentationNodeTransformer.kt
deleted file mode 100644
index 318d20b3..00000000
--- a/core/src/main/kotlin/Model/transformers/DocumentationNodeTransformer.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.jetbrains.dokka.Model.transformers
-
-import org.jetbrains.dokka.Model.Module
-
-interface DocumentationNodeTransformer {
- operator fun invoke(original: Module): Module
- operator fun invoke(modules: Collection<Module>): Module
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/pages/DefaultMarkdownToContentConverter.kt b/core/src/main/kotlin/pages/DefaultMarkdownToContentConverter.kt
new file mode 100644
index 00000000..72b5ead2
--- /dev/null
+++ b/core/src/main/kotlin/pages/DefaultMarkdownToContentConverter.kt
@@ -0,0 +1,229 @@
+package org.jetbrains.dokka.pages
+
+import org.intellij.markdown.MarkdownElementTypes
+import org.intellij.markdown.MarkdownTokenTypes
+import org.jetbrains.dokka.MarkdownNode
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.plugability.DokkaContext
+
+class DefaultMarkdownToContentConverter(
+ private val context: DokkaContext
+) : MarkdownToContentConverter {
+ override fun buildContent(
+ node: MarkdownNode,
+ dci: DCI,
+ platforms: Set<PlatformData>,
+ links: Map<String, DRI>,
+ styles: Set<Style>,
+ extras: Set<Extra>
+
+ ): List<ContentNode> {
+// println(tree.toTestString())
+
+ fun buildChildren(node: MarkdownNode, newStyles: Set<Style> = emptySet(), newExtras: Set<Extra> = emptySet()) =
+ node.children.flatMap {
+ buildContent(it, dci, platforms, links, styles + newStyles, extras + newExtras)
+ }.coalesceText(platforms, styles + newStyles, extras + newExtras)
+
+ fun buildHeader(level: Int) =
+ ContentHeader(buildChildren(node), level, dci, platforms, styles)
+
+ return when (node.type) {
+ MarkdownElementTypes.ATX_1 -> listOf(buildHeader(1))
+ MarkdownElementTypes.ATX_2 -> listOf(buildHeader(2))
+ MarkdownElementTypes.ATX_3 -> listOf(buildHeader(3))
+ MarkdownElementTypes.ATX_4 -> listOf(buildHeader(4))
+ MarkdownElementTypes.ATX_5 -> listOf(buildHeader(5))
+ MarkdownElementTypes.ATX_6 -> listOf(buildHeader(6))
+ MarkdownElementTypes.UNORDERED_LIST -> listOf(
+ ContentList(
+ buildChildren(node),
+ false,
+ dci,
+ platforms,
+ styles,
+ extras
+ )
+ )
+ MarkdownElementTypes.ORDERED_LIST -> listOf(
+ ContentList(
+ buildChildren(node),
+ true,
+ dci,
+ platforms,
+ styles,
+ extras
+ )
+ )
+ MarkdownElementTypes.LIST_ITEM -> TODO()
+ MarkdownElementTypes.STRONG,
+ MarkdownTokenTypes.EMPH,
+ MarkdownElementTypes.EMPH ->
+ buildChildren(node, setOf(TextStyle.Strong))
+ // TODO
+ MarkdownElementTypes.CODE_SPAN -> TODO()
+// val startDelimiter = node.child(MarkdownTokenTypes.BACKTICK)?.text
+// if (startDelimiter != null) {
+// val text = node.text.substring(startDelimiter.length).removeSuffix(startDelimiter)
+// val codeSpan = ContentCode().apply { append(ContentText(text)) }
+// parent.append(codeSpan)
+// }
+
+ MarkdownElementTypes.CODE_BLOCK,
+ MarkdownElementTypes.CODE_FENCE -> {
+ val language = node.child(MarkdownTokenTypes.FENCE_LANG)?.text?.trim() ?: ""
+ listOf(ContentCode(buildChildren(node), language, dci, platforms, styles, extras)) // TODO
+ }
+ MarkdownElementTypes.PARAGRAPH -> buildChildren(node, newStyles = setOf(TextStyle.Paragraph))
+
+ MarkdownElementTypes.INLINE_LINK -> {
+// val linkTextNode = node.child(MarkdownElementTypes.LINK_TEXT)
+// val destination = node.child(MarkdownElementTypes.LINK_DESTINATION)
+// if (linkTextNode != null) {
+// if (destination != null) {
+// val link = ContentExternalLink(destination.text)
+// renderLinkTextTo(linkTextNode, link, linkResolver)
+// parent.append(link)
+// } else {
+// val link = ContentExternalLink(linkTextNode.getLabelText())
+// renderLinkTextTo(linkTextNode, link, linkResolver)
+// parent.append(link)
+// }
+// }
+ //TODO: Linking!!!
+// ContentLink()
+ TODO()
+ }
+ MarkdownElementTypes.SHORT_REFERENCE_LINK,
+ MarkdownElementTypes.FULL_REFERENCE_LINK -> {
+ 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
+ links[destination]?.let { dri ->
+ listOf(
+ ContentResolvedLink(
+ buildChildren(node),
+ destination,
+ DCI(dri, ContentKind.Symbol),
+ platforms,
+ styles,
+ extras
+ )
+ )
+ } ?: let {
+ context.logger.error("Apparently there is no link resolved for $destination")
+ emptyList<ContentNode>()
+ }
+ }
+ MarkdownTokenTypes.WHITE_SPACE -> {
+ // Don't append first space if start of header (it is added during formatting later)
+ // v
+ // #### Some Heading
+// if (nodeStack.peek() !is ContentHeading || node.parent?.children?.first() != node) {
+// parent.append(ContentText(node.text))
+// }
+ listOf(ContentText(" ", dci, platforms, styles, extras))
+ }
+ MarkdownTokenTypes.EOL -> {
+// if ((keepEol(nodeStack.peek()) && node.parent?.children?.last() != node) ||
+// // Keep extra blank lines when processing lists (affects Markdown formatting)
+// (processingList(nodeStack.peek()) && node.previous?.type == MarkdownTokenTypes.EOL)) {
+// parent.append(ContentText(node.text))
+// }
+ listOf(ContentText(" ", dci, platforms, styles, extras))
+ }
+
+ MarkdownTokenTypes.CODE_LINE -> {
+ listOf(ContentText(node.text, dci, platforms, styles, extras)) // TODO check
+// if (parent is ContentBlockCode) {
+// parent.append(content)
+// } else {
+// parent.append(ContentBlockCode().apply { append(content) })
+// }
+ }
+
+ MarkdownTokenTypes.TEXT ->
+// fun createEntityOrText(text: String): ContentNode {
+// if (text == "&amp;" || text == "&quot;" || text == "&lt;" || text == "&gt;") {
+// return ContentEntity(text)
+// }
+// if (text == "&") {
+// return ContentEntity("&amp;")
+// }
+// val decodedText = EntityConverter.replaceEntities(text, true, true)
+// if (decodedText != text) {
+// return ContentEntity(text)
+// }
+// return ContentText(text)
+// }
+//
+// parent.append(createEntityOrText(node.text))
+ listOf(ContentText(node.text, dci, platforms, styles, extras)) // TODO
+
+ MarkdownTokenTypes.COLON,
+ MarkdownTokenTypes.SINGLE_QUOTE,
+ MarkdownTokenTypes.DOUBLE_QUOTE,
+ MarkdownTokenTypes.LT,
+ MarkdownTokenTypes.GT,
+ MarkdownTokenTypes.LPAREN,
+ MarkdownTokenTypes.RPAREN,
+ MarkdownTokenTypes.LBRACKET,
+ MarkdownTokenTypes.RBRACKET,
+ MarkdownTokenTypes.EXCLAMATION_MARK,
+ MarkdownTokenTypes.BACKTICK,
+ MarkdownTokenTypes.CODE_FENCE_CONTENT -> {
+ listOf(ContentText(node.text, dci, platforms, styles, extras))
+ }
+
+ MarkdownElementTypes.LINK_DEFINITION -> TODO()
+
+ MarkdownTokenTypes.EMAIL_AUTOLINK ->
+ listOf(
+ ContentResolvedLink(
+ listOf(ContentText(node.text, dci, platforms, styles, extras)),
+ "mailto:${node.text}",
+ dci, platforms, styles, extras
+ )
+ )
+
+ else -> buildChildren(node)
+ }
+ }
+
+ private fun Collection<ContentNode>.coalesceText(
+ platforms: Set<PlatformData>,
+ styles: Set<Style>,
+ extras: Set<Extra>
+ ) =
+ this
+ .sliceWhen { prev, next -> prev::class != next::class }
+ .flatMap { nodes ->
+ when (nodes.first()) {
+ is ContentText -> listOf(
+ ContentText(
+ nodes.joinToString("") { (it as ContentText).text },
+ nodes.first().dci, platforms, styles, extras
+ )
+ )
+ else -> nodes
+ }
+ }
+}
+
+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)) {
+ newCollection.add(currentSlice)
+ currentSlice = mutableListOf<T>()
+ }
+ }
+ if (this.isNotEmpty()) {
+ currentSlice.add(this.last())
+ newCollection.add(currentSlice)
+ }
+ return newCollection
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/pages/MarkdownToContentConverter.kt b/core/src/main/kotlin/pages/MarkdownToContentConverter.kt
index 8caddeb0..fe4736b7 100644
--- a/core/src/main/kotlin/pages/MarkdownToContentConverter.kt
+++ b/core/src/main/kotlin/pages/MarkdownToContentConverter.kt
@@ -1,14 +1,10 @@
package org.jetbrains.dokka.pages
-import org.intellij.markdown.MarkdownElementTypes
-import org.intellij.markdown.MarkdownTokenTypes
-import org.jetbrains.dokka.DokkaLogger
import org.jetbrains.dokka.MarkdownNode
import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.plugability.DokkaContext
-class MarkdownToContentConverter(
- private val logger: DokkaLogger
-) {
+interface MarkdownToContentConverter {
fun buildContent(
node: MarkdownNode,
dci: DCI,
@@ -16,214 +12,5 @@ class MarkdownToContentConverter(
links: Map<String, DRI> = emptyMap(),
styles: Set<Style> = emptySet(),
extras: Set<Extra> = emptySet()
-
- ): List<ContentNode> {
-// println(tree.toTestString())
-
- fun buildChildren(node: MarkdownNode, newStyles: Set<Style> = emptySet(), newExtras: Set<Extra> = emptySet()) =
- node.children.flatMap {
- buildContent(it, dci, platforms, links, styles + newStyles, extras + newExtras)
- }.coalesceText(platforms, styles + newStyles, extras + newExtras)
-
- fun buildHeader(level: Int) =
- ContentHeader(buildChildren(node), level, dci, platforms, styles)
-
- return when (node.type) {
- MarkdownElementTypes.ATX_1 -> listOf(buildHeader(1))
- MarkdownElementTypes.ATX_2 -> listOf(buildHeader(2))
- MarkdownElementTypes.ATX_3 -> listOf(buildHeader(3))
- MarkdownElementTypes.ATX_4 -> listOf(buildHeader(4))
- MarkdownElementTypes.ATX_5 -> listOf(buildHeader(5))
- MarkdownElementTypes.ATX_6 -> listOf(buildHeader(6))
- MarkdownElementTypes.UNORDERED_LIST -> listOf(
- ContentList(
- buildChildren(node),
- false,
- dci,
- platforms,
- styles,
- extras
- )
- )
- MarkdownElementTypes.ORDERED_LIST -> listOf(
- ContentList(
- buildChildren(node),
- true,
- dci,
- platforms,
- styles,
- extras
- )
- )
- MarkdownElementTypes.LIST_ITEM -> TODO()
- MarkdownElementTypes.STRONG,
- MarkdownTokenTypes.EMPH,
- MarkdownElementTypes.EMPH ->
- buildChildren(node, setOf(TextStyle.Strong))
- // TODO
- MarkdownElementTypes.CODE_SPAN -> TODO()
-// val startDelimiter = node.child(MarkdownTokenTypes.BACKTICK)?.text
-// if (startDelimiter != null) {
-// val text = node.text.substring(startDelimiter.length).removeSuffix(startDelimiter)
-// val codeSpan = ContentCode().apply { append(ContentText(text)) }
-// parent.append(codeSpan)
-// }
-
- MarkdownElementTypes.CODE_BLOCK,
- MarkdownElementTypes.CODE_FENCE -> {
- val language = node.child(MarkdownTokenTypes.FENCE_LANG)?.text?.trim() ?: ""
- listOf(ContentCode(buildChildren(node), language, dci, platforms, styles, extras)) // TODO
- }
- MarkdownElementTypes.PARAGRAPH -> buildChildren(node, newStyles = setOf(TextStyle.Paragraph))
-
- MarkdownElementTypes.INLINE_LINK -> {
-// val linkTextNode = node.child(MarkdownElementTypes.LINK_TEXT)
-// val destination = node.child(MarkdownElementTypes.LINK_DESTINATION)
-// if (linkTextNode != null) {
-// if (destination != null) {
-// val link = ContentExternalLink(destination.text)
-// renderLinkTextTo(linkTextNode, link, linkResolver)
-// parent.append(link)
-// } else {
-// val link = ContentExternalLink(linkTextNode.getLabelText())
-// renderLinkTextTo(linkTextNode, link, linkResolver)
-// parent.append(link)
-// }
-// }
- //TODO: Linking!!!
-// ContentLink()
- TODO()
- }
- MarkdownElementTypes.SHORT_REFERENCE_LINK,
- MarkdownElementTypes.FULL_REFERENCE_LINK -> {
- 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
- links[destination]?.let { dri ->
- listOf(
- ContentResolvedLink(
- buildChildren(node),
- destination,
- DCI(dri, ContentKind.Symbol),
- platforms,
- styles,
- extras
- )
- )
- } ?: let {
- logger.error("Apparently there is no link resolved for $destination")
- emptyList<ContentNode>()
- }
- }
- MarkdownTokenTypes.WHITE_SPACE -> {
- // Don't append first space if start of header (it is added during formatting later)
- // v
- // #### Some Heading
-// if (nodeStack.peek() !is ContentHeading || node.parent?.children?.first() != node) {
-// parent.append(ContentText(node.text))
-// }
- listOf(ContentText(" ", dci, platforms, styles, extras))
- }
- MarkdownTokenTypes.EOL -> {
-// if ((keepEol(nodeStack.peek()) && node.parent?.children?.last() != node) ||
-// // Keep extra blank lines when processing lists (affects Markdown formatting)
-// (processingList(nodeStack.peek()) && node.previous?.type == MarkdownTokenTypes.EOL)) {
-// parent.append(ContentText(node.text))
-// }
- listOf(ContentText(" ", dci, platforms, styles, extras))
- }
-
- MarkdownTokenTypes.CODE_LINE -> {
- listOf(ContentText(node.text, dci, platforms, styles, extras)) // TODO check
-// if (parent is ContentBlockCode) {
-// parent.append(content)
-// } else {
-// parent.append(ContentBlockCode().apply { append(content) })
-// }
- }
-
- MarkdownTokenTypes.TEXT ->
-// fun createEntityOrText(text: String): ContentNode {
-// if (text == "&amp;" || text == "&quot;" || text == "&lt;" || text == "&gt;") {
-// return ContentEntity(text)
-// }
-// if (text == "&") {
-// return ContentEntity("&amp;")
-// }
-// val decodedText = EntityConverter.replaceEntities(text, true, true)
-// if (decodedText != text) {
-// return ContentEntity(text)
-// }
-// return ContentText(text)
-// }
-//
-// parent.append(createEntityOrText(node.text))
- listOf(ContentText(node.text, dci, platforms, styles, extras)) // TODO
-
- MarkdownTokenTypes.COLON,
- MarkdownTokenTypes.SINGLE_QUOTE,
- MarkdownTokenTypes.DOUBLE_QUOTE,
- MarkdownTokenTypes.LT,
- MarkdownTokenTypes.GT,
- MarkdownTokenTypes.LPAREN,
- MarkdownTokenTypes.RPAREN,
- MarkdownTokenTypes.LBRACKET,
- MarkdownTokenTypes.RBRACKET,
- MarkdownTokenTypes.EXCLAMATION_MARK,
- MarkdownTokenTypes.BACKTICK,
- MarkdownTokenTypes.CODE_FENCE_CONTENT -> {
- listOf(ContentText(node.text, dci, platforms, styles, extras))
- }
-
- MarkdownElementTypes.LINK_DEFINITION -> TODO()
-
- MarkdownTokenTypes.EMAIL_AUTOLINK ->
- listOf(
- ContentResolvedLink(
- listOf(ContentText(node.text, dci, platforms, styles, extras)),
- "mailto:${node.text}",
- dci, platforms, styles, extras
- )
- )
-
- else -> buildChildren(node)
- }
- }
-
- private fun Collection<ContentNode>.coalesceText(
- platforms: Set<PlatformData>,
- styles: Set<Style>,
- extras: Set<Extra>
- ) =
- this
- .sliceWhen { prev, next -> prev::class != next::class }
- .flatMap { nodes ->
- when (nodes.first()) {
- is ContentText -> listOf(
- ContentText(
- nodes.joinToString("") { (it as ContentText).text },
- nodes.first().dci, platforms, styles, extras
- )
- )
- else -> nodes
- }
- }
+ ): List<ContentNode>
}
-
-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)) {
- newCollection.add(currentSlice)
- currentSlice = mutableListOf<T>()
- }
- }
- if (this.isNotEmpty()) {
- currentSlice.add(this.last())
- newCollection.add(currentSlice)
- }
- return newCollection
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/pages/transformers/PageNodeTransformer.kt b/core/src/main/kotlin/pages/transformers/PageNodeTransformer.kt
deleted file mode 100644
index 0d0f8057..00000000
--- a/core/src/main/kotlin/pages/transformers/PageNodeTransformer.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.jetbrains.dokka.pages.transformers
-
-import org.jetbrains.dokka.pages.ModulePageNode
-
-interface PageNodeTransformer {
- operator fun invoke(original: ModulePageNode): ModulePageNode
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/plugability/DefaultExtensions.kt b/core/src/main/kotlin/plugability/DefaultExtensions.kt
new file mode 100644
index 00000000..dd656386
--- /dev/null
+++ b/core/src/main/kotlin/plugability/DefaultExtensions.kt
@@ -0,0 +1,25 @@
+package org.jetbrains.dokka.plugability
+
+import org.jetbrains.dokka.CoreExtensions
+import org.jetbrains.dokka.pages.DefaultMarkdownToContentConverter
+import org.jetbrains.dokka.renderers.DefaultRenderer
+import org.jetbrains.dokka.renderers.HtmlRenderer
+import org.jetbrains.dokka.resolvers.DefaultLocationProvider
+import org.jetbrains.dokka.transformers.descriptors.DefaultDescriptorToDocumentationTranslator
+import org.jetbrains.dokka.transformers.documentation.DefaultDocumentationNodeMerger
+import org.jetbrains.dokka.transformers.documentation.DefaultDocumentationToPageTranslator
+
+object DefaultExtensions : DokkaExtensionHandler {
+ @Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST")
+ override fun <T : Any, E : ExtensionPoint<T>> get(point: E, askDefault: AskDefault): List<T> =
+ when (point) {
+ CoreExtensions.descriptorToDocumentationTranslator -> DefaultDescriptorToDocumentationTranslator
+ CoreExtensions.documentationMerger -> DefaultDocumentationNodeMerger
+ CoreExtensions.markdownToContentConverterFactory -> ::DefaultMarkdownToContentConverter
+ CoreExtensions.documentationToPageTranslator -> DefaultDocumentationToPageTranslator
+ CoreExtensions.renderer -> ::HtmlRenderer
+ CoreExtensions.locationProvider -> ::DefaultLocationProvider
+ CoreExtensions.fileExtension -> ".html"
+ else -> null
+ }.let { listOfNotNull(it) as List<T> }
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/plugability/DokkaContext.kt b/core/src/main/kotlin/plugability/DokkaContext.kt
index b917ff99..31c56728 100644
--- a/core/src/main/kotlin/plugability/DokkaContext.kt
+++ b/core/src/main/kotlin/plugability/DokkaContext.kt
@@ -1,23 +1,35 @@
package org.jetbrains.dokka.plugability
import org.jetbrains.dokka.DokkaLogger
+import org.jetbrains.dokka.EnvironmentAndFacade
+import org.jetbrains.dokka.pages.PlatformData
import java.io.File
import java.net.URLClassLoader
import java.util.*
import kotlin.reflect.KClass
import kotlin.reflect.full.createInstance
-interface DokkaContext {
- operator fun <T, E> get(point: E, askDefault: AskDefault = AskDefault.WhenEmpty): List<Extension<T>>
+
+interface DokkaExtensionHandler {
+ operator fun <T, E> get(point: E, askDefault: AskDefault = AskDefault.WhenEmpty): List<T>
where T : Any, E : ExtensionPoint<T>
+}
+
+interface DokkaContext : DokkaExtensionHandler {
fun <T : DokkaPlugin> plugin(kclass: KClass<T>): T?
val logger: DokkaLogger
+ val platforms: Map<PlatformData, EnvironmentAndFacade>
+
companion object {
- fun create(pluginsClasspath: Iterable<File>, logger: DokkaLogger): DokkaContext =
- DokkaContextConfigurationImpl(logger, DefaultContext(logger)).apply {
+ fun create(
+ pluginsClasspath: Iterable<File>,
+ logger: DokkaLogger,
+ platforms: Map<PlatformData, EnvironmentAndFacade>
+ ): DokkaContext =
+ DokkaContextConfigurationImpl(logger, DefaultExtensions, platforms).apply {
pluginsClasspath.map { it.relativeTo(File(".").absoluteFile).toURI().toURL() }
.toTypedArray()
.let { URLClassLoader(it, this.javaClass.classLoader) }
@@ -28,13 +40,27 @@ interface DokkaContext {
}
}
+fun <T, E> DokkaContext.single(point: E): T where T : Any, E : ExtensionPoint<T> {
+ fun throwBadArity(substitution: String): Nothing = throw IllegalStateException(
+ "$point was expected to have exactly one extension registered, but $substitution found."
+ )
+
+ val extensions = get(point, AskDefault.WhenEmpty)
+ return when (extensions.size) {
+ 0 -> throwBadArity("none was")
+ 1 -> extensions.first()
+ else -> throwBadArity("multiple were")
+ }
+}
+
interface DokkaContextConfiguration {
fun addExtension(extension: Extension<*>)
}
private class DokkaContextConfigurationImpl(
override val logger: DokkaLogger,
- private val defaultContext: DokkaContext?
+ private val defaultHandler: DokkaExtensionHandler?,
+ override val platforms: Map<PlatformData, EnvironmentAndFacade>
) : DokkaContext, DokkaContextConfiguration {
private val plugins = mutableMapOf<KClass<*>, DokkaPlugin>()
@@ -45,15 +71,16 @@ private class DokkaContextConfigurationImpl(
@Suppress("UNCHECKED_CAST")
override operator fun <T, E> get(point: E, askDefault: AskDefault) where T : Any, E : ExtensionPoint<T> =
when (askDefault) {
- AskDefault.Never -> extensions[point].orEmpty()
- AskDefault.Always -> extensions[point].orEmpty() + defaultContext?.get(point, askDefault).orEmpty()
+ AskDefault.Never -> actions(point).orEmpty()
+ AskDefault.Always -> actions(point).orEmpty() + defaultHandler?.get(point, askDefault).orEmpty()
AskDefault.WhenEmpty ->
- extensions[point]?.takeIf { it.isNotEmpty() } ?: defaultContext?.get(point, askDefault).orEmpty()
- } as List<Extension<T>>
+ actions(point)?.takeIf { it.isNotEmpty() } ?: defaultHandler?.get(point, askDefault).orEmpty()
+ } as List<T>
+
+ private fun <E : ExtensionPoint<*>> actions(point: E) = extensions[point]?.map { it.action }
@Suppress("UNCHECKED_CAST")
- override fun <T : DokkaPlugin> plugin(kclass: KClass<T>) =
- (plugins[kclass] ?: defaultContext?.plugin(kclass) ?: pluginStubFor(kclass)) as T
+ override fun <T : DokkaPlugin> plugin(kclass: KClass<T>) = (plugins[kclass] ?: pluginStubFor(kclass)) as T
private fun <T : DokkaPlugin> pluginStubFor(kclass: KClass<T>): DokkaPlugin =
pluginStubs.getOrPut(kclass) { kclass.createInstance().also { it.context = this } }
@@ -69,7 +96,7 @@ private class DokkaContextConfigurationImpl(
}
fun logInitialisationInfo() {
- val pluginNames: List<String> = plugins.values.map { it::class.qualifiedName.toString() }
+ val pluginNames = plugins.values.map { it::class.qualifiedName.toString() }
val loadedListForDebug = extensions.run { keys + values.flatten() }.toList()
.joinToString(prefix = "[\n", separator = ",\n", postfix = "\n]") { "\t$it" }
@@ -89,16 +116,6 @@ private fun checkClasspath(classLoader: URLClassLoader) {
}
}
-class DefaultContext(override val logger: DokkaLogger) : DokkaContext {
- override fun <T : Any, E : ExtensionPoint<T>> get(point: E, askDefault: AskDefault): List<Extension<T>> =
- when (point) {
-
- else -> emptyList()
- }
-
- override fun <T : DokkaPlugin> plugin(kclass: KClass<T>): Nothing? = null
-}
-
enum class AskDefault {
Always, Never, WhenEmpty
} \ No newline at end of file
diff --git a/core/src/main/kotlin/plugability/extensions.kt b/core/src/main/kotlin/plugability/extensions.kt
index c1573e1a..3039cb5a 100644
--- a/core/src/main/kotlin/plugability/extensions.kt
+++ b/core/src/main/kotlin/plugability/extensions.kt
@@ -11,7 +11,7 @@ class Extension<T : Any> internal constructor(
internal val extensionPoint: ExtensionPoint<T>,
internal val pluginClass: String,
internal val extensionName: String,
- internal val action: T,
+ val action: T,
internal val ordering: (OrderDsl.() -> Unit)? = null
) {
override fun toString() = "Extension: $pluginClass/$extensionName"
diff --git a/core/src/main/kotlin/renderers/DefaultRenderer.kt b/core/src/main/kotlin/renderers/DefaultRenderer.kt
index 3b16c093..3f851849 100644
--- a/core/src/main/kotlin/renderers/DefaultRenderer.kt
+++ b/core/src/main/kotlin/renderers/DefaultRenderer.kt
@@ -1,9 +1,14 @@
package org.jetbrains.dokka.renderers
import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.resolvers.LocationProvider
-abstract class DefaultRenderer(val fileWriter: FileWriter, val locationProvider: LocationProvider) : Renderer {
+abstract class DefaultRenderer(
+ protected val fileWriter: FileWriter,
+ protected val locationProvider: LocationProvider,
+ protected val context: DokkaContext
+) : Renderer {
protected abstract fun buildHeader(level: Int, text: String): String
protected abstract fun buildLink(text: String, address: String): String
diff --git a/core/src/main/kotlin/renderers/HtmlRenderer.kt b/core/src/main/kotlin/renderers/HtmlRenderer.kt
index 3b778671..46548699 100644
--- a/core/src/main/kotlin/renderers/HtmlRenderer.kt
+++ b/core/src/main/kotlin/renderers/HtmlRenderer.kt
@@ -2,13 +2,18 @@ package org.jetbrains.dokka.renderers
import org.jetbrains.dokka.htmlEscape
import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.resolvers.LocationProvider
import java.io.File
import java.net.URL
import java.nio.file.Path
import java.nio.file.Paths
-open class HtmlRenderer(fileWriter: FileWriter, locationProvider: LocationProvider) : DefaultRenderer(fileWriter, locationProvider) {
+open class HtmlRenderer(
+ fileWriter: FileWriter,
+ locationProvider: LocationProvider,
+ context: DokkaContext
+) : DefaultRenderer(fileWriter, locationProvider, context) {
override fun buildList(node: ContentList, pageContext: PageNode): String = if (node.ordered) {
"<ol>${buildListItems(node.children, pageContext)}</ol>"
diff --git a/core/src/main/kotlin/renderers/Renderer.kt b/core/src/main/kotlin/renderers/Renderer.kt
index 24e01cdb..91483a46 100644
--- a/core/src/main/kotlin/renderers/Renderer.kt
+++ b/core/src/main/kotlin/renderers/Renderer.kt
@@ -1,6 +1,7 @@
package org.jetbrains.dokka.renderers
import org.jetbrains.dokka.pages.PageNode
+import org.jetbrains.dokka.plugability.DokkaContext
interface Renderer {
fun render(root: PageNode)
diff --git a/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt b/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt
index 208410fe..ec5aa29a 100644
--- a/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt
+++ b/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt
@@ -1,11 +1,20 @@
package org.jetbrains.dokka.resolvers
+import org.jetbrains.dokka.CoreExtensions
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.htmlEscape
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.single
+
+open class DefaultLocationProvider(
+ private val pageGraphRoot: PageNode,
+ private val configuration: DokkaConfiguration,
+ context: DokkaContext
+): LocationProvider { // TODO: cache
+ private val extension = context.single(CoreExtensions.fileExtension)
-open class DefaultLocationProvider(private val pageGraphRoot: PageNode, val configuration: DokkaConfiguration, val extension: String): LocationProvider { // TODO: cache
override fun resolve(node: PageNode, context: PageNode?): String = pathTo(node, context) + extension
override fun resolve(dri: DRI, platforms: List<PlatformData>, context: PageNode?): String =
diff --git a/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt b/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt
deleted file mode 100644
index b0877527..00000000
--- a/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.jetbrains.dokka.transformers
-
-import org.jetbrains.dokka.DokkaLogger
-import org.jetbrains.dokka.Model.Module
-import org.jetbrains.dokka.pages.DefaultPageBuilder
-import org.jetbrains.dokka.pages.DefaultPageContentBuilder
-import org.jetbrains.dokka.pages.MarkdownToContentConverter
-import org.jetbrains.dokka.pages.ModulePageNode
-
-
-class DefaultDocumentationToPageTransformer(
- private val markdownConverter: MarkdownToContentConverter,
- private val logger: DokkaLogger
-) : DocumentationToPageTransformer {
- override fun transform(module: Module): ModulePageNode =
- DefaultPageBuilder { node, kind, operation ->
- DefaultPageContentBuilder.group(node.dri, node.platformData, kind, markdownConverter, logger, operation)
- }.pageForModule(module)
-
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/transformers/PageNodeTransformer.kt b/core/src/main/kotlin/transformers/PageNodeTransformer.kt
deleted file mode 100644
index b86e0b34..00000000
--- a/core/src/main/kotlin/transformers/PageNodeTransformer.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.jetbrains.dokka.transformers
-
-import org.jetbrains.dokka.pages.ModulePageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-
-interface PageNodeTransformer {
- fun invoke(input: ModulePageNode, dokkaContext: DokkaContext): ModulePageNode
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/DokkaDescriptorVisitor.kt b/core/src/main/kotlin/transformers/descriptors/DefaultDescriptorToDocumentationTranslator.kt
index 6c82f2c3..19aeef92 100644
--- a/core/src/main/kotlin/DokkaDescriptorVisitor.kt
+++ b/core/src/main/kotlin/transformers/descriptors/DefaultDescriptorToDocumentationTranslator.kt
@@ -1,5 +1,6 @@
-package org.jetbrains.dokka
+package org.jetbrains.dokka.transformers.descriptors
+import org.jetbrains.dokka.DokkaResolutionFacade
import org.jetbrains.dokka.Model.*
import org.jetbrains.dokka.Model.ClassKind
import org.jetbrains.dokka.Model.Function
@@ -7,6 +8,7 @@ import org.jetbrains.dokka.links.Callable
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.links.withClass
import org.jetbrains.dokka.pages.PlatformData
+import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
import org.jetbrains.kotlin.idea.kdoc.findKDoc
@@ -20,6 +22,17 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
+object DefaultDescriptorToDocumentationTranslator: DescriptorToDocumentationTranslator {
+ override fun invoke(
+ packageFragments: Iterable<PackageFragmentDescriptor>,
+ platformData: PlatformData,
+ context: DokkaContext
+ ) = DokkaDescriptorVisitor(platformData, context.platforms[platformData]?.facade!!).run {
+ packageFragments.map { visitPackageFragmentDescriptor(it, DRI.topLevel) }
+ }.let { Module(it) }
+
+}
+
class DokkaDescriptorVisitor(
private val platformData: PlatformData,
private val resolutionFacade: DokkaResolutionFacade
@@ -186,6 +199,10 @@ class KotlinTypeWrapper(private val kotlinType: KotlinType) : TypeWrapper {
override val constructorFqName = fqNameSafe?.asString()
override val constructorNamePathSegments: List<String> =
fqNameSafe?.pathSegments()?.map { it.asString() } ?: emptyList()
- override val arguments: List<KotlinTypeWrapper> by lazy { kotlinType.arguments.map { KotlinTypeWrapper(it.type) } }
+ override val arguments: List<KotlinTypeWrapper> by lazy { kotlinType.arguments.map {
+ KotlinTypeWrapper(
+ it.type
+ )
+ } }
override val dri: DRI? by lazy { declarationDescriptor?.let { DRI.from(it) } }
} \ No newline at end of file
diff --git a/core/src/main/kotlin/transformers/descriptors/DescriptorToDocumentationTranslator.kt b/core/src/main/kotlin/transformers/descriptors/DescriptorToDocumentationTranslator.kt
new file mode 100644
index 00000000..d08aba21
--- /dev/null
+++ b/core/src/main/kotlin/transformers/descriptors/DescriptorToDocumentationTranslator.kt
@@ -0,0 +1,15 @@
+package org.jetbrains.dokka.transformers.descriptors
+
+import org.jetbrains.dokka.Model.Module
+import org.jetbrains.dokka.Model.Package
+import org.jetbrains.dokka.pages.PlatformData
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
+
+interface DescriptorToDocumentationTranslator {
+ fun invoke(
+ packageFragments: Iterable<PackageFragmentDescriptor>,
+ platformData: PlatformData,
+ context: DokkaContext
+ ): Module
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt b/core/src/main/kotlin/transformers/documentation/DefaultDocumentationNodeMerger.kt
index ae4f8d99..46ba2816 100644
--- a/core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt
+++ b/core/src/main/kotlin/transformers/documentation/DefaultDocumentationNodeMerger.kt
@@ -1,23 +1,19 @@
-package org.jetbrains.dokka.Model.transformers
+package org.jetbrains.dokka.transformers.documentation
import org.jetbrains.dokka.Model.*
import org.jetbrains.dokka.Model.Function
+import org.jetbrains.dokka.plugability.DokkaContext
-internal object DocumentationNodesMerger : DocumentationNodeTransformer {
- override fun invoke(original: Module) = Module(
- original.packages.map { mergePackageContent(it) }
- )
- override fun invoke(modules: Collection<Module>): Module =
- Module(merge(modules.flatMap { it.packages }, Package::mergeWith))
+internal object DefaultDocumentationNodeMerger : DocumentationNodeMerger {
+ override fun invoke(modules: Collection<Module>, context: DokkaContext): Module =
+ Module(
+ merge(
+ modules.flatMap { it.packages },
+ Package::mergeWith
+ )
+ )
}
-private fun mergePackageContent(original: Package) = Package(
- original.dri,
- merge(original.functions, Function::mergeWith),
- merge(original.properties, Property::mergeWith),
- merge(original.classes, Class::mergeWith)
-)
-
private fun <T: DocumentationNode> merge(elements: List<T>, reducer: (T, T) -> T): List<T> =
elements.groupingBy { it.dri }
.reduce { _, left, right -> reducer(left, right)}
diff --git a/core/src/main/kotlin/transformers/documentation/DefaultDocumentationToPageTranslator.kt b/core/src/main/kotlin/transformers/documentation/DefaultDocumentationToPageTranslator.kt
new file mode 100644
index 00000000..236d0864
--- /dev/null
+++ b/core/src/main/kotlin/transformers/documentation/DefaultDocumentationToPageTranslator.kt
@@ -0,0 +1,24 @@
+package org.jetbrains.dokka.transformers.documentation
+
+import org.jetbrains.dokka.CoreExtensions
+import org.jetbrains.dokka.Model.Module
+import org.jetbrains.dokka.pages.DefaultPageBuilder
+import org.jetbrains.dokka.pages.DefaultPageContentBuilder
+import org.jetbrains.dokka.pages.ModulePageNode
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.single
+
+
+object DefaultDocumentationToPageTranslator : DocumentationToPageTranslator {
+ override fun invoke(module: Module, context: DokkaContext): ModulePageNode =
+ DefaultPageBuilder { node, kind, operation ->
+ DefaultPageContentBuilder.group(
+ node.dri,
+ node.platformData,
+ kind,
+ context.single(CoreExtensions.markdownToContentConverterFactory).invoke(context),
+ context.logger,
+ operation
+ )
+ }.pageForModule(module)
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/transformers/documentation/DocumentationNodeMerger.kt b/core/src/main/kotlin/transformers/documentation/DocumentationNodeMerger.kt
new file mode 100644
index 00000000..0423f47c
--- /dev/null
+++ b/core/src/main/kotlin/transformers/documentation/DocumentationNodeMerger.kt
@@ -0,0 +1,8 @@
+package org.jetbrains.dokka.transformers.documentation
+
+import org.jetbrains.dokka.Model.Module
+import org.jetbrains.dokka.plugability.DokkaContext
+
+interface DocumentationNodeMerger {
+ operator fun invoke(modules: Collection<Module>, context: DokkaContext): Module
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/transformers/documentation/DocumentationNodeTransformer.kt b/core/src/main/kotlin/transformers/documentation/DocumentationNodeTransformer.kt
new file mode 100644
index 00000000..8ac4a7c2
--- /dev/null
+++ b/core/src/main/kotlin/transformers/documentation/DocumentationNodeTransformer.kt
@@ -0,0 +1,8 @@
+package org.jetbrains.dokka.transformers.documentation
+
+import org.jetbrains.dokka.Model.Module
+import org.jetbrains.dokka.plugability.DokkaContext
+
+interface DocumentationNodeTransformer {
+ operator fun invoke(original: Module, context: DokkaContext): Module
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt b/core/src/main/kotlin/transformers/documentation/DocumentationToPageTranslator.kt
index 19703025..ffe34226 100644
--- a/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt
+++ b/core/src/main/kotlin/transformers/documentation/DocumentationToPageTranslator.kt
@@ -1,11 +1,12 @@
-package org.jetbrains.dokka.transformers
+package org.jetbrains.dokka.transformers.documentation
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.Model.DocumentationNode
import org.jetbrains.dokka.Model.Module
import org.jetbrains.dokka.pages.ModulePageNode
import org.jetbrains.dokka.pages.PageNode
+import org.jetbrains.dokka.plugability.DokkaContext
-interface DocumentationToPageTransformer {
- fun transform(module: Module): ModulePageNode // TODO refactor this... some more?
+interface DocumentationToPageTranslator {
+ operator fun invoke(module: Module, context: DokkaContext): ModulePageNode
} \ No newline at end of file
diff --git a/core/src/main/kotlin/transformers/pages/PageNodeTransformer.kt b/core/src/main/kotlin/transformers/pages/PageNodeTransformer.kt
new file mode 100644
index 00000000..286835f9
--- /dev/null
+++ b/core/src/main/kotlin/transformers/pages/PageNodeTransformer.kt
@@ -0,0 +1,8 @@
+package org.jetbrains.dokka.transformers.pages
+
+import org.jetbrains.dokka.pages.ModulePageNode
+import org.jetbrains.dokka.plugability.DokkaContext
+
+interface PageNodeTransformer {
+ operator fun invoke(input: ModulePageNode, dokkaContext: DokkaContext): ModulePageNode
+} \ No newline at end of file