FIR: add support for varargs in annotation calls

This commit is contained in:
Jinseong Jeon
2020-07-13 00:34:51 -07:00
committed by Mikhail Glukhikh
parent 4e6bd33eca
commit 5600eefea5
17 changed files with 54 additions and 27 deletions
@@ -1,5 +1,5 @@
FILE: annotations.kt
@R|kotlin/annotation/Target|(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FILE|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FUNCTION|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.TYPE|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|) public final annotation class Simple : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FILE|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FUNCTION|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.TYPE|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|)) public final annotation class Simple : R|kotlin/Annotation| {
public constructor(): R|annotations/Simple| {
super<R|kotlin/Any|>()
}
@@ -1,5 +1,5 @@
FILE: lowPriorityInResolution.kt
@R|kotlin/Suppress|(String(INVISIBLE_MEMBER), String(INVISIBLE_REFERENCE)) @R|kotlin/internal/LowPriorityInOverloadResolution|() public final fun foo(): R|kotlin/Int| {
@R|kotlin/Suppress|(vararg(String(INVISIBLE_MEMBER), String(INVISIBLE_REFERENCE))) @R|kotlin/internal/LowPriorityInOverloadResolution|() public final fun foo(): R|kotlin/Int| {
^foo Int(1)
}
public final fun foo(): R|kotlin/String| {
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
import org.jetbrains.kotlin.fir.expressions.builder.buildVarargArgumentsExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildVariableAssignment
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
@@ -39,6 +40,7 @@ import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
import kotlin.math.min
open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
private inline val builtinTypes: BuiltinTypes get() = session.builtinTypes
@@ -692,16 +694,39 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
// TODO: it's temporary incorrect solution until we design resolve and completion for annotation calls
it.argumentList.transformArguments(integerLiteralTypeApproximator, null)
annotationCall.getCorrespondingConstructorReferenceOrNull(session)?.let { calleeReference ->
val argumentMapping =
mapArguments(it.arguments, calleeReference.resolvedSymbol.fir as FirFunction<*>)
.toArgumentToParameterMapping()
it.replaceArgumentList(buildResolvedArgumentList(argumentMapping))
val callee = calleeReference.resolvedSymbol.fir as FirFunction<*>
val argumentMapping = mapArguments(it.arguments, callee).toArgumentToParameterMapping()
val varargParameter = callee.valueParameters.firstOrNull { param -> param.isVararg }
if (varargParameter == null) {
it.replaceArgumentList(buildResolvedArgumentList(argumentMapping))
} else {
// TODO: refactor/reuse [Candidate#handleVarargs] in [FirCallCompletionResultsWriterTransformer]
val varargParameterTypeRef = varargParameter.returnTypeRef
val arrayType = varargParameterTypeRef.coneType
val elementType = arrayType.arrayElementType()
var firstIndex = it.argumentList.arguments.size
val newArgumentMapping = mutableMapOf<FirExpression, FirValueParameter>()
val varargArgument = buildVarargArgumentsExpression {
varargElementType = varargParameterTypeRef.withReplacedConeType(elementType)
this@buildVarargArgumentsExpression.typeRef = varargParameterTypeRef
for ((i, arg) in it.argumentList.arguments.withIndex()) {
val valueParameter = argumentMapping[arg] ?: continue
if (valueParameter.isVararg) {
firstIndex = min(firstIndex, i)
arguments += arg
} else {
newArgumentMapping[arg] = valueParameter
}
}
}
newArgumentMapping[varargArgument] = varargParameter
it.replaceArgumentList(buildResolvedArgumentList(newArgumentMapping))
}
}
it.replaceResolveStatus(status)
dataFlowAnalyzer.exitAnnotationCall(it)
}.compose()
}
}
private inline fun <T> withFirArrayOfCallTransformer(block: () -> T): T {
@@ -1,5 +1,4 @@
// !LANGUAGE: -ProhibitAssigningSingleElementsToVarargsInNamedForm
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FULL_JDK
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FULL_JDK
@@ -1,5 +1,5 @@
// WITH_REFLECT
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
import java.util.Arrays
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
// IGNORE_BACKEND: JS, NATIVE
@@ -28,12 +28,14 @@ FILE fqName:<root> fileName:/annotationsWithVarargParameters.kt
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
annotations:
A(xs = ['abc', 'def'])
BLOCK_BODY
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
annotations:
A(xs = 'abc')
A(xs = ['abc'])
BLOCK_BODY
FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.Unit
annotations:
A(xs = <null>)
A(xs = [])
BLOCK_BODY
@@ -3,7 +3,7 @@ FILE fqName:test fileName:/fileAnnotations.kt
A(x = 'File annotation')
CLASS ANNOTATION_CLASS name:A modality:FINAL visibility:public superTypes:[kotlin.Annotation]
annotations:
Target(allowedTargets = GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:FILE' type=kotlin.annotation.AnnotationTarget)
Target(allowedTargets = [GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:FILE' type=kotlin.annotation.AnnotationTarget])
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:test.A
CONSTRUCTOR visibility:public <> (x:kotlin.String) returnType:test.A [primary]
VALUE_PARAMETER name:x index:0 type:kotlin.String
@@ -28,4 +28,6 @@ FILE fqName:<root> fileName:/spreadOperatorInAnnotationArguments.kt
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
annotations:
A(xs = [SPREAD_ELEMENT, SPREAD_ELEMENT])
BLOCK_BODY
@@ -2,7 +2,7 @@ FILE fqName:<root> fileName:/typeAliasesWithAnnotations.kt
TYPEALIAS name:TestTypeAlias visibility:public expandedType:kotlin.String
CLASS ANNOTATION_CLASS name:TestAnn modality:FINAL visibility:public superTypes:[kotlin.Annotation]
annotations:
Target(allowedTargets = GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:TYPEALIAS' type=kotlin.annotation.AnnotationTarget)
Target(allowedTargets = [GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:TYPEALIAS' type=kotlin.annotation.AnnotationTarget])
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.TestAnn
CONSTRUCTOR visibility:public <> (x:kotlin.String) returnType:<root>.TestAnn [primary]
VALUE_PARAMETER name:x index:0 type:kotlin.String
@@ -1,7 +1,7 @@
FILE fqName:<root> fileName:/typeParametersWithAnnotations.kt
CLASS ANNOTATION_CLASS name:Anno modality:FINAL visibility:public superTypes:[kotlin.Annotation]
annotations:
Target(allowedTargets = GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:TYPE_PARAMETER' type=kotlin.annotation.AnnotationTarget)
Target(allowedTargets = [GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:TYPE_PARAMETER' type=kotlin.annotation.AnnotationTarget])
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Anno
CONSTRUCTOR visibility:public <> () returnType:<root>.Anno [primary]
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
@@ -84,10 +84,14 @@ FILE fqName:<root> fileName:/varargsInAnnotationArguments.kt
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
annotations:
A1(xs = ['1', '2', '3'])
A2(xs = ['a', 'b', 'c'])
AA(xs = [A1(xs = ['4']), A1(xs = ['5']), A1(xs = ['6'])])
BLOCK_BODY
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
annotations:
A1(xs = <null>)
A2(xs = <null>)
AA(xs = <null>)
A1(xs = [])
A2(xs = [])
AA(xs = [])
BLOCK_BODY
@@ -1,7 +1,7 @@
FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
FUN name:scopedFlow visibility:public modality:FINAL <R> (block:kotlin.coroutines.SuspendFunction2<<root>.CoroutineScope, <root>.FlowCollector<R of <root>.scopedFlow>, kotlin.Unit>) returnType:<root>.Flow<R of <root>.scopedFlow>
annotations:
OptIn(markerClass = CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>)
OptIn(markerClass = [CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>])
TYPE_PARAMETER name:R index:0 variance: superTypes:[kotlin.Any?]
VALUE_PARAMETER name:block index:0 type:kotlin.coroutines.SuspendFunction2<<root>.CoroutineScope, <root>.FlowCollector<R of <root>.scopedFlow>, kotlin.Unit>
annotations:
@@ -53,7 +53,7 @@ FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
BLOCK_BODY
FUN name:unsafeFlow visibility:public modality:FINAL <T> (block:kotlin.coroutines.SuspendFunction1<<root>.FlowCollector<T of <root>.unsafeFlow>, kotlin.Unit>) returnType:<root>.Flow<T of <root>.unsafeFlow> [inline]
annotations:
OptIn(markerClass = CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>)
OptIn(markerClass = [CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>])
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
VALUE_PARAMETER name:block index:0 type:kotlin.coroutines.SuspendFunction1<<root>.FlowCollector<T of <root>.unsafeFlow>, kotlin.Unit> [crossinline]
annotations:
@@ -191,7 +191,7 @@ FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:flow visibility:public modality:FINAL <T> (block:kotlin.coroutines.SuspendFunction1<<root>.FlowCollector<T of <root>.flow>, kotlin.Unit>) returnType:<root>.Flow<T of <root>.flow>
annotations:
OptIn(markerClass = CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>)
OptIn(markerClass = [CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>])
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
VALUE_PARAMETER name:block index:0 type:kotlin.coroutines.SuspendFunction1<<root>.FlowCollector<T of <root>.flow>, kotlin.Unit>
annotations:
@@ -201,7 +201,7 @@ FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
CALL 'public final fun TODO (): kotlin.Nothing [inline] declared in kotlin' type=kotlin.Nothing origin=null
FUN name:flowScope visibility:public modality:FINAL <R> (block:kotlin.coroutines.SuspendFunction1<<root>.CoroutineScope, R of <root>.flowScope>) returnType:R of <root>.flowScope [suspend]
annotations:
OptIn(markerClass = CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>)
OptIn(markerClass = [CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>])
TYPE_PARAMETER name:R index:0 variance: superTypes:[kotlin.Any?]
VALUE_PARAMETER name:block index:0 type:kotlin.coroutines.SuspendFunction1<<root>.CoroutineScope, R of <root>.flowScope>
annotations:
@@ -309,7 +309,7 @@ FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:produce visibility:public modality:FINAL <E> ($receiver:<root>.CoroutineScope, block:kotlin.coroutines.SuspendFunction1<<root>.ProducerScope<E of <root>.produce>, kotlin.Unit>) returnType:<root>.ReceiveChannel<E of <root>.produce>
annotations:
OptIn(markerClass = CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>)
OptIn(markerClass = [CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalTypeInference modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.experimental.ExperimentalTypeInference>])
TYPE_PARAMETER name:E index:0 variance: superTypes:[kotlin.Any?]
$receiver: VALUE_PARAMETER name:<this> type:<root>.CoroutineScope
VALUE_PARAMETER name:block index:0 type:kotlin.coroutines.SuspendFunction1<<root>.ProducerScope<E of <root>.produce>, kotlin.Unit>