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

Enhance typealias presentation #3053

Merged
merged 1 commit into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -644,20 +644,21 @@ public final class org/jetbrains/dokka/links/TypeReference$Companion {

public final class org/jetbrains/dokka/model/ActualTypealias : org/jetbrains/dokka/model/properties/ExtraProperty {
public static final field Companion Lorg/jetbrains/dokka/model/ActualTypealias$Companion;
public fun <init> (Ljava/util/Map;)V
public final fun component1 ()Ljava/util/Map;
public final fun copy (Ljava/util/Map;)Lorg/jetbrains/dokka/model/ActualTypealias;
public static synthetic fun copy$default (Lorg/jetbrains/dokka/model/ActualTypealias;Ljava/util/Map;ILjava/lang/Object;)Lorg/jetbrains/dokka/model/ActualTypealias;
public fun <init> (Lorg/jetbrains/dokka/model/DTypeAlias;)V
public final fun component1 ()Lorg/jetbrains/dokka/model/DTypeAlias;
public final fun copy (Lorg/jetbrains/dokka/model/DTypeAlias;)Lorg/jetbrains/dokka/model/ActualTypealias;
public static synthetic fun copy$default (Lorg/jetbrains/dokka/model/ActualTypealias;Lorg/jetbrains/dokka/model/DTypeAlias;ILjava/lang/Object;)Lorg/jetbrains/dokka/model/ActualTypealias;
public fun equals (Ljava/lang/Object;)Z
public fun getKey ()Lorg/jetbrains/dokka/model/properties/ExtraProperty$Key;
public final fun getTypeAlias ()Lorg/jetbrains/dokka/model/DTypeAlias;
public final fun getUnderlyingType ()Ljava/util/Map;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class org/jetbrains/dokka/model/ActualTypealias$Companion : org/jetbrains/dokka/model/properties/ExtraProperty$Key {
public synthetic fun mergeStrategyFor (Ljava/lang/Object;Ljava/lang/Object;)Lorg/jetbrains/dokka/model/properties/MergeStrategy;
public fun mergeStrategyFor (Lorg/jetbrains/dokka/model/ActualTypealias;Lorg/jetbrains/dokka/model/ActualTypealias;)Lorg/jetbrains/dokka/model/properties/MergeStrategy$Replace;
public fun mergeStrategyFor (Lorg/jetbrains/dokka/model/ActualTypealias;Lorg/jetbrains/dokka/model/ActualTypealias;)Lorg/jetbrains/dokka/model/properties/MergeStrategy$Fail;
}

public final class org/jetbrains/dokka/model/AdditionalExtrasKt {
Expand Down Expand Up @@ -1311,11 +1312,12 @@ public final class org/jetbrains/dokka/model/DProperty : org/jetbrains/dokka/mod
public fun withNewExtras (Lorg/jetbrains/dokka/model/properties/PropertyContainer;)Lorg/jetbrains/dokka/model/DProperty;
}

public final class org/jetbrains/dokka/model/DTypeAlias : org/jetbrains/dokka/model/Documentable, org/jetbrains/dokka/model/WithGenerics, org/jetbrains/dokka/model/WithType, org/jetbrains/dokka/model/WithVisibility, org/jetbrains/dokka/model/properties/WithExtraProperties {
public fun <init> (Lorg/jetbrains/dokka/links/DRI;Ljava/lang/String;Lorg/jetbrains/dokka/model/Bound;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/util/Set;Ljava/util/List;Lorg/jetbrains/dokka/model/properties/PropertyContainer;)V
public synthetic fun <init> (Lorg/jetbrains/dokka/links/DRI;Ljava/lang/String;Lorg/jetbrains/dokka/model/Bound;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/util/Set;Ljava/util/List;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final class org/jetbrains/dokka/model/DTypeAlias : org/jetbrains/dokka/model/Documentable, org/jetbrains/dokka/model/WithGenerics, org/jetbrains/dokka/model/WithSources, org/jetbrains/dokka/model/WithType, org/jetbrains/dokka/model/WithVisibility, org/jetbrains/dokka/model/properties/WithExtraProperties {
public fun <init> (Lorg/jetbrains/dokka/links/DRI;Ljava/lang/String;Lorg/jetbrains/dokka/model/Bound;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/util/Set;Ljava/util/List;Ljava/util/Map;Lorg/jetbrains/dokka/model/properties/PropertyContainer;)V
public synthetic fun <init> (Lorg/jetbrains/dokka/links/DRI;Ljava/lang/String;Lorg/jetbrains/dokka/model/Bound;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/util/Set;Ljava/util/List;Ljava/util/Map;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Lorg/jetbrains/dokka/links/DRI;
public final fun component10 ()Lorg/jetbrains/dokka/model/properties/PropertyContainer;
public final fun component10 ()Ljava/util/Map;
public final fun component11 ()Lorg/jetbrains/dokka/model/properties/PropertyContainer;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Lorg/jetbrains/dokka/model/Bound;
public final fun component4 ()Ljava/util/Map;
Expand All @@ -1324,8 +1326,8 @@ public final class org/jetbrains/dokka/model/DTypeAlias : org/jetbrains/dokka/mo
public final fun component7 ()Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;
public final fun component8 ()Ljava/util/Set;
public final fun component9 ()Ljava/util/List;
public final fun copy (Lorg/jetbrains/dokka/links/DRI;Ljava/lang/String;Lorg/jetbrains/dokka/model/Bound;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/util/Set;Ljava/util/List;Lorg/jetbrains/dokka/model/properties/PropertyContainer;)Lorg/jetbrains/dokka/model/DTypeAlias;
public static synthetic fun copy$default (Lorg/jetbrains/dokka/model/DTypeAlias;Lorg/jetbrains/dokka/links/DRI;Ljava/lang/String;Lorg/jetbrains/dokka/model/Bound;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/util/Set;Ljava/util/List;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ILjava/lang/Object;)Lorg/jetbrains/dokka/model/DTypeAlias;
public final fun copy (Lorg/jetbrains/dokka/links/DRI;Ljava/lang/String;Lorg/jetbrains/dokka/model/Bound;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/util/Set;Ljava/util/List;Ljava/util/Map;Lorg/jetbrains/dokka/model/properties/PropertyContainer;)Lorg/jetbrains/dokka/model/DTypeAlias;
public static synthetic fun copy$default (Lorg/jetbrains/dokka/model/DTypeAlias;Lorg/jetbrains/dokka/links/DRI;Ljava/lang/String;Lorg/jetbrains/dokka/model/Bound;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/util/Set;Ljava/util/List;Ljava/util/Map;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ILjava/lang/Object;)Lorg/jetbrains/dokka/model/DTypeAlias;
public fun equals (Ljava/lang/Object;)Z
public fun getChildren ()Ljava/util/List;
public fun getDocumentation ()Ljava/util/Map;
Expand All @@ -1335,6 +1337,7 @@ public final class org/jetbrains/dokka/model/DTypeAlias : org/jetbrains/dokka/mo
public fun getGenerics ()Ljava/util/List;
public fun getName ()Ljava/lang/String;
public fun getSourceSets ()Ljava/util/Set;
public fun getSources ()Ljava/util/Map;
public fun getType ()Lorg/jetbrains/dokka/model/Bound;
public final fun getUnderlyingType ()Ljava/util/Map;
public fun getVisibility ()Ljava/util/Map;
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/kotlin/model/Documentable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,9 @@ data class DTypeAlias(
override val expectPresentInSet: DokkaSourceSet?,
override val sourceSets: Set<DokkaSourceSet>,
override val generics: List<DTypeParameter>,
override val sources: SourceSetDependent<DocumentableSource>,
override val extra: PropertyContainer<DTypeAlias> = PropertyContainer.empty()
) : Documentable(), WithType, WithVisibility, WithExtraProperties<DTypeAlias>, WithGenerics {
) : Documentable(), WithType, WithVisibility, WithExtraProperties<DTypeAlias>, WithGenerics, WithSources {
override val children: List<Nothing>
get() = emptyList()

Expand Down
15 changes: 12 additions & 3 deletions core/src/main/kotlin/model/additionalExtras.kt
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,22 @@ object PrimaryConstructorExtra : ExtraProperty<DFunction>, ExtraProperty.Key<DFu
override val key: ExtraProperty.Key<DFunction, *> = this
}

data class ActualTypealias(val underlyingType: SourceSetDependent<Bound>) : ExtraProperty<DClasslike> {
data class ActualTypealias(
val typeAlias: DTypeAlias
) : ExtraProperty<DClasslike> {

@Suppress("unused")
@Deprecated(message = "It can be removed soon. Use [typeAlias.underlyingType]", ReplaceWith("this.typeAlias.underlyingType"))
val underlyingType: SourceSetDependent<Bound>
get() = typeAlias.underlyingType

companion object : ExtraProperty.Key<DClasslike, ActualTypealias> {
override fun mergeStrategyFor(
left: ActualTypealias,
right: ActualTypealias
) =
MergeStrategy.Replace(ActualTypealias(left.underlyingType + right.underlyingType))
) = MergeStrategy.Fail {
throw IllegalStateException("Adding [ActualTypealias] should be after merging all documentables")
}
}

override val key: ExtraProperty.Key<DClasslike, ActualTypealias> = ActualTypealias
Expand Down
73 changes: 29 additions & 44 deletions plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,39 +82,18 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog
}
}

private fun actualTypealiasedSignature(c: DClasslike, sourceSet: DokkaSourceSet, aliasedType: Bound): ContentGroup {
@Suppress("UNCHECKED_CAST")
val deprecationStyles = (c as? WithExtraProperties<out Documentable>)
?.stylesIfDeprecated(sourceSet)
?: emptySet()

return contentBuilder.contentFor(
c,
ContentKind.Symbol,
setOf(TextStyle.Monospace),
sourceSets = setOf(sourceSet)
) {
keyword("actual ")
keyword("typealias ")
link(c.name.orEmpty(), c.dri, styles = mainStyles + deprecationStyles)
operator(" = ")
signatureForProjection(aliasedType)
}
}

private fun classlikeSignature(c: DClasslike): List<ContentNode> {
@Suppress("UNCHECKED_CAST")
val typeAliasUnderlyingType = (c as? WithExtraProperties<DClasslike>)
val typeAlias = (c as? WithExtraProperties<DClasslike>)
?.extra
?.get(ActualTypealias)
?.underlyingType
?.typeAlias

return c.sourceSets.map { sourceSetData ->
val sourceSetType = typeAliasUnderlyingType?.get(sourceSetData)
if (sourceSetType == null) {
regularSignature(c, sourceSetData)
if (typeAlias != null && sourceSetData in typeAlias.sourceSets) {
regularSignature(typeAlias, sourceSetData)
} else {
actualTypealiasedSignature(c, sourceSetData, sourceSetType)
regularSignature(c, sourceSetData)
}
}
}
Expand Down Expand Up @@ -361,27 +340,33 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog

private fun signature(t: DTypeAlias) =
t.sourceSets.map {
contentBuilder.contentFor(t, sourceSets = setOf(it)) {
t.underlyingType.entries.groupBy({ it.value }, { it.key }).map { (type, platforms) ->
+contentBuilder.contentFor(
t,
ContentKind.Symbol,
setOf(TextStyle.Monospace),
sourceSets = platforms.toSet()
) {
annotationsBlock(t)
t.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") }
processExtraModifiers(t)
keyword("typealias ")
group(styles = mainStyles + t.stylesIfDeprecated(it)) {
signatureForProjection(t.type)
}
operator(" = ")
signatureForTypealiasTarget(t, type)
}
regularSignature(t, it)
}

private fun regularSignature(
t: DTypeAlias,
sourceSet: DokkaSourceSet
) = contentBuilder.contentFor(t, sourceSets = setOf(sourceSet)) {
t.underlyingType.entries.groupBy({ it.value }, { it.key }).map { (type, platforms) ->
+contentBuilder.contentFor(
t,
ContentKind.Symbol,
setOf(TextStyle.Monospace),
sourceSets = platforms.toSet()
) {
annotationsBlock(t)
t.visibility[sourceSet]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") }
if (t.expectPresentInSet != null) keyword("actual ")
processExtraModifiers(t)
keyword("typealias ")
group(styles = mainStyles + t.stylesIfDeprecated(sourceSet)) {
signatureForProjection(t.type)
}
operator(" = ")
signatureForTypealiasTarget(t, type)
}
}
}

private fun signature(t: DTypeParameter) =
t.sourceSets.map {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ import org.jetbrains.dokka.model.properties.WithExtraProperties
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer

/**
* Since we can not merge [DClasslike] with [DTypeAlias.underlyingType] and [DTypeAlias.extra],
* we have this transformer to add [ActualTypealias] extra in expect [DClasslike]
*
* The transformer should be applied after merging all documentables
*/
// TODO assign actual [DTypeAlias.expectPresentInSet] an expect source set, currently, [DTypeAlias.expectPresentInSet] always = null
class ActualTypealiasAdder : DocumentableTransformer {

override fun invoke(original: DModule, context: DokkaContext) = original.generateTypealiasesMap().let { aliases ->
Expand Down Expand Up @@ -66,30 +73,36 @@ class ActualTypealiasAdder : DocumentableTransformer {
elements.map { element ->
if (element.expectPresentInSet != null) {
typealiases[element.dri]?.let { ta ->
val merged = element.withNewExtras(element.extra + ActualTypealias(ta.underlyingType)).let {
val actualTypealiasExtra = ActualTypealias(ta.copy(expectPresentInSet = element.expectPresentInSet))
val merged = element.withNewExtras(element.extra + actualTypealiasExtra).let {
when (it) {
is DClass -> it.copy(
documentation = element.documentation + ta.documentation,
sources = element.sources + ta.sources,
sourceSets = element.sourceSets + ta.sourceSets
)

is DEnum -> it.copy(
documentation = element.documentation + ta.documentation,
sources = element.sources + ta.sources,
sourceSets = element.sourceSets + ta.sourceSets
)

is DInterface -> it.copy(
documentation = element.documentation + ta.documentation,
sources = element.sources + ta.sources,
sourceSets = element.sourceSets + ta.sourceSets
)

is DObject -> it.copy(
documentation = element.documentation + ta.documentation,
sources = element.sources + ta.sources,
sourceSets = element.sourceSets + ta.sourceSets
)

is DAnnotation -> it.copy(
documentation = element.documentation + ta.documentation,
sources = element.sources + ta.sources,
sourceSets = element.sourceSets + ta.sourceSets
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,7 @@ private class DokkaDescriptorVisitor(
documentation = resolveDescriptorData(),
sourceSets = setOf(sourceSet),
generics = generics.await(),
sources = descriptor.createSources(),
extra = PropertyContainer.withAll(
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
info.exceptionInSupertypesOrNull(),
Expand Down
37 changes: 35 additions & 2 deletions plugins/base/src/test/kotlin/signatures/SignatureTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import org.jetbrains.dokka.model.dfs
import org.junit.jupiter.api.Test
import utils.*
import kotlin.test.assertEquals

class SignatureTest : BaseAbstractTest() {
private val configuration = dokkaConfiguration {
sourceSets {
Expand Down Expand Up @@ -36,7 +35,8 @@ class SignatureTest : BaseAbstractTest() {
name = "jvm"
dependentSourceSets = setOf(DokkaSourceSetID("test", "common"))
sourceRoots = listOf("src/main/kotlin/jvm/Test.kt")
classpath = listOf(commonStdlibPath!!)
classpath = listOf(
commonStdlibPath ?: throw IllegalStateException("Common stdlib is not found"),)
externalDocumentationLinks = listOf(stdlibExternalDocumentationLink)
}
}
Expand Down Expand Up @@ -549,6 +549,39 @@ class SignatureTest : BaseAbstractTest() {
}
}
}
@Test
fun `actual typealias should have generic parameters and fully qualified name of the expansion type`() {
val writerPlugin = TestOutputWriterPlugin()

testInline(
"""
|/src/main/kotlin/common/Test.kt
|package example
|
|expect class Array<T>
|
|/src/main/kotlin/jvm/Test.kt
|package example
|
|actual typealias Array<T> = kotlin.Array<T>
""".trimMargin(),
mppConfiguration,
pluginOverrides = listOf(writerPlugin)
) {
renderingStage = { _, _ ->
val signatures = writerPlugin.writer.renderedContent("test/example/-array/index.html").signature().toList()

signatures[0].match(
"expect class ", A("Array"), "<", A("T"), ">",
ignoreSpanWithTokenStyle = true
)
signatures[1].match(
"actual typealias ", A("Array"), "<", A("T"), "> = ", A("kotlin.Array"), "<", A("T"), ">",
ignoreSpanWithTokenStyle = true
)
}
}
}

@Test
fun `type with an actual typealias`() {
Expand Down
Loading