Skip to content

Commit d9d8423

Browse files
authored
Fix page merging of implicit expect/actual with a single declaration (#4016)
The main idea of this fix is that pages with implicit expect/actual declarations and a single declaration should have the same name since they are merged by `PageMerger` based on the page name. Before the fix, pages with the same DRI/path were unmerged, which caused an exception.
1 parent fe809dc commit d9d8423

File tree

2 files changed

+76
-4
lines changed

2 files changed

+76
-4
lines changed

dokka-subprojects/plugin-base/src/main/kotlin/org/jetbrains/dokka/base/translators/documentables/DefaultPageCreator.kt

+8-4
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ public open class DefaultPageCreator(
117117
props.mergeClashingDocumentable().map(::pageForProperties)
118118
else
119119
classlikes.renameClashingDocumentable().map(::pageForClasslike) +
120-
functions.renameClashingDocumentable().map(::pageForFunction) +
121-
props.renameClashingDocumentable().mapNotNull(::pageForProperty)
120+
(functions + props).renameClashingDocumentable().mapNotNull(::pageForMember)
122121

123122
return ClasslikePageNode(
124123
documentables.first().nameAfterClash(), contentForClasslikesAndEntries(documentables), dri, documentables,
@@ -158,8 +157,7 @@ public open class DefaultPageCreator(
158157
entries.mergeClashingDocumentable().map(::pageForEnumEntries)
159158
else
160159
nestedClasslikes.renameClashingDocumentable().map(::pageForClasslike) +
161-
functions.renameClashingDocumentable().map(::pageForFunction) +
162-
props.renameClashingDocumentable().mapNotNull(::pageForProperty) +
160+
(functions + props).renameClashingDocumentable().mapNotNull(::pageForMember) +
163161
entries.renameClashingDocumentable().map(::pageForEnumEntry)
164162

165163

@@ -207,6 +205,12 @@ public open class DefaultPageCreator(
207205
return MemberPageNode(fs.first().nameAfterClash(), contentForMembers(fs), dri, fs)
208206
}
209207

208+
private fun pageForMember(d: Documentable): MemberPageNode? = when (d) {
209+
is DProperty -> pageForProperty(d)
210+
is DFunction -> pageForFunction(d)
211+
else -> throw IllegalStateException()
212+
}
213+
210214
public open fun pageForProperty(p: DProperty): MemberPageNode? =
211215
MemberPageNode(p.nameAfterClash(), contentForProperty(p), setOf(p.dri), listOf(p))
212216

dokka-subprojects/plugin-base/src/test/kotlin/expectActuals/ExpectActualsTest.kt

+68
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ package expectActuals
66

77
import org.jetbrains.dokka.DokkaSourceSetID
88
import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
9+
import org.jetbrains.dokka.model.DFunction
10+
import org.jetbrains.dokka.model.DProperty
11+
import org.jetbrains.dokka.model.dfs
912
import org.jetbrains.dokka.model.withDescendants
1013
import org.jetbrains.dokka.pages.ClasslikePageNode
14+
import org.jetbrains.dokka.pages.MemberPageNode
1115
import kotlin.test.Test
1216
import kotlin.test.assertEquals
1317
import kotlin.test.assertTrue
@@ -435,4 +439,68 @@ class ExpectActualsTest : BaseAbstractTest() {
435439
}
436440
}
437441
}
442+
443+
@Test
444+
fun `should merge an implicit-expectActual function with a single property #3685`() = testInline(
445+
"""
446+
/src/common/test.kt
447+
expect class Skiko
448+
449+
/src/jvm/test.kt
450+
actual class Skiko actual constructor() {
451+
val isShowing = false
452+
fun isShowing(): Boolean {
453+
return false
454+
}
455+
}
456+
457+
/src/native/test.kt
458+
actual class Skiko actual constructor(){
459+
fun isShowing(): Boolean {
460+
return false
461+
}
462+
}
463+
""".trimMargin(),
464+
multiplatformConfiguration
465+
) {
466+
pagesGenerationStage = { root ->
467+
val cl = root.dfs { it.name == "Skiko" && it is ClasslikePageNode } ?: throw IllegalStateException()
468+
assertEquals(2, cl.children.count { it.name == "[jvm]isShowing" })
469+
}
470+
renderingStage = { root, _ ->
471+
val documentables = (root.dfs { it.name == "[jvm]isShowing" } as MemberPageNode).documentables
472+
assertEquals(listOf(DFunction::class, DProperty::class), documentables.map { it::class })
473+
}
474+
}
475+
476+
@Test
477+
fun `should merge an implicit-expectActual property with a single function #3685`() = testInline(
478+
"""
479+
/src/common/test.kt
480+
expect class Skiko
481+
482+
/src/jvm/test.kt
483+
actual class Skiko actual constructor() {
484+
val isShowing = false
485+
fun isShowing(): Boolean {
486+
return false
487+
}
488+
}
489+
490+
/src/native/test.kt
491+
actual class Skiko actual constructor(){
492+
val isShowing = false
493+
}
494+
""".trimMargin(),
495+
multiplatformConfiguration
496+
) {
497+
pagesGenerationStage = { root ->
498+
val cl = root.dfs { it.name == "Skiko" && it is ClasslikePageNode } ?: throw IllegalStateException()
499+
assertEquals(2, cl.children.count { it.name == "[jvm]isShowing" })
500+
}
501+
renderingStage = { root, _ ->
502+
val documentables = (root.dfs { it.name == "[jvm]isShowing" } as MemberPageNode).documentables
503+
assertEquals(listOf(DFunction::class, DProperty::class), documentables.map { it::class })
504+
}
505+
}
438506
}

0 commit comments

Comments
 (0)