FIR: Transform annotations on type arguments during body resolve.
This commit is contained in:
committed by
TeamCityServer
parent
d6e428cd98
commit
4f0b52b653
@@ -18,16 +18,30 @@ val ConeKotlinType.isMarkedNullable: Boolean get() = nullability == ConeNullabil
|
||||
|
||||
val ConeKotlinType.classId: ClassId? get() = this.safeAs<ConeClassLikeType>()?.lookupTag?.classId
|
||||
|
||||
fun ConeKotlinType.contains(predicate: (ConeKotlinType) -> Boolean): Boolean {
|
||||
return contains(predicate, null)
|
||||
/**
|
||||
* Recursively visits each [ConeKotlinType] inside (including itself) and performs the given action.
|
||||
*/
|
||||
fun ConeKotlinType.forEachType(action: (ConeKotlinType) -> Unit) {
|
||||
action(this)
|
||||
|
||||
return when (this) {
|
||||
is ConeFlexibleType -> {
|
||||
lowerBound.forEachType(action)
|
||||
upperBound.forEachType(action)
|
||||
}
|
||||
is ConeDefinitelyNotNullType -> original.forEachType(action)
|
||||
is ConeIntersectionType -> intersectedTypes.forEach { it.forEachType(action) }
|
||||
else -> typeArguments.forEach { if (it is ConeKotlinTypeProjection) it.type.forEachType(action) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.contains(predicate: (ConeKotlinType) -> Boolean, visited: SmartSet<ConeKotlinType>?): Boolean {
|
||||
if (visited?.contains(this) == true) return false
|
||||
if (predicate(this)) return true
|
||||
fun ConeKotlinType.contains(predicate: (ConeKotlinType) -> Boolean): Boolean {
|
||||
return contains(predicate, SmartSet.create())
|
||||
}
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val visited = visited ?: SmartSet.create()
|
||||
private fun ConeKotlinType.contains(predicate: (ConeKotlinType) -> Boolean, visited: SmartSet<ConeKotlinType>): Boolean {
|
||||
if (this in visited) return false
|
||||
if (predicate(this)) return true
|
||||
visited += this
|
||||
|
||||
return when (this) {
|
||||
@@ -74,6 +88,7 @@ val ConeKotlinType.isArrayType: Boolean
|
||||
return isBuiltinType(StandardClassIds.Array, false) ||
|
||||
StandardClassIds.primitiveArrayTypeByElementType.values.any { isBuiltinType(it, false) }
|
||||
}
|
||||
|
||||
// Same as [KotlinBuiltIns#isNonPrimitiveArray]
|
||||
val ConeKotlinType.isNonPrimitiveArray: Boolean
|
||||
get() = this is ConeClassLikeType && lookupTag.classId == StandardClassIds.Array
|
||||
|
||||
+8
-3
@@ -21,9 +21,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFull
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
|
||||
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.createCurrentScopeList
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
|
||||
open class FirBodyResolveTransformer(
|
||||
@@ -77,6 +75,13 @@ open class FirBodyResolveTransformer(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
resolvedTypeRef.coneType.forEachType {
|
||||
it.type.attributes.customAnnotations.forEach { typeArgumentAnnotation ->
|
||||
typeArgumentAnnotation.accept(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
return resolvedTypeRef.transformAnnotations(this, data)
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -26,4 +26,19 @@ annotation class TypeAnn
|
||||
|
||||
val onType: (@TypeAnn A).(@Ann a: @TypeAnn A, @TypeAnn A)->@TypeAnn A? = { null }
|
||||
|
||||
fun (@TypeAnn A).extFun(@Ann a: @TypeAnn A): @TypeAnn A? = null
|
||||
fun (@TypeAnn A).extFun(@Ann a: @TypeAnn A): @TypeAnn A? = null
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class TypeAnnWithArg(val arg: String)
|
||||
|
||||
fun badArgs(a: (@TypeAnnWithArg(<!NAMED_PARAMETER_NOT_FOUND!>unresolved<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!> Int) -> Unit) {}
|
||||
|
||||
typealias BadArgsInTypeAlias = (<!NO_VALUE_FOR_PARAMETER!>@TypeAnnWithArg<!> Int) -> Unit
|
||||
fun badArgsInTypeAlias(a: BadArgsInTypeAlias) {}
|
||||
|
||||
typealias T<X> = (X) -> Unit
|
||||
fun badArgsInTypeAliasInstance(a: T<@TypeAnnWithArg(arg = <!ARGUMENT_TYPE_MISMATCH!>123<!>) Int>) {}
|
||||
|
||||
typealias BadArgsInRecursive = (((<!NO_VALUE_FOR_PARAMETER!>@TypeAnnWithArg<!> Int) -> Unit) -> <!NO_VALUE_FOR_PARAMETER!>@TypeAnnWithArg<!> String) -> Unit
|
||||
|
||||
typealias BadArgsMultiple = (<!NO_VALUE_FOR_PARAMETER!>@TypeAnnWithArg<!> Int, @TypeAnnWithArg(arg = <!ARGUMENT_TYPE_MISMATCH!>123<!>) Int) -> Unit
|
||||
|
||||
+16
-1
@@ -26,4 +26,19 @@ annotation class TypeAnn
|
||||
|
||||
val onType: (@TypeAnn A).(<!UNSUPPORTED!>@Ann<!> a: @TypeAnn A, @TypeAnn A)->@TypeAnn A? = <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!>{<!> null }
|
||||
|
||||
fun (@TypeAnn A).extFun(@Ann a: @TypeAnn A): @TypeAnn A? = null
|
||||
fun (@TypeAnn A).extFun(@Ann a: @TypeAnn A): @TypeAnn A? = null
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class TypeAnnWithArg(val arg: String)
|
||||
|
||||
fun badArgs(a: (@TypeAnnWithArg(<!NAMED_PARAMETER_NOT_FOUND!>unresolved<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!> Int) -> Unit) {}
|
||||
|
||||
typealias BadArgsInTypeAlias = (@<!NO_VALUE_FOR_PARAMETER!>TypeAnnWithArg<!> Int) -> Unit
|
||||
fun badArgsInTypeAlias(a: BadArgsInTypeAlias) {}
|
||||
|
||||
typealias T<X> = (X) -> Unit
|
||||
fun badArgsInTypeAliasInstance(a: T<@TypeAnnWithArg(arg = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>123<!>) Int>) {}
|
||||
|
||||
typealias BadArgsInRecursive = (((@<!NO_VALUE_FOR_PARAMETER!>TypeAnnWithArg<!> Int) -> Unit) -> @<!NO_VALUE_FOR_PARAMETER!>TypeAnnWithArg<!> String) -> Unit
|
||||
|
||||
typealias BadArgsMultiple = (@<!NO_VALUE_FOR_PARAMETER!>TypeAnnWithArg<!> Int, @TypeAnnWithArg(arg = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>123<!>) Int) -> Unit
|
||||
|
||||
+15
@@ -2,6 +2,9 @@ package
|
||||
|
||||
public val inVal: (x: kotlin.Int) -> kotlin.Unit
|
||||
public val onType: (@TypeAnn A).(a: @TypeAnn A, @TypeAnn A) -> @TypeAnn A?
|
||||
public fun badArgs(/*0*/ a: (@TypeAnnWithArg kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
||||
public fun badArgsInTypeAlias(/*0*/ a: BadArgsInTypeAlias /* = (@TypeAnnWithArg kotlin.Int) -> kotlin.Unit */): kotlin.Unit
|
||||
public fun badArgsInTypeAliasInstance(/*0*/ a: T<@TypeAnnWithArg(arg = 123) kotlin.Int> /* = (@TypeAnnWithArg(arg = 123) kotlin.Int) -> kotlin.Unit */): kotlin.Unit
|
||||
public fun f(/*0*/ @Ann x: kotlin.Int): kotlin.Unit
|
||||
public fun inParam(/*0*/ fn: (x: kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
||||
public fun inParamNested(/*0*/ fn1: (fn2: (n: kotlin.Int) -> kotlin.Unit) -> kotlin.Unit): kotlin.Unit
|
||||
@@ -30,3 +33,15 @@ public final annotation class Ann : kotlin.Annotation {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class TypeAnnWithArg : kotlin.Annotation {
|
||||
public constructor TypeAnnWithArg(/*0*/ arg: kotlin.String)
|
||||
public final val arg: kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
public typealias BadArgsInRecursive = (((@TypeAnnWithArg kotlin.Int) -> kotlin.Unit) -> @TypeAnnWithArg kotlin.String) -> kotlin.Unit
|
||||
public typealias BadArgsInTypeAlias = (@TypeAnnWithArg kotlin.Int) -> kotlin.Unit
|
||||
public typealias BadArgsMultiple = (@TypeAnnWithArg kotlin.Int, @TypeAnnWithArg(arg = 123) kotlin.Int) -> kotlin.Unit
|
||||
public typealias T</*0*/ X> = (X) -> kotlin.Unit
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE, -UNUSED_PARAMETER
|
||||
class A
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class x
|
||||
|
||||
fun @x A.foo(a: @x Int) {
|
||||
val v: @x Int = 1
|
||||
}
|
||||
|
||||
fun <T> @x List<@x T>.foo(l: List<@x T>): @x List<@x T> = throw Exception()
|
||||
|
||||
fun <T, U: T> List<@x T>.firstTyped(): U = throw Exception()
|
||||
|
||||
val <T> @x List<@x T>.f: Int get() = 42
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class TypeAnnWithArg(val arg: String)
|
||||
|
||||
fun badArgs(a: List<@TypeAnnWithArg(<!NAMED_PARAMETER_NOT_FOUND!>unresolved<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!> Int>) {}
|
||||
fun badArgsWithProjection(a: Array<out @TypeAnnWithArg(<!NAMED_PARAMETER_NOT_FOUND!>unresolved<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!> Int>) {}
|
||||
|
||||
typealias BadArgsInTypeAlias = List<<!NO_VALUE_FOR_PARAMETER!>@TypeAnnWithArg<!> Int>
|
||||
fun badArgsInTypeAlias(a: BadArgsInTypeAlias) {}
|
||||
|
||||
typealias T<X> = List<X>
|
||||
fun badArgsInTypeAliasInstance(a: T<@TypeAnnWithArg(arg = <!ARGUMENT_TYPE_MISMATCH!>123<!>) Int>) {}
|
||||
|
||||
typealias BadArgsInTypeParameter<<!WRONG_ANNOTATION_TARGET!>@TypeAnnWithArg(arg = <!ARGUMENT_TYPE_MISMATCH!>123<!>)<!> X> = List<X>
|
||||
|
||||
typealias BadArgsInRecursive = List<Map<List<<!NO_VALUE_FOR_PARAMETER!>@TypeAnnWithArg<!> Int>, <!NO_VALUE_FOR_PARAMETER!>@TypeAnnWithArg<!> String>>
|
||||
|
||||
typealias BadArgsMultiple = Map<<!NO_VALUE_FOR_PARAMETER!>@TypeAnnWithArg<!> Int, @TypeAnnWithArg(arg = <!ARGUMENT_TYPE_MISMATCH!>123<!>) Int>
|
||||
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE, -UNUSED_PARAMETER
|
||||
class A
|
||||
|
||||
@@ -13,4 +12,22 @@ fun <T> @x List<@x T>.foo(l: List<@x T>): @x List<@x T> = throw Exception()
|
||||
|
||||
fun <T, U: T> List<@x T>.firstTyped(): U = throw Exception()
|
||||
|
||||
val <T> @x List<@x T>.f: Int get() = 42
|
||||
val <T> @x List<@x T>.f: Int get() = 42
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class TypeAnnWithArg(val arg: String)
|
||||
|
||||
fun badArgs(a: List<@TypeAnnWithArg(<!NAMED_PARAMETER_NOT_FOUND!>unresolved<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!> Int>) {}
|
||||
fun badArgsWithProjection(a: Array<out @TypeAnnWithArg(<!NAMED_PARAMETER_NOT_FOUND!>unresolved<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!> Int>) {}
|
||||
|
||||
typealias BadArgsInTypeAlias = List<@<!NO_VALUE_FOR_PARAMETER!>TypeAnnWithArg<!> Int>
|
||||
fun badArgsInTypeAlias(a: BadArgsInTypeAlias) {}
|
||||
|
||||
typealias T<X> = List<X>
|
||||
fun badArgsInTypeAliasInstance(a: T<@TypeAnnWithArg(arg = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>123<!>) Int>) {}
|
||||
|
||||
typealias BadArgsInTypeParameter<<!WRONG_ANNOTATION_TARGET!>@TypeAnnWithArg(arg = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>123<!>)<!> X> = List<X>
|
||||
|
||||
typealias BadArgsInRecursive = List<Map<List<@<!NO_VALUE_FOR_PARAMETER!>TypeAnnWithArg<!> Int>, @<!NO_VALUE_FOR_PARAMETER!>TypeAnnWithArg<!> String>>
|
||||
|
||||
typealias BadArgsMultiple = Map<@<!NO_VALUE_FOR_PARAMETER!>TypeAnnWithArg<!> Int, @TypeAnnWithArg(arg = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>123<!>) Int>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package
|
||||
|
||||
public val </*0*/ T> @x kotlin.collections.List<@x T>.f: kotlin.Int
|
||||
public fun badArgs(/*0*/ a: kotlin.collections.List<@TypeAnnWithArg kotlin.Int>): kotlin.Unit
|
||||
public fun badArgsInTypeAlias(/*0*/ a: BadArgsInTypeAlias /* = kotlin.collections.List<@TypeAnnWithArg kotlin.Int> */): kotlin.Unit
|
||||
public fun badArgsInTypeAliasInstance(/*0*/ a: T<@TypeAnnWithArg(arg = 123) kotlin.Int> /* = kotlin.collections.List<@TypeAnnWithArg(arg = 123) kotlin.Int> */): kotlin.Unit
|
||||
public fun badArgsWithProjection(/*0*/ a: kotlin.Array<out @TypeAnnWithArg kotlin.Int>): kotlin.Unit
|
||||
public fun </*0*/ T, /*1*/ U : T> kotlin.collections.List<@x T>.firstTyped(): U
|
||||
public fun @x A.foo(/*0*/ a: @x kotlin.Int): kotlin.Unit
|
||||
public fun </*0*/ T> @x kotlin.collections.List<@x T>.foo(/*0*/ l: kotlin.collections.List<@x T>): @x kotlin.collections.List<@x T>
|
||||
@@ -12,9 +16,22 @@ public final class A {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class TypeAnnWithArg : kotlin.Annotation {
|
||||
public constructor TypeAnnWithArg(/*0*/ arg: kotlin.String)
|
||||
public final val arg: kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class x : kotlin.Annotation {
|
||||
public constructor x()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
public typealias BadArgsInRecursive = kotlin.collections.List<kotlin.collections.Map<kotlin.collections.List<@TypeAnnWithArg kotlin.Int>, @TypeAnnWithArg kotlin.String>>
|
||||
public typealias BadArgsInTypeAlias = kotlin.collections.List<@TypeAnnWithArg kotlin.Int>
|
||||
public typealias BadArgsInTypeParameter</*0*/ @TypeAnnWithArg(arg = 123) X> = kotlin.collections.List<X>
|
||||
public typealias BadArgsMultiple = kotlin.collections.Map<@TypeAnnWithArg kotlin.Int, @TypeAnnWithArg(arg = 123) kotlin.Int>
|
||||
public typealias T</*0*/ X> = kotlin.collections.List<X>
|
||||
|
||||
Vendored
-26
@@ -1,26 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
// TESTCASE NUMBER: 1, 2
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class Ann(val x: Int)
|
||||
|
||||
/*
|
||||
* TESTCASE NUMBER: 1
|
||||
* UNEXPECTED BEHAVIOUR
|
||||
*/
|
||||
fun case_1() {
|
||||
val x: (Int) -> @Ann(unresolved_reference) Unit = {} // OK, no error in IDE and in the compiler
|
||||
}
|
||||
|
||||
/*
|
||||
* TESTCASE NUMBER: 2
|
||||
* UNEXPECTED BEHAVIOUR
|
||||
*/
|
||||
fun case_2() {
|
||||
val x: (@Ann(unresolved_reference) Int) -> Unit = { a: Int -> println(a) } // OK, no error in IDE and in the compiler
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
fun case_3() {
|
||||
val x: (@Ann(unresolved_reference) Int) -> Unit = { a -> println(a) } // ERROR (if argument type isn't specified explicitly)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
/*
|
||||
|
||||
Vendored
+1
-1
@@ -5,7 +5,7 @@
|
||||
annotation class Ann(val x: Int)
|
||||
|
||||
// TESTCASE NUMBER: 1
|
||||
fun foo(i: Inv<@Ann(unresolved_reference) String>) {}
|
||||
fun foo(i: Inv<@Ann(<!UNRESOLVED_REFERENCE!>unresolved_reference<!>) String>) {}
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun test(vararg a: @Ann(unresolved_reference) Any) {}
|
||||
|
||||
Vendored
+1
-1
@@ -2,4 +2,4 @@
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class Ann(val x: Int)
|
||||
|
||||
fun case_1(): Inv<@Ann(unresolved_reference) String> = TODO()
|
||||
fun case_1(): Inv<@Ann(<!UNRESOLVED_REFERENCE!>unresolved_reference<!>) String> = TODO()
|
||||
|
||||
Vendored
-20
@@ -1,20 +0,0 @@
|
||||
|
||||
// TESTCASE NUMBER: 1, 2
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class Ann
|
||||
|
||||
/*
|
||||
* TESTCASE NUMBER: 1
|
||||
* UNEXPECTED BEHAVIOUR
|
||||
*/
|
||||
open class TypeToken<T>
|
||||
|
||||
val case_1 = object : TypeToken<@Ann(unresolved_reference) String>() {}
|
||||
|
||||
/*
|
||||
* TESTCASE NUMBER: 2
|
||||
* UNEXPECTED BEHAVIOUR
|
||||
*/
|
||||
interface A
|
||||
|
||||
val case_2 = object: @Ann(<!TOO_MANY_ARGUMENTS, UNRESOLVED_REFERENCE!>unresolved_reference<!>) A {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
|
||||
// FIR_IDENTICAL
|
||||
/*
|
||||
* KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE)
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user