[FIR] Store fir for invalid when branches
^KTIJ-25646 fixed Merge-request: KT-MR-10646 Merged-by: Egor Kulikov <Egor.Kulikov@jetbrains.com>
This commit is contained in:
+6
@@ -2023,6 +2023,12 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/ClassNameBeforeDot.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassReferenceInIncorrectWhenClause.kt")
|
||||
public void testClassReferenceInIncorrectWhenClause() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/ClassReferenceInIncorrectWhenClause.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassWithMultipleSuperTypeCalls.kt")
|
||||
public void testClassWithMultipleSuperTypeCalls() throws Exception {
|
||||
|
||||
+6
@@ -2023,6 +2023,12 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/ClassNameBeforeDot.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassReferenceInIncorrectWhenClause.kt")
|
||||
public void testClassReferenceInIncorrectWhenClause() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/ClassReferenceInIncorrectWhenClause.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassWithMultipleSuperTypeCalls.kt")
|
||||
public void testClassWithMultipleSuperTypeCalls() throws Exception {
|
||||
|
||||
+6
@@ -2023,6 +2023,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/ClassNameBeforeDot.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassReferenceInIncorrectWhenClause.kt")
|
||||
public void testClassReferenceInIncorrectWhenClause() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/ClassReferenceInIncorrectWhenClause.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassWithMultipleSuperTypeCalls.kt")
|
||||
public void testClassWithMultipleSuperTypeCalls() throws Exception {
|
||||
|
||||
+6
@@ -2023,6 +2023,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/ClassNameBeforeDot.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassReferenceInIncorrectWhenClause.kt")
|
||||
public void testClassReferenceInIncorrectWhenClause() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/ClassReferenceInIncorrectWhenClause.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassWithMultipleSuperTypeCalls.kt")
|
||||
public void testClassWithMultipleSuperTypeCalls() throws Exception {
|
||||
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
class SomeClass() {}
|
||||
|
||||
fun someFun() {
|
||||
when {
|
||||
is <caret>SomeClass
|
||||
}
|
||||
}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in ROOT) class SomeClass
|
||||
+6
@@ -491,6 +491,12 @@ public class FirOutOfContentRootLazyBodiesCalculatorTestGenerated extends Abstra
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invalidWhen.kt")
|
||||
public void testInvalidWhen() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/invalidWhen.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("labelForInfix.kt")
|
||||
public void testLabelForInfix() throws Exception {
|
||||
|
||||
+6
@@ -491,6 +491,12 @@ public class FirSourceLazyBodiesCalculatorTestGenerated extends AbstractFirSourc
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invalidWhen.kt")
|
||||
public void testInvalidWhen() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/invalidWhen.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("labelForInfix.kt")
|
||||
public void testLabelForInfix() throws Exception {
|
||||
|
||||
+6
@@ -7312,6 +7312,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNoSubjectAndCommas.kt")
|
||||
public void testWhenWithNoSubjectAndCommas() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenWithNoSubjectAndCommas.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNothingTypedSubject.kt")
|
||||
public void testWhenWithNothingTypedSubject() throws Exception {
|
||||
|
||||
+6
@@ -7312,6 +7312,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNoSubjectAndCommas.kt")
|
||||
public void testWhenWithNoSubjectAndCommas() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenWithNoSubjectAndCommas.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNothingTypedSubject.kt")
|
||||
public void testWhenWithNothingTypedSubject() throws Exception {
|
||||
|
||||
+6
@@ -7312,6 +7312,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNoSubjectAndCommas.kt")
|
||||
public void testWhenWithNoSubjectAndCommas() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenWithNoSubjectAndCommas.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNothingTypedSubject.kt")
|
||||
public void testWhenWithNothingTypedSubject() throws Exception {
|
||||
|
||||
+6
@@ -7318,6 +7318,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNoSubjectAndCommas.kt")
|
||||
public void testWhenWithNoSubjectAndCommas() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenWithNoSubjectAndCommas.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNothingTypedSubject.kt")
|
||||
public void testWhenWithNothingTypedSubject() throws Exception {
|
||||
|
||||
+2
-1
@@ -513,7 +513,8 @@ private fun ConeSimpleDiagnostic.getFactory(source: KtSourceElement): KtDiagnost
|
||||
DiagnosticKind.ExpressionExpected -> when (source.elementType) {
|
||||
KtNodeTypes.BINARY_EXPRESSION -> FirErrors.ASSIGNMENT_IN_EXPRESSION_CONTEXT
|
||||
KtNodeTypes.FUN -> FirErrors.ANONYMOUS_FUNCTION_WITH_NAME
|
||||
KtNodeTypes.WHEN_CONDITION_IN_RANGE, KtNodeTypes.WHEN_CONDITION_IS_PATTERN -> FirErrors.EXPECTED_CONDITION
|
||||
KtNodeTypes.WHEN_CONDITION_IN_RANGE, KtNodeTypes.WHEN_CONDITION_IS_PATTERN, KtNodeTypes.WHEN_CONDITION_EXPRESSION ->
|
||||
FirErrors.EXPECTED_CONDITION
|
||||
else -> FirErrors.EXPRESSION_EXPECTED
|
||||
}
|
||||
|
||||
|
||||
+66
-42
@@ -738,11 +738,9 @@ class ExpressionsConverter(
|
||||
|
||||
@OptIn(FirContractViolation::class)
|
||||
val subject = FirExpressionRef<FirWhenExpression>()
|
||||
var shouldBind = hasSubject
|
||||
whenEntryNodes.mapTo(whenEntries) {
|
||||
convertWhenEntry(
|
||||
it,
|
||||
subject.takeIf { hasSubject }
|
||||
)
|
||||
convertWhenEntry(it, subject, hasSubject)
|
||||
}
|
||||
return buildWhenExpression {
|
||||
source = whenExpression.toFirSourceElement()
|
||||
@@ -750,6 +748,7 @@ class ExpressionsConverter(
|
||||
this.subjectVariable = subjectVariable
|
||||
usedAsExpression = whenExpression.usedAsExpression
|
||||
for (entry in whenEntries) {
|
||||
shouldBind = shouldBind || entry.shouldBindSubject
|
||||
val branch = entry.firBlock
|
||||
val entrySource = entry.node.toFirSourceElement()
|
||||
branches += if (!entry.isElse) {
|
||||
@@ -777,7 +776,7 @@ class ExpressionsConverter(
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
if (hasSubject) {
|
||||
if (shouldBind) {
|
||||
subject.bind(it)
|
||||
}
|
||||
}
|
||||
@@ -789,23 +788,33 @@ class ExpressionsConverter(
|
||||
*/
|
||||
private fun convertWhenEntry(
|
||||
whenEntry: LighterASTNode,
|
||||
whenRefWithSubject: FirExpressionRef<FirWhenExpression>?
|
||||
whenRefWithSubject: FirExpressionRef<FirWhenExpression>,
|
||||
hasSubject: Boolean,
|
||||
): WhenEntry {
|
||||
var isElse = false
|
||||
var firBlock: FirBlock = buildEmptyExpressionBlock()
|
||||
val conditions = mutableListOf<FirExpression>()
|
||||
var shouldBindSubject = false
|
||||
whenEntry.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
WHEN_CONDITION_EXPRESSION -> conditions += convertWhenConditionExpression(it, whenRefWithSubject)
|
||||
WHEN_CONDITION_IN_RANGE -> conditions += convertWhenConditionInRange(it, whenRefWithSubject)
|
||||
WHEN_CONDITION_IS_PATTERN -> conditions += convertWhenConditionIsPattern(it, whenRefWithSubject)
|
||||
WHEN_CONDITION_EXPRESSION -> conditions += convertWhenConditionExpression(it, whenRefWithSubject.takeIf { hasSubject })
|
||||
WHEN_CONDITION_IN_RANGE -> {
|
||||
val (condition, shouldBind) = convertWhenConditionInRange(it, whenRefWithSubject, hasSubject)
|
||||
conditions += condition
|
||||
shouldBindSubject = shouldBindSubject || shouldBind
|
||||
}
|
||||
WHEN_CONDITION_IS_PATTERN -> {
|
||||
val (condition, shouldBind) = convertWhenConditionIsPattern(it, whenRefWithSubject, hasSubject)
|
||||
conditions += condition
|
||||
shouldBindSubject = shouldBindSubject || shouldBind
|
||||
}
|
||||
ELSE_KEYWORD -> isElse = true
|
||||
BLOCK -> firBlock = declarationsConverter.convertBlock(it)
|
||||
else -> if (it.isExpression()) firBlock = declarationsConverter.convertBlock(it)
|
||||
}
|
||||
}
|
||||
|
||||
return WhenEntry(conditions, firBlock, whenEntry, isElse)
|
||||
return WhenEntry(conditions, firBlock, whenEntry, isElse, shouldBindSubject)
|
||||
}
|
||||
|
||||
private fun convertWhenConditionExpression(
|
||||
@@ -841,10 +850,13 @@ class ExpressionsConverter(
|
||||
}
|
||||
}
|
||||
|
||||
private data class WhenConditionConvertedResults(val expression: FirExpression, val shouldBindSubject: Boolean)
|
||||
|
||||
private fun convertWhenConditionInRange(
|
||||
whenCondition: LighterASTNode,
|
||||
whenRefWithSubject: FirExpressionRef<FirWhenExpression>?
|
||||
): FirExpression {
|
||||
whenRefWithSubject: FirExpressionRef<FirWhenExpression>,
|
||||
hasSubject: Boolean,
|
||||
): WhenConditionConvertedResults {
|
||||
var isNegate = false
|
||||
var firExpression: FirExpression? = null
|
||||
var conditionSource: KtLightSourceElement? = null
|
||||
@@ -861,19 +873,9 @@ class ExpressionsConverter(
|
||||
}
|
||||
}
|
||||
|
||||
val subjectExpression = if (whenRefWithSubject != null) {
|
||||
buildWhenSubjectExpression {
|
||||
whenRef = whenRefWithSubject
|
||||
source = whenCondition.toFirSourceElement()
|
||||
}
|
||||
} else {
|
||||
return buildErrorExpression {
|
||||
source = whenCondition.toFirSourceElement()
|
||||
diagnostic = ConeSimpleDiagnostic(
|
||||
"No expression in condition with expression",
|
||||
DiagnosticKind.ExpressionExpected
|
||||
)
|
||||
}
|
||||
val subjectExpression = buildWhenSubjectExpression {
|
||||
whenRef = whenRefWithSubject
|
||||
source = whenCondition.toFirSourceElement()
|
||||
}
|
||||
|
||||
val calculatedFirExpression = firExpression ?: buildErrorExpression(
|
||||
@@ -881,18 +883,34 @@ class ExpressionsConverter(
|
||||
ConeSyntaxDiagnostic("No range in condition with range")
|
||||
)
|
||||
|
||||
return calculatedFirExpression.generateContainsOperation(
|
||||
val result = calculatedFirExpression.generateContainsOperation(
|
||||
subjectExpression,
|
||||
inverted = isNegate,
|
||||
baseSource = whenCondition.toFirSourceElement(),
|
||||
operationReferenceSource = conditionSource
|
||||
)
|
||||
return if (hasSubject) {
|
||||
WhenConditionConvertedResults(result, false)
|
||||
} else {
|
||||
WhenConditionConvertedResults(
|
||||
buildErrorExpression {
|
||||
source = whenCondition.toFirSourceElement()
|
||||
diagnostic = ConeSimpleDiagnostic(
|
||||
"No expression in condition with expression",
|
||||
DiagnosticKind.ExpressionExpected
|
||||
)
|
||||
nonExpressionElement = result
|
||||
},
|
||||
true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertWhenConditionIsPattern(
|
||||
whenCondition: LighterASTNode,
|
||||
whenRefWithSubject: FirExpressionRef<FirWhenExpression>?
|
||||
): FirExpression {
|
||||
whenRefWithSubject: FirExpressionRef<FirWhenExpression>,
|
||||
hasSubject: Boolean,
|
||||
): WhenConditionConvertedResults {
|
||||
lateinit var firOperation: FirOperation
|
||||
lateinit var firType: FirTypeRef
|
||||
whenCondition.forEachChildren {
|
||||
@@ -903,27 +921,33 @@ class ExpressionsConverter(
|
||||
}
|
||||
}
|
||||
|
||||
val subjectExpression = if (whenRefWithSubject != null) {
|
||||
buildWhenSubjectExpression {
|
||||
source = whenCondition.toFirSourceElement()
|
||||
whenRef = whenRefWithSubject
|
||||
}
|
||||
} else {
|
||||
return buildErrorExpression {
|
||||
source = whenCondition.toFirSourceElement()
|
||||
diagnostic = ConeSimpleDiagnostic(
|
||||
"No expression in condition with expression",
|
||||
DiagnosticKind.ExpressionExpected
|
||||
)
|
||||
}
|
||||
val subjectExpression = buildWhenSubjectExpression {
|
||||
source = whenCondition.toFirSourceElement()
|
||||
whenRef = whenRefWithSubject
|
||||
}
|
||||
|
||||
return buildTypeOperatorCall {
|
||||
val result = buildTypeOperatorCall {
|
||||
source = whenCondition.toFirSourceElement()
|
||||
operation = firOperation
|
||||
conversionTypeRef = firType
|
||||
argumentList = buildUnaryArgumentList(subjectExpression)
|
||||
}
|
||||
|
||||
return if (hasSubject) {
|
||||
WhenConditionConvertedResults(result, false)
|
||||
} else {
|
||||
WhenConditionConvertedResults(
|
||||
buildErrorExpression {
|
||||
source = whenCondition.toFirSourceElement()
|
||||
diagnostic = ConeSimpleDiagnostic(
|
||||
"No expression in condition with expression",
|
||||
DiagnosticKind.ExpressionExpected
|
||||
)
|
||||
nonExpressionElement = result
|
||||
},
|
||||
true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-4
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.lightTree.fir
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import org.jetbrains.kotlin.KtLightSourceElement
|
||||
import org.jetbrains.kotlin.fir.builder.buildBalancedOrExpressionTree
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSyntaxDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
@@ -16,7 +17,8 @@ data class WhenEntry(
|
||||
val conditions: List<FirExpression>,
|
||||
val firBlock: FirBlock,
|
||||
val node: LighterASTNode,
|
||||
val isElse: Boolean = false
|
||||
val isElse: Boolean = false,
|
||||
val shouldBindSubject: Boolean = false,
|
||||
) {
|
||||
fun toFirWhenCondition(): FirExpression {
|
||||
require(conditions.isNotEmpty())
|
||||
@@ -24,9 +26,9 @@ data class WhenEntry(
|
||||
}
|
||||
|
||||
fun toFirWhenConditionWithoutSubject(): FirExpression {
|
||||
return when (val condition = conditions.firstOrNull()) {
|
||||
null -> buildErrorExpression(null, ConeSyntaxDiagnostic("No expression in condition with expression"))
|
||||
else -> condition
|
||||
return when (conditions.size) {
|
||||
0 -> buildErrorExpression(null, ConeSyntaxDiagnostic("No expression in condition with expression"))
|
||||
else -> buildBalancedOrExpressionTree(conditions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -446,6 +446,11 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invalidWhen.kt")
|
||||
public void testInvalidWhen() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/invalidWhen.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("labelForInfix.kt")
|
||||
public void testLabelForInfix() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/labelForInfix.kt");
|
||||
|
||||
@@ -2283,6 +2283,7 @@ open class RawFirBuilder(
|
||||
|
||||
@OptIn(FirContractViolation::class)
|
||||
val ref = FirExpressionRef<FirWhenExpression>()
|
||||
var shouldBind = hasSubject
|
||||
return buildWhenExpression {
|
||||
source = expression.toFirSourceElement()
|
||||
this.subject = subjectExpression
|
||||
@@ -2307,12 +2308,36 @@ open class RawFirBuilder(
|
||||
val ktCondition = entry.conditions.first()
|
||||
buildWhenBranch {
|
||||
source = entrySource
|
||||
condition = ((ktCondition as? KtWhenConditionWithExpression)?.expression
|
||||
?: ktCondition)
|
||||
.toFirExpression(
|
||||
"No expression in condition with expression",
|
||||
DiagnosticKind.ExpressionExpected
|
||||
)
|
||||
condition =
|
||||
if (entry.conditions.size == 1 && ktCondition is KtWhenConditionWithExpression) {
|
||||
(ktCondition.expression ?: ktCondition).toFirExpression(
|
||||
"No expression in condition with expression",
|
||||
DiagnosticKind.ExpressionExpected,
|
||||
)
|
||||
} else {
|
||||
buildBalancedOrExpressionTree(entry.conditions.map { condition ->
|
||||
if (condition is KtWhenConditionWithExpression) {
|
||||
condition.expression.toFirExpression(
|
||||
"No expression in condition with expression",
|
||||
DiagnosticKind.ExpressionExpected
|
||||
)
|
||||
} else {
|
||||
shouldBind = true
|
||||
buildErrorExpression {
|
||||
source = condition.toFirSourceElement()
|
||||
nonExpressionElement = condition.toFirWhenCondition(
|
||||
ref,
|
||||
{ toFirExpression(it) },
|
||||
{ toFirOrErrorType() },
|
||||
)
|
||||
diagnostic = ConeSimpleDiagnostic(
|
||||
"No expression in condition with expression",
|
||||
DiagnosticKind.ExpressionExpected,
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
result = branchBody
|
||||
}
|
||||
}
|
||||
@@ -2325,7 +2350,7 @@ open class RawFirBuilder(
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
if (hasSubject) {
|
||||
if (shouldBind) {
|
||||
ref.bind(it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class SomeClass() {}
|
||||
|
||||
fun someFun() {
|
||||
when {
|
||||
is SomeClass
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
FILE: invalidWhen.kt
|
||||
public? final? class SomeClass : R|kotlin/Any| {
|
||||
public? constructor(): R|SomeClass| {
|
||||
LAZY_super<R|kotlin/Any|>
|
||||
}
|
||||
|
||||
}
|
||||
public? final? fun someFun(): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
@@ -0,0 +1,14 @@
|
||||
FILE: invalidWhen.kt
|
||||
public? final? class SomeClass : R|kotlin/Any| {
|
||||
public? [ContainingClassKey=SomeClass] constructor(): R|SomeClass| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public? final? fun someFun(): R|kotlin/Unit| {
|
||||
when () {
|
||||
ERROR_EXPR(No expression in condition with expression) -> {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -446,6 +446,11 @@ public class RawFirBuilderLazyBodiesTestCaseGenerated extends AbstractRawFirBuil
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invalidWhen.kt")
|
||||
public void testInvalidWhen() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/invalidWhen.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("labelForInfix.kt")
|
||||
public void testLabelForInfix() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/labelForInfix.kt");
|
||||
|
||||
+5
@@ -446,6 +446,11 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invalidWhen.kt")
|
||||
public void testInvalidWhen() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/invalidWhen.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("labelForInfix.kt")
|
||||
public void testLabelForInfix() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/labelForInfix.kt");
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ internal class FirWhenSubjectExpressionImpl(
|
||||
override var annotations: MutableOrEmptyList<FirAnnotation>,
|
||||
override val whenRef: FirExpressionRef<FirWhenExpression>,
|
||||
) : FirWhenSubjectExpression() {
|
||||
override val typeRef: FirTypeRef get() = whenRef.value.subject!!.typeRef
|
||||
override val typeRef: FirTypeRef get() = whenRef.value.subject?.typeRef ?: org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef(source)
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
annotations.forEach { it.accept(visitor, data) }
|
||||
|
||||
+1
-1
@@ -418,7 +418,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
|
||||
impl(whenSubjectExpression) {
|
||||
default("typeRef") {
|
||||
value = "whenRef.value.subject!!.typeRef"
|
||||
value = "whenRef.value.subject?.typeRef ?: org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef(source)"
|
||||
withGetter = true
|
||||
}
|
||||
useTypes(whenExpression)
|
||||
|
||||
+4
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.diagnostics
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
|
||||
import org.jetbrains.kotlin.psi.psiUtil.allChildren
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStringTemplateExpressionElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtTokenSets
|
||||
@@ -1115,6 +1117,8 @@ object LightTreePositioningStrategies {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isValid(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): Boolean = true
|
||||
}
|
||||
|
||||
val NON_FINAL_MODIFIER_OR_NAME: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(
|
||||
|
||||
+2
@@ -992,6 +992,8 @@ object PositioningStrategies {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isValid(element: PsiElement): Boolean = true
|
||||
}
|
||||
|
||||
val NON_FINAL_MODIFIER_OR_NAME: PositioningStrategy<KtModifierListOwner> =
|
||||
|
||||
@@ -9,7 +9,7 @@ fun foo() =
|
||||
cond2() -> 2
|
||||
<!CONDITION_TYPE_MISMATCH!>4<!> -> 34
|
||||
<!CONDITION_TYPE_MISMATCH, TYPE_MISMATCH!>Pair(1, 2)<!> -> 3
|
||||
<!EXPECTED_CONDITION!>in 1..10<!> -> 34
|
||||
<!ARGUMENT_TYPE_MISMATCH, EXPECTED_CONDITION!>in 1..10<!> -> 34
|
||||
<!CONDITION_TYPE_MISMATCH!>4<!> -> 38
|
||||
<!EXPECTED_CONDITION!>is Int<!> -> 33
|
||||
else -> 34
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// FIR_IDENTICAL
|
||||
fun someFun() {
|
||||
when {
|
||||
<!EXPECTED_CONDITION!>is <!UNRESOLVED_REFERENCE!>SomeClass<!><!><!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> <!EXPECTED_CONDITION!>is <!UNRESOLVED_REFERENCE!>OtherClass<!><!><!SYNTAX!><!>
|
||||
}
|
||||
|
||||
val x = 0
|
||||
when {
|
||||
x == 1<!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> x == 2 -> {}
|
||||
}
|
||||
}
|
||||
Generated
+6
@@ -7318,6 +7318,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNoSubjectAndCommas.kt")
|
||||
public void testWhenWithNoSubjectAndCommas() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/controlStructures/whenWithNoSubjectAndCommas.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenWithNothingTypedSubject.kt")
|
||||
public void testWhenWithNothingTypedSubject() throws Exception {
|
||||
|
||||
Vendored
+1
-1
@@ -15,7 +15,7 @@ fun case_1(value_1: TypesProvider) {
|
||||
when {
|
||||
getBoolean()<!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> value_1.getBoolean() -> return
|
||||
value_1.getBoolean() && getBoolean()<!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> getLong() == 1000L -> return
|
||||
<!CONDITION_TYPE_MISMATCH, TYPE_MISMATCH!>Out<Int>()<!><!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> getLong()<!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> {}<!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> Any()<!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> throw Exception() -> return
|
||||
<!CONDITION_TYPE_MISMATCH, TYPE_MISMATCH!>Out<Int>()<!><!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> <!CONDITION_TYPE_MISMATCH, TYPE_MISMATCH!>getLong()<!><!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> <!CONDITION_TYPE_MISMATCH!>{}<!><!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> <!CONDITION_TYPE_MISMATCH, TYPE_MISMATCH!>Any()<!><!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> throw Exception() -> return
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
+6
@@ -491,6 +491,12 @@ public class FirVisualizerForRawFirDataGenerated extends AbstractFirVisualizerTe
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invalidWhen.kt")
|
||||
public void testInvalidWhen() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/invalidWhen.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("labelForInfix.kt")
|
||||
public void testLabelForInfix() throws Exception {
|
||||
|
||||
+6
@@ -491,6 +491,12 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizerTe
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invalidWhen.kt")
|
||||
public void testInvalidWhen() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/invalidWhen.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("labelForInfix.kt")
|
||||
public void testLabelForInfix() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user