From 6b95bcdbdb932cdb0a2df9f17138784b5ea7c5ed Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 16 Apr 2021 11:06:43 +0300 Subject: [PATCH] FIR: support separate ASSIGNMENT_IN_EXPRESSION_CONTEXT --- .../generator/diagnostics/FirDiagnosticsList.kt | 1 + .../kotlin/fir/analysis/diagnostics/FirErrors.kt | 2 ++ .../diagnostics/coneDiagnosticToFirDiagnostic.kt | 14 +++++++++----- .../kt770.kt351.kt735_StatementType.fir.kt | 4 ++-- .../fir/diagnostics/KtFirDataClassConverters.kt | 7 +++++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 5 +++++ .../api/fir/diagnostics/KtFirDiagnosticsImpl.kt | 8 ++++++++ 7 files changed, 34 insertions(+), 7 deletions(-) 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 003cb402df1..2493b14f8e1 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 @@ -50,6 +50,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val ILLEGAL_CONST_EXPRESSION by error() val ILLEGAL_UNDERSCORE by error() val EXPRESSION_EXPECTED by error(PositioningStrategy.SELECTOR_BY_QUALIFIED) + val ASSIGNMENT_IN_EXPRESSION_CONTEXT by error() val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error() val NOT_A_LOOP_LABEL by error() val VARIABLE_EXPECTED by error() 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 e1ee81b3540..26fa8ee936c 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 @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration @@ -76,6 +77,7 @@ object FirErrors { val ILLEGAL_CONST_EXPRESSION by error0() val ILLEGAL_UNDERSCORE by error0() val EXPRESSION_EXPECTED by error0(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) + val ASSIGNMENT_IN_EXPRESSION_CONTEXT by error0() val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error0() val NOT_A_LOOP_LABEL by error0() val VARIABLE_EXPECTED by error0() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index c3a3794fe42..b63bd3bdf56 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -48,9 +48,9 @@ private fun ConeDiagnostic.toFirDiagnostic( FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type) is ConeNoTypeArgumentsOnRhsError -> FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type) - is ConeSimpleDiagnostic -> when { - source.kind is FirFakeSourceElementKind -> null - else -> this.getFactory().on(qualifiedAccessSource ?: source) + is ConeSimpleDiagnostic -> when (source.kind) { + is FirFakeSourceElementKind -> null + else -> this.getFactory(source).on(qualifiedAccessSource ?: source) } is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(source, this.target) is ConeStubDiagnostic -> null @@ -158,7 +158,7 @@ private fun mapInapplicableCandidateError( }.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) } } -private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<*> { +private fun ConeSimpleDiagnostic.getFactory(source: FirSourceElement): FirDiagnosticFactory0<*> { @Suppress("UNCHECKED_CAST") return when (kind) { DiagnosticKind.Syntax -> FirErrors.SYNTAX @@ -174,7 +174,11 @@ private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<*> { DiagnosticKind.RecursionInImplicitTypes -> FirErrors.RECURSION_IN_IMPLICIT_TYPES DiagnosticKind.Java -> FirErrors.ERROR_FROM_JAVA_RESOLUTION DiagnosticKind.SuperNotAllowed -> FirErrors.SUPER_IS_NOT_AN_EXPRESSION - DiagnosticKind.ExpressionExpected -> FirErrors.EXPRESSION_EXPECTED + DiagnosticKind.ExpressionExpected -> if (source.elementType == KtNodeTypes.BINARY_EXPRESSION) { + FirErrors.ASSIGNMENT_IN_EXPRESSION_CONTEXT + } else { + FirErrors.EXPRESSION_EXPECTED + } DiagnosticKind.JumpOutsideLoop -> FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP DiagnosticKind.NotLoopLabel -> FirErrors.NOT_A_LOOP_LABEL DiagnosticKind.VariableExpected -> FirErrors.VARIABLE_EXPECTED diff --git a/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt index 0f21703676b..69c11908581 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt @@ -149,9 +149,9 @@ fun bar(a: Unit) {} fun testStatementInExpressionContext() { var z = 34 - val a1: Unit = z = 334 + val a1: Unit = z = 334 val f = for (i in 1..10) {} - if (true) return z = 34 + if (true) return z = 34 return while (true) {} } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index f10f0c86a2b..536310d7390 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration @@ -94,6 +95,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.ASSIGNMENT_IN_EXPRESSION_CONTEXT) { firDiagnostic -> + AssignmentInExpressionContextImpl( + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP) { firDiagnostic -> BreakOrContinueOutsideALoopImpl( firDiagnostic as FirPsiDiagnostic<*>, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index afc5a7e0d7b..1d5ed661ad7 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration @@ -87,6 +88,10 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ExpressionExpected::class } + abstract class AssignmentInExpressionContext : KtFirDiagnostic() { + override val diagnosticClass get() = AssignmentInExpressionContext::class + } + abstract class BreakOrContinueOutsideALoop : KtFirDiagnostic() { override val diagnosticClass get() = BreakOrContinueOutsideALoop::class } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 0c95cc3dd64..b4514a9f649 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration @@ -109,6 +110,13 @@ internal class ExpressionExpectedImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class AssignmentInExpressionContextImpl( + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.AssignmentInExpressionContext(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class BreakOrContinueOutsideALoopImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken,