Skip to content

Commit 3d8be6c

Browse files
authored
[K2] Fix typealiased type that leads to functional type (#3396)
* [K2] Fix typealiased type to function * Add check on emptiness
1 parent 81666e9 commit 3d8be6c

File tree

3 files changed

+80
-12
lines changed

3 files changed

+80
-12
lines changed

dokka-subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ internal class TypeTranslator(
3737
is KtTypeArgumentWithVariance -> toBoundFrom(typeProjection.type).wrapWithVariance(typeProjection.variance)
3838
}
3939

40-
private fun KtAnalysisSession.toTypeConstructorFromTypeAliased(classType: KtUsualClassType): TypeAliased {
40+
private fun KtAnalysisSession.toBoundFromTypeAliased(classType: KtNonErrorClassType): TypeAliased {
4141
val classSymbol = classType.classSymbol
4242
return if (classSymbol is KtTypeAliasSymbol)
4343
TypeAliased(
@@ -77,7 +77,7 @@ internal class TypeTranslator(
7777
fun KtAnalysisSession.toBoundFrom(type: KtType): Bound =
7878
when (type) {
7979
is KtUsualClassType -> {
80-
if (type.classSymbol is KtTypeAliasSymbol) toTypeConstructorFromTypeAliased(type)
80+
if (type.classSymbol is KtTypeAliasSymbol) toBoundFromTypeAliased(type)
8181
else toTypeConstructorFrom(type)
8282
}
8383

@@ -92,16 +92,8 @@ internal class TypeTranslator(
9292

9393
is KtClassErrorType -> UnresolvedBound(type.toString())
9494
is KtFunctionalType -> {
95-
/**
96-
* For example
97-
* `typealias CompletionHandler = (cause: Throwable?) -> Unit`
98-
* has functional type with no type arguments in K2
99-
* In K1 we have a usual generic type
100-
*/
101-
if (type.ownTypeArguments.isEmpty())
102-
toTypeConstructorFrom(type)
103-
else
104-
toFunctionalTypeConstructorFrom(type)
95+
if (type.classSymbol is KtTypeAliasSymbol) toBoundFromTypeAliased(type)
96+
else toFunctionalTypeConstructorFrom(type)
10597
}
10698
is KtDynamicType -> Dynamic
10799
is KtDefinitelyNotNullType -> DefinitelyNonNullable(

dokka-subprojects/plugin-base/src/main/kotlin/org/jetbrains/dokka/base/signatures/KotlinSignatureProvider.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,12 @@ public class KotlinSignatureProvider(
483483
type.projections
484484

485485
punctuation("(")
486+
if(args.isEmpty()) {
487+
contentBuilder.logger.warn("Functional type should have at least one argument in ${type.dri}")
488+
text("ERROR CLASS: functional type should have at least one argument in ${type.dri}")
489+
return@contentFor
490+
}
491+
486492
args.subList(0, args.size - 1).forEachIndexed { i, arg ->
487493
signatureForProjection(arg)
488494
if (i < args.size - 2) punctuation(", ")
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package model
6+
7+
import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.driOrNull
8+
import org.jetbrains.dokka.links.DRI
9+
import org.jetbrains.dokka.model.*
10+
import utils.AbstractModelTest
11+
import kotlin.test.Test
12+
import kotlin.test.assertTrue
13+
14+
class TypesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "types") {
15+
16+
@Test
17+
fun `type with typealias to functional type with parameter`() {
18+
inlineModelTest(
19+
"""
20+
|typealias HttpExceptionCallback<T> = String.(T) -> String
21+
|fun <T> exception(callback: HttpExceptionCallback<T>){}"""
22+
) {
23+
with((this / "types" / "HttpExceptionCallback").cast<DTypeAlias>()) {
24+
name equals "HttpExceptionCallback"
25+
assertTrue(type is GenericTypeConstructor)
26+
(type as GenericTypeConstructor).projections counts 1
27+
underlyingType.values.first().driOrNull equals DRI("kotlin", "Function2")
28+
}
29+
with((this / "types" / "exception").cast<DFunction>()) {
30+
name equals "exception"
31+
val parameterType = parameters.first().type
32+
assertTrue(parameterType is TypeAliased)
33+
with(parameterType) {
34+
assertTrue(typeAlias is GenericTypeConstructor)
35+
(typeAlias as GenericTypeConstructor).projections counts 1
36+
assertTrue(inner is FunctionalTypeConstructor)
37+
(inner as FunctionalTypeConstructor).dri equals DRI("kotlin", "Function2")
38+
(inner as FunctionalTypeConstructor).projections counts 3
39+
}
40+
}
41+
}
42+
}
43+
44+
@Test
45+
fun `type with typealias to functional type`() {
46+
inlineModelTest(
47+
"""
48+
|typealias CompletionHandler = (cause: Throwable?) -> Unit
49+
|fun exception(callback: CompletionHandler){}"""
50+
) {
51+
with((this / "types" / "CompletionHandler").cast<DTypeAlias>()) {
52+
assertTrue(type is GenericTypeConstructor)
53+
(type as GenericTypeConstructor).projections counts 0
54+
name equals "CompletionHandler"
55+
underlyingType.values.first().driOrNull equals DRI("kotlin", "Function1")
56+
}
57+
with((this / "types" / "exception").cast<DFunction>()) {
58+
name equals "exception"
59+
val parameterType = parameters.first().type
60+
assertTrue(parameterType is TypeAliased)
61+
with(parameterType) {
62+
assertTrue(typeAlias is GenericTypeConstructor)
63+
assertTrue(inner is FunctionalTypeConstructor)
64+
(inner as FunctionalTypeConstructor).dri equals DRI("kotlin", "Function1")
65+
(inner as FunctionalTypeConstructor).projections counts 2
66+
}
67+
}
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)