FIR: handle named arguments in annotations properly
This commit is contained in:
committed by
Mikhail Glukhikh
parent
4f36697737
commit
c3fc524c0d
@@ -446,9 +446,6 @@ internal fun FirReference.statementOrigin(): IrStatementOrigin? {
|
||||
}
|
||||
}
|
||||
|
||||
fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
|
||||
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
|
||||
|
||||
internal fun IrDeclarationParent.declareThisReceiverParameter(
|
||||
symbolTable: SymbolTable,
|
||||
thisType: IrType,
|
||||
|
||||
+10
-6
@@ -6,10 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.backend.generators
|
||||
|
||||
import org.jetbrains.kotlin.fir.backend.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
@@ -19,6 +16,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.isFunctional
|
||||
import org.jetbrains.kotlin.fir.resolve.getCorrespondingConstructorReferenceOrNull
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
@@ -327,6 +325,7 @@ class CallAndReferenceGenerator(
|
||||
val calleeReference = when (call) {
|
||||
is FirFunctionCall -> call.calleeReference
|
||||
is FirDelegatedConstructorCall -> call.calleeReference
|
||||
is FirAnnotationCall -> call.getCorrespondingConstructorReferenceOrNull(session)
|
||||
else -> null
|
||||
} as? FirResolvedNamedReference
|
||||
val function = (calleeReference?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir
|
||||
@@ -334,7 +333,7 @@ class CallAndReferenceGenerator(
|
||||
val argumentMapping = call.argumentMapping
|
||||
if (argumentMapping != null && argumentMapping.isNotEmpty()) {
|
||||
if (valueParameters != null) {
|
||||
return applyArgumentsWithReorderingIfNeeded(argumentMapping, valueParameters)
|
||||
return applyArgumentsWithReorderingIfNeeded(call, argumentMapping, valueParameters)
|
||||
}
|
||||
}
|
||||
for ((index, argument) in call.arguments.withIndex()) {
|
||||
@@ -365,10 +364,15 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
|
||||
private fun IrCallWithIndexedArgumentsBase.applyArgumentsWithReorderingIfNeeded(
|
||||
call: FirCall,
|
||||
argumentMapping: Map<FirExpression, FirValueParameter>,
|
||||
valueParameters: List<FirValueParameter>,
|
||||
): IrExpressionBase {
|
||||
if (needArgumentReordering(argumentMapping.values, valueParameters)) {
|
||||
// Assuming compile-time constants only inside annotation, we don't need a block to reorder arguments to preserve semantics.
|
||||
// But, we still need to pick correct indices for named arguments.
|
||||
if (call !is FirAnnotationCall &&
|
||||
needArgumentReordering(argumentMapping.values, valueParameters)
|
||||
) {
|
||||
return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply {
|
||||
for ((argument, parameter) in argumentMapping) {
|
||||
val parameterIndex = valueParameters.indexOf(parameter)
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||
@@ -462,3 +463,16 @@ private fun FirQualifiedAccess.expressionTypeOrUnitForAssignment(): ConeKotlinTy
|
||||
}
|
||||
return StandardClassIds.Unit.constructClassLikeType(emptyArray(), isNullable = false)
|
||||
}
|
||||
|
||||
fun FirAnnotationCall.getCorrespondingConstructorReferenceOrNull(session: FirSession): FirResolvedNamedReference? =
|
||||
annotationTypeRef.coneTypeSafe<ConeKotlinType>()?.classId?.let {
|
||||
(session.firSymbolProvider.getClassLikeSymbolByFqName(it) as? FirRegularClassSymbol)?.fir
|
||||
?.getPrimaryConstructorIfAny()
|
||||
?.let { annotationConstructor ->
|
||||
buildResolvedNamedReference {
|
||||
source = this@getCorrespondingConstructorReferenceOrNull.source
|
||||
name = it.shortClassName
|
||||
resolvedSymbol = annotationConstructor.symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-1
@@ -25,7 +25,20 @@ data class ArgumentMapping(
|
||||
// parameterToCallArgumentMap.values() should be [ 'bar()', 'foo()' ]
|
||||
val parameterToCallArgumentMap: Map<FirValueParameter, ResolvedCallArgument>,
|
||||
val diagnostics: List<ResolutionDiagnostic>
|
||||
)
|
||||
) {
|
||||
fun toArgumentToParameterMapping(): Map<FirExpression, FirValueParameter> {
|
||||
val argumentToParameterMapping = mutableMapOf<FirExpression, FirValueParameter>()
|
||||
parameterToCallArgumentMap.forEach { (valueParameter, resolvedArgument) ->
|
||||
when (resolvedArgument) {
|
||||
is ResolvedCallArgument.SimpleArgument -> argumentToParameterMapping[resolvedArgument.callArgument] = valueParameter
|
||||
is ResolvedCallArgument.VarargArgument -> resolvedArgument.arguments.forEach {
|
||||
argumentToParameterMapping[it] = valueParameter
|
||||
}
|
||||
}
|
||||
}
|
||||
return argumentToParameterMapping
|
||||
}
|
||||
}
|
||||
|
||||
private val EmptyArgumentMapping = ArgumentMapping(emptyMap(), emptyList())
|
||||
|
||||
|
||||
+1
-10
@@ -159,16 +159,7 @@ internal object MapArguments : ResolutionStage() {
|
||||
val function = symbol.fir
|
||||
|
||||
val mapping = mapArguments(callInfo.arguments, function)
|
||||
val argumentToParameterMapping = mutableMapOf<FirExpression, FirValueParameter>()
|
||||
mapping.parameterToCallArgumentMap.forEach { (valueParameter, resolvedArgument) ->
|
||||
when (resolvedArgument) {
|
||||
is ResolvedCallArgument.SimpleArgument -> argumentToParameterMapping[resolvedArgument.callArgument] = valueParameter
|
||||
is ResolvedCallArgument.VarargArgument -> resolvedArgument.arguments.forEach {
|
||||
argumentToParameterMapping[it] = valueParameter
|
||||
}
|
||||
}
|
||||
}
|
||||
candidate.argumentMapping = argumentToParameterMapping
|
||||
candidate.argumentMapping = mapping.toArgumentToParameterMapping()
|
||||
|
||||
var applicability = CandidateApplicability.RESOLVED
|
||||
mapping.diagnostics.forEach {
|
||||
|
||||
+9
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.candidate
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.mapArguments
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver
|
||||
@@ -641,6 +642,14 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
(annotationCall.transformChildren(transformer, data) as FirAnnotationCall).also {
|
||||
// TODO: it's temporary incorrect solution until we design resolve and completion for annotation calls
|
||||
it.argumentList.transformArguments(integerLiteralTypeApproximator, null)
|
||||
if (it.arguments.any { arg -> arg is FirNamedArgumentExpression }) {
|
||||
annotationCall.getCorrespondingConstructorReferenceOrNull(session)?.let { calleeReference ->
|
||||
val argumentMapping =
|
||||
mapArguments(it.arguments, calleeReference.resolvedSymbol.fir as FirFunction<*>)
|
||||
.toArgumentToParameterMapping()
|
||||
it.replaceArgumentList(buildResolvedArgumentList(argumentMapping))
|
||||
}
|
||||
}
|
||||
it.replaceResolveStatus(status)
|
||||
dataFlowAnalyzer.exitAnnotationCall(it)
|
||||
}.compose()
|
||||
|
||||
@@ -93,6 +93,9 @@ val FirClassSymbol<*>.superConeTypes
|
||||
|
||||
val FirClass<*>.superConeTypes get() = superTypeRefs.mapNotNull { it.coneTypeSafe<ConeClassLikeType>() }
|
||||
|
||||
fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
|
||||
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
|
||||
|
||||
fun FirRegularClass.collectEnumEntries(): Collection<FirEnumEntry> {
|
||||
assert(classKind == ClassKind.ENUM_CLASS)
|
||||
return declarations.filterIsInstance<FirEnumEntry>()
|
||||
|
||||
Vendored
+1
-1
@@ -57,7 +57,7 @@ FILE fqName:<root> fileName:/annotationsWithDefaultParameterValues.kt
|
||||
BLOCK_BODY
|
||||
FUN name:test4 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
annotations:
|
||||
A(x = '456', y = <null>)
|
||||
A(x = <null>, y = '456')
|
||||
BLOCK_BODY
|
||||
FUN name:test5 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
annotations:
|
||||
|
||||
@@ -63,7 +63,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:onCompletion visibility:public modality:FINAL <T> ($receiver:<root>.Flow<T of <root>.onCompletion>, action:kotlin.coroutines.SuspendFunction1<kotlin.Throwable?, kotlin.Unit>) returnType:IrErrorType
|
||||
annotations:
|
||||
Deprecated(message = GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:HIDDEN' type=kotlin.DeprecationLevel, replaceWith = 'binary compatibility with a version w/o FlowCollector receiver', level = <null>)
|
||||
Deprecated(message = 'binary compatibility with a version w/o FlowCollector receiver', replaceWith = <null>, level = GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:HIDDEN' type=kotlin.DeprecationLevel)
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.Flow<T of <root>.onCompletion>
|
||||
VALUE_PARAMETER name:action index:0 type:kotlin.coroutines.SuspendFunction1<kotlin.Throwable?, kotlin.Unit>
|
||||
|
||||
Reference in New Issue
Block a user