Skip to content

Commit

Permalink
Enhance typealias presentation (#3053)
Browse files Browse the repository at this point in the history
  • Loading branch information
vmishenev committed Jul 3, 2023
1 parent 12a386b commit cbd9733
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 62 deletions.
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

0 comments on commit cbd9733

Please sign in to comment.