FIR checker: ILLEGAL_DECLARATION_IN_WHEN_SUBJECT

This commit is contained in:
Tianyu Geng
2021-06-22 15:35:15 -07:00
committed by Mikhail Glukhikh
parent 31573a98e8
commit 768ddea18f
8 changed files with 68 additions and 6 deletions
@@ -873,6 +873,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
}
val INVALID_IF_AS_EXPRESSION by error<KtIfExpression>(PositioningStrategy.IF_EXPRESSION)
val ELSE_MISPLACED_IN_WHEN by error<KtWhenEntry>(PositioningStrategy.ELSE_ENTRY)
val ILLEGAL_DECLARATION_IN_WHEN_SUBJECT by error<KtElement> {
parameter<String>("illegalReason")
}
}
val CONTEXT_TRACKING by object : DiagnosticGroup("Context tracking") {
@@ -480,6 +480,7 @@ object FirErrors {
val NO_ELSE_IN_WHEN by error1<KtWhenExpression, List<WhenMissingCase>>(SourceElementPositioningStrategies.WHEN_EXPRESSION)
val INVALID_IF_AS_EXPRESSION by error0<KtIfExpression>(SourceElementPositioningStrategies.IF_EXPRESSION)
val ELSE_MISPLACED_IN_WHEN by error0<KtWhenEntry>(SourceElementPositioningStrategies.ELSE_ENTRY)
val ILLEGAL_DECLARATION_IN_WHEN_SUBJECT by error1<KtElement, String>()
// Context tracking
val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION by error1<KtSimpleNameExpression, FirTypeParameterSymbol>()
@@ -61,6 +61,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
get() = setOf(
FirExhaustiveWhenChecker,
FirWhenConditionChecker,
FirWhenSubjectChecker,
)
override val loopExpressionCheckers: Set<FirLoopExpressionChecker>
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.lexer.KtTokens
object FirWhenSubjectChecker : FirWhenExpressionChecker() {
override fun check(expression: FirWhenExpression, context: CheckerContext, reporter: DiagnosticReporter) {
val subject = expression.subject
val subjectVariable = expression.subjectVariable
val source = (subjectVariable ?: subject)?.source ?: return
when {
subject?.source?.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION -> {
reporter.reportOn(source, FirErrors.ILLEGAL_DECLARATION_IN_WHEN_SUBJECT, "destructuring declaration", context)
}
subjectVariable?.source?.getChild(KtTokens.VAR_KEYWORD) != null -> {
reporter.reportOn(source, FirErrors.ILLEGAL_DECLARATION_IN_WHEN_SUBJECT, "var", context)
}
subjectVariable?.source?.getChild(KtNodeTypes.PROPERTY_DELEGATE) != null -> {
reporter.reportOn(source, FirErrors.ILLEGAL_DECLARATION_IN_WHEN_SUBJECT, "delegated property", context)
}
subjectVariable != null && subjectVariable.initializer == null -> {
reporter.reportOn(source, FirErrors.ILLEGAL_DECLARATION_IN_WHEN_SUBJECT, "variable without initializer", context)
}
}
}
}
@@ -11,18 +11,18 @@ fun testSimpleValInWhenSubject() {
}
fun testValWithoutInitializerWhenSubject() {
when (val y: Any) {
when (<!ILLEGAL_DECLARATION_IN_WHEN_SUBJECT!>val y: Any<!>) {
is String -> <!UNINITIALIZED_VARIABLE!>y<!>.<!UNRESOLVED_REFERENCE!>length<!>
}
}
fun testVarInWhenSubject() {
when (var y = foo()) {
when (<!ILLEGAL_DECLARATION_IN_WHEN_SUBJECT!>var y = foo()<!>) {
is String -> y.length
}
}
fun testDelegatedValInWhenSubject() {
when (val y by lazy { 42 }) {
when (<!ILLEGAL_DECLARATION_IN_WHEN_SUBJECT!>val y by lazy { 42 }<!>) {
}
}