aboutsummaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorPaweł Marks <pmarks@virtuslab.com>2020-02-11 15:11:36 +0100
committerPaweł Marks <Kordyjan@users.noreply.github.com>2020-02-12 15:12:09 +0100
commitc770225d5f89535ae5651c422c52633473751364 (patch)
treef860fedc02bf715449aae6920b6aa110d5575aec /core/src
parent944695d967c2f93e41e4bfd640238f3e9b1c9434 (diff)
downloaddokka-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.kt35
-rw-r--r--core/src/test/kotlin/basic/DRITest.kt43
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