Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make a default value dependent on source set #2449

Merged
merged 7 commits into from Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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("expression.values.first()"))
IgnatBeresnev marked this conversation as resolved.
Show resolved Hide resolved
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
62 changes: 35 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
d.extra[DefaultValue]?.expression?.let {
it[sourceSet] ?: if (d is DParameter) it[d.expectPresentInSet] else null
}
?.let { expr ->
operator(" = ")
highlightValue(expr)
}
IgnatBeresnev marked this conversation as resolved.
Show resolved Hide resolved
}

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,8 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog
link(p.name, p.dri)
operator(": ")
signatureForProjection(p.type)
p.extra[DefaultValue]?.run {
operator(" = ")
highlightValue(value)
}
// expect properties cannot have a default value
defaultValueAssign(p, sourceSet)
}
}

Expand All @@ -274,20 +285,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 +323,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