diff --git a/dokka-subprojects/analysis-kotlin-descriptors-compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt b/dokka-subprojects/analysis-kotlin-descriptors-compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt index fffdd2f561..65a3097d2b 100644 --- a/dokka-subprojects/analysis-kotlin-descriptors-compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt +++ b/dokka-subprojects/analysis-kotlin-descriptors-compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt @@ -740,8 +740,6 @@ private class DokkaDescriptorVisitor( ): DFunction { val dri = parent.copy(callable = Callable.from(descriptor)) val isGetter = descriptor is PropertyGetterDescriptor - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual suspend fun PropertyDescriptor.asParameter(parent: DRI) = DParameter( @@ -798,7 +796,7 @@ private class DokkaDescriptorVisitor( type = descriptor.returnType!!.toBound(), generics = generics.await(), modifier = descriptor.modifier().toSourceSetDependent(), - expectPresentInSet = sourceSet.takeIf { isExpect }, + expectPresentInSet = null, receiver = descriptor.extensionReceiverParameter?.let { visitReceiverParameterDescriptor( it, @@ -807,7 +805,7 @@ private class DokkaDescriptorVisitor( }, sources = descriptor.createSources(), sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), + isExpectActual = false, extra = PropertyContainer.withAll( descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), diff --git a/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt b/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt index 3e0bc8ebc3..fc183a13cd 100644 --- a/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt +++ b/dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt @@ -40,11 +40,8 @@ import org.jetbrains.kotlin.analysis.api.types.* import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.java.JavaVisibilities -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier -import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier internal class DefaultSymbolToDocumentableTranslator(context: DokkaContext) : AsyncSourceToDocumentableTranslator { private val kotlinAnalysis = context.plugin().querySingle { kotlinAnalysis } @@ -93,12 +90,6 @@ internal class DokkaSymbolVisitor( private fun T.toSourceSetDependent() = if (this != null) mapOf(sourceSet to this) else emptyMap() - // KT-54846 will replace - private val KtDeclarationSymbol.isActual - get() = (psi as? KtModifierListOwner)?.hasActualModifier() == true - private val KtDeclarationSymbol.isExpect - get() = (psi as? KtModifierListOwner)?.hasExpectModifier() == true - private fun List.filterSymbolsInSourceSet(moduleFiles: Set): List = filter { when (val file = it.psi?.containingFile) { is KtFile -> moduleFiles.contains(file) @@ -481,8 +472,10 @@ internal class DokkaSymbolVisitor( withExceptionCatcher(propertySymbol) { val dri = createDRIWithOverridden(propertySymbol).origin val inheritedFrom = dri.getInheritedFromDRI(parent) - val isExpect = propertySymbol.isExpect - val isActual = propertySymbol.isActual + val (isExpect, isActual) = when (propertySymbol) { + is KtKotlinPropertySymbol -> propertySymbol.isExpect to propertySymbol.isActual + is KtSyntheticJavaPropertySymbol -> false to false + } val generics = propertySymbol.typeParameters.mapIndexed { index, symbol -> visitVariantTypeParameter( @@ -592,9 +585,6 @@ internal class DokkaSymbolVisitor( // for SyntheticJavaProperty val inheritedFrom = if(propertyAccessorSymbol.origin == KtSymbolOrigin.JAVA_SYNTHETIC_PROPERTY) dri.copy(callable = null) else null - val isExpect = propertyAccessorSymbol.isExpect - val isActual = propertyAccessorSymbol.isActual - val generics = propertyAccessorSymbol.typeParameters.mapIndexed { index, symbol -> visitVariantTypeParameter( index, @@ -616,7 +606,7 @@ internal class DokkaSymbolVisitor( parameters = propertyAccessorSymbol.valueParameters.mapIndexed { index, symbol -> visitValueParameter(index, symbol, dri) }, - expectPresentInSet = sourceSet.takeIf { isExpect }, + expectPresentInSet = null, sources = propertyAccessorSymbol.getSource(), visibility = propertyAccessorSymbol.visibility.toDokkaVisibility().toSourceSetDependent(), generics = generics, @@ -624,7 +614,7 @@ internal class DokkaSymbolVisitor( modifier = propertyAccessorSymbol.getDokkaModality().toSourceSetDependent(), type = toBoundFrom(propertyAccessorSymbol.returnType), sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), + isExpectActual = false, extra = PropertyContainer.withAll( propertyAccessorSymbol.additionalExtras()?.toSourceSetDependent()?.toAdditionalModifiers(), inheritedFrom?.let { InheritedMember(it.toSourceSetDependent()) }, diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/expectActuals/ExpectActualsTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/expectActuals/ExpectActualsTest.kt index addc0d0929..0dcc7b4884 100644 --- a/dokka-subprojects/plugin-base/src/test/kotlin/expectActuals/ExpectActualsTest.kt +++ b/dokka-subprojects/plugin-base/src/test/kotlin/expectActuals/ExpectActualsTest.kt @@ -14,6 +14,135 @@ import kotlin.test.assertTrue class ExpectActualsTest : BaseAbstractTest() { + private val multiplatformConfiguration = dokkaConfiguration { + sourceSets { + val commonId = sourceSet { + sourceRoots = listOf("src/common/") + analysisPlatform = "common" + name = "common" + displayName = "common" + }.value.sourceSetID + sourceSet { + sourceRoots = listOf("src/jvm/") + analysisPlatform = "jvm" + name = "jvm" + displayName = "jvm" + dependentSourceSets = setOf(commonId) + } + sourceSet { + sourceRoots = listOf("src/native/") + analysisPlatform = "native" + name = "native" + displayName = "native" + dependentSourceSets = setOf(commonId) + } + } + } + private val commonSourceSetId = + multiplatformConfiguration.sourceSets.single { it.displayName == "common" }.sourceSetID + + @Test + fun `property inside expect class should be marked as expect`() = testInline( + """ + /src/common/test.kt + expect class ExpectActualClass { + val property: String? + } + + /src/jvm/test.kt + actual class ExpectActualClass { + actual val property: String? = null + } + + /src/native/test.kt + actual class ExpectActualClass { + actual val property: String? = null + } + """.trimMargin(), + multiplatformConfiguration + ) { + documentablesTransformationStage = { module -> + val cls = module.packages.single().classlikes.single { it.name == "ExpectActualClass" } + assertTrue(cls.isExpectActual) + assertEquals(commonSourceSetId, cls.expectPresentInSet?.sourceSetID) + val property = cls.properties.single { it.name == "property" } + assertTrue(property.isExpectActual) + assertEquals(commonSourceSetId, property.expectPresentInSet?.sourceSetID) + } + } + + @Test + fun `function inside expect class should be marked as expect`() = testInline( + """ + /src/common/test.kt + expect class ExpectActualClass { + fun function(): String? + } + + /src/jvm/test.kt + actual class ExpectActualClass { + actual fun function(): String? = null + } + + /src/native/test.kt + actual class ExpectActualClass { + actual fun function(): String? = null + } + """.trimMargin(), + multiplatformConfiguration + ) { + documentablesTransformationStage = { module -> + val cls = module.packages.single().classlikes.single { it.name == "ExpectActualClass" } + assertTrue(cls.isExpectActual) + assertEquals(commonSourceSetId, cls.expectPresentInSet?.sourceSetID) + val function = cls.functions.single { it.name == "function" } + assertTrue(function.isExpectActual) + assertEquals(commonSourceSetId, function.expectPresentInSet?.sourceSetID) + } + } + + @Test + fun `top level expect property should be marked as expect`() = testInline( + """ + /src/common/test.kt + expect val property: String? + + /src/jvm/test.kt + actual val property: String? = null + + /src/native/test.kt + actual val property: String? = null + """.trimMargin(), + multiplatformConfiguration + ) { + documentablesTransformationStage = { module -> + val property = module.packages.single().properties.single { it.name == "property" } + assertTrue(property.isExpectActual) + assertEquals(commonSourceSetId, property.expectPresentInSet?.sourceSetID) + } + } + + @Test + fun `top level expect function should be marked as expect`() = testInline( + """ + /src/common/test.kt + expect fun function(): String? + + /src/jvm/test.kt + actual fun function(): String? = null + + /src/native/test.kt + actual fun function(): String? = null + """.trimMargin(), + multiplatformConfiguration + ) { + documentablesTransformationStage = { module -> + val function = module.packages.single().functions.single { it.name == "function" } + assertTrue(function.isExpectActual) + assertEquals(commonSourceSetId, function.expectPresentInSet?.sourceSetID) + } + } + @Test fun `three same named expect actual classes`() {