aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Marks <pmarks@virtuslab.com>2020-03-31 08:39:01 +0200
committerPaweł Marks <Kordyjan@users.noreply.github.com>2020-03-31 16:02:09 +0200
commit6fec129cc61bd2a54f9d1111057c650430426013 (patch)
treef375410110c17bb3e68723bbbc0f60d382d96fba
parent810f3c922fb4f11dc3fbdddee82d919189ed8526 (diff)
downloaddokka-6fec129cc61bd2a54f9d1111057c650430426013.tar.gz
dokka-6fec129cc61bd2a54f9d1111057c650430426013.tar.bz2
dokka-6fec129cc61bd2a54f9d1111057c650430426013.zip
Make PageContentBuilder to create proper content for all tags
-rw-r--r--core/src/main/kotlin/model/Documentable.kt29
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt124
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt16
-rw-r--r--plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt47
-rw-r--r--plugins/base/src/test/kotlin/utils/contentUtils.kt7
5 files changed, 169 insertions, 54 deletions
diff --git a/core/src/main/kotlin/model/Documentable.kt b/core/src/main/kotlin/model/Documentable.kt
index 00a26d90..fec94537 100644
--- a/core/src/main/kotlin/model/Documentable.kt
+++ b/core/src/main/kotlin/model/Documentable.kt
@@ -37,9 +37,27 @@ data class PlatformDependent<out T>(
yieldAll(map.values)
}
+ val allEntries: Sequence<Pair<PlatformData?, T>> = sequence {
+ expect?.also { yield(null to it) }
+ map.forEach { (k, v) -> yield(k to v) }
+ }
+
+ fun getOrExpect(platform: PlatformData): T? = map[platform] ?: expect
+
companion object {
fun <T> empty(): PlatformDependent<T> = PlatformDependent(emptyMap())
+
fun <T> from(platformData: PlatformData, element: T) = PlatformDependent(mapOf(platformData to element))
+
+ @Suppress("UNCHECKED_CAST")
+ fun <T> from(pairs: Iterable<Pair<PlatformData?, T>>) =
+ PlatformDependent(
+ pairs.filter { it.first != null }.toMap() as Map<PlatformData, T>,
+ pairs.firstOrNull { it.first == null }?.second
+ )
+
+ fun <T> from(vararg pairs: Pair<PlatformData?, T>) = from(pairs.asIterable())
+
fun <T> expectFrom(element: T) = PlatformDependent(map = emptyMap(), expect = element)
}
}
@@ -330,12 +348,18 @@ sealed class Projection
sealed class Bound : Projection()
data class OtherParameter(val name: String) : Bound()
object Star : Projection()
-data class TypeConstructor(val dri: DRI, val projections: List<Projection>, val modifier: FunctionModifiers = FunctionModifiers.NONE) : Bound()
+data class TypeConstructor(
+ val dri: DRI,
+ val projections: List<Projection>,
+ val modifier: FunctionModifiers = FunctionModifiers.NONE
+) : Bound()
+
data class Nullable(val inner: Bound) : Bound()
data class Variance(val kind: Kind, val inner: Bound) : Projection() {
enum class Kind { In, Out }
}
-data class PrimitiveJavaType(val name: String): Bound()
+
+data class PrimitiveJavaType(val name: String) : Bound()
object Void : Bound()
object JavaObject : Bound()
@@ -376,6 +400,7 @@ sealed class JavaVisibility(name: String) : Visibility(name) {
}
fun <T> PlatformDependent<T>?.orEmpty(): PlatformDependent<T> = this ?: PlatformDependent.empty()
+
sealed class DocumentableSource(val path: String)
class DescriptorDocumentableSource(val descriptor: DeclarationDescriptor) :
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
index 41d4b917..177d5021 100644
--- a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
+++ b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
@@ -3,15 +3,21 @@ package org.jetbrains.dokka.base.translators.documentables
import org.jetbrains.dokka.base.signatures.SignatureProvider
import org.jetbrains.dokka.base.transformers.documentables.InheritorsInfo
import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder.DocumentableContentBuilder
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.DFunction
-import org.jetbrains.dokka.model.doc.Property
-import org.jetbrains.dokka.model.doc.TagWrapper
+import org.jetbrains.dokka.model.doc.*
import org.jetbrains.dokka.model.properties.WithExtraProperties
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.utilities.DokkaLogger
-import org.jetbrains.kotlin.backend.common.phaser.defaultDumper
+import kotlin.reflect.KClass
+import kotlin.reflect.full.isSubclassOf
+
+private typealias GroupedTags = Map<KClass<out TagWrapper>, List<Pair<PlatformData?, TagWrapper>>>
+
+private val specialTags: Set<KClass<out TagWrapper>> =
+ setOf(Property::class, Description::class, Constructor::class, Receiver::class, Param::class)
+
open class DefaultPageCreator(
commentsToContentConverter: CommentsToContentConverter,
@@ -51,12 +57,12 @@ open class DefaultPageCreator(
open fun pageForFunction(f: DFunction) = MemberPageNode(f.name, contentForFunction(f), setOf(f.dri), f)
private val WithScope.filteredFunctions
- get() = functions.filter { it.extra[InheritedFunction]?.isInherited != true }
+ get() = functions.filter { it.extra[InheritedFunction]?.isInherited != true }
protected open fun contentForModule(m: DModule) = contentBuilder.contentFor(m) {
header(1) { text(m.name) }
block("Packages", 2, ContentKind.Packages, m.packages, m.platformData.toSet()) {
- link(it.name, it.dri)
+ link(it.name, it.dri)
}
// text("Index\n") TODO
// text("Link to allpage here")
@@ -123,7 +129,7 @@ open class DefaultPageCreator(
header(1) { text(e.name.orEmpty()) }
+buildSignature(e)
- +contentForComments(e) { it !is Property }
+ +contentForComments(e)
+contentForScope(e, e.dri, e.platformData)
}
@@ -135,7 +141,8 @@ open class DefaultPageCreator(
+buildSignature(c)
}
}
- +contentForComments(c) { it !is Property }
+ breakLine()
+ +contentForComments(c)
if (c is WithConstructors) {
block(
@@ -173,33 +180,98 @@ open class DefaultPageCreator(
+contentForScope(c, c.dri, c.platformData)
}
+ @Suppress("UNCHECKED_CAST")
+ private inline fun <reified T: TagWrapper> GroupedTags.withTypeUnnamed(): PlatformDependent<T> =
+ (this[T::class] as List<Pair<PlatformData, T>>?)
+ ?.let { PlatformDependent.from(it) }.orEmpty()
+
+ @Suppress("UNCHECKED_CAST")
+ private inline fun <reified T: NamedTagWrapper> GroupedTags.withTypeNamed(): Map<String, PlatformDependent<T>> =
+ (this[T::class] as List<Pair<PlatformData, T>>?)
+ ?.groupBy { it.second.name }
+ ?.mapValues { (_, v) -> PlatformDependent.from(v) }
+ .orEmpty()
+
protected open fun contentForComments(
- d: Documentable,
- filtering: (TagWrapper) -> Boolean = { true }
- ) = contentBuilder.contentFor(d) {
- d.documentation.map{(k,v) -> (k to v.children.filter(filtering).map{p -> (k to p)})}.flatMap { it.second }
- .groupBy { it.second.toHeaderString() }.mapValues {(k,v) -> v.groupBy { it.first }}
- .forEach{ groupedByHeader ->
- header(3) { text(groupedByHeader.key) }
- d.documentation.expect?.also{
- it.children.filter(filtering).filter{it.toHeaderString() == groupedByHeader.key}
- .forEach {
+ d: Documentable
+ ): List<ContentNode> {
+ val tags: GroupedTags = d.documentation.allEntries.flatMap { (pd, doc) ->
+ doc.children.asSequence().map { pd to it }
+ }.groupBy { it.second::class }
+
+ val platforms = d.platformData
+
+ fun DocumentableContentBuilder.contentForDescription() {
+ val description = tags.withTypeUnnamed<Description>()
+ if (description.any { it.value.root.children.isNotEmpty() }) {
+ platforms.forEach { platform ->
+ description.getOrExpect(platform)?.also {
+ group(platformData = setOf(platform)) {
comment(it.root)
breakLine()
}
+ }
}
- platformDependentHint(d.dri,groupedByHeader.value.keys){
- groupedByHeader.value.forEach{
- group(d.dri, setOf(it.key)){
- it.value.forEach {
- comment(it.second.root)
+ }
+ }
+
+ fun DocumentableContentBuilder.contentForParams() {
+ val receiver = tags.withTypeUnnamed<Receiver>()
+ val params = tags.withTypeNamed<Param>()
+
+ if (params.isNotEmpty()) {
+ header(4, kind = ContentKind.Parameters) { text("Parameters") }
+ table(kind = ContentKind.Parameters) {
+ platforms.flatMap { platform ->
+ val receiverRow = receiver.getOrExpect(platform)?.let {
+ buildGroup(platformData = setOf(platform)) {
+ text("<receiver>")
+ comment(it.root)
}
- breakLine()
}
+
+ val paramRows = params.mapNotNull { (_, param) ->
+ param.getOrExpect(platform)?.let {
+ buildGroup(platformData = setOf(platform)) {
+ text(it.name)
+ comment(it.root)
+ }
+ }
+ }
+
+ listOfNotNull(receiverRow) + paramRows
}
}
}
- }.children
+ }
+
+ fun DocumentableContentBuilder.contentForUnnamedTags() {
+ val unnamedTags: List<PlatformDependent<TagWrapper>> =
+ tags.filterNot { (k, _) -> k.isSubclassOf(NamedTagWrapper::class) || k in specialTags }
+ .map { (_, v) -> PlatformDependent.from(v) }
+ platforms.forEach { platform ->
+ unnamedTags.forEach { pdTag ->
+ pdTag.getOrExpect(platform)?.also { tag ->
+ group(platformData = setOf(platform)) {
+ header(4) { text(tag.toHeaderString()) }
+ comment(tag.root)
+ }
+ }
+ }
+ }
+ }
+
+ return contentBuilder.contentFor(d) {
+ if (tags.isNotEmpty()) {
+ header(3) { text("Description") }
+ platformDependentHint(platformData = platforms.toSet()) {
+ contentForDescription()
+ contentForParams()
+ contentForUnnamedTags()
+ }
+ }
+ }.children
+ }
protected open fun contentForFunction(f: DFunction) = contentBuilder.contentFor(f) {
group(f.dri, f.platformData.toSet(), ContentKind.Functions) {
@@ -221,4 +293,4 @@ open class DefaultPageCreator(
// ?.firstOrNull()
// ?.root
// ?.docTagSummary() ?: ""
-} \ No newline at end of file
+}
diff --git a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
index 516e5524..f77b4592 100644
--- a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
+++ b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
@@ -114,6 +114,22 @@ open class PageContentBuilder(
)
}
+ fun table(
+ dri: DRI = mainDRI,
+ kind: Kind = ContentKind.Main,
+ platformData: Set<PlatformData> = mainPlatformData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ operation: DocumentableContentBuilder.() -> List<ContentGroup>
+ ) {
+ contents += ContentTable(
+ emptyList(),
+ operation(),
+ DCI(setOf(mainDRI), kind),
+ platformData, styles, extra
+ )
+ }
+
fun <T : Documentable> block(
name: String,
level: Int,
diff --git a/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt b/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt
index 9f8ebb00..6b86d727 100644
--- a/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt
+++ b/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt
@@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test
import utils.pWrapped
import utils.signature
import utils.signatureWithReceiver
+import utils.unnamedTag
class ContentForParamsTest : AbstractCoreTest() {
private val testConfiguration = dokkaConfiguration {
@@ -94,10 +95,8 @@ class ContentForParamsTest : AbstractCoreTest() {
signature("function", null, "abc" to "String")
header(3) { +"Description" }
platformHinted {
- header(4) { +"Author" }
- +"Kordyjan"
- header(4) { +"Since" }
- +"0.11"
+ unnamedTag("Author") { +"Kordyjan" }
+ unnamedTag("Since") { +"0.11" }
}
}
}
@@ -129,10 +128,8 @@ class ContentForParamsTest : AbstractCoreTest() {
header(3) { +"Description" }
platformHinted {
pWrapped("comment to function")
- header(4) { +"Author" }
- +"Kordyjan"
- header(4) { +"Since" }
- +"0.11"
+ unnamedTag("Author") { +"Kordyjan" }
+ unnamedTag("Since") { +"0.11" }
}
}
}
@@ -167,7 +164,7 @@ class ContentForParamsTest : AbstractCoreTest() {
table {
group {
+"abc"
- +"comment to param"
+ group { +"comment to param" }
}
}
}
@@ -206,15 +203,15 @@ class ContentForParamsTest : AbstractCoreTest() {
table {
group {
+"first"
- +"comment to first param"
+ group { +"comment to first param" }
}
group {
+"second"
- +"comment to second param"
+ group { +"comment to second param" }
}
group {
+"third"
- +"comment to third param"
+ group { +"comment to third param" }
}
}
}
@@ -251,15 +248,15 @@ class ContentForParamsTest : AbstractCoreTest() {
table {
group {
+"first"
- +"comment to first param"
+ group { +"comment to first param" }
}
group {
+"second"
- +"comment to second param"
+ group { +"comment to second param" }
}
group {
+"third"
- +"comment to third param"
+ group { +"comment to third param" }
}
}
}
@@ -297,11 +294,11 @@ class ContentForParamsTest : AbstractCoreTest() {
table {
group {
+"<receiver>"
- +"comment to receiver"
+ group { +"comment to receiver" }
}
group {
+"abc"
- +"comment to param"
+ group { +"comment to param" }
}
}
}
@@ -339,11 +336,11 @@ class ContentForParamsTest : AbstractCoreTest() {
table {
group {
+"first"
- +"comment to first param"
+ group { +"comment to first param" }
}
group {
+"third"
- +"comment to third param"
+ group { +"comment to third param" }
}
}
}
@@ -384,21 +381,19 @@ class ContentForParamsTest : AbstractCoreTest() {
table {
group {
+"first"
- +"comment to first param"
+ group { +"comment to first param" }
}
group {
+"second"
- +"comment to second param"
+ group { +"comment to second param" }
}
group {
+"third"
- +"comment to third param"
+ group { +"comment to third param" }
}
}
- header(4) { +"Author" }
- +"Kordyjan"
- header(4) { +"Since" }
- +"0.11"
+ unnamedTag("Author") { +"Kordyjan" }
+ unnamedTag("Since") { +"0.11" }
}
}
}
diff --git a/plugins/base/src/test/kotlin/utils/contentUtils.kt b/plugins/base/src/test/kotlin/utils/contentUtils.kt
index 4bb36553..1e19058a 100644
--- a/plugins/base/src/test/kotlin/utils/contentUtils.kt
+++ b/plugins/base/src/test/kotlin/utils/contentUtils.kt
@@ -1,6 +1,7 @@
package utils
import matchers.content.*
+import org.jetbrains.dokka.pages.ContentGroup
//TODO: Try to unify those functions after update to 1.4
fun ContentMatcherBuilder<*>.signature(
@@ -53,4 +54,10 @@ fun ContentMatcherBuilder<*>.pWrapped(text: String) =
group {// TODO: remove it when double wrapping for descriptions will be resolved
group { +text }
br()
+ }
+
+fun ContentMatcherBuilder<*>.unnamedTag(tag: String, content: ContentMatcherBuilder<ContentGroup>.() -> Unit) =
+ group {
+ header(4) { +tag }
+ group { content() }
} \ No newline at end of file