[FIR] Implement MANY_LAMBDA_EXPRESSION_ARGUMENTS diagnostics, fix tests

This commit is contained in:
Ivan Kochurkin
2021-04-27 19:51:01 +03:00
committed by TeamCityServer
parent b8002cb54f
commit 525cc6df97
12 changed files with 68 additions and 26 deletions
@@ -255,6 +255,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val NAMED_PARAMETER_NOT_FOUND by error<KtValueArgument>(PositioningStrategy.NAME_OF_NAMED_ARGUMENT) {
parameter<String>("name")
}
val MANY_LAMBDA_EXPRESSION_ARGUMENTS by error<KtValueArgument>()
}
val AMBIGUITY by object : DiagnosticGroup("Ambiguity") {
@@ -212,6 +212,7 @@ object FirErrors {
val TOO_MANY_ARGUMENTS by error1<PsiElement, FirCallableDeclaration<*>>()
val NO_VALUE_FOR_PARAMETER by error1<KtElement, FirValueParameter>(SourceElementPositioningStrategies.VALUE_ARGUMENTS)
val NAMED_PARAMETER_NOT_FOUND by error1<KtValueArgument, String>(SourceElementPositioningStrategies.NAME_OF_NAMED_ARGUMENT)
val MANY_LAMBDA_EXPRESSION_ARGUMENTS by error0<KtValueArgument>()
// Ambiguity
val OVERLOAD_RESOLUTION_AMBIGUITY by error1<PsiElement, Collection<AbstractFirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -155,6 +155,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LOCAL_OBJECT_NOT_
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_COMPANION_OBJECTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_LAMBDA_EXPRESSION_ARGUMENTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
@@ -461,6 +462,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
map.put(ARGUMENT_PASSED_TWICE, "An argument is already passed for this parameter")
map.put(NO_VALUE_FOR_PARAMETER, "No value passed for parameter ''{0}''", NAME)
map.put(NAMED_PARAMETER_NOT_FOUND, "Cannot find a parameter with this name: {0}", TO_STRING)
map.put(MANY_LAMBDA_EXPRESSION_ARGUMENTS, "Only one lambda expression is allowed outside a parenthesized argument list")
map.put(ARGUMENT_TYPE_MISMATCH, "Argument type mismatch: actual type is {1} but {0} was expected", TO_STRING, TO_STRING)
@@ -142,6 +142,7 @@ private fun mapInapplicableCandidateError(
rootCause.argument.name.asString()
)
is UnsafeCall -> mapUnsafeCallError(diagnostic.candidate, rootCause, source, qualifiedAccessSource)
is ManyLambdaExpressionArguments -> FirErrors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.on(rootCause.argument.source ?: source)
else -> null
}
}.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) }
@@ -61,11 +61,20 @@ fun BodyResolveComponents.mapArguments(
if (arguments.isEmpty() && function.valueParameters.isEmpty()) {
return EmptyArgumentMapping
}
val externalArgument: FirExpression? = arguments.lastOrNull { it is FirLambdaArgumentExpression }
var argumentsInParenthesis: List<FirExpression> = if (externalArgument == null) {
arguments
} else {
arguments.subList(0, arguments.size - 1)
val argumentsInParenthesis: MutableList<FirExpression> = mutableListOf()
val excessLambdaArguments: MutableList<FirExpression> = mutableListOf()
var externalArgument: FirExpression? = null
for (argument in arguments) {
if (argument is FirLambdaArgumentExpression) {
if (externalArgument == null) {
externalArgument = argument
} else {
excessLambdaArguments.add(argument)
}
} else {
argumentsInParenthesis.add(argument)
}
}
// If this is an overloading indexed access operator, it could have default values or a vararg parameter in the middle.
@@ -82,7 +91,8 @@ fun BodyResolveComponents.mapArguments(
isSpread = false
name = function.valueParameters.last().name
}
argumentsInParenthesis = argumentsInParenthesis.dropLast(1) + listOf(namedV)
argumentsInParenthesis.removeAt(argumentsInParenthesis.size - 1)
argumentsInParenthesis.add(namedV)
}
}
@@ -91,6 +101,7 @@ fun BodyResolveComponents.mapArguments(
if (externalArgument != null) {
processor.processExternalArgument(externalArgument)
}
processor.processExcessLambdaArguments(excessLambdaArguments)
processor.processDefaultsAndRunChecks()
return ArgumentMapping(processor.result, processor.diagnostics ?: emptyList())
@@ -212,6 +223,10 @@ private class FirCallArgumentsProcessor(
result[lastParameter] = ResolvedCallArgument.SimpleArgument(externalArgument)
}
fun processExcessLambdaArguments(excessLambdaArguments: List<FirExpression>) {
excessLambdaArguments.forEach { arg -> addDiagnostic(ManyLambdaExpressionArguments(arg)) }
}
fun processDefaultsAndRunChecks() {
for ((parameter, resolvedArgument) in result) {
if (!parameter.isVararg) {
@@ -97,4 +97,8 @@ class ArgumentTypeMismatch(
class NullForNotNullType(
val argument: FirExpression
) : ResolutionDiagnostic(INAPPLICABLE)
) : ResolutionDiagnostic(INAPPLICABLE)
class ManyLambdaExpressionArguments(
val argument: FirExpression
) : ResolutionDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR)