FIR: support separate ASSIGNMENT_IN_EXPRESSION_CONTEXT
This commit is contained in:
+1
@@ -50,6 +50,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
val ILLEGAL_CONST_EXPRESSION by error<PsiElement>()
|
val ILLEGAL_CONST_EXPRESSION by error<PsiElement>()
|
||||||
val ILLEGAL_UNDERSCORE by error<PsiElement>()
|
val ILLEGAL_UNDERSCORE by error<PsiElement>()
|
||||||
val EXPRESSION_EXPECTED by error<PsiElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED)
|
val EXPRESSION_EXPECTED by error<PsiElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED)
|
||||||
|
val ASSIGNMENT_IN_EXPRESSION_CONTEXT by error<FirSourceElement, KtBinaryExpression>()
|
||||||
val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error<PsiElement>()
|
val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error<PsiElement>()
|
||||||
val NOT_A_LOOP_LABEL by error<PsiElement>()
|
val NOT_A_LOOP_LABEL by error<PsiElement>()
|
||||||
val VARIABLE_EXPECTED by error<PsiElement>()
|
val VARIABLE_EXPECTED by error<PsiElement>()
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
|||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
@@ -76,6 +77,7 @@ object FirErrors {
|
|||||||
val ILLEGAL_CONST_EXPRESSION by error0<PsiElement>()
|
val ILLEGAL_CONST_EXPRESSION by error0<PsiElement>()
|
||||||
val ILLEGAL_UNDERSCORE by error0<PsiElement>()
|
val ILLEGAL_UNDERSCORE by error0<PsiElement>()
|
||||||
val EXPRESSION_EXPECTED by error0<PsiElement>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
|
val EXPRESSION_EXPECTED by error0<PsiElement>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
|
||||||
|
val ASSIGNMENT_IN_EXPRESSION_CONTEXT by error0<FirSourceElement, KtBinaryExpression>()
|
||||||
val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error0<PsiElement>()
|
val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error0<PsiElement>()
|
||||||
val NOT_A_LOOP_LABEL by error0<PsiElement>()
|
val NOT_A_LOOP_LABEL by error0<PsiElement>()
|
||||||
val VARIABLE_EXPECTED by error0<PsiElement>()
|
val VARIABLE_EXPECTED by error0<PsiElement>()
|
||||||
|
|||||||
+9
-5
@@ -48,9 +48,9 @@ private fun ConeDiagnostic.toFirDiagnostic(
|
|||||||
FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type)
|
FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type)
|
||||||
is ConeNoTypeArgumentsOnRhsError ->
|
is ConeNoTypeArgumentsOnRhsError ->
|
||||||
FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type)
|
FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.on(qualifiedAccessSource ?: source, this.desiredCount, this.type)
|
||||||
is ConeSimpleDiagnostic -> when {
|
is ConeSimpleDiagnostic -> when (source.kind) {
|
||||||
source.kind is FirFakeSourceElementKind -> null
|
is FirFakeSourceElementKind -> null
|
||||||
else -> this.getFactory().on(qualifiedAccessSource ?: source)
|
else -> this.getFactory(source).on(qualifiedAccessSource ?: source)
|
||||||
}
|
}
|
||||||
is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(source, this.target)
|
is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.on(source, this.target)
|
||||||
is ConeStubDiagnostic -> null
|
is ConeStubDiagnostic -> null
|
||||||
@@ -158,7 +158,7 @@ private fun mapInapplicableCandidateError(
|
|||||||
}.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) }
|
}.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")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return when (kind) {
|
return when (kind) {
|
||||||
DiagnosticKind.Syntax -> FirErrors.SYNTAX
|
DiagnosticKind.Syntax -> FirErrors.SYNTAX
|
||||||
@@ -174,7 +174,11 @@ private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<*> {
|
|||||||
DiagnosticKind.RecursionInImplicitTypes -> FirErrors.RECURSION_IN_IMPLICIT_TYPES
|
DiagnosticKind.RecursionInImplicitTypes -> FirErrors.RECURSION_IN_IMPLICIT_TYPES
|
||||||
DiagnosticKind.Java -> FirErrors.ERROR_FROM_JAVA_RESOLUTION
|
DiagnosticKind.Java -> FirErrors.ERROR_FROM_JAVA_RESOLUTION
|
||||||
DiagnosticKind.SuperNotAllowed -> FirErrors.SUPER_IS_NOT_AN_EXPRESSION
|
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.JumpOutsideLoop -> FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP
|
||||||
DiagnosticKind.NotLoopLabel -> FirErrors.NOT_A_LOOP_LABEL
|
DiagnosticKind.NotLoopLabel -> FirErrors.NOT_A_LOOP_LABEL
|
||||||
DiagnosticKind.VariableExpected -> FirErrors.VARIABLE_EXPECTED
|
DiagnosticKind.VariableExpected -> FirErrors.VARIABLE_EXPECTED
|
||||||
|
|||||||
Vendored
+2
-2
@@ -149,9 +149,9 @@ fun bar(a: Unit) {}
|
|||||||
|
|
||||||
fun testStatementInExpressionContext() {
|
fun testStatementInExpressionContext() {
|
||||||
var z = 34
|
var z = 34
|
||||||
val a1: Unit = <!EXPRESSION_EXPECTED!>z = 334<!>
|
val a1: Unit = <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>z = 334<!>
|
||||||
val f = for (i in 1..10) {}
|
val f = for (i in 1..10) {}
|
||||||
if (true) return <!EXPRESSION_EXPECTED!>z = 34<!>
|
if (true) return <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>z = 34<!>
|
||||||
return <!EXPRESSION_EXPECTED!>while (true) {}<!>
|
return <!EXPRESSION_EXPECTED!>while (true) {}<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||||
import org.jetbrains.kotlin.fir.psi
|
import org.jetbrains.kotlin.fir.psi
|
||||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
@@ -94,6 +95,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.ASSIGNMENT_IN_EXPRESSION_CONTEXT) { firDiagnostic ->
|
||||||
|
AssignmentInExpressionContextImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP) { firDiagnostic ->
|
add(FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP) { firDiagnostic ->
|
||||||
BreakOrContinueOutsideALoopImpl(
|
BreakOrContinueOutsideALoopImpl(
|
||||||
firDiagnostic as FirPsiDiagnostic<*>,
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
|||||||
+5
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
|||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
@@ -87,6 +88,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = ExpressionExpected::class
|
override val diagnosticClass get() = ExpressionExpected::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class AssignmentInExpressionContext : KtFirDiagnostic<KtBinaryExpression>() {
|
||||||
|
override val diagnosticClass get() = AssignmentInExpressionContext::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class BreakOrContinueOutsideALoop : KtFirDiagnostic<PsiElement>() {
|
abstract class BreakOrContinueOutsideALoop : KtFirDiagnostic<PsiElement>() {
|
||||||
override val diagnosticClass get() = BreakOrContinueOutsideALoop::class
|
override val diagnosticClass get() = BreakOrContinueOutsideALoop::class
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
|||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
@@ -109,6 +110,13 @@ internal class ExpressionExpectedImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class AssignmentInExpressionContextImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.AssignmentInExpressionContext(), KtAbstractFirDiagnostic<KtBinaryExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class BreakOrContinueOutsideALoopImpl(
|
internal class BreakOrContinueOutsideALoopImpl(
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
Reference in New Issue
Block a user