[FIR] Improve mapping arguments to parameters
This commit is contained in:
@@ -324,16 +324,19 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
|
||||
internal fun FirExpression.getExpectedType(
|
||||
session: FirSession,
|
||||
parameter: FirValueParameter/*, languageVersionSettings: LanguageVersionSettings*/
|
||||
) =
|
||||
// if (this.isSpread || this.isArrayAssignedAsNamedArgumentInAnnotation(parameter, languageVersionSettings)) {
|
||||
// parameter.type.unwrap()
|
||||
// } else {
|
||||
if (parameter.isVararg && (this !is FirWrappedArgumentExpression || !isSpread)) {
|
||||
): ConeKotlinType {
|
||||
val shouldUnwrapVarargType = when (this) {
|
||||
is FirSpreadArgumentExpression -> !isSpread
|
||||
is FirNamedArgumentExpression -> false
|
||||
else -> true
|
||||
}
|
||||
|
||||
return if (parameter.isVararg && shouldUnwrapVarargType) {
|
||||
parameter.returnTypeRef.coneTypeUnsafe<ConeKotlinType>().varargElementType(session)
|
||||
} else {
|
||||
parameter.returnTypeRef.coneTypeUnsafe()
|
||||
}//?.varargElementType?.unwrap() ?: parameter.type.unwrap()
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun ConeKotlinType.varargElementType(session: FirSession): ConeKotlinType {
|
||||
@@ -354,4 +357,4 @@ fun FirTypeRef.isExtensionFunctionType(session: FirSession): Boolean {
|
||||
if (typeAlias.expandedTypeRef.annotations.any(FirAnnotationCall::isExtensionFunctionAnnotationCall)) return true
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -109,6 +109,8 @@ class Candidate(
|
||||
var argumentMapping: Map<FirExpression, FirValueParameter>? = null
|
||||
val postponedAtoms = mutableListOf<PostponedResolvedAtomMarker>()
|
||||
|
||||
val diagnostics: MutableList<ResolutionDiagnostic> = mutableListOf()
|
||||
|
||||
fun dispatchReceiverExpression(): FirExpression = when (explicitReceiverKind) {
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> callInfo.explicitReceiver!!
|
||||
else -> dispatchReceiverValue?.receiverExpression ?: FirNoReceiverExpression
|
||||
|
||||
+257
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSpreadArgumentExpression
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.set
|
||||
|
||||
|
||||
data class ArgumentMapping(
|
||||
// This map should be ordered by arguments as written, e.g.:
|
||||
// fun foo(a: Int, b: Int) {}
|
||||
// foo(b = bar(), a = qux())
|
||||
// parameterToCallArgumentMap.values() should be [ 'bar()', 'foo()' ]
|
||||
val parameterToCallArgumentMap: Map<FirValueParameter, ResolvedCallArgument>,
|
||||
val diagnostics: List<ResolutionDiagnostic>
|
||||
)
|
||||
|
||||
private val EmptyArgumentMapping = ArgumentMapping(emptyMap(), emptyList())
|
||||
|
||||
fun mapArguments(
|
||||
arguments: List<FirExpression>,
|
||||
function: FirFunction<*>
|
||||
): ArgumentMapping {
|
||||
if (arguments.isEmpty() && function.valueParameters.isEmpty()) {
|
||||
return EmptyArgumentMapping
|
||||
}
|
||||
val externalArgument: FirExpression? = arguments.lastOrNull { it is FirLambdaArgumentExpression }
|
||||
val argumentsInParenthesis: List<FirExpression> = if (externalArgument == null) {
|
||||
arguments
|
||||
} else {
|
||||
arguments.subList(0, arguments.size - 1)
|
||||
}
|
||||
|
||||
val processor = FirCallArgumentsProcessor(function)
|
||||
processor.processArgumentsInParenthesis(argumentsInParenthesis)
|
||||
if (externalArgument != null) {
|
||||
processor.processExternalArgument(externalArgument)
|
||||
}
|
||||
processor.processDefaultsAndRunChecks()
|
||||
|
||||
return ArgumentMapping(processor.result, processor.diagnostics ?: emptyList())
|
||||
}
|
||||
|
||||
private class FirCallArgumentsProcessor(private val function: FirFunction<*>) {
|
||||
private var state = State.POSITION_ARGUMENTS
|
||||
private var currentPositionedParameterIndex = 0
|
||||
private var varargArguments: MutableList<FirExpression>? = null
|
||||
private var nameToParameter: Map<Name, FirValueParameter>? = null
|
||||
var diagnostics: MutableList<ResolutionDiagnostic>? = null
|
||||
private set
|
||||
val result: MutableMap<FirValueParameter, ResolvedCallArgument> = LinkedHashMap()
|
||||
|
||||
private enum class State {
|
||||
POSITION_ARGUMENTS,
|
||||
VARARG_POSITION,
|
||||
NAMED_ONLY_ARGUMENTS
|
||||
}
|
||||
|
||||
fun processArgumentsInParenthesis(arguments: List<FirExpression>) {
|
||||
for (argument in arguments) {
|
||||
val argumentName = argument.argumentName
|
||||
|
||||
// process position argument
|
||||
if (argumentName == null) {
|
||||
if (processPositionArgument(argument)) {
|
||||
state = State.VARARG_POSITION
|
||||
}
|
||||
}
|
||||
// process named argument
|
||||
else {
|
||||
if (state == State.VARARG_POSITION) {
|
||||
completeVarargPositionArguments()
|
||||
}
|
||||
state = State.NAMED_ONLY_ARGUMENTS
|
||||
|
||||
processNamedArgument(argument, argumentName)
|
||||
}
|
||||
}
|
||||
if (state == State.VARARG_POSITION) {
|
||||
completeVarargPositionArguments()
|
||||
}
|
||||
}
|
||||
|
||||
// return true, if it was mapped to vararg parameter
|
||||
private fun processPositionArgument(argument: FirExpression): Boolean {
|
||||
if (state == State.NAMED_ONLY_ARGUMENTS) {
|
||||
addDiagnostic(MixingNamedAndPositionArguments(argument))
|
||||
return false
|
||||
}
|
||||
|
||||
val parameter = parameters.getOrNull(currentPositionedParameterIndex)
|
||||
if (parameter == null) {
|
||||
addDiagnostic(TooManyArguments(argument, function))
|
||||
return false
|
||||
}
|
||||
|
||||
if (!parameter.isVararg) {
|
||||
currentPositionedParameterIndex++
|
||||
|
||||
result[parameter] = ResolvedCallArgument.SimpleArgument(argument)
|
||||
return false
|
||||
}
|
||||
// all position arguments will be mapped to current vararg parameter
|
||||
else {
|
||||
addVarargArgument(argument)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private fun processNamedArgument(argument: FirExpression, name: Name) {
|
||||
if (!function.hasStableParameterNames) {
|
||||
addDiagnostic(NamedArgumentNotAllowed(argument, function))
|
||||
}
|
||||
|
||||
val parameter = findParameterByName(argument, name) ?: return
|
||||
|
||||
result[parameter]?.let {
|
||||
addDiagnostic(ArgumentPassedTwice(argument, parameter, it))
|
||||
return
|
||||
}
|
||||
|
||||
result[parameter] = ResolvedCallArgument.SimpleArgument(argument)
|
||||
|
||||
if (parameters.getOrNull(currentPositionedParameterIndex) == parameter) {
|
||||
state = State.POSITION_ARGUMENTS
|
||||
currentPositionedParameterIndex++
|
||||
}
|
||||
}
|
||||
|
||||
fun processExternalArgument(externalArgument: FirExpression) {
|
||||
val lastParameter = parameters.lastOrNull()
|
||||
if (lastParameter == null) {
|
||||
addDiagnostic(TooManyArguments(externalArgument, function))
|
||||
return
|
||||
}
|
||||
|
||||
if (lastParameter.isVararg) {
|
||||
addDiagnostic(VarargArgumentOutsideParentheses(externalArgument, lastParameter))
|
||||
return
|
||||
}
|
||||
|
||||
val previousOccurrence = result[lastParameter]
|
||||
if (previousOccurrence != null) {
|
||||
addDiagnostic(TooManyArguments(externalArgument, function))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
result[lastParameter] = ResolvedCallArgument.SimpleArgument(externalArgument)
|
||||
}
|
||||
|
||||
fun processDefaultsAndRunChecks() {
|
||||
for ((parameter, resolvedArgument) in result) {
|
||||
if (!parameter.isVararg) {
|
||||
if (resolvedArgument !is ResolvedCallArgument.SimpleArgument) {
|
||||
error("Incorrect resolved argument for parameter $parameter :$resolvedArgument")
|
||||
} else if (resolvedArgument.callArgument.isSpread) {
|
||||
addDiagnostic(NonVarargSpread(resolvedArgument.callArgument))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (parameter in parameters) {
|
||||
if (!result.containsKey(parameter)) {
|
||||
if (parameter.defaultValue != null) {
|
||||
result[parameter] = ResolvedCallArgument.DefaultArgument
|
||||
} else if (parameter.isVararg) {
|
||||
result[parameter] = ResolvedCallArgument.VarargArgument(emptyList())
|
||||
} else {
|
||||
addDiagnostic(NoValueForParameter(parameter, function))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun completeVarargPositionArguments() {
|
||||
assert(state == State.VARARG_POSITION) { "Incorrect state: $state" }
|
||||
val parameter = parameters[currentPositionedParameterIndex]
|
||||
result.put(parameter, ResolvedCallArgument.VarargArgument(varargArguments!!))
|
||||
}
|
||||
|
||||
private fun addVarargArgument(argument: FirExpression) {
|
||||
if (varargArguments == null) {
|
||||
varargArguments = ArrayList()
|
||||
}
|
||||
varargArguments!!.add(argument)
|
||||
}
|
||||
|
||||
private fun getParameterByName(name: Name): FirValueParameter? {
|
||||
if (nameToParameter == null) {
|
||||
nameToParameter = parameters.associateBy { it.name }
|
||||
}
|
||||
return nameToParameter!![name]
|
||||
}
|
||||
|
||||
private fun findParameterByName(argument: FirExpression, name: Name): FirValueParameter? {
|
||||
val parameter = getParameterByName(name)
|
||||
|
||||
// TODO
|
||||
// if (descriptor is CallableMemberDescriptor && descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||
// if (parameter == null) {
|
||||
// for (valueParameter in descriptor.valueParameters) {
|
||||
// val matchedParameter = valueParameter.overriddenDescriptors.firstOrNull {
|
||||
// it.containingDeclaration.hasStableParameterNames() && it.name == name
|
||||
// }
|
||||
// if (matchedParameter != null) {
|
||||
// addDiagnostic(NamedArgumentReference(argument, valueParameter))
|
||||
// addDiagnostic(NameForAmbiguousParameter(argument, valueParameter, matchedParameter))
|
||||
// return valueParameter
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// parameter.getOverriddenParameterWithOtherName()?.let {
|
||||
// addDiagnostic(NameForAmbiguousParameter(argument, parameter, it))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
if (parameter == null) addDiagnostic(NameNotFound(argument, function))
|
||||
|
||||
return parameter
|
||||
}
|
||||
|
||||
private fun addDiagnostic(diagnostic: ResolutionDiagnostic) {
|
||||
if (diagnostics == null) {
|
||||
diagnostics = mutableListOf()
|
||||
}
|
||||
diagnostics!!.add(diagnostic)
|
||||
}
|
||||
|
||||
private val FirExpression.isSpread: Boolean
|
||||
get() = this is FirSpreadArgumentExpression && isSpread
|
||||
|
||||
private val parameters: List<FirValueParameter>
|
||||
get() = function.valueParameters
|
||||
|
||||
private val FirExpression.argumentName: Name?
|
||||
get() = (this as? FirNamedArgumentExpression)?.name
|
||||
|
||||
// TODO: handle java functions
|
||||
private val FirFunction<*>.hasStableParameterNames: Boolean
|
||||
get() = true
|
||||
}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
|
||||
class FirCallArgumentsProcessor(
|
||||
private val function: FirFunction<*>,
|
||||
private val arguments: List<FirExpression>
|
||||
) {
|
||||
class Result(val argumentMapping: Map<FirExpression, FirValueParameter>, val isSuccess: Boolean)
|
||||
|
||||
fun process(): Result {
|
||||
var currentState: State = State.PositionalOnly(function.valueParameters)
|
||||
for (argument in arguments) {
|
||||
if (argument is FirNamedArgumentExpression || argument is FirLambdaArgumentExpression) {
|
||||
currentState = State.PositionalThenNamed(
|
||||
function.valueParameters,
|
||||
currentState.argumentMap,
|
||||
currentState.usedParameters
|
||||
)
|
||||
}
|
||||
val status = currentState.processArgument(argument)
|
||||
if (status != MappingStatus.SUCCESS) {
|
||||
// unmapped argument
|
||||
return Result(currentState.argumentMap, isSuccess = false)
|
||||
}
|
||||
}
|
||||
|
||||
for (valueParameter in function.valueParameters) {
|
||||
if (valueParameter !in currentState.usedParameters && !valueParameter.isVararg && valueParameter.defaultValue == null) {
|
||||
// unmapped parameter
|
||||
return Result(currentState.argumentMap, isSuccess = false)
|
||||
}
|
||||
}
|
||||
return Result(currentState.argumentMap, isSuccess = currentState.argumentMap.size == arguments.size)
|
||||
}
|
||||
|
||||
private enum class MappingStatus {
|
||||
SUCCESS,
|
||||
ERROR
|
||||
}
|
||||
|
||||
private sealed class State(
|
||||
val valueParameters: List<FirValueParameter>,
|
||||
val argumentMap: MutableMap<FirExpression, FirValueParameter> = mutableMapOf(),
|
||||
val usedParameters: MutableSet<FirValueParameter> = mutableSetOf()
|
||||
) {
|
||||
abstract fun processArgument(argument: FirExpression): MappingStatus
|
||||
|
||||
class PositionalOnly(valueParameters: List<FirValueParameter>) : State(valueParameters) {
|
||||
var currentParameterIndex: Int = 0
|
||||
|
||||
val currentParameter get() = valueParameters.getOrNull(currentParameterIndex)
|
||||
|
||||
override fun processArgument(argument: FirExpression): MappingStatus {
|
||||
require(argument !is FirNamedArgumentExpression) {
|
||||
"Positional-only argument processor state should not receive ${argument.render()}"
|
||||
}
|
||||
|
||||
val currentParameter = currentParameter ?: return MappingStatus.ERROR
|
||||
argumentMap[argument] = currentParameter
|
||||
|
||||
val isSpread = argument is FirWrappedArgumentExpression && argument.isSpread
|
||||
if (!currentParameter.isVararg || isSpread) {
|
||||
usedParameters += currentParameter
|
||||
currentParameterIndex++
|
||||
}
|
||||
|
||||
if (!currentParameter.isVararg && isSpread) {
|
||||
return MappingStatus.ERROR
|
||||
}
|
||||
|
||||
return MappingStatus.SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
class PositionalThenNamed(
|
||||
valueParameters: List<FirValueParameter>,
|
||||
argumentMap: MutableMap<FirExpression, FirValueParameter>,
|
||||
usedParameters: MutableSet<FirValueParameter>
|
||||
) : State(valueParameters, argumentMap, usedParameters) {
|
||||
val nameToParameter = valueParameters.associateBy { it.name }
|
||||
|
||||
private fun map(parameter: FirValueParameter, argument: FirExpression): MappingStatus {
|
||||
if (parameter in usedParameters) return MappingStatus.ERROR
|
||||
argumentMap[argument] = parameter
|
||||
usedParameters += parameter
|
||||
return MappingStatus.SUCCESS
|
||||
}
|
||||
|
||||
override fun processArgument(argument: FirExpression): MappingStatus {
|
||||
when (argument) {
|
||||
is FirNamedArgumentExpression -> {
|
||||
val name = argument.name
|
||||
val parameter = nameToParameter[name] ?: return MappingStatus.ERROR
|
||||
return map(parameter, argument)
|
||||
}
|
||||
is FirLambdaArgumentExpression -> {
|
||||
val lastParameter = valueParameters.lastOrNull() ?: return MappingStatus.ERROR
|
||||
return map(lastParameter, argument)
|
||||
}
|
||||
else -> {
|
||||
return MappingStatus.ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
|
||||
|
||||
abstract class ResolutionDiagnostic(val applicability: CandidateApplicability)
|
||||
|
||||
abstract class InapplicableArgumentDiagnostic : ResolutionDiagnostic(CandidateApplicability.INAPPLICABLE) {
|
||||
abstract val argument: FirExpression
|
||||
}
|
||||
|
||||
class MixingNamedAndPositionArguments(override val argument: FirExpression) : InapplicableArgumentDiagnostic()
|
||||
class TooManyArguments(
|
||||
val argument: FirExpression,
|
||||
val function: FirFunction<*>
|
||||
) : ResolutionDiagnostic(CandidateApplicability.PARAMETER_MAPPING_ERROR)
|
||||
|
||||
class NamedArgumentNotAllowed(
|
||||
override val argument: FirExpression,
|
||||
val function: FirFunction<*>
|
||||
) : InapplicableArgumentDiagnostic()
|
||||
|
||||
class ArgumentPassedTwice(
|
||||
override val argument: FirExpression,
|
||||
val valueParameter: FirValueParameter,
|
||||
val firstOccurrence: ResolvedCallArgument
|
||||
) : InapplicableArgumentDiagnostic()
|
||||
|
||||
class VarargArgumentOutsideParentheses(
|
||||
override val argument: FirExpression,
|
||||
val valueParameter: FirValueParameter
|
||||
) : InapplicableArgumentDiagnostic()
|
||||
|
||||
class NonVarargSpread(override val argument: FirExpression) : InapplicableArgumentDiagnostic()
|
||||
|
||||
class NoValueForParameter(
|
||||
val valueParameter: FirValueParameter,
|
||||
val function: FirFunction<*>
|
||||
) : ResolutionDiagnostic(CandidateApplicability.PARAMETER_MAPPING_ERROR)
|
||||
|
||||
class NameNotFound(
|
||||
override val argument: FirExpression,
|
||||
val function: FirFunction<*>
|
||||
) : InapplicableArgumentDiagnostic()
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
|
||||
sealed class ResolvedCallArgument {
|
||||
abstract val arguments: List<FirExpression>
|
||||
|
||||
object DefaultArgument : ResolvedCallArgument() {
|
||||
override val arguments: List<FirExpression>
|
||||
get() = emptyList()
|
||||
|
||||
}
|
||||
|
||||
class SimpleArgument(val callArgument: FirExpression) : ResolvedCallArgument() {
|
||||
override val arguments: List<FirExpression>
|
||||
get() = listOf(callArgument)
|
||||
|
||||
}
|
||||
|
||||
class VarargArgument(override val arguments: List<FirExpression>) : ResolvedCallArgument()
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.min
|
||||
|
||||
|
||||
abstract class ResolutionStage {
|
||||
@@ -154,11 +155,26 @@ internal object MapArguments : ResolutionStage() {
|
||||
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
|
||||
val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportApplicability(CandidateApplicability.HIDDEN)
|
||||
val function = symbol.fir
|
||||
val processor = FirCallArgumentsProcessor(function, callInfo.arguments)
|
||||
val mappingResult = processor.process()
|
||||
candidate.argumentMapping = mappingResult.argumentMapping
|
||||
if (!mappingResult.isSuccess) {
|
||||
return sink.yieldApplicability(CandidateApplicability.PARAMETER_MAPPING_ERROR)
|
||||
|
||||
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
|
||||
|
||||
var applicability = CandidateApplicability.RESOLVED
|
||||
mapping.diagnostics.forEach {
|
||||
candidate.diagnostics += it
|
||||
applicability = min(applicability, it.applicability)
|
||||
}
|
||||
if (applicability < CandidateApplicability.RESOLVED) {
|
||||
return sink.yieldApplicability(applicability)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,24 +4,30 @@ fun baz(f: () -> Unit, other: Boolean = true) {}
|
||||
|
||||
|
||||
fun test() {
|
||||
// OK
|
||||
foo {}
|
||||
foo() {}
|
||||
foo({})
|
||||
|
||||
// Bad
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(1) {}
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(f = {}) {}
|
||||
|
||||
// OK
|
||||
bar(1) {}
|
||||
bar(x = 1) {}
|
||||
bar(1, {})
|
||||
bar(x = 1, f = {})
|
||||
|
||||
// Bad
|
||||
<!INAPPLICABLE_CANDIDATE!>bar<!> {}
|
||||
<!INAPPLICABLE_CANDIDATE!>bar<!>({})
|
||||
|
||||
// OK
|
||||
baz(other = false, f = {})
|
||||
baz({}, false)
|
||||
|
||||
// Bad
|
||||
<!INAPPLICABLE_CANDIDATE!>baz<!> {}
|
||||
<!INAPPLICABLE_CANDIDATE!>baz<!>() {}
|
||||
<!INAPPLICABLE_CANDIDATE!>baz<!>(other = false) {}
|
||||
|
||||
@@ -9,7 +9,7 @@ fun test() {
|
||||
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>()
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(0.0, false, 0, "")
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, 2.0, third = true, "")
|
||||
foo(1, 2.0, third = true, "")
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(second = 0.0, first = 0, fourth = "")
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(first = 0.0, second = 0, third = "", fourth = false)
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(first = 0, second = 0.0, third = false, fourth = "", first = 1)
|
||||
|
||||
@@ -9,9 +9,9 @@ FILE: simple.kt
|
||||
R|/foo|(third = Boolean(false), second = Double(2.71), fourth = String(?!), first = Int(0))
|
||||
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#()
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(Double(0.0), Boolean(false), Int(0), String())
|
||||
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#(Int(1), Double(2.0), third = Boolean(true), String())
|
||||
R|/foo|(Int(1), Double(2.0), third = Boolean(true), String())
|
||||
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#(second = Double(0.0), first = Int(0), fourth = String())
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(first = Double(0.0), second = Int(0), third = String(), fourth = Boolean(false))
|
||||
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#(first = Int(0), second = Double(0.0), third = Boolean(false), fourth = String(), first = Int(1))
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(first = Int(0), second = Double(0.0), third = Boolean(false), fourth = String(), first = Int(1))
|
||||
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#(Int(0), Double(0.0), Boolean(false), foth = String())
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@ FILE: vararg.kt
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(String())
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(Int(1), Int(2))
|
||||
R|/bar|(Int(1), z = Boolean(true), vararg(y = *R|kotlin/arrayOf|<R|kotlin/String|>(vararg(String(my), String(yours)))))
|
||||
<Inapplicable(PARAMETER_MAPPING_ERROR): [/bar]>#(Int(0), z = Boolean(false), y = String(), y = String(other))
|
||||
<Inapplicable(INAPPLICABLE): [/bar]>#(Int(0), z = Boolean(false), y = String(), y = String(other))
|
||||
<Inapplicable(PARAMETER_MAPPING_ERROR): [/bar]>#(Int(0), String(), Boolean(true))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user