diff options
author | Andrzej Ratajczak <andrzej.ratajczak98@gmail.com> | 2020-06-25 14:22:51 +0200 |
---|---|---|
committer | Andrzej Ratajczak <32793002+BarkingBad@users.noreply.github.com> | 2020-09-08 12:52:59 +0200 |
commit | a1f8efc30b4421ce371b02b747bbeac24fafd7ba (patch) | |
tree | 7dba1baab9ad4d8db7436e65c7e9c26618a07c89 /plugins/base/src/main/kotlin | |
parent | 270ff58ea44b7700be45062f75bbc7fd50d183eb (diff) | |
download | dokka-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')
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 }) |