From b48870c11f41662459fbe9f708d35397c56f4d09 Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Wed, 20 Oct 2021 03:39:18 +0300 Subject: [PATCH] FIR checker: pass expected array type in ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION This is needed by the IDE quickfix to generate the correct `arrayOf` (or `intArrayOf`, etc`) wrapper call. --- .../diagnostics/KtFirDataClassConverters.kt | 2 ++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 2 ++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 2 ++ .../diagnostics/FirDiagnosticsList.kt | 4 ++- .../fir/analysis/diagnostics/FirErrors.kt | 2 +- .../expression/FirNamedVarargChecker.kt | 29 ++++++++++++++----- .../diagnostics/FirErrorsDefaultMessages.kt | 3 +- 7 files changed, 33 insertions(+), 11 deletions(-) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index af09a15a94e..cf02ff69ba3 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -1475,12 +1475,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert } add(FirErrors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION.errorFactory) { firDiagnostic -> AssigningSingleElementToVarargInNamedFormFunctionErrorImpl( + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), firDiagnostic as KtPsiDiagnostic, token, ) } add(FirErrors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION.warningFactory) { firDiagnostic -> AssigningSingleElementToVarargInNamedFormFunctionWarningImpl( + firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a), firDiagnostic as KtPsiDiagnostic, token, ) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index fa1f3bc5fef..aca3b2ac851 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1062,10 +1062,12 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract class AssigningSingleElementToVarargInNamedFormFunctionError : KtFirDiagnostic() { override val diagnosticClass get() = AssigningSingleElementToVarargInNamedFormFunctionError::class + abstract val expectedArrayType: KtType } abstract class AssigningSingleElementToVarargInNamedFormFunctionWarning : KtFirDiagnostic() { override val diagnosticClass get() = AssigningSingleElementToVarargInNamedFormFunctionWarning::class + abstract val expectedArrayType: KtType } abstract class AssigningSingleElementToVarargInNamedFormAnnotationError : KtFirDiagnostic() { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 6f0323a1799..5a0a0aaebe5 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1270,11 +1270,13 @@ internal class SpreadOfNullableImpl( ) : KtFirDiagnostic.SpreadOfNullable(), KtAbstractFirDiagnostic internal class AssigningSingleElementToVarargInNamedFormFunctionErrorImpl( + override val expectedArrayType: KtType, override val firDiagnostic: KtPsiDiagnostic, override val token: ValidityToken, ) : KtFirDiagnostic.AssigningSingleElementToVarargInNamedFormFunctionError(), KtAbstractFirDiagnostic internal class AssigningSingleElementToVarargInNamedFormFunctionWarningImpl( + override val expectedArrayType: KtType, override val firDiagnostic: KtPsiDiagnostic, override val token: ValidityToken, ) : KtFirDiagnostic.AssigningSingleElementToVarargInNamedFormFunctionWarning(), KtAbstractFirDiagnostic diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index c9457109394..929bb321b31 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -493,7 +493,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val SPREAD_OF_NULLABLE by error(PositioningStrategy.SPREAD_OPERATOR) - val ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION by deprecationError(LanguageFeature.ProhibitAssigningSingleElementsToVarargsInNamedForm) + val ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION by deprecationError(LanguageFeature.ProhibitAssigningSingleElementsToVarargsInNamedForm) { + parameter("expectedArrayType") + } val ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION by deprecationError(LanguageFeature.ProhibitAssigningSingleElementsToVarargsInNamedForm) val REDUNDANT_SPREAD_OPERATOR_IN_NAMED_FORM_IN_ANNOTATION by warning() val REDUNDANT_SPREAD_OPERATOR_IN_NAMED_FORM_IN_FUNCTION by warning() diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 1a88e8a3549..4aaedf3a7da 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -334,7 +334,7 @@ object FirErrors { val MANY_LAMBDA_EXPRESSION_ARGUMENTS by error0() val NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER by error1() val SPREAD_OF_NULLABLE by error0(SourceElementPositioningStrategies.SPREAD_OPERATOR) - val ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION by deprecationError0(ProhibitAssigningSingleElementsToVarargsInNamedForm) + val ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION by deprecationError1(ProhibitAssigningSingleElementsToVarargsInNamedForm) val ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION by deprecationError0(ProhibitAssigningSingleElementsToVarargsInNamedForm) val REDUNDANT_SPREAD_OPERATOR_IN_NAMED_FORM_IN_ANNOTATION by warning0() val REDUNDANT_SPREAD_OPERATOR_IN_NAMED_FORM_IN_FUNCTION by warning0() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNamedVarargChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNamedVarargChecker.kt index d357e770400..c1aea5a1009 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNamedVarargChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNamedVarargChecker.kt @@ -18,7 +18,9 @@ import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirErrorTypeRef +import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.isArrayType object FirNamedVarargChecker : FirCallChecker() { @@ -28,9 +30,6 @@ object FirNamedVarargChecker : FirCallChecker() { expression !is FirDelegatedConstructorCall && expression !is FirArrayOfCall) return val isAnnotation = expression is FirAnnotation - val singleElementToVarargErrorFactory = - if (isAnnotation) FirErrors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION - else FirErrors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION val redundantSpreadWarningFactory = if (isAnnotation) FirErrors.REDUNDANT_SPREAD_OPERATOR_IN_NAMED_FORM_IN_ANNOTATION else FirErrors.REDUNDANT_SPREAD_OPERATOR_IN_NAMED_FORM_IN_FUNCTION @@ -40,7 +39,7 @@ object FirNamedVarargChecker : FirCallChecker() { else LanguageFeature.AllowAssigningArrayElementsToVarargsInNamedFormForFunctions ) - fun checkArgument(argument: FirExpression, isVararg: Boolean) { + fun checkArgument(argument: FirExpression, isVararg: Boolean, expectedArrayType: ConeKotlinType?) { if (argument !is FirNamedArgumentExpression) return if (argument.isSpread) { if (isVararg && (expression as? FirResolvable)?.calleeReference !is FirErrorNamedReference) { @@ -53,20 +52,34 @@ object FirNamedVarargChecker : FirCallChecker() { if (argument.expression is FirArrayOfCall) return if (allowAssignArray && typeRef.isArrayType) return - reporter.reportOn(argument.expression.source, singleElementToVarargErrorFactory, context) + if (isAnnotation) { + reporter.reportOn( + argument.expression.source, + FirErrors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION, + context + ) + } else { + require(expectedArrayType != null) { "expectedArrayType must be passed for function call" } + reporter.reportOn( + argument.expression.source, + FirErrors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION, + expectedArrayType, + context, + ) + } } if (expression is FirArrayOfCall) { // FirArrayOfCall has the `vararg` argument expression pre-flattened and doesn't have an argument mapping. - expression.arguments.forEach { checkArgument(it, it is FirNamedArgumentExpression) } + expression.arguments.forEach { checkArgument(it, it is FirNamedArgumentExpression, null /* not used for annotation call */) } } else { val argumentMap = expression.argumentMapping ?: return for ((argument, parameter) in argumentMap) { if (!parameter.isVararg) continue if (argument is FirVarargArgumentsExpression) { - argument.arguments.forEach { checkArgument(it, true) } + argument.arguments.forEach { checkArgument(it, true, parameter.returnTypeRef.coneType) } } else { - checkArgument(argument, false) + checkArgument(argument, false, parameter.returnTypeRef.coneType) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 60bfe042eb0..4931229986f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -839,7 +839,8 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(SPREAD_OF_NULLABLE, "The spread operator (*foo) may not be applied to an argument of nullable type") map.put( ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION, - "Assigning single elements to varargs in named form is forbidden" + "Assigning single elements to varargs in named form is forbidden", + NOT_RENDERED ) map.put( ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION,