[FIR] Implement MANY_LAMBDA_EXPRESSION_ARGUMENTS diagnostics, fix tests
This commit is contained in:
committed by
TeamCityServer
parent
b8002cb54f
commit
525cc6df97
+2
@@ -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)
|
||||
|
||||
+2
@@ -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)
|
||||
|
||||
|
||||
+1
@@ -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)) }
|
||||
|
||||
+21
-6
@@ -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) {
|
||||
|
||||
+5
-1
@@ -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)
|
||||
+1
-1
@@ -25,5 +25,5 @@ fun test() {
|
||||
|
||||
foo("", 1) <!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
|
||||
foo("", 1) <!TOO_MANY_ARGUMENTS!>{}<!> <!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
foo("", 1) <!TOO_MANY_ARGUMENTS!>{}<!> <!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
}
|
||||
|
||||
+3
-3
@@ -6,9 +6,9 @@ fun test(x: () -> Unit, y: () -> Unit) {
|
||||
}
|
||||
|
||||
fun main() {
|
||||
test {
|
||||
<!NO_VALUE_FOR_PARAMETER!>test {
|
||||
1
|
||||
} {
|
||||
} <!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{
|
||||
2
|
||||
}
|
||||
}<!><!>
|
||||
}
|
||||
@@ -23,9 +23,9 @@ fun testNoArgs() {
|
||||
noArgs() // comment
|
||||
// comment
|
||||
<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
noArgs() <!TOO_MANY_ARGUMENTS!>{}<!> <!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
noArgs() <!TOO_MANY_ARGUMENTS!>{}<!> <!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
noArgs() <!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
<!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
}
|
||||
|
||||
fun testLambdaArg() {
|
||||
@@ -35,7 +35,7 @@ fun testLambdaArg() {
|
||||
{}
|
||||
oneLambdaArg()
|
||||
{}
|
||||
<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
<!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
oneLambdaArg(
|
||||
{},
|
||||
<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
@@ -52,19 +52,19 @@ fun testLambdaArg() {
|
||||
{}
|
||||
oneLambdaArg() {}/*
|
||||
block comment, no new line
|
||||
*/ <!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
*/ <!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
oneLambdaArg() {}/*
|
||||
block comment with new line
|
||||
*/
|
||||
<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
<!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
oneLambdaArg() {}// comment
|
||||
// comment
|
||||
<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
oneLambdaArg() {} <!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
<!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
oneLambdaArg() {} <!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
oneLambdaArg() {}
|
||||
<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
<!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
oneLambdaArg() {} // comment
|
||||
<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
<!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
}
|
||||
|
||||
fun testVararg() {
|
||||
@@ -83,9 +83,9 @@ fun testVararg() {
|
||||
varargFn(1,2,3) // comment
|
||||
// comment
|
||||
<!VARARG_OUTSIDE_PARENTHESES!>{}<!>
|
||||
varargFn(1,2,3) <!ARGUMENT_TYPE_MISMATCH!>{}<!> <!ARGUMENT_TYPE_MISMATCH, VARARG_OUTSIDE_PARENTHESES!>{}<!>
|
||||
varargFn(1,2,3) <!ARGUMENT_TYPE_MISMATCH!>{}<!>
|
||||
<!ARGUMENT_TYPE_MISMATCH, VARARG_OUTSIDE_PARENTHESES!>{}<!>
|
||||
varargFn(1,2,3) {} <!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
varargFn(1,2,3) {}
|
||||
<!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
}
|
||||
|
||||
fun testTwoLambdas() {
|
||||
@@ -96,14 +96,14 @@ fun testTwoLambdas() {
|
||||
)
|
||||
|
||||
fun bar(): () -> Unit {
|
||||
twoLambdaArgs()
|
||||
{}
|
||||
twoLambdaArgs(<!NO_VALUE_FOR_PARAMETER!>)<!>
|
||||
{}
|
||||
<!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
|
||||
return if (true) {
|
||||
twoLambdaArgs({})
|
||||
{}
|
||||
<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
<!MANY_LAMBDA_EXPRESSION_ARGUMENTS!>{}<!>
|
||||
} else {
|
||||
{}
|
||||
}
|
||||
|
||||
+6
@@ -828,6 +828,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.MANY_LAMBDA_EXPRESSION_ARGUMENTS) { firDiagnostic ->
|
||||
ManyLambdaExpressionArgumentsImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY) { firDiagnostic ->
|
||||
OverloadResolutionAmbiguityImpl(
|
||||
firDiagnostic.a.map { abstractFirBasedSymbol ->
|
||||
|
||||
+4
@@ -595,6 +595,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val name: String
|
||||
}
|
||||
|
||||
abstract class ManyLambdaExpressionArguments : KtFirDiagnostic<KtValueArgument>() {
|
||||
override val diagnosticClass get() = ManyLambdaExpressionArguments::class
|
||||
}
|
||||
|
||||
abstract class OverloadResolutionAmbiguity : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = OverloadResolutionAmbiguity::class
|
||||
abstract val candidates: List<KtSymbol>
|
||||
|
||||
+7
@@ -953,6 +953,13 @@ internal class NamedParameterNotFoundImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ManyLambdaExpressionArgumentsImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ManyLambdaExpressionArguments(), KtAbstractFirDiagnostic<KtValueArgument> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class OverloadResolutionAmbiguityImpl(
|
||||
override val candidates: List<KtSymbol>,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
|
||||
Reference in New Issue
Block a user