Analysis API: add KtType.isDenotable()

This commit is contained in:
Tianyu Geng
2021-12-07 13:26:32 -08:00
committed by teamcity
parent 2f393cdd02
commit 5fbe5981f7
20 changed files with 405 additions and 5 deletions
@@ -19,9 +19,17 @@ public abstract class KtTypeInfoProvider : KtAnalysisSessionComponent() {
public abstract fun isFunctionalInterfaceType(type: KtType): Boolean
public abstract fun getFunctionClassKind(type: KtType): FunctionClassKind?
public abstract fun canBeNull(type: KtType): Boolean
public abstract fun isDenotable(type: KtType): Boolean
}
public interface KtTypeInfoProviderMixIn : KtAnalysisSessionMixIn {
/**
* Returns true if this type is denotable. A denotable type is a type that can be written in Kotlin by end users. See
* https://kotlinlang.org/spec/type-system.html#type-kinds for more details.
*/
public val KtType.isDenotable: Boolean
get() = analysisSession.typeInfoProvider.isDenotable(this)
/**
* Returns true if this type is a functional interface type, a.k.a. SAM type, e.g., Runnable.
*/
@@ -0,0 +1,7 @@
fun test() {
class A
@Denotable("A") A()
@Denotable("kotlin.collections.List<A>") listOf(A())
@Nondenotable("<no name provided>") object {}
@Nondenotable("kotlin.collections.List<<no name provided>>") listOf(object {})
}
@@ -0,0 +1,7 @@
fun test() {
class A
@Denotable("A") A()
@Denotable("kotlin.collections.List<A>") listOf(A())
@Nondenotable("<anonymous>") object {}
@Nondenotable("kotlin.collections.List<<anonymous>>") listOf(object {})
}
@@ -0,0 +1,6 @@
interface A
fun test(a: A) {
@Denotable("kotlin.Int") 1
@Denotable("kotlin.String") ""
Denotable("A") a
}
@@ -0,0 +1,28 @@
fun test(a: Any?) {
if (a is String) {
(@Denotable("kotlin.String") a).length
if (a is Int) {
(@Denotable("kotlin.Int") a).inc()
}
if (a is String) {
(@Denotable("kotlin.String") a).length
}
}
if (a != null) {
(@Denotable("kotlin.Any") a).hashCode()
}
if (a == null) {
(@Denotable("kotlin.Any?") a).isNothing()
}
if (a is String || a is Int) {
(@Denotable("kotlin.Any?") a).length
(@Denotable("kotlin.Any?") a).inc()
}
@Nondenotable("(kotlin.Comparable<*> & java.io.Serializable)") if (true) {
""
} else {
1
}
}
fun Nothing?.isNothing() {}
@@ -0,0 +1,28 @@
fun test(a: Any?) {
if (a is String) {
(@Denotable("kotlin.String") a).length
if (a is Int) {
(@Nondenotable("(kotlin.String&kotlin.Int)") a).inc()
}
if (a is String) {
(@Denotable("kotlin.String") a).length
}
}
if (a != null) {
(@Denotable("kotlin.Any") a).hashCode()
}
if (a == null) {
(@Denotable("kotlin.Nothing?") a).isNothing()
}
if (a is String || a is Int) {
(@Nondenotable("(kotlin.Comparable<(kotlin.String&kotlin.Int)>&java.io.Serializable)") a).length
(@Nondenotable("(kotlin.Comparable<(kotlin.String&kotlin.Int)>&java.io.Serializable)") a).inc()
}
@Nondenotable("(kotlin.Comparable<*>&java.io.Serializable)") if (true) {
""
} else {
1
}
}
fun Nothing?.isNothing() {}
@@ -0,0 +1,25 @@
interface A
fun <T> test(t: T) {
@Denotable("T") t
if (t != null) {
(@Nondenotable("T & Any") t).equals("")
}
val outs = take(getOutProjection())
@Denotable("A") outs
val ins = take(getInProjection())
@Denotable(kotlin.Any?) ins
}
fun getOutProjection(): MutableList<out A> {
TODO()
}
fun getInProjection(): MutableList<in A> {
TODO()
}
fun <T> take(l: MutableList<T>): T {
TODO()
}
@@ -0,0 +1,25 @@
interface A
fun <T> test(t: T) {
@Denotable("T") t
if (t != null) {
(@Nondenotable("T!!") t).equals("")
}
val outs = take(getOutProjection())
@Denotable("A") outs
val ins = take(getInProjection())
@Denotable(kotlin.Any?) ins
}
fun getOutProjection(): MutableList<out A> {
TODO()
}
fun getInProjection(): MutableList<in A> {
TODO()
}
fun <T> take(l: MutableList<T>): T {
TODO()
}
@@ -0,0 +1,8 @@
@Target(AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
annotation class Denotable(val type: String)
@Target(AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
annotation class Nondenotable(val type: String)