diff --git a/core/api/core.api b/core/api/core.api index 74b4b4229f..8add4bd8d9 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -1385,7 +1385,8 @@ public final class org/jetbrains/dokka/model/DTypeParameter : org/jetbrains/dokk public final class org/jetbrains/dokka/model/DefaultValue : org/jetbrains/dokka/model/properties/ExtraProperty { public static final field Companion Lorg/jetbrains/dokka/model/DefaultValue$Companion; - public fun (Lorg/jetbrains/dokka/model/Expression;)V + public fun (Ljava/util/Map;)V + public final fun getExpression ()Ljava/util/Map; public fun getKey ()Lorg/jetbrains/dokka/model/properties/ExtraProperty$Key; public final fun getValue ()Lorg/jetbrains/dokka/model/Expression; } diff --git a/core/src/main/kotlin/model/defaultValues.kt b/core/src/main/kotlin/model/defaultValues.kt index d9caecd9db..a118eb4da5 100644 --- a/core/src/main/kotlin/model/defaultValues.kt +++ b/core/src/main/kotlin/model/defaultValues.kt @@ -3,9 +3,15 @@ package org.jetbrains.dokka.model import org.jetbrains.dokka.model.properties.ExtraProperty import org.jetbrains.dokka.model.properties.MergeStrategy -class DefaultValue(val value: Expression): ExtraProperty { +class DefaultValue(val expression: SourceSetDependent): ExtraProperty { + + @Deprecated("Use `expression` property that depends on source set", ReplaceWith("this.expression.values.first()")) + val value: Expression + get() = expression.values.first() companion object : ExtraProperty.Key { - override fun mergeStrategyFor(left: DefaultValue, right: DefaultValue): MergeStrategy = MergeStrategy.Remove // TODO pass a logger somehow and log this + override fun mergeStrategyFor(left: DefaultValue, right: DefaultValue): MergeStrategy = + MergeStrategy.Replace(DefaultValue(left.expression + right.expression)) + } override val key: ExtraProperty.Key diff --git a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt index 3c9daa2942..772fb61f58 100644 --- a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt +++ b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt @@ -13,7 +13,10 @@ import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.Nullable import org.jetbrains.dokka.model.TypeConstructor import org.jetbrains.dokka.model.properties.WithExtraProperties -import org.jetbrains.dokka.pages.* +import org.jetbrains.dokka.pages.ContentKind +import org.jetbrains.dokka.pages.ContentNode +import org.jetbrains.dokka.pages.TextStyle +import org.jetbrains.dokka.pages.TokenStyle import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.plugin import org.jetbrains.dokka.plugability.querySingle @@ -117,6 +120,19 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog } ?: regularSignature(c, sourceSetData) } + private fun PageContentBuilder.DocumentableContentBuilder.defaultValueAssign( + d: WithExtraProperties, + sourceSet: DokkaSourceSet + ) { + // a default value of parameter can be got from expect source set + // but expect properties cannot have a default value + d.extra[DefaultValue]?.expression?.let { + it[sourceSet] ?: if (d is DParameter) it[d.expectPresentInSet] else null + }?.let { expr -> + operator(" = ") + highlightValue(expr) + } + } private fun regularSignature(c: DClasslike, sourceSet: DokkaSourceSet) = contentBuilder.contentFor( @@ -197,10 +213,7 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog text(param.name.orEmpty()) operator(": ") signatureForProjection(param.type) - param.extra[DefaultValue]?.let { - operator(" = ") - highlightValue(it.value) - } + defaultValueAssign(param, sourceSet) } punctuation(")") } @@ -228,20 +241,20 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog (this.sources[sourceSet] as? DescriptorDocumentableSource)?.descriptor?.findPsi() is KtParameter private fun propertySignature(p: DProperty) = - p.sourceSets.map { + p.sourceSets.map { sourceSet -> contentBuilder.contentFor( p, ContentKind.Symbol, - setOf(TextStyle.Monospace) + p.stylesIfDeprecated(it), - sourceSets = setOf(it) + setOf(TextStyle.Monospace) + p.stylesIfDeprecated(sourceSet), + sourceSets = setOf(sourceSet) ) { annotationsBlock(p) - p.visibility[it].takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") } - if (p.isExpectActual) keyword(if (it == p.expectPresentInSet) "expect " else "actual ") - p.modifier[it].takeIf { it !in ignoredModifiers }?.let { + p.visibility[sourceSet].takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") } + if (p.isExpectActual) keyword(if (sourceSet == p.expectPresentInSet) "expect " else "actual ") + p.modifier[sourceSet].takeIf { it !in ignoredModifiers }?.let { if (it is JavaModifier.Empty) KotlinModifier.Open else it }?.name?.let { keyword("$it ") } - p.modifiers()[it]?.toSignatureString()?.let { keyword(it) } + p.modifiers()[sourceSet]?.toSignatureString()?.let { keyword(it) } p.setter?.let { keyword("var ") } ?: keyword("val ") list(p.generics, prefix = "<", suffix = "> ", separatorStyles = mainStyles + TokenStyle.Punctuation, @@ -256,10 +269,7 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog link(p.name, p.dri) operator(": ") signatureForProjection(p.type) - p.extra[DefaultValue]?.run { - operator(" = ") - highlightValue(value) - } + defaultValueAssign(p, sourceSet) } } @@ -274,20 +284,20 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog } private fun functionSignature(f: DFunction) = - f.sourceSets.map { + f.sourceSets.map { sourceSet -> contentBuilder.contentFor( f, ContentKind.Symbol, - setOf(TextStyle.Monospace) + f.stylesIfDeprecated(it), - sourceSets = setOf(it) + setOf(TextStyle.Monospace) + f.stylesIfDeprecated(sourceSet), + sourceSets = setOf(sourceSet) ) { annotationsBlock(f) - f.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") } - if (f.isExpectActual) keyword(if (it == f.expectPresentInSet) "expect " else "actual ") - f.modifier[it]?.takeIf { it !in ignoredModifiers }?.let { + f.visibility[sourceSet]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") } + if (f.isExpectActual) keyword(if (sourceSet == f.expectPresentInSet) "expect " else "actual ") + f.modifier[sourceSet]?.takeIf { it !in ignoredModifiers }?.let { if (it is JavaModifier.Empty) KotlinModifier.Open else it }?.name?.let { keyword("$it ") } - f.modifiers()[it]?.toSignatureString()?.let { keyword(it) } + f.modifiers()[sourceSet]?.toSignatureString()?.let { keyword(it) } keyword("fun ") val usedGenerics = if (f.isConstructor) f.generics.filter { f uses it } else f.generics list(usedGenerics, prefix = "<", suffix = "> ", @@ -312,10 +322,7 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog text(param.name!!) operator(": ") signatureForProjection(param.type) - param.extra[DefaultValue]?.run { - operator(" = ") - highlightValue(value) - } + defaultValueAssign(param, sourceSet) } } punctuation(")") diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt index 6bc8774da0..918489638e 100644 --- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt +++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt @@ -467,7 +467,7 @@ private class DokkaDescriptorVisitor( .toAdditionalExtras()).toSet().toSourceSetDependent().toAdditionalModifiers(), (descriptor.getAnnotationsWithBackingField() + descriptor.fileLevelAnnotations()).toSourceSetDependent() .toAnnotations(), - descriptor.getDefaultValue()?.let { DefaultValue(it) }, + descriptor.getDefaultValue()?.let { DefaultValue(it.toSourceSetDependent()) }, InheritedMember(inheritedFrom.toSourceSetDependent()), ) ) @@ -712,7 +712,7 @@ private class DokkaDescriptorVisitor( extra = PropertyContainer.withAll(listOfNotNull( descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), - descriptor.getDefaultValue()?.let { DefaultValue(it) } + descriptor.getDefaultValue()?.let { DefaultValue(it.toSourceSetDependent()) } )) ) diff --git a/plugins/base/src/test/kotlin/model/FunctionsTest.kt b/plugins/base/src/test/kotlin/model/FunctionsTest.kt index 29c81a6593..fa65a477d2 100644 --- a/plugins/base/src/test/kotlin/model/FunctionsTest.kt +++ b/plugins/base/src/test/kotlin/model/FunctionsTest.kt @@ -344,7 +344,7 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun parameters.forEach { p -> p.name equals "x" p.type.name.assertNotNull("Parameter type: ") equals "String" - p.extra[DefaultValue]?.value equals StringConstant("") + p.extra[DefaultValue]?.expression?.get(sourceSets.single()) equals StringConstant("") } } } @@ -363,7 +363,7 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun parameters.forEach { p -> p.name equals "x" p.type.name.assertNotNull("Parameter type: ") equals "Float" - p.extra[DefaultValue]?.value equals FloatConstant(3.14f) + p.extra[DefaultValue]?.expression?.get(sourceSets.single()) equals FloatConstant(3.14f) } } } diff --git a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt index ddf1c89294..7048823987 100644 --- a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt +++ b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt @@ -17,6 +17,25 @@ class SignatureTest : BaseAbstractTest() { } } + private val mppConfiguration = dokkaConfiguration { + moduleName = "test" + sourceSets { + sourceSet { + name = "common" + sourceRoots = listOf("src/main/kotlin/common/Test.kt") + classpath = listOf(commonStdlibPath!!) + externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) + } + sourceSet { + name = "jvm" + dependentSourceSets = setOf(DokkaSourceSetID("test", "common")) + sourceRoots = listOf("src/main/kotlin/jvm/Test.kt") + classpath = listOf(commonStdlibPath!!) + externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) + } + } + } + fun source(signature: String) = """ |/src/main/kotlin/test/Test.kt @@ -419,26 +438,6 @@ class SignatureTest : BaseAbstractTest() { @Test fun `actual fun`() { - - val configuration = dokkaConfiguration { - moduleName = "test" - sourceSets { - sourceSet { - name = "common" - sourceRoots = listOf("src/main/kotlin/common/Test.kt") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - sourceSet { - name = "jvm" - dependentSourceSets = setOf(DokkaSourceSetID("test", "common")) - sourceRoots = listOf("src/main/kotlin/jvm/Test.kt") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - } - } - val writerPlugin = TestOutputWriterPlugin() testInline( @@ -454,7 +453,7 @@ class SignatureTest : BaseAbstractTest() { |actual fun simpleFun(): String = "Celebrimbor" | """.trimMargin(), - configuration, + mppConfiguration, pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ -> @@ -475,27 +474,45 @@ class SignatureTest : BaseAbstractTest() { } @Test - fun `type with an actual typealias`() { + fun `actual property with a default value`() { + val writerPlugin = TestOutputWriterPlugin() - val configuration = dokkaConfiguration { - moduleName = "test" - sourceSets { - sourceSet { - name = "common" - sourceRoots = listOf("src/main/kotlin/common/Test.kt") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - sourceSet { - name = "jvm" - dependentSourceSets = setOf(DokkaSourceSetID("test", "common")) - sourceRoots = listOf("src/main/kotlin/jvm/Test.kt") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } + testInline( + """ + |/src/main/kotlin/common/Test.kt + |package example + | + |expect val prop: Int + | + |/src/main/kotlin/jvm/Test.kt + |package example + | + |actual val prop: Int = 2 + | + """.trimMargin(), + mppConfiguration, + pluginOverrides = listOf(writerPlugin) + ) { + renderingStage = { _, _ -> + val signatures = writerPlugin.writer.renderedContent("test/example/prop.html").signature().toList() + + signatures[0].match( + "expect val ", A("prop"), + ": ", A("Int"), Span(), + ignoreSpanWithTokenStyle = true + ) + signatures[1].match( + "actual val ", A("prop"), + ": ", A("Int"), + " = 2", Span(), + ignoreSpanWithTokenStyle = true + ) } } + } + @Test + fun `type with an actual typealias`() { val writerPlugin = TestOutputWriterPlugin() testInline( @@ -512,7 +529,7 @@ class SignatureTest : BaseAbstractTest() { |actual typealias Foo = Bar | """.trimMargin(), - configuration, + mppConfiguration, pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ ->