Skip to content

Commit 14d7bf8

Browse files
committed
refactor type replace logic to handle more types
1 parent 66eecd7 commit 14d7bf8

File tree

5 files changed

+38
-18
lines changed

5 files changed

+38
-18
lines changed

kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import com.google.devtools.ksp.symbol.Nullability
3131
import org.jetbrains.kotlin.analysis.api.KtStarTypeProjection
3232
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
3333
import org.jetbrains.kotlin.analysis.api.annotations.annotations
34-
import org.jetbrains.kotlin.analysis.api.components.buildClassType
3534
import org.jetbrains.kotlin.analysis.api.symbols.*
3635
import org.jetbrains.kotlin.analysis.api.types.*
3736

@@ -111,24 +110,12 @@ class KSTypeImpl private constructor(internal val type: KtType) : KSType {
111110
}
112111

113112
override fun replace(arguments: List<KSTypeArgument>): KSType {
114-
if (arguments.isNotEmpty() && arguments.size != type.typeArguments().size) {
115-
return KSErrorType
116-
}
117-
return analyze {
118-
analysisSession.buildClassType((type as KtNonErrorClassType).classSymbol) {
119-
arguments.forEach { arg -> argument(arg.toKtTypeProjection()) }
120-
}.let { getCached(it) }
121-
}
113+
return type.replace(arguments.map { it.toKtTypeProjection() })?.let { getCached(it) } ?: KSErrorType
122114
}
123115

124116
override fun starProjection(): KSType {
125-
return analyze {
126-
analysisSession.buildClassType((type as KtNonErrorClassType).classSymbol) {
127-
type.typeArguments().forEach {
128-
argument(KtStarTypeProjection(type.token))
129-
}
130-
}.let { getCached(it) }
131-
}
117+
return type.replace(List(type.typeArguments().size) { KtStarTypeProjection(type.token) })
118+
?.let { getCached(it) } ?: KSErrorType
132119
}
133120

134121
override fun makeNullable(): KSType {

kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/util.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.analysis.api.analyze
3737
import org.jetbrains.kotlin.analysis.api.annotations.*
3838
import org.jetbrains.kotlin.analysis.api.components.KtSubstitutorBuilder
3939
import org.jetbrains.kotlin.analysis.api.components.buildClassType
40+
import org.jetbrains.kotlin.analysis.api.components.buildTypeParameterType
4041
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter
4142
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirValueParameterSymbol
4243
import org.jetbrains.kotlin.analysis.api.lifetime.KtAlwaysAccessibleLifetimeToken
@@ -549,3 +550,19 @@ internal fun KtType.isAssignableFrom(that: KtType): Boolean {
549550
}
550551
}
551552
}
553+
554+
// TODO: fix flexible type creation once upstream available.
555+
internal fun KtType.replace(newArgs: List<KtTypeProjection>): KtType? {
556+
if (newArgs.isNotEmpty() && newArgs.size != this.typeArguments().size) {
557+
return null
558+
}
559+
return analyze {
560+
when (val symbol = classifierSymbol()) {
561+
is KtClassLikeSymbol -> analysisSession.buildClassType(symbol) {
562+
newArgs.forEach { arg -> argument(arg) }
563+
}
564+
is KtTypeParameterSymbol -> analysisSession.buildTypeParameterType(symbol)
565+
else -> throw IllegalStateException("Unexpected type $this")
566+
}
567+
}
568+
}

kotlin-analysis-api/testData/replaceWithErrorTypeArgs.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@
9898
// KLE.E.asType([INVARIANT Int, INVARIANT String]): <ERROR TYPE>
9999
// KLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): <ERROR TYPE>
100100
// KLE.E.asType(emptyList()): KLE
101+
// default type:A
102+
// flexible type star:T
101103
// END
102104

103105
// MODULE: lib
@@ -118,12 +120,15 @@ enum class KLE {
118120
// MODULE: main(lib)
119121
// FILE: JS.java
120122
class JS<T1, T2> {}
121-
class JS1<T> {}
123+
class JS1<T> {
124+
T p;
125+
}
122126
enum JSE {
123127
E
124128
}
125129

126130
// FILE: KS.kt
131+
fun <A> f(a: A) = TODO()
127132
class KS<T1, T2>
128133
class KS1<T>
129134
enum class KSE {

test-utils/src/main/kotlin/com/google/devtools/ksp/processor/ReplaceWithErrorTypeArgsProcessor.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.google.devtools.ksp.processor
1919

2020
import com.google.devtools.ksp.getClassDeclarationByName
21+
import com.google.devtools.ksp.getDeclaredProperties
2122
import com.google.devtools.ksp.processing.Resolver
2223
import com.google.devtools.ksp.symbol.*
2324

@@ -58,6 +59,11 @@ open class ReplaceWithErrorTypeArgsProcessor : AbstractTestProcessor() {
5859
results.add("$declName.asType($yargs): ${decl.asType(yargs)}")
5960
results.add("$declName.asType(emptyList()): ${decl.asType(emptyList())}")
6061
}
62+
val function = resolver.getFunctionDeclarationsByName(resolver.getKSNameFromString("f"), true).single()
63+
results.add("default type:${function.parameters.single().type.resolve().replace(emptyList())}")
64+
// TODO: fix flexible type creation once upstream available.
65+
val js1 = resolver.getClassDeclarationByName("JS1")!!
66+
results.add("flexible type star:${js1.getDeclaredProperties().single().type.resolve().starProjection()}")
6167
return emptyList()
6268
}
6369

test-utils/testData/api/replaceWithErrorTypeArgs.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@
9898
// KLE.E.asType([INVARIANT Int, INVARIANT String]): <ERROR TYPE>
9999
// KLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): <ERROR TYPE>
100100
// KLE.E.asType(emptyList()): KLE.E
101+
// default type:A
102+
// flexible type star:(T..T?)
101103
// END
102104

103105
// MODULE: lib
@@ -118,12 +120,15 @@ enum class KLE {
118120
// MODULE: main(lib)
119121
// FILE: JS.java
120122
class JS<T1, T2> {}
121-
class JS1<T> {}
123+
class JS1<T> {
124+
T p;
125+
}
122126
enum JSE {
123127
E
124128
}
125129

126130
// FILE: KS.kt
131+
fun <A> f(a: A) = TODO()
127132
class KS<T1, T2>
128133
class KS1<T>
129134
enum class KSE {

0 commit comments

Comments
 (0)