FIR: Transform annotations on type arguments during body resolve.

This commit is contained in:
Mark Punzalan
2021-10-06 07:02:11 +00:00
committed by TeamCityServer
parent d6e428cd98
commit 4f0b52b653
14 changed files with 150 additions and 63 deletions
@@ -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
@@ -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)
}
@@ -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
@@ -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
@@ -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>
@@ -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,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE
/*
@@ -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) {}
@@ -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()
@@ -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,4 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE)
*