[FIR] Implement ELSE_MISPLACED_IN_WHEN diagnostics, fix tests
This commit is contained in:
committed by
TeamCityServer
parent
7f4da93cc3
commit
00bc04b3df
+1
@@ -39,6 +39,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
OPEN_MODIFIER,
|
||||
WHEN_EXPRESSION,
|
||||
IF_EXPRESSION,
|
||||
ELSE_ENTRY,
|
||||
VARIANCE_MODIFIER,
|
||||
LATEINIT_MODIFIER,
|
||||
INLINE_OR_VALUE_MODIFIER,
|
||||
|
||||
+1
@@ -642,6 +642,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
parameter<List<WhenMissingCase>>("missingWhenCases")
|
||||
}
|
||||
val INVALID_IF_AS_EXPRESSION by error<KtIfExpression>(PositioningStrategy.IF_EXPRESSION)
|
||||
val ELSE_MISPLACED_IN_WHEN by error<KtWhenEntry>(PositioningStrategy.ELSE_ENTRY)
|
||||
}
|
||||
|
||||
val CONTEXT_TRACKING by object : DiagnosticGroup("Context tracking") {
|
||||
|
||||
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameterList
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
|
||||
@@ -377,6 +378,7 @@ object FirErrors {
|
||||
// When expressions
|
||||
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)
|
||||
|
||||
// Context tracking
|
||||
val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION by error1<KtSimpleNameExpression, FirTypeParameterSymbol>()
|
||||
|
||||
+9
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.expressions.ExhaustivenessStatus
|
||||
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
|
||||
import org.jetbrains.kotlin.fir.expressions.isExhaustive
|
||||
|
||||
object FirExhaustiveWhenChecker : FirWhenExpressionChecker() {
|
||||
@@ -27,6 +28,14 @@ object FirExhaustiveWhenChecker : FirWhenExpressionChecker() {
|
||||
reporter.reportOn(source, FirErrors.NO_ELSE_IN_WHEN, missingCases, context)
|
||||
}
|
||||
}
|
||||
|
||||
val branchesCount = expression.branches.size
|
||||
for (indexedValue in expression.branches.withIndex()) {
|
||||
val branch = indexedValue.value
|
||||
if (branch.condition is FirElseIfTrueCondition && indexedValue.index < branchesCount - 1) {
|
||||
reporter.reportOn(branch.source, FirErrors.ELSE_MISPLACED_IN_WHEN, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val FirSourceElement.isIfExpression: Boolean
|
||||
|
||||
+14
@@ -501,6 +501,17 @@ object LightTreePositioningStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
val ELSE_ENTRY = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
return markElement(tree.elseKeyword(node) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
}
|
||||
|
||||
val ARRAY_ACCESS = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
@@ -577,6 +588,9 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.whenKeyword(node: Ligh
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.ifKeyword(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtTokens.IF_KEYWORD)
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.elseKeyword(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtTokens.ELSE_KEYWORD)
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.returnKeyword(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtTokens.RETURN_KEYWORD)
|
||||
|
||||
|
||||
+5
@@ -163,6 +163,11 @@ object SourceElementPositioningStrategies {
|
||||
PositioningStrategies.IF_EXPRESSION
|
||||
)
|
||||
|
||||
val ELSE_ENTRY = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.ELSE_ENTRY,
|
||||
PositioningStrategies.ELSE_ENTRY
|
||||
)
|
||||
|
||||
val ARRAY_ACCESS = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.ARRAY_ACCESS,
|
||||
PositioningStrategies.ARRAY_ACCESS
|
||||
|
||||
@@ -6,7 +6,7 @@ fun foo() : Int {
|
||||
var z = 0
|
||||
when(d) {
|
||||
5, 3 -> z++
|
||||
else -> { z = -1000 }
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> { z = -1000 }
|
||||
return z -> 34
|
||||
}
|
||||
}
|
||||
@@ -23,4 +23,4 @@ fun fff(): Int {
|
||||
return 34
|
||||
}
|
||||
|
||||
fun bar(): Int = 8
|
||||
fun bar(): Int = 8
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ fun t5(x: Int) = <!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
}
|
||||
|
||||
fun foo3(x: Int) = when(x) {
|
||||
else -> 1
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> 1
|
||||
2 -> 2
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,6 @@ fun fourth(arg: Color) = when (arg) {
|
||||
|
||||
fun fifth(arg: Any?) = when (arg) {
|
||||
is Any -> "Any"
|
||||
else -> ""
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> ""
|
||||
else -> null
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ fun test() {
|
||||
val z = 1
|
||||
|
||||
when (z) {
|
||||
else -> 1
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> 1
|
||||
1 -> 2
|
||||
}
|
||||
|
||||
|
||||
Vendored
+3
-3
@@ -18,7 +18,7 @@ fun case1() {
|
||||
val z = JavaEnum.Val_3
|
||||
val when1 = when (z) {
|
||||
JavaEnum.Val_1 -> { false }
|
||||
else -> {true}
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> {true}
|
||||
JavaEnum.Val_2 -> { false }
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ fun case1() {
|
||||
fun case2() {
|
||||
val z = JavaEnum.Val_3
|
||||
val when1 = when (z) {
|
||||
else -> {true}
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> {true}
|
||||
JavaEnum.Val_1 -> { false }
|
||||
JavaEnum.Val_2 -> { false }
|
||||
}
|
||||
@@ -37,7 +37,7 @@ fun case2() {
|
||||
fun case3() {
|
||||
val z = JavaEnum.Val_3
|
||||
val when1 = when (z) {
|
||||
else -> {true}
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> {true}
|
||||
JavaEnum.Val_1 -> { false }
|
||||
JavaEnum.Val_2 -> { false }
|
||||
else -> { true }
|
||||
|
||||
Vendored
+3
-3
@@ -3,21 +3,21 @@
|
||||
|
||||
// TESTCASE NUMBER: 1
|
||||
fun case_1(value_1: Int): String = when (value_1) {
|
||||
else -> ""
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> ""
|
||||
1 -> ""
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun case_2(value_1: Int): String = when (value_1) {
|
||||
1 -> ""
|
||||
else -> ""
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> ""
|
||||
2 -> ""
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
fun case_3(value_1: Int): String {
|
||||
when (value_1) {
|
||||
else -> return ""
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> return ""
|
||||
else -> return ""
|
||||
}
|
||||
|
||||
|
||||
Vendored
+3
-3
@@ -3,21 +3,21 @@
|
||||
|
||||
// TESTCASE NUMBER: 1
|
||||
fun case_1(value_1: Int): String = when {
|
||||
else -> ""
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> ""
|
||||
value_1 == 1 -> ""
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun case_2(value_1: Int): String = when {
|
||||
value_1 == 1 -> ""
|
||||
else -> ""
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> ""
|
||||
value_1 == 2 -> ""
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
fun case_3(): String {
|
||||
when {
|
||||
else -> return ""
|
||||
<!ELSE_MISPLACED_IN_WHEN!>else<!> -> return ""
|
||||
else -> return ""
|
||||
}
|
||||
|
||||
|
||||
+7
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameterList
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
|
||||
/*
|
||||
@@ -1793,6 +1794,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ELSE_MISPLACED_IN_WHEN) { firDiagnostic ->
|
||||
ElseMisplacedInWhenImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION) { firDiagnostic ->
|
||||
TypeParameterIsNotAnExpressionImpl(
|
||||
firSymbolBuilder.classifierBuilder.buildTypeParameterSymbol(firDiagnostic.a.fir),
|
||||
|
||||
+5
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameterList
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
|
||||
@@ -1260,6 +1261,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = InvalidIfAsExpression::class
|
||||
}
|
||||
|
||||
abstract class ElseMisplacedInWhen : KtFirDiagnostic<KtWhenEntry>() {
|
||||
override val diagnosticClass get() = ElseMisplacedInWhen::class
|
||||
}
|
||||
|
||||
abstract class TypeParameterIsNotAnExpression : KtFirDiagnostic<KtSimpleNameExpression>() {
|
||||
override val diagnosticClass get() = TypeParameterIsNotAnExpression::class
|
||||
abstract val typeParameter: KtTypeParameterSymbol
|
||||
|
||||
+8
@@ -52,6 +52,7 @@ import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameterList
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
|
||||
@@ -2041,6 +2042,13 @@ internal class InvalidIfAsExpressionImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ElseMisplacedInWhenImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ElseMisplacedInWhen(), KtAbstractFirDiagnostic<KtWhenEntry> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class TypeParameterIsNotAnExpressionImpl(
|
||||
override val typeParameter: KtTypeParameterSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
|
||||
Vendored
+1
-1
@@ -35,7 +35,7 @@ fun test() {
|
||||
val z = 1
|
||||
|
||||
when (z) {
|
||||
else -> 1
|
||||
<error descr="[ELSE_MISPLACED_IN_WHEN] ">else</error> -> 1
|
||||
1 -> 2
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user