aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/Formats
diff options
context:
space:
mode:
authorKrystianUjma <kujma@virtuslab.com>2019-03-19 11:34:38 +0100
committerKrystianUjma <kujma@virtuslab.com>2019-03-19 15:56:01 +0100
commit2e94ac4098d9e2582223485b981114fa462e5757 (patch)
treeed1b772bce9d790c473b346bcce435e893b29be7 /core/src/main/kotlin/Formats
parentb566f8852e94f9a17be86bf845aeff6c36bd8378 (diff)
parenta9c91cb7dc54c1554be5cf8de90516c929c0c1cb (diff)
downloaddokka-2e94ac4098d9e2582223485b981114fa462e5757.tar.gz
dokka-2e94ac4098d9e2582223485b981114fa462e5757.tar.bz2
dokka-2e94ac4098d9e2582223485b981114fa462e5757.zip
Merge branch 'kotlin-website-jonnyzzz' into multiplatform-support
Diffstat (limited to 'core/src/main/kotlin/Formats')
-rw-r--r--core/src/main/kotlin/Formats/FormatDescriptor.kt1
-rw-r--r--core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt10
-rw-r--r--core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt130
-rw-r--r--core/src/main/kotlin/Formats/PackageListService.kt11
-rw-r--r--core/src/main/kotlin/Formats/StructuredFormatService.kt691
-rw-r--r--core/src/main/kotlin/Formats/YamlOutlineService.kt2
6 files changed, 617 insertions, 228 deletions
diff --git a/core/src/main/kotlin/Formats/FormatDescriptor.kt b/core/src/main/kotlin/Formats/FormatDescriptor.kt
index b497fb0f..4bac8aa0 100644
--- a/core/src/main/kotlin/Formats/FormatDescriptor.kt
+++ b/core/src/main/kotlin/Formats/FormatDescriptor.kt
@@ -25,6 +25,7 @@ abstract class FileGeneratorBasedFormatDescriptor : FormatDescriptor {
override fun configureOutput(binder: Binder): Unit = with(binder) {
bind<Generator>() toType NodeLocationAwareGenerator::class
bind<NodeLocationAwareGenerator>() toType generatorServiceClass
+ bind(generatorServiceClass.java) // https://github.com/google/guice/issues/847
bind<LanguageService>() toType languageServiceClass
diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt
index a98002d4..51ceb47e 100644
--- a/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt
+++ b/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt
@@ -57,8 +57,8 @@ open class KotlinWebsiteOutputBuilder(
}
}
- override fun appendAsOverloadGroup(to: StringBuilder, platforms: Set<String>, block: () -> Unit) {
- div(to, "overload-group", calculateDataAttributes(platforms), true) {
+ override fun appendAsOverloadGroup(to: StringBuilder, platforms: PlatformsData, block: () -> Unit) {
+ div(to, "overload-group", calculateDataAttributes(platforms.keys), true) {
ensureParagraph()
block()
ensureParagraph()
@@ -159,14 +159,14 @@ open class KotlinWebsiteOutputBuilder(
return "$platformsAttr$kotlinVersionAttr$jreVersionAttr"
}
- override fun appendIndexRow(platforms: Set<String>, block: () -> Unit) {
+ override fun appendIndexRow(platforms: PlatformsData, block: () -> Unit) {
if (platforms.isNotEmpty())
- wrap("<tr${calculateDataAttributes(platforms)}>", "</tr>", block)
+ wrap("<tr${calculateDataAttributes(platforms.keys)}>", "</tr>", block)
else
appendTableRow(block)
}
- override fun appendPlatforms(platforms: Set<String>) {
+ override fun appendPlatforms(platforms: PlatformsData) {
}
}
diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
index 6ced75b5..86bc9df9 100644
--- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
+++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
@@ -3,7 +3,6 @@ package org.jetbrains.dokka
import com.google.inject.Inject
import com.google.inject.name.Named
import org.jetbrains.dokka.Utilities.impliedPlatformsName
-import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import java.io.File
@@ -20,7 +19,7 @@ open class KotlinWebsiteHtmlOutputBuilder(
generator: NodeLocationAwareGenerator,
languageService: LanguageService,
extension: String,
- impliedPlatforms: List<String>,
+ val impliedPlatforms: List<String>,
templateService: HtmlTemplateService
) : HtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) {
private var needHardLineBreaks = false
@@ -60,7 +59,7 @@ open class KotlinWebsiteHtmlOutputBuilder(
}
}
- override fun appendAsOverloadGroup(to: StringBuilder, platforms: Set<String>, block: () -> Unit) {
+ override fun appendAsOverloadGroup(to: StringBuilder, platforms: PlatformsData, block: () -> Unit) {
div(to, "overload-group", calculateDataAttributes(platforms)) {
block()
}
@@ -69,27 +68,29 @@ open class KotlinWebsiteHtmlOutputBuilder(
override fun appendLink(href: String, body: () -> Unit) = wrap("<a href=\"$href\">", "</a>", body)
override fun appendTable(vararg columns: String, body: () -> Unit) {
- to.appendln("<table class=\"api-docs-table\">")
- body()
- to.appendln("</table>")
+ //to.appendln("<table class=\"api-docs-table\">")
+ div(to, "api-declarations-list") {
+ body()
+ }
+ //to.appendln("</table>")
}
override fun appendTableBody(body: () -> Unit) {
- to.appendln("<tbody>")
+ //to.appendln("<tbody>")
body()
- to.appendln("</tbody>")
+ //to.appendln("</tbody>")
}
override fun appendTableRow(body: () -> Unit) {
- to.appendln("<tr>")
+ //to.appendln("<tr>")
body()
- to.appendln("</tr>")
+ //to.appendln("</tr>")
}
override fun appendTableCell(body: () -> Unit) {
- to.appendln("<td>")
+// to.appendln("<td>")
body()
- to.appendln("\n</td>")
+// to.appendln("\n</td>")
}
override fun appendSymbol(text: String) {
@@ -122,34 +123,79 @@ open class KotlinWebsiteHtmlOutputBuilder(
else -> "identifier"
}
- fun calculateDataAttributes(platforms: Set<String>): String {
- fun String.isKotlinVersion() = this.startsWith("Kotlin")
- fun String.isJREVersion() = this.startsWith("JRE")
- val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)
- val jreVersion = platforms.singleOrNull(String::isJREVersion)
- val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() }
+ private data class PlatformsForElement(
+ val platformToVersion: Map<String, String>
+ )
+
+ private fun calculatePlatforms(platforms: PlatformsData): PlatformsForElement {
+ //val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)?.removePrefix("Kotlin ")
+ val jreVersion = platforms.keys.filter(String::isJREVersion).min()?.takeUnless { it.endsWith("6") }
+ val targetPlatforms = platforms.filterNot { it.key.isJREVersion() } +
+ listOfNotNull(jreVersion?.let { it to platforms[it]!! })
+
+ return PlatformsForElement(
+ targetPlatforms.mapValues { (_, nodes) -> effectiveSinceKotlinForNodes(nodes) }
+ )
+ }
- val kotlinVersionAttr = kotlinVersion?.let { " data-kotlin-version=\"$it\"" } ?: ""
- val jreVersionAttr = jreVersion?.let { " data-jre-version=\"$it\"" } ?: ""
- val platformsAttr = targetPlatforms.ifNotEmpty { " data-platform=\"${targetPlatforms.joinToString()}\"" } ?: ""
- return "$platformsAttr$kotlinVersionAttr$jreVersionAttr"
+ private fun calculateDataAttributes(platforms: PlatformsData): String {
+ val platformToVersion = calculatePlatforms(platforms).platformToVersion
+ val (platformNames, versions) = platformToVersion.toList().unzip()
+ return "data-platform=\"${platformNames.joinToString()}\" "+
+ "data-kotlin-version=\"${versions.joinToString()}\""
}
- override fun appendIndexRow(platforms: Set<String>, block: () -> Unit) {
- if (platforms.isNotEmpty())
- wrap("<tr${calculateDataAttributes(platforms)}>", "</tr>", block)
- else
- appendTableRow(block)
+ override fun appendIndexRow(platforms: PlatformsData, block: () -> Unit) {
+// if (platforms.isNotEmpty())
+// wrap("<tr${calculateDataAttributes(platforms)}>", "</tr>", block)
+// else
+// appendTableRow(block)
+ div(to, "declarations", otherAttributes = " ${calculateDataAttributes(platforms)}") {
+ block()
+ }
}
- override fun appendPlatforms(platforms: Set<String>) {}
+ override fun appendPlatforms(platforms: PlatformsData) {
+ val platformToVersion = calculatePlatforms(platforms).platformToVersion
+ div(to, "tags") {
+ div(to, "spacer") {}
+ platformToVersion.entries.sortedBy {
+ platformSortWeight(it.key)
+ }.forEach { (platform, version) ->
+ div(to, "tags__tag platform tag-value-$platform",
+ otherAttributes = " data-tag-version=\"$version\"") {
+ to.append(platform)
+ }
+ }
+ div(to, "tags__tag kotlin-version") {
+ to.append(mergeVersions(platformToVersion.values.toList()))
+ }
+ }
+ }
+
+ override fun appendAsNodeDescription(platforms: PlatformsData, block: () -> Unit) {
+ div(to, "node-page-main", otherAttributes = " ${calculateDataAttributes(platforms)}") {
+ block()
+ }
+
+ }
override fun appendBreadcrumbSeparator() {
to.append(" / ")
}
+ override fun appendPlatformsAsText(platforms: PlatformsData) {
+ appendHeader(5) {
+ val filtered = platforms.keys.filterNot { it.isJREVersion() }.sortedBy { platformSortWeight(it) }
+ if (filtered.isNotEmpty()) {
+ to.append("For ")
+ filtered.joinTo(to)
+ }
+ }
+ }
+
override fun appendSampleBlockCode(language: String, imports: () -> Unit, body: () -> Unit) {
- div(to, "sample") {
+ div(to, "sample", otherAttributes = " data-min-compiler-version=\"1.3\"") {
appendBlockCode(language) {
imports()
wrap("\n\nfun main(args: Array<String>) {".htmlEscape(), "}") {
@@ -169,6 +215,29 @@ open class KotlinWebsiteHtmlOutputBuilder(
appendContent(section)
}
}
+
+ override fun appendAsPlatformDependentBlock(platforms: PlatformsData, block: (PlatformsData) -> Unit) {
+ if (platforms.isNotEmpty())
+ wrap("<div ${calculateDataAttributes(platforms)}>", "</div>") {
+ block(platforms)
+ }
+ else
+ block(platforms)
+ }
+
+ override fun appendAsSummaryGroup(platforms: PlatformsData, block: (PlatformsData) -> Unit) {
+ div(to, "summary-group", otherAttributes = " ${calculateDataAttributes(platforms)}") {
+ block(platforms)
+ }
+ }
+
+ fun platformSortWeight(name: String) = when(name.toLowerCase()) {
+ "common" -> 0
+ "jvm" -> 1
+ "js" -> 3
+ "native" -> 4
+ else -> 2 // This is hack to support JRE/JUnit and so on
+ }
}
class KotlinWebsiteHtmlFormatService @Inject constructor(
@@ -184,3 +253,6 @@ class KotlinWebsiteHtmlFormatService @Inject constructor(
KotlinWebsiteHtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService)
}
+
+private fun String.isKotlinVersion() = this.startsWith("Kotlin")
+private fun String.isJREVersion() = this.startsWith("JRE", ignoreCase=true) \ No newline at end of file
diff --git a/core/src/main/kotlin/Formats/PackageListService.kt b/core/src/main/kotlin/Formats/PackageListService.kt
index 7b68098e..e675d927 100644
--- a/core/src/main/kotlin/Formats/PackageListService.kt
+++ b/core/src/main/kotlin/Formats/PackageListService.kt
@@ -32,10 +32,13 @@ class DefaultPackageListService @Inject constructor(
node.members.forEach { visit(it, relocated = true) }
}
NodeKind.GroupNode -> {
- //only children of top-level GN records interesting for us, since link to top-level ones should point to GN
- node.members.forEach { it.members.forEach { visit(it, relocated = true) } }
- //record signature of GN as signature of type alias and class merged to GN, so link to it should point to GN
- node.detailOrNull(NodeKind.Signature)?.let { visit(it, relocated = true) }
+ if (node.members.isNotEmpty()) {
+ // Only nodes only has single file is need to be relocated
+ // TypeAliases for example
+ node.origins
+ .filter { it.members.isEmpty() }
+ .forEach { visit(it, relocated = true) }
+ }
}
else -> {
if (nodeKind in NodeKind.classLike || nodeKind in NodeKind.memberLike) {
diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt
index 410de281..04810498 100644
--- a/core/src/main/kotlin/Formats/StructuredFormatService.kt
+++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt
@@ -1,18 +1,59 @@
package org.jetbrains.dokka
import org.jetbrains.dokka.LanguageService.RenderMode
+import org.jetbrains.kotlin.utils.keysToMap
import java.util.*
data class FormatLink(val text: String, val href: String)
+private data class Summarized(
+ val data: List<SummarizedBySummary>
+) {
+
+ constructor(data: Map<ContentNode, Map<ContentNode, List<DocumentationNode>>>) : this(
+ data.entries.map { (summary, signatureToMember) ->
+ SummarizedBySummary(
+ summary,
+ signatureToMember.map { (signature, nodes) ->
+ SummarizedNodes(signature, nodes)
+ }
+ )
+ }
+ )
+
+ data class SummarizedNodes(val content: ContentNode, val nodes: List<DocumentationNode>) {
+ val platforms = effectivePlatformsForMembers(nodes)
+ }
+ data class SummarizedBySummary(val content: ContentNode, val signatures: List<SummarizedNodes>) {
+ val platforms = effectivePlatformsForMembers(signatures.flatMap { it.nodes })
+ val platformsOnSignature = !samePlatforms(signatures.map { it.platforms })
+ }
+
+
+ fun computePlatformLevel(): PlatformPlacement {
+ if (data.any { it.platformsOnSignature }) {
+ return PlatformPlacement.Signature
+ }
+ if (samePlatforms(data.map { it.platforms })) {
+ return PlatformPlacement.Row
+ }
+ return PlatformPlacement.Summary
+ }
+ val platformPlacement: PlatformPlacement = computePlatformLevel()
+ val platforms = effectivePlatformsForMembers(data.flatMap { it.signatures.flatMap { it.nodes } })
+
+
+ enum class PlatformPlacement {
+ Row, Summary, Signature
+ }
+}
+
abstract class StructuredOutputBuilder(val to: StringBuilder,
val location: Location,
val generator: NodeLocationAwareGenerator,
val languageService: LanguageService,
val extension: String,
- val impliedPlatforms: List<String>) : FormattedOutputBuilder {
-
- protected fun DocumentationNode.location() = generator.location(this)
+ impliedPlatforms: List<String>) : FormattedOutputBuilder {
protected fun wrap(prefix: String, suffix: String, body: () -> Unit) {
to.append(prefix)
@@ -83,6 +124,14 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
+ open fun appendAsPlatformDependentBlock(platforms: PlatformsData, block: (PlatformsData) -> Unit) {
+ block(platforms)
+ }
+
+ open fun appendAsSummaryGroup(platforms: PlatformsData, block: (PlatformsData) -> Unit) {
+ appendAsPlatformDependentBlock(platforms, block)
+ }
+
open fun appendSymbol(text: String) {
appendText(text)
}
@@ -95,6 +144,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
appendText(text)
}
+ open fun appendAsNodeDescription(platforms: PlatformsData, block: () -> Unit) {
+ block()
+ }
+
fun appendEntity(text: String) {
to.append(text)
}
@@ -158,7 +211,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
is ContentNodeLink -> {
val node = content.node
- val linkTo = if (node != null) locationHref(location, node) else "#"
+ val linkTo = if (node != null) locationHref(location, node, generator) else "#"
appendLinkIfNotThisPage(linkTo, content)
}
is ContentExternalLink -> appendLinkIfNotThisPage(content.href, content)
@@ -196,31 +249,19 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
- open fun link(from: DocumentationNode,
- to: DocumentationNode,
- name: (DocumentationNode) -> String = DocumentationNode::name): FormatLink = link(from, to, extension, name)
-
- open fun link(from: DocumentationNode,
- to: DocumentationNode,
- extension: String,
- name: (DocumentationNode) -> String = DocumentationNode::name): FormatLink {
- if (to.owner?.kind == NodeKind.GroupNode)
- return link(from, to.owner!!, extension, name)
-
- if (from.owner?.kind == NodeKind.GroupNode)
- return link(from.owner!!, to, extension, name)
+ open fun link(
+ from: DocumentationNode,
+ to: DocumentationNode,
+ name: (DocumentationNode) -> String = DocumentationNode::name
+ ): FormatLink = link(from, to, extension, name)
- return FormatLink(name(to), from.location().relativePathTo(to.location()))
- }
-
- fun locationHref(from: Location, to: DocumentationNode): String {
- val topLevelPage = to.references(RefKind.TopLevelPage).singleOrNull()?.to
- if (topLevelPage != null) {
- val signature = to.detailOrNull(NodeKind.Signature)
- return from.relativePathTo(topLevelPage.location(), signature?.name ?: to.name)
- }
- return from.relativePathTo(to.location())
- }
+ open fun link(
+ from: DocumentationNode,
+ to: DocumentationNode,
+ extension: String,
+ name: (DocumentationNode) -> String = DocumentationNode::name
+ ): FormatLink =
+ FormatLink(name(to), generator.relativePathToLocation(from, to))
private fun DocumentationNode.isModuleOrPackage(): Boolean =
kind == NodeKind.Module || kind == NodeKind.Package
@@ -229,18 +270,25 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
block()
}
- protected open fun appendAsOverloadGroup(to: StringBuilder, platforms: Set<String>, block: () -> Unit) {
+ protected open fun appendAsOverloadGroup(to: StringBuilder, platforms: PlatformsData, block: () -> Unit) {
block()
}
- protected open fun appendIndexRow(platforms: Set<String>, block: () -> Unit) {
+ protected open fun appendIndexRow(platforms: PlatformsData, block: () -> Unit) {
appendTableRow(block)
}
- protected open fun appendPlatforms(platforms: Set<String>) {
+ protected open fun appendPlatformsAsText(platforms: PlatformsData) {
+ if (platforms.isNotEmpty()) {
+ appendLine()
+ appendText(platforms.keys.joinToString(prefix = "(", postfix = ")"))
+ }
+ }
+
+ protected open fun appendPlatforms(platforms: PlatformsData) {
if (platforms.isNotEmpty()) {
appendLine()
- appendText(platforms.joinToString(prefix = "(", postfix = ")"))
+ appendText(platforms.keys.joinToString(prefix = "(", postfix = ")"))
}
}
@@ -289,7 +337,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
val packageName = if (singleNode.name.isEmpty()) "<root>" else singleNode.name
appendHeader(2) { appendText("Package $packageName") }
}
- singleNode.appendPlatforms()
appendContent(singleNode.content)
} else {
val breakdownByName = nodes.groupBy { node -> node.name }
@@ -302,45 +349,136 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
private fun appendDocumentation(overloads: Iterable<DocumentationNode>, isSingleNode: Boolean) {
- val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> node.content }
+ val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node ->
+ when (node.kind) {
+ NodeKind.GroupNode -> node.origins.map { it.content }
+ else -> node.content
+ }
+ }
if (breakdownBySummary.size == 1) {
- formatOverloadGroup(breakdownBySummary.values.single(), isSingleNode)
+ val node = breakdownBySummary.values.single()
+ appendAsNodeDescription(effectivePlatformsForMembers(node)) {
+ formatOverloadGroup(node, isSingleNode)
+ }
} else {
for ((_, items) in breakdownBySummary) {
-
- appendAsOverloadGroup(to, platformsOfItems(items)) {
+ appendAsOverloadGroup(to, effectivePlatformsForMembers(items)) {
formatOverloadGroup(items)
}
-
}
}
}
private fun formatOverloadGroup(items: List<DocumentationNode>, isSingleNode: Boolean = false) {
+
+ val platformsPerGroup = samePlatforms(
+ items.flatMap {
+ if (it.kind == NodeKind.GroupNode) {
+ it.origins.groupBy { origin ->
+ languageService.render(origin)
+ }.values.map { origins -> effectivePlatformsForMembers(origins) }
+ } else {
+ listOf(effectivePlatformsForNode(it))
+ }
+ }
+ )
+
+ if (platformsPerGroup) {
+ appendAsPlatformDependentBlock(effectivePlatformsForMembers(items)) { platforms ->
+ appendPlatforms(platforms)
+ }
+ }
for ((index, item) in items.withIndex()) {
if (index > 0) appendLine()
+
+ if (item.kind == NodeKind.GroupNode) {
+ renderGroupNode(item, isSingleNode, !platformsPerGroup)
+ } else {
+ renderSimpleNode(item, isSingleNode, !platformsPerGroup)
+ }
+
+ }
+ // All items have exactly the same documentation, so we can use any item to render it
+ val item = items.first()
+ // TODO: remove this block cause there is no one node with OverloadGroupNote detail
+ item.details(NodeKind.OverloadGroupNote).forEach {
+ appendContent(it.content)
+ }
+
+ if (item.kind == NodeKind.GroupNode) {
+ val groupByContent = item.origins.groupBy { it.content }
+ if (groupByContent.count { !it.key.isEmpty() } > 1) {
+ if (groupByContent.size > 1) println("[mult] Found ov diff: ${generator.location(item).path}")
+ }
+ for ((content, origins) in groupByContent) {
+ if (content.isEmpty()) continue
+ appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms ->
+ if (groupByContent.count { !it.key.isEmpty() } > 1) {
+ appendPlatformsAsText(platforms)
+ }
+ appendContent(content.summary)
+ content.appendDescription()
+ }
+ }
+ } else {
+ if (!item.content.isEmpty()) {
+ val platforms = effectivePlatformsForNode(item)
+ appendAsPlatformDependentBlock(platforms) {
+ appendContent(item.summary)
+ item.content.appendDescription()
+ }
+ }
+ }
+ }
+
+
+ fun renderSimpleNode(item: DocumentationNode, isSingleNode: Boolean, withPlatforms: Boolean = true) {
+ appendAsPlatformDependentBlock(effectivePlatformsForMembers(listOf(item))) { platforms ->
+ // TODO: use summarizesignatures
val rendered = languageService.render(item)
item.detailOrNull(NodeKind.Signature)?.let {
if (item.kind !in NodeKind.classLike || !isSingleNode)
appendAnchor(it.name)
}
+ if (withPlatforms) {
+ appendPlatforms(platforms)
+ }
appendAsSignature(rendered) {
appendCode { appendContent(rendered) }
item.appendSourceLink()
}
item.appendOverrides()
item.appendDeprecation()
- item.appendPlatforms()
}
- // All items have exactly the same documentation, so we can use any item to render it
- val item = items.first()
- item.details(NodeKind.OverloadGroupNote).forEach {
- appendContent(it.content)
+ }
+
+ fun renderGroupNode(item: DocumentationNode, isSingleNode: Boolean, withPlatforms: Boolean = true) {
+ // TODO: use summarizesignatures
+ val groupBySignature = item.origins.groupBy {
+ languageService.render(it)
}
- appendContent(item.content.summary)
- item.appendDescription()
+ for ((sign, nodes) in groupBySignature) {
+ appendAsPlatformDependentBlock(effectivePlatformsForMembers(nodes)) { platforms ->
+ val first = nodes.first()
+ first.detailOrNull(NodeKind.Signature)?.let {
+ if (item.kind !in NodeKind.classLike || !isSingleNode)
+ appendAnchor(it.name)
+ }
+
+ if (withPlatforms) {
+ appendPlatforms(platforms)
+ }
+
+ appendAsSignature(sign) {
+ appendCode { appendContent(sign) }
+ }
+ first.appendOverrides()
+ first.appendDeprecation()
+ }
+
+ }
}
private fun DocumentationNode.appendSourceLink() {
@@ -355,7 +493,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
overrides.forEach {
appendParagraph {
to.append("Overrides ")
- val location = location().relativePathTo(it.location())
+ val location = generator.relativePathToLocation(this, it)
appendLink(FormatLink(it.owner!!.name + "." + it.name, location))
}
@@ -367,82 +505,95 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
val deprecationParameter = deprecation!!.details(NodeKind.Parameter).firstOrNull()
val deprecationValue = deprecationParameter?.details(NodeKind.Value)?.firstOrNull()
appendLine()
- if (deprecationValue != null) {
- appendStrong { to.append("Deprecated:") }
- appendText(" " + deprecationValue.name.removeSurrounding("\""))
- appendLine()
- appendLine()
- } else if (deprecation?.content != Content.Empty) {
- appendStrong { to.append("Deprecated:") }
- to.append(" ")
- appendContent(deprecation!!.content)
- } else {
- appendStrong { to.append("Deprecated") }
- appendLine()
- appendLine()
- }
- }
- }
-
- private fun DocumentationNode.appendPlatforms() {
- val platforms = if (isModuleOrPackage())
- platformsToShow.toSet() + platformsOfItems(members)
- else
- platformsToShow
-
- if (platforms.isEmpty()) return
-
- appendParagraph {
- appendStrong { to.append("Platform and version requirements:") }
- to.append(" " + platforms.joinToString())
- }
- }
-
- protected fun platformsOfItems(items: List<DocumentationNode>): Set<String> {
- val platforms = items.asSequence().map {
- when (it.kind) {
- NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module, NodeKind.GroupNode -> platformsOfItems(it.members)
- else -> it.platformsToShow.toSet()
- }
- }
-
- fun String.isKotlinVersion() = this.startsWith("Kotlin")
-
- // Calculating common platforms for items
- return platforms.reduce { result, platformsOfItem ->
- val otherKotlinVersion = result.find { it.isKotlinVersion() }
- val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() }
-
- // When no Kotlin version specified, it means that version is 1.0
- if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) {
- val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct()
-
- val minVersion = allKotlinVersions.min()!!
- val resultVersion = when {
- allKotlinVersions.size == 1 -> allKotlinVersions.single()
- minVersion.endsWith("+") -> minVersion
- else -> minVersion + "+"
+ when {
+ deprecationValue != null -> {
+ appendStrong { to.append("Deprecated:") }
+ appendText(" " + deprecationValue.name.removeSurrounding("\""))
+ appendLine()
+ appendLine()
+ }
+ deprecation?.content != Content.Empty -> {
+ appendStrong { to.append("Deprecated:") }
+ to.append(" ")
+ appendContent(deprecation!!.content)
+ }
+ else -> {
+ appendStrong { to.append("Deprecated") }
+ appendLine()
+ appendLine()
}
-
- result.intersect(otherPlatforms) + resultVersion
- } else {
- result.intersect(platformsOfItem)
}
}
}
- val DocumentationNode.platformsToShow: List<String>
- get() = platforms.let { if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it }
- private fun DocumentationNode.appendDescription() {
- if (content.description != ContentEmpty) {
- appendContent(content.description)
- }
- content.getSectionsWithSubjects().forEach {
+// protected fun platformsOfItems(items: List<DocumentationNode>): Set<String> {
+// val platforms = items.asSequence().map {
+// when (it.kind) {
+// NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module -> platformsOfItems(it.members)
+// NodeKind.GroupNode -> platformsOfItems(it.origins)
+// else -> it.platformsToShow.toSet()
+// }
+// }
+//
+// fun String.isKotlinVersion() = this.startsWith("Kotlin")
+//
+// if (platforms.count() == 0) return emptySet()
+//
+// // Calculating common platforms for items
+// return platforms.reduce { result, platformsOfItem ->
+// val otherKotlinVersion = result.find { it.isKotlinVersion() }
+// val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() }
+//
+// // When no Kotlin version specified, it means that version is 1.0
+// if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) {
+// result.intersect(platformsOfItem) + mergeVersions(otherKotlinVersion, kotlinVersions)
+// } else {
+// result.intersect(platformsOfItem)
+// }
+// }
+// }
+//
+// protected fun unionPlatformsOfItems(items: List<DocumentationNode>): Set<String> {
+// val platforms = items.asSequence().map {
+// when (it.kind) {
+// NodeKind.GroupNode -> unionPlatformsOfItems(it.origins)
+// else -> it.platformsToShow.toSet()
+// }
+// }
+//
+// fun String.isKotlinVersion() = this.startsWith("Kotlin")
+//
+// if (platforms.count() == 0) return emptySet()
+//
+// // Calculating common platforms for items
+// return platforms.reduce { result, platformsOfItem ->
+// val otherKotlinVersion = result.find { it.isKotlinVersion() }
+// val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() }
+//
+// // When no Kotlin version specified, it means that version is 1.0
+// if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) {
+// result.union(otherPlatforms) + mergeVersions(otherKotlinVersion, kotlinVersions)
+// } else {
+// result.union(otherPlatforms)
+// }
+// }
+// }
+
+// val DocumentationNode.platformsToShow: List<String>
+// get() = platforms
+
+ private fun Content.appendDescription() {
+ if (description != ContentEmpty) {
+ appendContent(description)
+ }
+
+
+ getSectionsWithSubjects().forEach {
appendSectionWithSubject(it.key, it.value)
}
- for (section in content.sections.filter { it.subjectName == null }) {
+ for (section in sections.filter { it.subjectName == null }) {
appendSectionWithTag(section)
}
}
@@ -461,6 +612,38 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
}
+
+ fun appendOriginsGroupByContent(node: DocumentationNode) {
+ require(node.kind == NodeKind.GroupNode)
+ val groupByContent =
+ node.origins.groupBy { it.content }
+ .mapValues { (_, origins) ->
+ effectivePlatformsForMembers(origins)
+ }
+ .filterNot { it.key.isEmpty() }
+ .toList()
+ .sortedByDescending { it.second.size }
+
+ if (groupByContent.size > 1) println("[mult] Found diff: ${generator.location(node).path}")
+ for ((content, platforms) in groupByContent) {
+ appendAsPlatformDependentBlock(platforms) {
+ if (groupByContent.size > 1) {
+ appendPlatformsAsText(platforms)
+ }
+ appendContent(content.summary)
+ content.appendDescription()
+ }
+ }
+ }
+ }
+
+ inner class SingleNodePageBuilder(val node: DocumentationNode, noHeader: Boolean = false) :
+ PageBuilder(listOf(node), noHeader) {
+
+ override fun build() {
+ super.build()
+ SectionsBuilder(node).build()
+ }
}