aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin
diff options
context:
space:
mode:
authorAndrzej Ratajczak <andrzej.ratajczak98@gmail.com>2020-06-25 14:22:51 +0200
committerAndrzej Ratajczak <32793002+BarkingBad@users.noreply.github.com>2020-09-08 12:52:59 +0200
commita1f8efc30b4421ce371b02b747bbeac24fafd7ba (patch)
tree7dba1baab9ad4d8db7436e65c7e9c26618a07c89 /plugins/base/src/main/kotlin
parent270ff58ea44b7700be45062f75bbc7fd50d183eb (diff)
downloaddokka-a1f8efc30b4421ce371b02b747bbeac24fafd7ba.tar.gz
dokka-a1f8efc30b4421ce371b02b747bbeac24fafd7ba.tar.bz2
dokka-a1f8efc30b4421ce371b02b747bbeac24fafd7ba.zip
Changed way of merging documentables to avoid exception on merging documentables of different types. Minor javadoc fixes. Changed constructor names. Add handling same name pages clash for different platforms
Diffstat (limited to 'plugins/base/src/main/kotlin')
-rw-r--r--plugins/base/src/main/kotlin/DokkaBase.kt2
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt1
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt40
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt410
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt45
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt2
6 files changed, 299 insertions, 201 deletions
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt
index 44a532f8..fcea6be9 100644
--- a/plugins/base/src/main/kotlin/DokkaBase.kt
+++ b/plugins/base/src/main/kotlin/DokkaBase.kt
@@ -54,7 +54,7 @@ class DokkaBase : DokkaPlugin() {
}
val documentableMerger by extending {
- CoreExtensions.documentableMerger with DefaultDocumentableMerger
+ CoreExtensions.documentableMerger providing ::DefaultDocumentableMerger
}
val deprecatedDocumentableFilter by extending {
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
index c25aa543..e085af1a 100644
--- a/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
+++ b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
@@ -4,6 +4,7 @@ import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProvider
import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation
import org.jetbrains.dokka.base.resolvers.shared.PackageList
+import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.model.DisplaySourceSet
import org.jetbrains.dokka.pages.RootPageNode
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt
index 096104cc..0269d7a6 100644
--- a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt
+++ b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt
@@ -1,5 +1,6 @@
package org.jetbrains.dokka.base.resolvers.local
+import org.jetbrains.dokka.base.renderers.sourceSets
import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.links.PointingToDeclaration
@@ -26,35 +27,46 @@ open class DokkaLocationProvider(
pageGraphRoot.children.forEach { registerPath(it, emptyList()) }
}
- protected open val pagesIndex: Map<DRI, ContentPage> =
+ protected val pagesIndex: Map<Pair<DRI, DisplaySourceSet>, ContentPage> =
pageGraphRoot.withDescendants().filterIsInstance<ContentPage>()
- .flatMap { it.dri.map { dri -> dri to it } }
+ .flatMap { page ->
+ page.dri.flatMap { dri ->
+ page.sourceSets().map { sourceSet -> (dri to sourceSet) to page }
+ }
+ }
.groupingBy { it.first }
- .aggregate { dri, _, (_, page), first ->
- if (first) page else throw AssertionError("Multiple pages associated with dri: $dri")
+ .aggregate { key, _, (_, page), first ->
+ if (first) page else throw AssertionError("Multiple pages associated with key: ${key.first}/${key.second}")
}
- protected open val anchorsIndex: Map<DRI, ContentPage> =
+ protected val anchorsIndex: Map<Pair<DRI, DisplaySourceSet>, ContentPage> =
pageGraphRoot.withDescendants().filterIsInstance<ContentPage>()
.flatMap { page ->
page.content.withDescendants()
.filter { it.extra[SymbolAnchorHint] != null }
.mapNotNull { it.dci.dri.singleOrNull() }
.distinct()
- .map { it to page }
+ .flatMap { dri ->
+ page.sourceSets().map { sourceSet ->
+ (dri to sourceSet) to page
+ }
+ }
}.toMap()
override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean) =
pathTo(node, context) + if (!skipExtension) extension else ""
- override fun resolve(dri: DRI, sourceSets: Set<DisplaySourceSet>, context: PageNode?) =
- getLocalLocation(dri, context)
- ?: getLocalLocation(dri.copy(target = PointingToDeclaration), context)
- // Not found in PageGraph, that means it's an external link
- ?: getExternalLocation(dri, sourceSets)
- ?: getExternalLocation(dri.copy(target = PointingToDeclaration), sourceSets)
-
- private fun getLocalLocation(dri: DRI, context: PageNode?): String? =
+ override fun resolve(dri: DRI, sourceSets: Set<DisplaySourceSet>, context: PageNode?): String? =
+ sourceSets.mapNotNull { sourceSet ->
+ val driWithSourceSet = Pair(dri, sourceSet)
+ getLocalLocation(driWithSourceSet, context)
+ ?: getLocalLocation(driWithSourceSet.copy(first = dri.copy(target = PointingToDeclaration)), context)
+ // Not found in PageGraph, that means it's an external link
+ ?: getExternalLocation(dri, sourceSets)
+ ?: getExternalLocation(dri.copy(target = PointingToDeclaration), sourceSets)
+ }.distinct().singleOrNull()
+
+ private fun getLocalLocation(dri: Pair<DRI, DisplaySourceSet>, context: PageNode?): String? =
pagesIndex[dri]?.let { resolve(it, context) }
?: anchorsIndex[dri]?.let { resolve(it, context) + "#$dri" }
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt
index 17ead667..d556c9cb 100644
--- a/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt
+++ b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt
@@ -1,195 +1,269 @@
package org.jetbrains.dokka.base.transformers.documentables
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaSourceSetID
import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.WithExtraProperties
import org.jetbrains.dokka.model.properties.mergeExtras
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.documentation.DocumentableMerger
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
-internal object DefaultDocumentableMerger : DocumentableMerger {
+internal class DefaultDocumentableMerger(context: DokkaContext) : DocumentableMerger {
+ private val dependencyInfo = context.getDependencyInfo()
- override fun invoke(modules: Collection<DModule>, context: DokkaContext): DModule {
- return modules.reduce { left, right ->
+ override fun invoke(modules: Collection<DModule>): DModule {
+
+ return topologicalSort(modules).reduce { left, right ->
val list = listOf(left, right)
DModule(
name = modules.map { it.name }.distinct().joinToString("|"),
packages = merge(
- list.flatMap { it.packages },
- DPackage::mergeWith
- ),
+ list.flatMap { it.packages }
+ ) { pck1, pck2 -> pck1.mergeWith(pck2) },
documentation = list.map { it.documentation }.flatMap { it.entries }.associate { (k, v) -> k to v },
expectPresentInSet = list.firstNotNullResult { it.expectPresentInSet },
sourceSets = list.flatMap { it.sourceSets }.toSet()
).mergeExtras(left, right)
}
}
-}
-private fun <T : Documentable> merge(elements: List<T>, reducer: (T, T) -> T): List<T> =
- elements.groupingBy { it.dri }
- .reduce { _, left, right -> reducer(left, right) }
- .values.toList()
+ private fun topologicalSort(allModules: Collection<DModule>): List<DModule> {
-private fun <T> mergeExpectActual(
- elements: List<T>,
- reducer: (T, T) -> T
-): List<T> where T : Documentable, T : WithExpectActual {
+ val modulesMap: Map<DokkaSourceSetID, ModuleOfDifferentTranslators> =
+ allModules.groupBy { it.sourceSets.single().sourceSetID }
- fun analyzeExpectActual(sameDriElements: List<T>) = sameDriElements.reduce(reducer)
+ //this returns representation of graph where directed edges are leading from module to modules that depend on it
+ val graph: Map<ModuleOfDifferentTranslators?, List<ModuleOfDifferentTranslators>> = modulesMap.flatMap { (_, module) ->
+ module.first().sourceSets.single().dependentSourceSets.map { sourceSet ->
+ modulesMap[sourceSet] to module
+ }
+ }.groupBy { it.first }.entries
+ .map { it.key to it.value.map { it.second } }
+ .toMap()
- return elements.groupBy { it.dri }.values.map(::analyzeExpectActual)
-}
-fun DPackage.mergeWith(other: DPackage): DPackage = copy(
- functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
- properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
- classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- typealiases = merge(typealiases + other.typealiases, DTypeAlias::mergeWith),
- sourceSets = sourceSets + other.sourceSets
-).mergeExtras(this, other)
-
-fun DFunction.mergeWith(other: DFunction): DFunction = copy(
- parameters = merge(this.parameters + other.parameters, DParameter::mergeWith),
- receiver = receiver?.let { r -> other.receiver?.let { r.mergeWith(it) } ?: r } ?: other.receiver,
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sources = sources + other.sources,
- visibility = visibility + other.visibility,
- modifier = modifier + other.modifier,
- sourceSets = sourceSets + other.sourceSets,
- generics = merge(generics + other.generics, DTypeParameter::mergeWith)
-).mergeExtras(this, other)
-
-fun DProperty.mergeWith(other: DProperty): DProperty = copy(
- receiver = receiver?.let { r -> other.receiver?.let { r.mergeWith(it) } ?: r } ?: other.receiver,
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sources = sources + other.sources,
- visibility = visibility + other.visibility,
- modifier = modifier + other.modifier,
- sourceSets = sourceSets + other.sourceSets,
- getter = getter?.let { g -> other.getter?.let { g.mergeWith(it) } ?: g } ?: other.getter,
- setter = setter?.let { s -> other.setter?.let { s.mergeWith(it) } ?: s } ?: other.setter,
- generics = merge(generics + other.generics, DTypeParameter::mergeWith)
-).mergeExtras(this, other)
-
-fun DClasslike.mergeWith(other: DClasslike): DClasslike = when {
- this is DClass && other is DClass -> mergeWith(other)
- this is DEnum && other is DEnum -> mergeWith(other)
- this is DInterface && other is DInterface -> mergeWith(other)
- this is DObject && other is DObject -> mergeWith(other)
- this is DAnnotation && other is DAnnotation -> mergeWith(other)
- else -> throw IllegalStateException("${this::class.qualifiedName} ${this.name} cannot be mergesd with ${other::class.qualifiedName} ${other.name}")
+ val visited = modulesMap.map { it.value to false }.toMap().toMutableMap()
+ val topologicalSortedList: MutableList<ModuleOfDifferentTranslators> = mutableListOf()
+
+ fun dfs(module: ModuleOfDifferentTranslators) {
+ visited[module] = true
+ graph[module]?.forEach { if (!visited[it]!!) dfs(it) }
+ topologicalSortedList.add(0, module)
+ }
+ modulesMap.values.forEach { if (!visited[it]!!) dfs(it) }
+
+ return topologicalSortedList.flatten()
+ }
+
+ private fun DokkaContext.getDependencyInfo()
+ : Map<DokkaConfiguration.DokkaSourceSet, List<DokkaConfiguration.DokkaSourceSet>> {
+
+ fun getDependencies(sourceSet: DokkaConfiguration.DokkaSourceSet): List<DokkaConfiguration.DokkaSourceSet> =
+ listOf(sourceSet) + configuration.sourceSets.filter {
+ it.sourceSetID in sourceSet.dependentSourceSets
+ }.flatMap { getDependencies(it) }
+
+ return configuration.sourceSets.map { it to getDependencies(it) }.toMap()
+ }
+
+ private fun <T : Documentable> merge(elements: List<T>, reducer: (T, T) -> T): List<T> =
+ elements.groupingBy { it.dri }
+ .reduce { _, left, right -> reducer(left, right) }
+ .values.toList()
+
+ private fun <T> mergeExpectActual(
+ elements: List<T>,
+ reducer: (T, T) -> T
+ ): List<T> where T : Documentable, T : WithExpectActual {
+
+ fun analyzeExpectActual(sameDriElements: List<T>) = sameDriElements
+ .partition { it.expectPresentInSet != null }
+ .let { (expects, actuals) ->
+ expects.map { expect ->
+ listOf(expect) + actuals.filter { actual ->
+ dependencyInfo[actual.sourceSets.single()]
+ ?.contains(expect.expectPresentInSet!!)
+ ?: throw IllegalStateException("Cannot resolve expect/actual relation for ${actual.name}")
+ }
+ }.map { it.reduce(reducer) }
+ }
+
+ fun T.isExpectActual(): Boolean =
+ this.safeAs<WithExtraProperties<T>>().let { it != null && it.extra[IsExpectActual] != null }
+
+ fun mergeClashingElements(elements: List<T>) = if(elements.size <= 1) elements else elements.map {
+ when(it) {
+ is DClass -> it.copy(name = "${it.name}(${it.sourceSets.single().analysisPlatform.key})")
+ is DObject -> it.copy(name = "${it.name}(${it.sourceSets.single().analysisPlatform.key})")
+ is DAnnotation -> it.copy(name = "${it.name}(${it.sourceSets.single().analysisPlatform.key})")
+ is DInterface -> it.copy(name = "${it.name}(${it.sourceSets.single().analysisPlatform.key})")
+ is DEnum -> it.copy(name = "${it.name}(${it.sourceSets.single().analysisPlatform.key})")
+ is DFunction -> it.copy(name = "${it.name}(${it.sourceSets.single().analysisPlatform.key})")
+ is DProperty -> it.copy(name = "${it.name}(${it.sourceSets.single().analysisPlatform.key})")
+ else -> elements
+ }
+ } as List<T>
+
+ return elements.partition {
+ it.isExpectActual()
+ }.let { (expectActuals, notExpectActuals) ->
+ notExpectActuals.groupBy { it.dri }.values.flatMap(::mergeClashingElements) +
+ expectActuals.groupBy { it.dri }.values.flatMap(::analyzeExpectActual)
+ }
+ }
+
+ fun DPackage.mergeWith(other: DPackage): DPackage = copy(
+ functions = mergeExpectActual(functions + other.functions) { f1, f2 -> f1.mergeWith(f2) },
+ properties = mergeExpectActual(properties + other.properties) { p1, p2 -> p1.mergeWith(p2) },
+ classlikes = mergeExpectActual(classlikes + other.classlikes) { c1, c2 -> c1.mergeWith(c2) },
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ typealiases = merge(typealiases + other.typealiases) { ta1, ta2 -> ta1.mergeWith(ta2) },
+ sourceSets = sourceSets + other.sourceSets
+ ).mergeExtras(this, other)
+
+ fun DFunction.mergeWith(other: DFunction): DFunction = copy(
+ parameters = merge(this.parameters + other.parameters) { p1, p2 -> p1.mergeWith(p2) },
+ receiver = receiver?.let { r -> other.receiver?.let { r.mergeWith(it) } ?: r } ?: other.receiver,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources + other.sources,
+ visibility = visibility + other.visibility,
+ modifier = modifier + other.modifier,
+ sourceSets = sourceSets + other.sourceSets,
+ generics = merge(generics + other.generics) { tp1, tp2 -> tp1.mergeWith(tp2) },
+ ).mergeExtras(this, other)
+
+ fun DProperty.mergeWith(other: DProperty): DProperty = copy(
+ receiver = receiver?.let { r -> other.receiver?.let { r.mergeWith(it) } ?: r } ?: other.receiver,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources + other.sources,
+ visibility = visibility + other.visibility,
+ modifier = modifier + other.modifier,
+ sourceSets = sourceSets + other.sourceSets,
+ getter = getter?.let { g -> other.getter?.let { g.mergeWith(it) } ?: g } ?: other.getter,
+ setter = setter?.let { s -> other.setter?.let { s.mergeWith(it) } ?: s } ?: other.setter,
+ generics = merge(generics + other.generics) { tp1, tp2 -> tp1.mergeWith(tp2) },
+ ).mergeExtras(this, other)
+
+ fun DClasslike.mergeWith(other: DClasslike): DClasslike = when {
+ this is DClass && other is DClass -> mergeWith(other)
+ this is DEnum && other is DEnum -> mergeWith(other)
+ this is DInterface && other is DInterface -> mergeWith(other)
+ this is DObject && other is DObject -> mergeWith(other)
+ this is DAnnotation && other is DAnnotation -> mergeWith(other)
+ else -> throw IllegalStateException("${this::class.qualifiedName} ${this.name} cannot be merged with ${other::class.qualifiedName} ${other.name}")
+ }
+
+ fun DClass.mergeWith(other: DClass): DClass = copy(
+ constructors = mergeExpectActual(
+ constructors + other.constructors
+ ) { f1, f2 -> f1.mergeWith(f2) },
+ functions = mergeExpectActual(functions + other.functions) { f1, f2 -> f1.mergeWith(f2) },
+ properties = mergeExpectActual(properties + other.properties) { p1, p2 -> p1.mergeWith(p2) },
+ classlikes = mergeExpectActual(classlikes + other.classlikes) { c1, c2 -> c1.mergeWith(c2) },
+ companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
+ generics = merge(generics + other.generics) { tp1, tp2 -> tp1.mergeWith(tp2) },
+ modifier = modifier + other.modifier,
+ supertypes = supertypes + other.supertypes,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources + other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+ ).mergeExtras(this, other)
+
+ fun DEnum.mergeWith(other: DEnum): DEnum = copy(
+ entries = merge(entries + other.entries) { ee1, ee2 -> ee1.mergeWith(ee2) },
+ constructors = mergeExpectActual(
+ constructors + other.constructors
+ ) { f1, f2 -> f1.mergeWith(f2) },
+ functions = mergeExpectActual(functions + other.functions) { f1, f2 -> f1.mergeWith(f2) },
+ properties = mergeExpectActual(properties + other.properties) { p1, p2 -> p1.mergeWith(p2) },
+ classlikes = mergeExpectActual(classlikes + other.classlikes) { c1, c2 -> c1.mergeWith(c2) },
+ companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
+ supertypes = supertypes + other.supertypes,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources + other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+ ).mergeExtras(this, other)
+
+ fun DEnumEntry.mergeWith(other: DEnumEntry): DEnumEntry = copy(
+ functions = mergeExpectActual(functions + other.functions) { f1, f2 -> f1.mergeWith(f2) },
+ properties = mergeExpectActual(properties + other.properties) { p1, p2 -> p1.mergeWith(p2) },
+ classlikes = mergeExpectActual(classlikes + other.classlikes) { c1, c2 -> c1.mergeWith(c2) },
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sourceSets = sourceSets + other.sourceSets
+ ).mergeExtras(this, other)
+
+ fun DObject.mergeWith(other: DObject): DObject = copy(
+ functions = mergeExpectActual(functions + other.functions) { f1, f2 -> f1.mergeWith(f2) },
+ properties = mergeExpectActual(properties + other.properties) { p1, p2 -> p1.mergeWith(p2) },
+ classlikes = mergeExpectActual(classlikes + other.classlikes) { c1, c2 -> c1.mergeWith(c2) },
+ supertypes = supertypes + other.supertypes,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources + other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+ ).mergeExtras(this, other)
+
+ fun DInterface.mergeWith(other: DInterface): DInterface = copy(
+ functions = mergeExpectActual(functions + other.functions) { f1, f2 -> f1.mergeWith(f2) },
+ properties = mergeExpectActual(properties + other.properties) { p1, p2 -> p1.mergeWith(p2) },
+ classlikes = mergeExpectActual(classlikes + other.classlikes) { c1, c2 -> c1.mergeWith(c2) },
+ companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
+ generics = merge(generics + other.generics) { tp1, tp2 -> tp1.mergeWith(tp2) },
+ supertypes = supertypes + other.supertypes,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources + other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+ ).mergeExtras(this, other)
+
+ fun DAnnotation.mergeWith(other: DAnnotation): DAnnotation = copy(
+ constructors = mergeExpectActual(
+ constructors + other.constructors
+ ) { f1, f2 -> f1.mergeWith(f2) },
+ functions = mergeExpectActual(functions + other.functions) { f1, f2 -> f1.mergeWith(f2) },
+ properties = mergeExpectActual(properties + other.properties) { p1, p2 -> p1.mergeWith(p2) },
+ classlikes = mergeExpectActual(classlikes + other.classlikes) { c1, c2 -> c1.mergeWith(c2) },
+ companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources + other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets,
+ generics = merge(generics + other.generics) { tp1, tp2 -> tp1.mergeWith(tp2) }
+ ).mergeExtras(this, other)
+
+ fun DParameter.mergeWith(other: DParameter): DParameter = copy(
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sourceSets = sourceSets + other.sourceSets
+ ).mergeExtras(this, other)
+
+ fun DTypeParameter.mergeWith(other: DTypeParameter): DTypeParameter = copy(
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sourceSets = sourceSets + other.sourceSets
+ ).mergeExtras(this, other)
+
+ fun DTypeAlias.mergeWith(other: DTypeAlias): DTypeAlias = copy(
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ underlyingType = underlyingType + other.underlyingType,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+ ).mergeExtras(this, other)
}
-fun DClass.mergeWith(other: DClass): DClass = copy(
- constructors = mergeExpectActual(
- constructors + other.constructors,
- DFunction::mergeWith
- ),
- functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
- properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
- classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
- companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
- generics = merge(generics + other.generics, DTypeParameter::mergeWith),
- modifier = modifier + other.modifier,
- supertypes = supertypes + other.supertypes,
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sources = sources + other.sources,
- visibility = visibility + other.visibility,
- sourceSets = sourceSets + other.sourceSets
-).mergeExtras(this, other)
-
-fun DEnum.mergeWith(other: DEnum): DEnum = copy(
- entries = merge(entries + other.entries, DEnumEntry::mergeWith),
- constructors = mergeExpectActual(
- constructors + other.constructors,
- DFunction::mergeWith
- ),
- functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
- properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
- classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
- companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
- supertypes = supertypes + other.supertypes,
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sources = sources + other.sources,
- visibility = visibility + other.visibility,
- sourceSets = sourceSets + other.sourceSets
-).mergeExtras(this, other)
-
-fun DEnumEntry.mergeWith(other: DEnumEntry): DEnumEntry = copy(
- functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
- properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
- classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sourceSets = sourceSets + other.sourceSets
-).mergeExtras(this, other)
-
-fun DObject.mergeWith(other: DObject): DObject = copy(
- functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
- properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
- classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
- supertypes = supertypes + other.supertypes,
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sources = sources + other.sources,
- visibility = visibility + other.visibility,
- sourceSets = sourceSets + other.sourceSets
-).mergeExtras(this, other)
-
-fun DInterface.mergeWith(other: DInterface): DInterface = copy(
- functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
- properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
- classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
- companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
- generics = merge(generics + other.generics, DTypeParameter::mergeWith),
- supertypes = supertypes + other.supertypes,
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sources = sources + other.sources,
- visibility = visibility + other.visibility,
- sourceSets = sourceSets + other.sourceSets
-).mergeExtras(this, other)
-
-fun DAnnotation.mergeWith(other: DAnnotation): DAnnotation = copy(
- constructors = mergeExpectActual(
- constructors + other.constructors,
- DFunction::mergeWith
- ),
- functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
- properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
- classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
- companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sources = sources + other.sources,
- visibility = visibility + other.visibility,
- sourceSets = sourceSets + other.sourceSets,
- generics = merge(generics + other.generics, DTypeParameter::mergeWith)
-).mergeExtras(this, other)
-
-fun DParameter.mergeWith(other: DParameter): DParameter = copy(
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sourceSets = sourceSets + other.sourceSets
-).mergeExtras(this, other)
-
-fun DTypeParameter.mergeWith(other: DTypeParameter): DTypeParameter = copy(
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- sourceSets = sourceSets + other.sourceSets
-).mergeExtras(this, other)
-
-fun DTypeAlias.mergeWith(other: DTypeAlias): DTypeAlias = copy(
- documentation = documentation + other.documentation,
- expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
- underlyingType = underlyingType + other.underlyingType,
- visibility = visibility + other.visibility,
- sourceSets = sourceSets + other.sourceSets
-).mergeExtras(this, other)
+private typealias ModuleOfDifferentTranslators = List<DModule>
diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
index 8e5a1927..57d4f151 100644
--- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -12,6 +12,7 @@ import org.jetbrains.dokka.model.*
import org.jetbrains.dokka.model.Nullable
import org.jetbrains.dokka.model.TypeConstructor
import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.model.properties.ExtraProperty
import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator
@@ -140,6 +141,7 @@ private class DokkaDescriptorVisitor(
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
+ val isActual = descriptor.isActual
val info = descriptor.resolveClassDescriptionData()
return DInterface(
@@ -156,11 +158,11 @@ private class DokkaDescriptorVisitor(
generics = descriptor.declaredTypeParameters.map { it.toVariantTypeParameter() },
companion = descriptor.companion(driWithPlatform),
sourceSets = setOf(sourceSet),
- extra = PropertyContainer.withAll(
+ extra = PropertyContainer.withAll<DInterface>(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
- )
+ ).let { if (isExpect || isActual) it + IsExpectActual else it }
)
}
@@ -168,6 +170,7 @@ private class DokkaDescriptorVisitor(
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
+ val isActual = descriptor.isActual
val info = descriptor.resolveClassDescriptionData()
@@ -183,11 +186,11 @@ private class DokkaDescriptorVisitor(
supertypes = info.supertypes.toSourceSetDependent(),
documentation = info.docs,
sourceSets = setOf(sourceSet),
- extra = PropertyContainer.withAll(
+ extra = PropertyContainer.withAll<DObject>(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
- )
+ ).let { if (isExpect || isActual) it + IsExpectActual else it }
)
}
@@ -195,6 +198,7 @@ private class DokkaDescriptorVisitor(
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
+ val isActual = descriptor.isActual
val info = descriptor.resolveClassDescriptionData()
return DEnum(
@@ -212,11 +216,11 @@ private class DokkaDescriptorVisitor(
documentation = info.docs,
companion = descriptor.companion(driWithPlatform),
sourceSets = setOf(sourceSet),
- extra = PropertyContainer.withAll(
+ extra = PropertyContainer.withAll<DEnum>(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
- )
+ ).let { if (isExpect || isActual) it + IsExpectActual else it }
)
}
@@ -245,6 +249,8 @@ private class DokkaDescriptorVisitor(
fun annotationDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DAnnotation {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
+ val isExpect = descriptor.isExpect
+ val isActual = descriptor.isActual
return DAnnotation(
dri = driWithPlatform.dri,
@@ -253,12 +259,12 @@ private class DokkaDescriptorVisitor(
classlikes = scope.classlikes(driWithPlatform),
functions = scope.functions(driWithPlatform),
properties = scope.properties(driWithPlatform),
- expectPresentInSet = null,
+ expectPresentInSet = sourceSet.takeIf { isExpect },
sourceSets = setOf(sourceSet),
- extra = PropertyContainer.withAll(
+ extra = PropertyContainer.withAll<DAnnotation>(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
- ),
+ ).let { if (isExpect || isActual) it + IsExpectActual else it },
companion = descriptor.companionObjectDescriptor?.let { objectDescriptor(it, driWithPlatform) },
visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
generics = descriptor.declaredTypeParameters.map { it.toVariantTypeParameter() },
@@ -271,6 +277,7 @@ private class DokkaDescriptorVisitor(
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
+ val isActual = descriptor.isActual
val info = descriptor.resolveClassDescriptionData()
val actual = descriptor.createSources()
@@ -296,17 +303,18 @@ private class DokkaDescriptorVisitor(
modifier = descriptor.modifier().toSourceSetDependent(),
companion = descriptor.companion(driWithPlatform),
sourceSets = setOf(sourceSet),
- extra = PropertyContainer.withAll(
+ extra = PropertyContainer.withAll<DClass>(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
- )
+ ).let { if (isExpect || isActual) it + IsExpectActual else it }
)
}
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, parent: DRIWithPlatformInfo): DProperty {
val dri = parent.dri.copy(callable = Callable.from(descriptor))
val isExpect = descriptor.isExpect
+ val isActual = descriptor.isActual
val actual = descriptor.createSources()
return DProperty(
@@ -333,7 +341,7 @@ private class DokkaDescriptorVisitor(
(descriptor.additionalExtras() + descriptor.getAnnotationsWithBackingField()
.toAdditionalExtras()).toSet().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotationsWithBackingField().toSourceSetDependent().toAnnotations()
- )
+ ).let { if (isExpect || isActual) it + IsExpectActual else it }
)
}
@@ -346,6 +354,7 @@ private class DokkaDescriptorVisitor(
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, parent: DRIWithPlatformInfo): DFunction {
val (dri, inheritedFrom) = descriptor.createDRI()
val isExpect = descriptor.isExpect
+ val isActual = descriptor.isActual
val actual = descriptor.createSources()
return DFunction(
@@ -367,11 +376,11 @@ private class DokkaDescriptorVisitor(
modifier = descriptor.modifier().toSourceSetDependent(),
type = descriptor.returnType!!.toBound(),
sourceSets = setOf(sourceSet),
- extra = PropertyContainer.withAll(
+ extra = PropertyContainer.withAll<DFunction>(
InheritedFunction(inheritedFrom.toSourceSetDependent()),
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
- )
+ ).let { if (isExpect || isActual) it + IsExpectActual else it }
)
}
@@ -380,6 +389,7 @@ private class DokkaDescriptorVisitor(
val dri = parent.dri.copy(callable = Callable.from(descriptor, name))
val actual = descriptor.createSources()
val isExpect = descriptor.isExpect
+ val isActual = descriptor.isActual
return DFunction(
dri = dri,
@@ -418,7 +428,7 @@ private class DokkaDescriptorVisitor(
if (descriptor.isPrimary) {
it + PrimaryConstructorExtra
} else it
- }
+ }.let { if (isExpect || isActual) it + IsExpectActual else it }
)
}
@@ -443,6 +453,7 @@ private class DokkaDescriptorVisitor(
val dri = parent.copy(callable = Callable.from(descriptor))
val isGetter = descriptor is PropertyGetterDescriptor
val isExpect = descriptor.isExpect
+ val isActual = descriptor.isActual
fun PropertyDescriptor.asParameter(parent: DRI) =
DParameter(
@@ -490,10 +501,10 @@ private class DokkaDescriptorVisitor(
},
sources = descriptor.createSources(),
sourceSets = setOf(sourceSet),
- extra = PropertyContainer.withAll(
+ extra = PropertyContainer.withAll<DFunction>(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
- )
+ ).let { if (isExpect || isActual) it + IsExpectActual else it }
)
}
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
index 3cc77f96..615412f4 100644
--- a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
+++ b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
@@ -490,7 +490,7 @@ open class DefaultPageCreator(
header(2, name, kind = kind)
table(kind, extra = extra, styles = emptySet()) {
collection
- .groupBy { it.name }
+ .groupBy { it.name } // This groupBy should probably use LocationProvider
// This hacks displaying actual typealias signatures along classlike ones
.mapValues { if (it.value.any { it is DClasslike }) it.value.filter { it !is DTypeAlias } else it.value }
.toSortedMap(compareBy(nullsLast(String.CASE_INSENSITIVE_ORDER)) { it })