diff options
author | Paweł Marks <pmarks@virtuslab.com> | 2020-02-11 15:11:36 +0100 |
---|---|---|
committer | Paweł Marks <Kordyjan@users.noreply.github.com> | 2020-02-12 15:12:09 +0100 |
commit | c770225d5f89535ae5651c422c52633473751364 (patch) | |
tree | f860fedc02bf715449aae6920b6aa110d5575aec /core/src | |
parent | 944695d967c2f93e41e4bfd640238f3e9b1c9434 (diff) | |
download | dokka-c770225d5f89535ae5651c422c52633473751364.tar.gz dokka-c770225d5f89535ae5651c422c52633473751364.tar.bz2 dokka-c770225d5f89535ae5651c422c52633473751364.zip |
Fixes infinite recursion in DRI expansion caused by bounds on nullable parameters
Diffstat (limited to 'core/src')
-rw-r--r-- | core/src/main/kotlin/links/DRI.kt | 35 | ||||
-rw-r--r-- | core/src/test/kotlin/basic/DRITest.kt | 43 |
2 files changed, 57 insertions, 21 deletions
diff --git a/core/src/main/kotlin/links/DRI.kt b/core/src/main/kotlin/links/DRI.kt index 404813fa..c13eb04c 100644 --- a/core/src/main/kotlin/links/DRI.kt +++ b/core/src/main/kotlin/links/DRI.kt @@ -69,8 +69,6 @@ data class Callable( } sealed class TypeReference { - abstract val isNullable: Boolean - companion object { fun from(d: ReceiverParameterDescriptor): TypeReference? = when (d.value) { @@ -84,57 +82,52 @@ sealed class TypeReference { fun from(d: ValueParameterDescriptor): TypeReference? = from(d.type) + private fun fromPossiblyNullable(t: KotlinType, self: KotlinType? = null): TypeReference = + from(t, self).let { if (t.isMarkedNullable) Nullable(it) else it } private fun from(t: KotlinType, self: KotlinType? = null): TypeReference = - if (t == self) - if (t.isMarkedNullable) NullableSelfType else SelfType + if (self is KotlinType && self.constructor == t.constructor && self.arguments == t.arguments) + SelfType else when (val d = t.constructor.declarationDescriptor) { is TypeParameterDescriptor -> TypeParam( - d.upperBounds.map { from(it, self ?: t) }, - t.isMarkedNullable + d.upperBounds.map { fromPossiblyNullable(it, self ?: t) } ) else -> TypeConstructor( t.constructorName.orEmpty(), - t.arguments.map { from(it, self) }, - t.isMarkedNullable + t.arguments.map { fromProjection(it, self) } ) } - private fun from(t: TypeProjection, r: KotlinType? = null): TypeReference = + private fun fromProjection(t: TypeProjection, r: KotlinType? = null): TypeReference = if (t.isStarProjection) { - TypeConstructor("kotlin.Any", emptyList(), isNullable = true) + Nullable(TypeConstructor("kotlin.Any", emptyList())) } else { - from(t.type, r) + fromPossiblyNullable(t.type, r) } } } data class JavaClassReference(val name: String): TypeReference() { - override val isNullable = true override fun toString(): String = name } -data class TypeParam(val bounds: List<TypeReference>, override val isNullable: Boolean) : TypeReference() +data class TypeParam(val bounds: List<TypeReference>) : TypeReference() data class TypeConstructor( val fullyQualifiedName: String, - val params: List<TypeReference>, - override val isNullable: Boolean + val params: List<TypeReference> ) : TypeReference() { override fun toString() = fullyQualifiedName + - (if (params.isNotEmpty()) "[${params.joinToString(",")}]" else "") + - if (isNullable) "?" else "" + (if (params.isNotEmpty()) "[${params.joinToString(",")}]" else "") } object SelfType : TypeReference() { - override val isNullable = false override fun toString() = "^" } -object NullableSelfType : TypeReference() { - override val isNullable = true - override fun toString() = "^?" +data class Nullable(val wrapped: TypeReference) : TypeReference() { + override fun toString() = "$wrapped?" } private operator fun <T> List<T>.component6(): T = get(5) diff --git a/core/src/test/kotlin/basic/DRITest.kt b/core/src/test/kotlin/basic/DRITest.kt new file mode 100644 index 00000000..f8328e35 --- /dev/null +++ b/core/src/test/kotlin/basic/DRITest.kt @@ -0,0 +1,43 @@ +package basic + +import org.jetbrains.dokka.links.* +import org.junit.Assert.assertEquals +import org.junit.Test +import testApi.testRunner.AbstractCoreTest + +class DRITest: AbstractCoreTest() { + @Test + fun `#634`() { + val configuration = dokkaConfiguration { + passes { + pass { + sourceRoots = listOf("src/") + } + } + } + + testInline( + """ + |/src/main/kotlin/basic/Test.kt + |package toplevel + | + |inline fun <T, R : Comparable<R>> Array<out T>.mySortBy( + | crossinline selector: (T) -> R?): Array<out T> = TODO() + |} + """.trimMargin(), + configuration + ) { + documentablesMergingStage = { module -> + val expected = TypeConstructor("kotlin.Function1", listOf( + TypeParam(listOf(Nullable(TypeConstructor("kotlin.Any", emptyList())))), + Nullable(TypeParam(listOf(TypeConstructor("kotlin.Comparable", listOf(SelfType))))) + )) + val actual = module.packages.single() + .functions.single() + .dri.callable?.params?.single() + assertEquals(expected, actual) + } + } + } + +}
\ No newline at end of file |