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 {