diff options
11 files changed, 265 insertions, 190 deletions
diff --git a/core/src/main/kotlin/DokkaDescriptorVisitor.kt b/core/src/main/kotlin/DokkaDescriptorVisitor.kt index 63d3ea20..34b45f23 100644 --- a/core/src/main/kotlin/DokkaDescriptorVisitor.kt +++ b/core/src/main/kotlin/DokkaDescriptorVisitor.kt @@ -5,6 +5,7 @@ import org.jetbrains.dokka.Model.Function 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.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED @@ -17,7 +18,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope class DokkaDescriptorVisitor( - val platform: List<String>, + val platformData: PlatformData, private val resolutionFacade: DokkaResolutionFacade ) : DeclarationDescriptorVisitorEmptyBodies<DocumentationNode<*>, DRI>() { override fun visitDeclarationDescriptor(descriptor: DeclarationDescriptor, parent: DRI): Nothing { @@ -138,6 +139,6 @@ class DokkaDescriptorVisitor( destination.split('.') ).map { Pair(destination, DRI.from(it)) } }?.toMap() ?: emptyMap() - return Descriptor(this, doc, links, platform) + return Descriptor(this, doc, links, listOf(platformData)) } } diff --git a/core/src/main/kotlin/DokkaGenerator.kt b/core/src/main/kotlin/DokkaGenerator.kt index f5e8b832..11f583b3 100644 --- a/core/src/main/kotlin/DokkaGenerator.kt +++ b/core/src/main/kotlin/DokkaGenerator.kt @@ -2,10 +2,11 @@ package org.jetbrains.dokka import org.jetbrains.dokka.Model.Module import org.jetbrains.dokka.Model.transformers.DocumentationNodesMerger -import org.jetbrains.dokka.Utilities.genericPretty +//import org.jetbrains.dokka.Utilities.genericPretty import org.jetbrains.dokka.Utilities.pretty import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.pages.MarkdownToContentConverter +import org.jetbrains.dokka.pages.PlatformData import org.jetbrains.dokka.renderers.FileWriter import org.jetbrains.dokka.renderers.HtmlRenderer import org.jetbrains.dokka.resolvers.DefaultLocationProvider @@ -43,7 +44,7 @@ class DokkaGenerator( .distinct() .mapNotNull { facade.resolveSession.getPackageFragment(it) } .map { - DokkaDescriptorVisitor(pass.targets, facade).visitPackageFragmentDescriptor( + DokkaDescriptorVisitor(PlatformData(pass.analysisPlatform, pass.targets), facade).visitPackageFragmentDescriptor( it, DRI.topLevel ) @@ -55,11 +56,11 @@ class DokkaGenerator( } }.let { val markdownConverter = MarkdownToContentConverter(logger) - it.forEach { it.genericPretty().also(::nierzigoj) } +// it.forEach { it.genericPretty().also(::nierzigoj) } DefaultDocumentationToPageTransformer(markdownConverter, logger).transform(DocumentationNodesMerger(it)) } .also { - it.genericPretty().also(::nierzigoj) +// it.genericPretty().also(::nierzigoj) HtmlRenderer( FileWriter(configuration.outputDir, ""), DefaultLocationProvider(it, configuration, ".${configuration.format}") diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 7efe6818..fc81db6d 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,6 +1,7 @@ package org.jetbrains.dokka.Model import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.pages.PlatformData import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag @@ -66,7 +67,7 @@ class Descriptor<out T : DeclarationDescriptor>( val descriptor: T, val docTag: KDocTag?, val links: Map<String, DRI>, - val passes: List<String> + val platformData: List<PlatformData> ) : DeclarationDescriptor by descriptor { override fun equals(other: Any?): Boolean = @@ -83,6 +84,7 @@ abstract class DocumentationNode<out T : DeclarationDescriptor> { open val expectDescriptor: Descriptor<T>? = null open val actualDescriptors: List<Descriptor<T>> = emptyList() val descriptors by lazy { listOfNotNull(expectDescriptor) + actualDescriptors } + val platformData by lazy { descriptors.flatMap { it.platformData }.toSet() } abstract val dri: DRI diff --git a/core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt b/core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt index c5a67513..2fb2f7c0 100644 --- a/core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt +++ b/core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt @@ -28,7 +28,7 @@ fun <T:DeclarationDescriptor> Descriptor<T>.mergeWith(other: Descriptor<T>?) = D descriptor, docTag, links, - (passes + (other?.passes ?: emptyList())).distinct() + (platformData + (other?.platformData ?: emptyList())).distinct() ) fun <T:DeclarationDescriptor> List<Descriptor<T>>.merge() : List<Descriptor<T>> = diff --git a/core/src/main/kotlin/Utilities/nodeDebug.kt b/core/src/main/kotlin/Utilities/nodeDebug.kt index 8e2a7079..37655b0b 100644 --- a/core/src/main/kotlin/Utilities/nodeDebug.kt +++ b/core/src/main/kotlin/Utilities/nodeDebug.kt @@ -21,31 +21,31 @@ fun <T : DeclarationDescriptor> DocumentationNode<T>.pretty(prefix: String = "", .orEmpty() + if (children.isEmpty()) "\n" else "" } -fun Any.genericPretty(prefix: String = "", isLast: Boolean = true): String { - val nextPrefix = prefix + (if (isLast) ' ' else DOWN) + ' ' - - return prefix + (if (isLast) LAST else BRANCH) + this.stringify() + - allChildren().dropLast(1) - .map { it.genericPretty(nextPrefix, false) } - .plus(allChildren().lastOrNull()?.genericPretty(nextPrefix)) - .filterNotNull() - .takeIf { it.isNotEmpty() } - ?.joinToString(prefix = "\n", separator = "") - .orEmpty() + if (allChildren().isEmpty()) "\n" else "" -} +//fun Any.genericPretty(prefix: String = "", isLast: Boolean = true): String { +// val nextPrefix = prefix + (if (isLast) ' ' else DOWN) + ' ' +// +// return prefix + (if (isLast) LAST else BRANCH) + this.stringify() + +// allChildren().dropLast(1) +// .map { it.genericPretty(nextPrefix, false) } +// .plus(allChildren().lastOrNull()?.genericPretty(nextPrefix)) +// .filterNotNull() +// .takeIf { it.isNotEmpty() } +// ?.joinToString(prefix = "\n", separator = "") +// .orEmpty() + if (allChildren().isEmpty()) "\n" else "" +//} private fun Any.stringify() = when(this) { is ContentNode -> toString() + this.dci is PageNode -> this.name + this::class.simpleName else -> toString() } -private fun Any.allChildren() = when(this){ - is PageNode -> children + content - is ContentBlock -> this.children - is ContentHeader -> this.items - is ContentStyle -> this.items - is ContentSymbol -> this.parts - is ContentComment -> this.parts - is ContentGroup -> this.children - is ContentList -> this.items - else -> emptyList() -} +//private fun Any.allChildren() = when(this){ +// is PageNode -> children + content +// is ContentBlock -> this.children +// is ContentHeader -> this.items +// is ContentStyle -> this.items +// is ContentSymbol -> this.parts +// is ContentComment -> this.parts +// is ContentGroup -> this.children +// is ContentList -> this.items +// else -> emptyList() +//} diff --git a/core/src/main/kotlin/pages/ContentNodes.kt b/core/src/main/kotlin/pages/ContentNodes.kt index a94a42c5..40b5e114 100644 --- a/core/src/main/kotlin/pages/ContentNodes.kt +++ b/core/src/main/kotlin/pages/ContentNodes.kt @@ -29,8 +29,10 @@ data class ContentHeader( override val dci: DCI, override val platforms: Set<PlatformData>, override val style: Set<Style>, - override val extras: Set<Extra> -) : ContentComposite + override val extras: Set<Extra> = emptySet() +) : ContentComposite { + constructor(level: Int, c: ContentComposite) : this(c.children, level, c.dci, c.platforms, c.style, c.extras) +} /** Code blocks */ data class ContentCode( @@ -117,11 +119,11 @@ interface Style interface Kind enum class ContentKind : Kind { - Comment, Functions, Parameters, Properties, Classes, Packages, Symbol, Sample + Comment, Functions, Parameters, Properties, Classes, Packages, Symbol, Sample, Main } enum class TextStyle : Style { - Bold, Italic, Strong, Strikethrough + Bold, Italic, Strong, Strikethrough, Paragraph } interface HTMLMetadata: Extra { diff --git a/core/src/main/kotlin/pages/MarkdownToContentConverter.kt b/core/src/main/kotlin/pages/MarkdownToContentConverter.kt index b29614d7..8caddeb0 100644 --- a/core/src/main/kotlin/pages/MarkdownToContentConverter.kt +++ b/core/src/main/kotlin/pages/MarkdownToContentConverter.kt @@ -12,38 +12,55 @@ class MarkdownToContentConverter( fun buildContent( node: MarkdownNode, dci: DCI, - links: Map<String, DRI> = emptyMap() + platforms: Set<PlatformData>, + links: Map<String, DRI> = emptyMap(), + styles: Set<Style> = emptySet(), + extras: Set<Extra> = emptySet() + ): List<ContentNode> { // println(tree.toTestString()) - fun buildChildren(node: MarkdownNode) = node.children.flatMap { - buildContent(it, dci, links) - }.coalesceText() + 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(ContentHeader(buildChildren(node), 1, dci)) - MarkdownElementTypes.ATX_2 -> listOf(ContentHeader(buildChildren(node), 2, dci)) - MarkdownElementTypes.ATX_3 -> listOf(ContentHeader(buildChildren(node), 3, dci)) - MarkdownElementTypes.ATX_4 -> listOf(ContentHeader(buildChildren(node), 4, dci)) - MarkdownElementTypes.ATX_5 -> listOf(ContentHeader(buildChildren(node), 5, dci)) - MarkdownElementTypes.ATX_6 -> listOf(ContentHeader(buildChildren(node), 6, dci)) - MarkdownElementTypes.UNORDERED_LIST -> listOf(ContentList(buildChildren(node), false, dci)) - MarkdownElementTypes.ORDERED_LIST -> listOf(ContentList(buildChildren(node), true, dci)) - MarkdownElementTypes.LIST_ITEM -> TODO() - MarkdownElementTypes.EMPH -> listOf( - ContentStyle( + 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), - Style.Emphasis, - dci + false, + dci, + platforms, + styles, + extras ) - )// TODO - MarkdownElementTypes.STRONG -> listOf( - ContentStyle( + ) + MarkdownElementTypes.ORDERED_LIST -> listOf( + ContentList( buildChildren(node), - Style.Strong, - dci + true, + dci, + platforms, + styles, + extras ) - ) // TODO + ) + 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) { @@ -55,15 +72,9 @@ class MarkdownToContentConverter( MarkdownElementTypes.CODE_BLOCK, MarkdownElementTypes.CODE_FENCE -> { val language = node.child(MarkdownTokenTypes.FENCE_LANG)?.text?.trim() ?: "" - listOf(ContentCode(buildChildren(node).toString(), language, dci)) // TODO + listOf(ContentCode(buildChildren(node), language, dci, platforms, styles, extras)) // TODO } - MarkdownElementTypes.PARAGRAPH -> listOf( - ContentStyle( - buildChildren(node), - Style.Paragraph, - dci - ) - ) // TODO + MarkdownElementTypes.PARAGRAPH -> buildChildren(node, newStyles = setOf(TextStyle.Paragraph)) MarkdownElementTypes.INLINE_LINK -> { // val linkTextNode = node.child(MarkdownElementTypes.LINK_TEXT) @@ -90,7 +101,16 @@ class MarkdownToContentConverter( val destination = destinationNode.children.find { it.type == MarkdownTokenTypes.TEXT }?.text ?: destinationNode.text links[destination]?.let { dri -> - listOf(ContentLink(destination, dri, dci)) + 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>() @@ -103,7 +123,7 @@ class MarkdownToContentConverter( // if (nodeStack.peek() !is ContentHeading || node.parent?.children?.first() != node) { // parent.append(ContentText(node.text)) // } - listOf(ContentText(" ", dci)) + listOf(ContentText(" ", dci, platforms, styles, extras)) } MarkdownTokenTypes.EOL -> { // if ((keepEol(nodeStack.peek()) && node.parent?.children?.last() != node) || @@ -111,11 +131,11 @@ class MarkdownToContentConverter( // (processingList(nodeStack.peek()) && node.previous?.type == MarkdownTokenTypes.EOL)) { // parent.append(ContentText(node.text)) // } - listOf(ContentText(" ", dci)) + listOf(ContentText(" ", dci, platforms, styles, extras)) } MarkdownTokenTypes.CODE_LINE -> { - listOf(ContentText(node.text, dci)) // TODO check + listOf(ContentText(node.text, dci, platforms, styles, extras)) // TODO check // if (parent is ContentBlockCode) { // parent.append(content) // } else { @@ -139,15 +159,7 @@ class MarkdownToContentConverter( // } // // parent.append(createEntityOrText(node.text)) - listOf(ContentText(node.text, dci)) // TODO - - - MarkdownTokenTypes.EMPH -> -// val parentNodeType = node.parent?.type -// if (parentNodeType != MarkdownElementTypes.EMPH && parentNodeType != MarkdownElementTypes.STRONG) { -// parent.append(ContentText(node.text)) -// } - listOf(ContentStyle(buildChildren(node), Style.Emphasis, dci)) // TODO + listOf(ContentText(node.text, dci, platforms, styles, extras)) // TODO MarkdownTokenTypes.COLON, MarkdownTokenTypes.SINGLE_QUOTE, @@ -161,19 +173,29 @@ class MarkdownToContentConverter( MarkdownTokenTypes.EXCLAMATION_MARK, MarkdownTokenTypes.BACKTICK, MarkdownTokenTypes.CODE_FENCE_CONTENT -> { - listOf(ContentText(node.text, dci)) + listOf(ContentText(node.text, dci, platforms, styles, extras)) } MarkdownElementTypes.LINK_DEFINITION -> TODO() MarkdownTokenTypes.EMAIL_AUTOLINK -> - listOf(ContentResolvedLink(node.text, "mailto:${node.text}", dci)) + 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() = + private fun Collection<ContentNode>.coalesceText( + platforms: Set<PlatformData>, + styles: Set<Style>, + extras: Set<Extra> + ) = this .sliceWhen { prev, next -> prev::class != next::class } .flatMap { nodes -> @@ -181,7 +203,7 @@ class MarkdownToContentConverter( is ContentText -> listOf( ContentText( nodes.joinToString("") { (it as ContentText).text }, - nodes.first().dci + nodes.first().dci, platforms, styles, extras ) ) else -> nodes diff --git a/core/src/main/kotlin/pages/PageNodes.kt b/core/src/main/kotlin/pages/PageNodes.kt index 41692256..0d6072f7 100644 --- a/core/src/main/kotlin/pages/PageNodes.kt +++ b/core/src/main/kotlin/pages/PageNodes.kt @@ -4,69 +4,76 @@ import org.jetbrains.dokka.Model.DocumentationNode import org.jetbrains.dokka.Platform import org.jetbrains.dokka.links.DRI -abstract class PageNode( - val name: String, - val content: List<ContentNode>, - val parent: PageNode?, - val dri: DRI?, +interface PageNode { + val name: String + val content: ContentNode + val parent: PageNode? + val dri: DRI val documentationNode: DocumentationNode<*>? -) { val children: List<PageNode> - get() = _children +} - private val _children: MutableList<PageNode> = mutableListOf() +abstract class BasicPageNode(children: List<PageNode>): PageNode { - fun appendChildren(children: List<PageNode>) = _children.addAll(children) - fun appendChild(child: PageNode) = _children.add(child) + private lateinit var _parent: PageNode + override val parent: PageNode? by lazy { _parent } + override val children = children override fun equals(other: Any?): Boolean = if (other is PageNode) { - dri?.equals(other.dri) ?: (other.dri == null && name == other.name) + dri == other.dri && name == other.name } else false + + override fun hashCode(): Int = + (name + dri).hashCode() + + init { + children.forEach { if (it is BasicPageNode) it._parent = this } + } + } class ModulePageNode( - name: String, - content: List<ContentNode>, - parent: PageNode? = null, - documentationNode: DocumentationNode<*>? -): PageNode(name, content, parent, null, documentationNode) + override val name: String, + override val content: ContentNode, + override val documentationNode: DocumentationNode<*>?, + children: List<PageNode> +): BasicPageNode(children) { + override val parent: Nothing? = null + override val dri: DRI = DRI.topLevel +} class PackagePageNode( - name: String, - content: List<ContentNode>, - parent: PageNode, - dri: DRI, - documentationNode: DocumentationNode<*>? -): PageNode(name, content, parent, dri, documentationNode) + override val name: String, + override val content: ContentNode, + override val dri: DRI, + override val documentationNode: DocumentationNode<*>?, + children: List<PageNode> +): BasicPageNode(children) class ClassPageNode( - name: String, - content: List<ContentNode>, - parent: PageNode, - dri: DRI, - documentationNode: DocumentationNode<*>? -): PageNode(name, content, parent, dri, documentationNode) // class, companion object + override val name: String, + override val content: ContentNode, + override val dri: DRI, + override val documentationNode: DocumentationNode<*>?, + children: List<PageNode> +): BasicPageNode(children) class MemberPageNode( - name: String, - content: List<ContentNode>, - parent: PageNode, - dri: DRI, - documentationNode: DocumentationNode<*>? -): PageNode(name, content, parent, dri, documentationNode) // functions, extension functions, properties - -data class PlatformData(val platformName: String, val platformType: Platform) { - override fun toString() = platformName + override val name: String, + override val content: ContentNode, + override val dri: DRI, + override val documentationNode: DocumentationNode<*>?, + children: List<PageNode> = emptyList() +): BasicPageNode(children) + +data class PlatformData(val platformType: Platform, val targets: List<String>) { + override fun toString() = targets.toString() } - -fun PageNode.platforms(): List<PlatformData> = this.content.flatMap { it.platforms }.distinct() // TODO: Override equals??? fun PageNode.dfs(predicate: (PageNode) -> Boolean): PageNode? = if (predicate(this)) { this } else { this.children.asSequence().mapNotNull { it.dfs(predicate) }.firstOrNull() } - - // Navigation?? // content modifier? diff --git a/core/src/main/kotlin/renderers/DefaultRenderer.kt b/core/src/main/kotlin/renderers/DefaultRenderer.kt index 1acaaf4f..3b16c093 100644 --- a/core/src/main/kotlin/renderers/DefaultRenderer.kt +++ b/core/src/main/kotlin/renderers/DefaultRenderer.kt @@ -54,7 +54,7 @@ abstract class DefaultRenderer(val fileWriter: FileWriter, val locationProvider: } protected open fun buildPageContent(page: PageNode): String = - buildNavigation(page) + page.content.joinToString("\n") { it.build(page) } + buildNavigation(page) + page.content.build(page) protected open fun renderPage(page: PageNode) = fileWriter.write(locationProvider.resolve(page), buildPageContent(page), "") @@ -88,3 +88,5 @@ abstract class DefaultRenderer(val fileWriter: FileWriter, val locationProvider: renderPages(root) } } + +fun PageNode.platforms() = this.content.platforms.toList()
\ No newline at end of file diff --git a/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt b/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt index 669b720e..208410fe 100644 --- a/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt +++ b/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt @@ -13,7 +13,7 @@ open class DefaultLocationProvider(private val pageGraphRoot: PageNode, val conf // Not found in PageGraph, that means it's an external link ExternalLocationProvider.getLocation(dri, configuration.passesConfigurations - .filter { passConfig -> passConfig.targets.map { PlatformData(it, passConfig.analysisPlatform)}.toSet() == platforms.toSet() } // TODO: change targets to something better? + .filter { passConfig -> platforms.toSet().contains(PlatformData(passConfig.analysisPlatform, passConfig.targets)) } // TODO: change targets to something better? .flatMap { it.externalDocumentationLinks }.distinct() ) diff --git a/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt b/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt index 771226d5..3f3cb7a2 100644 --- a/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt +++ b/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt @@ -15,112 +15,129 @@ class DefaultDocumentationToPageTransformer( private val markdownConverter: MarkdownToContentConverter, private val logger: DokkaLogger ) : DocumentationToPageTransformer { - override fun transform(module: Module): ModulePageNode { - val platformData = emptyList<PlatformData>() - return PageBuilder(platformData).pageForModule(module) - } - - private inner class PageBuilder(private val platformData: List<PlatformData>) { - fun pageForModule(m: Module) = - ModulePageNode("root", contentForModule(m), documentationNode = m).apply { - // TODO change name - appendChildren(m.packages.map { pageForPackage(it, this) }) - } - - private fun pageForPackage(p: Package, parent: PageNode) = - PackagePageNode(p.name, contentForPackage(p), parent, p.dri, p).apply { - appendChildren(p.classes.map { pageForClass(it, this) }) - appendChildren(p.functions.map { pageForMember(it, this) }) - appendChildren(p.properties.map { pageForMember(it, this) }) - } - - private fun pageForClass(c: Class, parent: PageNode): ClassPageNode = - ClassPageNode(c.name, contentForClass(c), parent, c.dri, c).apply { - appendChildren(c.constructors.map { pageForMember(it, this) }) - appendChildren(c.classes.map { pageForClass(it, this) }) - appendChildren(c.functions.map { pageForMember(it, this) }) - appendChildren(c.properties.map { pageForMember(it, this) }) - } - - private fun pageForMember(m: CallableNode<*>, parent: PageNode): MemberPageNode = + override fun transform(module: Module): ModulePageNode = + PageBuilder().pageForModule(module) + + private inner class PageBuilder { + fun pageForModule(m: Module): ModulePageNode = + ModulePageNode("root", contentForModule(m), m, m.packages.map { pageForPackage(it) }) + + private fun pageForPackage(p: Package) = + PackagePageNode(p.name, contentForPackage(p), p.dri, p, + p.classes.map { pageForClass(it) } + + p.functions.map { pageForMember(it) } + + p.properties.map { pageForMember(it) }) + + private fun pageForClass(c: Class): ClassPageNode = + ClassPageNode(c.name, contentForClass(c), c.dri, c, + c.constructors.map { pageForMember(it) } + + c.classes.map { pageForClass(it) } + + c.functions.map { pageForMember(it) }) + + private fun pageForMember(m: CallableNode<*>): MemberPageNode = when (m) { - is Function -> MemberPageNode(m.name, contentForFunction(m), parent, m.dri, m) - is Property -> MemberPageNode(m.name, emptyList(), parent, m.dri, m) + is Function -> + MemberPageNode(m.name, contentForFunction(m), m.dri, m) else -> throw IllegalStateException("$m should not be present here") } - private fun contentForModule(m: Module) = content(DCI(m.dri, platformData)) { + private fun contentForModule(m: Module) = group(m) { header(1) { text("root") } - block("Packages", m.packages) { link(it.name, it.dri) } + block("Packages", 2, ContentKind.Packages, m.packages, m.platformData) { + link(it.name, it.dri) + } text("Index\n") text("Link to allpage here") } - private fun contentForPackage(p: Package) = content(DCI(p.dri, platformData)) { + private fun contentForPackage(p: Package) = group(p) { header(1) { text("Package ${p.name}") } - block("Types", p.classes) { + block("Types", 2, ContentKind.Properties, p.classes, p.platformData) { link(it.name, it.dri) text(it.briefDocstring) } - block("Functions", p.functions) { + block("Functions", 2, ContentKind.Functions, p.functions, p.platformData) { link(it.name, it.dri) signature(it) text(it.briefDocstring) } } - private fun contentForClass(c: Class) = content(DCI(c.dri, platformData)) { + private fun contentForClass(c: Class) = group(c) { header(1) { text(c.name) } c.commentsData.forEach { (doc, links) -> comment(doc, links) } - block("Constructors", c.constructors) { + block("Constructors", 2, ContentKind.Functions, c.constructors, c.platformData) { link(it.name, it.dri) signature(it) text(it.briefDocstring) } - block("Functions", c.functions) { + block("Functions", 2, ContentKind.Functions, c.functions, c.platformData) { link(it.name, it.dri) signature(it) text(it.briefDocstring) } } - private fun contentForFunction(f: Function) = content(DCI(f.dri, platformData)) { + private fun contentForFunction(f: Function) = group(f) { header(1) { text(f.name) } signature(f) - f.commentsData.forEach { (doc, links) -> markdown(doc, links) } - block("Parameters", f.children) { param -> - group { - text(param.name ?: "<receiver>") - param.commentsData.forEach { (doc, links) -> markdown(doc, links) } - } + f.commentsData.forEach { (doc, links) -> markdown(doc, links) } + block("Parameters", 2, ContentKind.Parameters, f.children, f.platformData) { + text(it.name ?: "<receiver>") + it.commentsData.forEach { (doc, links) -> markdown(doc, links) } } } } // TODO: Make some public builder or merge it with page builder, whateva - private inner class ContentBuilder(private val dci: DCI) { + private inner class ContentBuilder( + val node: DocumentationNode<*>, + val kind: Kind, + val styles: Set<Style> = emptySet(), + val extras: Set<Extra> = emptySet() + ) { private val contents = mutableListOf<ContentNode>() - fun build() = contents.toList() // should include nodes coalescence + fun build() = ContentGroup( + contents.toList(), + DCI(node.dri, kind), + node.platformData, + styles, + extras + ) - inline fun header(level: Int, block: ContentBuilder.() -> Unit) { - contents += ContentHeader(content(block), level, dci) + fun header(level: Int, block: ContentBuilder.() -> Unit) { + contents += ContentHeader(level, group(ContentKind.Symbol, block)) } + private fun createText(text: String) = + ContentText(text, DCI(node.dri, ContentKind.Symbol), node.platformData, styles, extras) + fun text(text: String) { - contents += ContentText(text, dci) + contents += createText(text) } - inline fun symbol(block: ContentBuilder.() -> Unit) { - contents += ContentSymbol(content(block), dci) + inline fun signature(f: Function, block: ContentBuilder.() -> Unit) { + contents += group(f, ContentKind.Symbol, block) } - inline fun <T: DocumentationNode<*>> block(name: String, elements: Iterable<T>, block: ContentBuilder.(T) -> Unit) { - contents += ContentBlock(name, elements.flatMap { content(dci.copy(dri = it.dri)) { group { block(it) } } }, dci) - } + inline fun <T : DocumentationNode<*>> block( + name: String, + level: Int, + kind: Kind, + elements: Iterable<T>, + platformData: Set<PlatformData>, + operation: ContentBuilder.(T) -> Unit + ) { + header(level) { text(name) } - inline fun group(block: ContentBuilder.() -> Unit) { - contents += ContentGroup(content(block), dci) + contents += ContentGroup( + elements.map { + group(it, kind) { operation(it) } + }, + DCI(node.dri, kind), + platformData, styles, extras + ) } inline fun <T> list( @@ -142,24 +159,45 @@ class DefaultDocumentationToPageTransformer( } fun link(text: String, address: DRI) { - contents += ContentLink(text, address, dci) + contents += ContentDRILink( + listOf(createText(text)), + address, + DCI(node.dri, ContentKind.Symbol), + node.platformData + ) } + fun comment(raw: String, links: Map<String, DRI>) { - contents += ContentComment(markdownConverter.buildContent(parseMarkdown(raw), dci, links), dci) + contents += group(ContentKind.Comment) { + contents += markdownConverter.buildContent( + parseMarkdown(raw), + DCI(node.dri, ContentKind.Comment), + node.platformData, + links + ) + } } fun markdown(raw: String, links: Map<String, DRI>) { - contents += markdownConverter.buildContent(parseMarkdown(raw), dci, links) + contents += markdownConverter.buildContent( + parseMarkdown(raw), DCI(node.dri, ContentKind.Sample), + node.platformData, + links + ) } - private inline fun content(block: ContentBuilder.() -> Unit): List<ContentNode> = content(dci, block) + private inline fun group(kind: Kind, block: ContentBuilder.() -> Unit): ContentGroup = + group(node, kind, block) } - private inline fun content(dci: DCI, block: ContentBuilder.() -> Unit): List<ContentNode> = - ContentBuilder(dci).apply(block).build() + private inline fun group( + node: DocumentationNode<*>, + kind: Kind = ContentKind.Main, + block: ContentBuilder.() -> Unit + ) = ContentBuilder(node, kind).apply(block).build() // When builder is made public it will be moved as extension method to someplace near Function model - private fun ContentBuilder.signature(f: Function) = symbol { + private fun ContentBuilder.signature(f: Function) = signature(f) { text("fun ") if (f.receiver is Parameter) { type(f.receiver.descriptors.first().descriptor.type) |