Skip to content

Commit

Permalink
Make a default value dependent on source set (#2449)
Browse files Browse the repository at this point in the history
* Make a default value dependent on source set

* Get a default value from an expect source set

* Fix default value for expect properties

* Deprecate `DefaultValue.value`

* Add test

* Refactor

* Reformat
  • Loading branch information
vmishenev committed Apr 28, 2022
1 parent 2e88c6f commit 4451b8e
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 73 deletions.
3 changes: 2 additions & 1 deletion core/api/core.api
Expand Up @@ -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 <init> (Lorg/jetbrains/dokka/model/Expression;)V
public fun <init> (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;
}
Expand Down
10 changes: 8 additions & 2 deletions core/src/main/kotlin/model/defaultValues.kt
Expand Up @@ -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<Documentable> {
class DefaultValue(val expression: SourceSetDependent<Expression>): ExtraProperty<Documentable> {

@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<Documentable, DefaultValue> {
override fun mergeStrategyFor(left: DefaultValue, right: DefaultValue): MergeStrategy<Documentable> = MergeStrategy.Remove // TODO pass a logger somehow and log this
override fun mergeStrategyFor(left: DefaultValue, right: DefaultValue): MergeStrategy<Documentable> =
MergeStrategy.Replace(DefaultValue(left.expression + right.expression))

}

override val key: ExtraProperty.Key<Documentable, *>
Expand Down
61 changes: 34 additions & 27 deletions plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt
Expand Up @@ -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
Expand Down Expand Up @@ -117,6 +120,19 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog
} ?: regularSignature(c, sourceSetData)
}

private fun <T : Documentable> PageContentBuilder.DocumentableContentBuilder.defaultValueAssign(
d: WithExtraProperties<T>,
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(
Expand Down Expand Up @@ -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(")")
}
Expand Down Expand Up @@ -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,
Expand All @@ -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)
}
}

Expand All @@ -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 = "> ",
Expand All @@ -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(")")
Expand Down
Expand Up @@ -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()),
)
)
Expand Down Expand Up @@ -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()) }
))
)

Expand Down
4 changes: 2 additions & 2 deletions plugins/base/src/test/kotlin/model/FunctionsTest.kt
Expand Up @@ -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("")
}
}
}
Expand All @@ -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)
}
}
}
Expand Down
95 changes: 56 additions & 39 deletions plugins/base/src/test/kotlin/signatures/SignatureTest.kt
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -454,7 +453,7 @@ class SignatureTest : BaseAbstractTest() {
|actual fun simpleFun(): String = "Celebrimbor"
|
""".trimMargin(),
configuration,
mppConfiguration,
pluginOverrides = listOf(writerPlugin)
) {
renderingStage = { _, _ ->
Expand All @@ -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(
Expand All @@ -512,7 +529,7 @@ class SignatureTest : BaseAbstractTest() {
|actual typealias Foo = Bar
|
""".trimMargin(),
configuration,
mppConfiguration,
pluginOverrides = listOf(writerPlugin)
) {
renderingStage = { _, _ ->
Expand Down

0 comments on commit 4451b8e

Please sign in to comment.