From 94664694dfdf1abe496f8858c823a52632ff9f8a Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 21 Oct 2021 14:50:14 +0300 Subject: [PATCH] [FIR] Prohibit confusing syntax inside when branches ^KT-48385 --- .../diagnostics/KtFirDataClassConverters.kt | 63 ++-------- .../api/fir/diagnostics/KtFirDiagnostics.kt | 60 ++------- .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 62 ++------- .../diagnostics/FirDiagnosticsList.kt | 1 + .../fir/analysis/diagnostics/FirErrors.kt | 2 + .../checkers/CommonExpressionCheckers.kt | 2 + .../FirConfusingWhenBranchSyntaxChecker.kt | 118 ++++++++++++++++++ .../diagnostics/FirDefaultErrorMessages.kt | 5 + .../fir/lightTree/converter/BaseConverter.kt | 1 + .../fir/lightTree/converter/ConverterUtil.kt | 37 +----- .../converter/DeclarationsConverter.kt | 1 + .../converter/ExpressionsConverter.kt | 4 +- .../org/jetbrains/kotlin/ElementTypeUtils.kt | 34 ++++- .../deprecatedSyntaxInConditions_after.fir.kt | 56 ++++----- ...deprecatedSyntaxInConditions_before.fir.kt | 56 ++++----- .../p-2/neg/11.1.fir.kt | 4 +- .../p-2/neg/3.1.fir.kt | 4 +- .../p-2/pos/11.1.fir.kt | 4 +- .../p-2/pos/3.1.fir.kt | 4 +- .../when-expression/p-5/pos/1.1.fir.kt | 12 +- .../when-expression/p-6/pos/5.1.fir.kt | 8 +- .../when-expression/p-6/pos/5.2.fir.kt | 4 +- 22 files changed, 280 insertions(+), 262 deletions(-) create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/syntax/FirConfusingWhenBranchSyntaxChecker.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index 462390bf55f..7f1398d965a 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -5,64 +5,13 @@ package org.jetbrains.kotlin.analysis.api.fir.diagnostics -import com.intellij.psi.PsiElement -import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.fir.FirPsiSourceElement import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors -import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.declarations.FirClass -import org.jetbrains.kotlin.fir.declarations.FirDeclaration -import org.jetbrains.kotlin.fir.declarations.FirProperty -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction -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.KtAnnotationEntry -import org.jetbrains.kotlin.psi.KtAnonymousInitializer -import org.jetbrains.kotlin.psi.KtArrayAccessExpression -import org.jetbrains.kotlin.psi.KtBackingField -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS -import org.jetbrains.kotlin.psi.KtCallExpression -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtConstructor -import org.jetbrains.kotlin.psi.KtConstructorDelegationCall -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtDeclarationWithBody -import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry -import org.jetbrains.kotlin.psi.KtDestructuringDeclaration -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtExpressionWithLabel -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.KtIfExpression -import org.jetbrains.kotlin.psi.KtImportDirective -import org.jetbrains.kotlin.psi.KtModifierListOwner -import org.jetbrains.kotlin.psi.KtNameReferenceExpression -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtPrimaryConstructor -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtPropertyAccessor -import org.jetbrains.kotlin.psi.KtReturnExpression -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.KtSuperExpression -import org.jetbrains.kotlin.psi.KtTypeAlias -import org.jetbrains.kotlin.psi.KtTypeParameter -import org.jetbrains.kotlin.psi.KtTypeProjection -import org.jetbrains.kotlin.psi.KtTypeReference -import org.jetbrains.kotlin.psi.KtValueArgument -import org.jetbrains.kotlin.psi.KtVariableDeclaration -import org.jetbrains.kotlin.psi.KtWhenCondition -import org.jetbrains.kotlin.psi.KtWhenEntry -import org.jetbrains.kotlin.psi.KtWhenExpression /* * This file was generated automatically @@ -3157,6 +3106,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.CONFUSING_BRANCH_CONDITION.errorFactory) { firDiagnostic -> + ConfusingBranchConditionErrorImpl( + firDiagnostic as FirPsiDiagnostic, + token, + ) + } + add(FirErrors.CONFUSING_BRANCH_CONDITION.warningFactory) { firDiagnostic -> + ConfusingBranchConditionWarningImpl( + firDiagnostic as FirPsiDiagnostic, + token, + ) + } add(FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION) { firDiagnostic -> TypeParameterIsNotAnExpressionImpl( firSymbolBuilder.classifierBuilder.buildTypeParameterSymbol(firDiagnostic.a.fir), diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index d5f030d2752..4f2ce931e8b 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -8,13 +8,7 @@ package org.jetbrains.kotlin.analysis.api.fir.diagnostics import com.intellij.psi.PsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnosticWithPsi -import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtVariableSymbol +import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings @@ -30,49 +24,7 @@ import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtAnnotationEntry -import org.jetbrains.kotlin.psi.KtAnonymousInitializer -import org.jetbrains.kotlin.psi.KtArrayAccessExpression -import org.jetbrains.kotlin.psi.KtBackingField -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS -import org.jetbrains.kotlin.psi.KtCallExpression -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtConstructor -import org.jetbrains.kotlin.psi.KtConstructorDelegationCall -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtDeclarationWithBody -import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry -import org.jetbrains.kotlin.psi.KtDestructuringDeclaration -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtEnumEntry -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtExpressionWithLabel -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.KtIfExpression -import org.jetbrains.kotlin.psi.KtImportDirective -import org.jetbrains.kotlin.psi.KtModifierListOwner -import org.jetbrains.kotlin.psi.KtNameReferenceExpression -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtPrimaryConstructor -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtPropertyAccessor -import org.jetbrains.kotlin.psi.KtReturnExpression -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.KtSuperExpression -import org.jetbrains.kotlin.psi.KtTypeAlias -import org.jetbrains.kotlin.psi.KtTypeParameter -import org.jetbrains.kotlin.psi.KtTypeProjection -import org.jetbrains.kotlin.psi.KtTypeReference -import org.jetbrains.kotlin.psi.KtValueArgument -import org.jetbrains.kotlin.psi.KtVariableDeclaration -import org.jetbrains.kotlin.psi.KtWhenCondition -import org.jetbrains.kotlin.psi.KtWhenEntry -import org.jetbrains.kotlin.psi.KtWhenExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible @@ -2203,6 +2155,14 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = DuplicateLabelInWhen::class } + abstract class ConfusingBranchConditionError : KtFirDiagnostic() { + override val diagnosticClass get() = ConfusingBranchConditionError::class + } + + abstract class ConfusingBranchConditionWarning : KtFirDiagnostic() { + override val diagnosticClass get() = ConfusingBranchConditionWarning::class + } + abstract class TypeParameterIsNotAnExpression : KtFirDiagnostic() { override val diagnosticClass get() = TypeParameterIsNotAnExpression::class abstract val typeParameter: KtTypeParameterSymbol diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 45db5883452..9bced8b2761 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -7,13 +7,7 @@ package org.jetbrains.kotlin.analysis.api.fir.diagnostics import com.intellij.psi.PsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement -import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtVariableSymbol +import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.config.LanguageFeature @@ -31,49 +25,7 @@ import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtAnnotationEntry -import org.jetbrains.kotlin.psi.KtAnonymousInitializer -import org.jetbrains.kotlin.psi.KtArrayAccessExpression -import org.jetbrains.kotlin.psi.KtBackingField -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS -import org.jetbrains.kotlin.psi.KtCallExpression -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtConstructor -import org.jetbrains.kotlin.psi.KtConstructorDelegationCall -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtDeclarationWithBody -import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry -import org.jetbrains.kotlin.psi.KtDestructuringDeclaration -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtEnumEntry -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtExpressionWithLabel -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.KtIfExpression -import org.jetbrains.kotlin.psi.KtImportDirective -import org.jetbrains.kotlin.psi.KtModifierListOwner -import org.jetbrains.kotlin.psi.KtNameReferenceExpression -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtPrimaryConstructor -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtPropertyAccessor -import org.jetbrains.kotlin.psi.KtReturnExpression -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.KtSuperExpression -import org.jetbrains.kotlin.psi.KtTypeAlias -import org.jetbrains.kotlin.psi.KtTypeParameter -import org.jetbrains.kotlin.psi.KtTypeProjection -import org.jetbrains.kotlin.psi.KtTypeReference -import org.jetbrains.kotlin.psi.KtValueArgument -import org.jetbrains.kotlin.psi.KtVariableDeclaration -import org.jetbrains.kotlin.psi.KtWhenCondition -import org.jetbrains.kotlin.psi.KtWhenEntry -import org.jetbrains.kotlin.psi.KtWhenExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible @@ -2655,6 +2607,16 @@ internal class DuplicateLabelInWhenImpl( override val token: ValidityToken, ) : KtFirDiagnostic.DuplicateLabelInWhen(), KtAbstractFirDiagnostic +internal class ConfusingBranchConditionErrorImpl( + override val firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.ConfusingBranchConditionError(), KtAbstractFirDiagnostic + +internal class ConfusingBranchConditionWarningImpl( + override val firDiagnostic: FirPsiDiagnostic, + override val token: ValidityToken, +) : KtFirDiagnostic.ConfusingBranchConditionWarning(), KtAbstractFirDiagnostic + internal class TypeParameterIsNotAnExpressionImpl( override val typeParameter: KtTypeParameterSymbol, override val firDiagnostic: FirPsiDiagnostic, 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 7f15bde068c..a2424125ad3 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 @@ -1117,6 +1117,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { } val COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT by error(PositioningStrategy.COMMAS) val DUPLICATE_LABEL_IN_WHEN by warning() + val CONFUSING_BRANCH_CONDITION by deprecationError(LanguageFeature.ProhibitConfusingSyntaxInWhenBranches) } val CONTEXT_TRACKING by object : DiagnosticGroup("Context tracking") { 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 8841f76f4a3..dfab16418bc 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 @@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature.ProhibitAssigningSingleElementsToVarargsInNamedForm +import org.jetbrains.kotlin.config.LanguageFeature.ProhibitConfusingSyntaxInWhenBranches import org.jetbrains.kotlin.config.LanguageFeature.ProhibitInvisibleAbstractMethodsInSuperclasses import org.jetbrains.kotlin.config.LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments import org.jetbrains.kotlin.config.LanguageFeature.ProhibitUseSiteTargetAnnotationsOnSuperTypes @@ -596,6 +597,7 @@ object FirErrors { val ILLEGAL_DECLARATION_IN_WHEN_SUBJECT by error1() val COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT by error0(SourceElementPositioningStrategies.COMMAS) val DUPLICATE_LABEL_IN_WHEN by warning0() + val CONFUSING_BRANCH_CONDITION by deprecationError0(ProhibitConfusingSyntaxInWhenBranches) // Context tracking val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION by error1() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt index 890471b5b24..3ad75a59405 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers import org.jetbrains.kotlin.fir.analysis.checkers.expression.* import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirCommaInWhenConditionChecker +import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirConfusingWhenBranchSyntaxChecker object CommonExpressionCheckers : ExpressionCheckers() { override val annotationCallCheckers: Set @@ -77,6 +78,7 @@ object CommonExpressionCheckers : ExpressionCheckers() { FirWhenConditionChecker, FirWhenSubjectChecker, FirCommaInWhenConditionChecker, + FirConfusingWhenBranchSyntaxChecker, ) override val loopExpressionCheckers: Set diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/syntax/FirConfusingWhenBranchSyntaxChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/syntax/FirConfusingWhenBranchSyntaxChecker.kt new file mode 100644 index 00000000000..034cb5cb2ba --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/syntax/FirConfusingWhenBranchSyntaxChecker.kt @@ -0,0 +1,118 @@ +/* + * 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.syntax + +import com.intellij.lang.LighterASTNode +import com.intellij.psi.PsiElement +import com.intellij.psi.tree.TokenSet +import com.intellij.util.diff.FlyweightCapableTreeStructure +import org.jetbrains.kotlin.ElementTypeUtils.getOperationSymbol +import org.jetbrains.kotlin.KtNodeTypes.* +import org.jetbrains.kotlin.fir.FirLightSourceElement +import org.jetbrains.kotlin.fir.FirPsiSourceElement +import org.jetbrains.kotlin.fir.FirRealPsiSourceElement +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.getChildren +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.analysis.diagnostics.isExpression +import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn +import org.jetbrains.kotlin.fir.expressions.FirWhenExpression +import org.jetbrains.kotlin.lexer.KtTokens.* +import org.jetbrains.kotlin.psi.* + +object FirConfusingWhenBranchSyntaxChecker : FirExpressionSyntaxChecker() { + private val prohibitedTokens = TokenSet.create( + IN_KEYWORD, NOT_IN, + LT, LTEQ, GT, GTEQ, + EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ, + ANDAND, OROR + ) + + override fun checkLightTree( + element: FirWhenExpression, + source: FirSourceElement, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + if (element.subject == null && element.subjectVariable == null) return + val tree = source.treeStructure + val entries = source.lighterASTNode.getChildren(tree).filter { it.tokenType == WHEN_ENTRY } + val offset = source.startOffset - source.lighterASTNode.startOffset + for (entry in entries) { + for (node in entry.getChildren(tree)) { + val expression = when (node.tokenType) { + WHEN_CONDITION_EXPRESSION -> node.getChildren(tree).firstOrNull { it.isExpression() } + WHEN_CONDITION_IN_RANGE -> node.getChildren(tree) + .firstOrNull { it.tokenType != OPERATION_REFERENCE && it.isExpression()} + else -> null + } ?: continue + checkConditionExpression(offset, expression, tree, context, reporter) + } + } + } + + private fun checkConditionExpression( + offset: Int, + expression: LighterASTNode, + tree: FlyweightCapableTreeStructure, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + val shouldReport = when (expression.tokenType) { + IS_EXPRESSION -> true + BINARY_EXPRESSION -> { + val operationTokenName = expression.getChildren(tree).first { it.tokenType == OPERATION_REFERENCE }.toString() + val operationToken = operationTokenName.getOperationSymbol() + operationToken in prohibitedTokens + } + else -> false + } + if (shouldReport) { + val source = FirLightSourceElement(expression, offset + expression.startOffset, offset + expression.endOffset, tree) + reporter.reportOn(source, FirErrors.CONFUSING_BRANCH_CONDITION, context) + } + } + + override fun checkPsi( + element: FirWhenExpression, + source: FirPsiSourceElement, + psi: PsiElement, + context: CheckerContext, + reporter: DiagnosticReporter + ) { + if (element.subject == null && element.subjectVariable == null) return + val whenExpression = psi as KtWhenExpression + if (whenExpression.subjectExpression == null && whenExpression.subjectVariable == null) return + for (entry in whenExpression.entries) { + for (condition in entry.conditions) { + checkCondition(condition, context, reporter) + } + } + } + + private fun checkCondition(condition: KtWhenCondition, context: CheckerContext, reporter: DiagnosticReporter) { + when (condition) { + is KtWhenConditionWithExpression -> checkConditionExpression(condition.expression, context, reporter) + is KtWhenConditionInRange -> checkConditionExpression(condition.rangeExpression, context, reporter) + } + } + + private fun checkConditionExpression(rawExpression: KtExpression?, context: CheckerContext, reporter: DiagnosticReporter) { + if (rawExpression == null) return + if (rawExpression is KtParenthesizedExpression) return + val shouldReport = when (val expression = KtPsiUtil.safeDeparenthesize(rawExpression)) { + is KtIsExpression -> true + is KtBinaryExpression -> expression.operationToken in prohibitedTokens + else -> false + } + if (shouldReport) { + val source = FirRealPsiSourceElement(rawExpression) + reporter.reportOn(source, FirErrors.CONFUSING_BRANCH_CONDITION, context) + } + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index ab5026be9ed..d570435f790 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -107,6 +107,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_OVERL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_UPPER_BOUNDS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFUSING_BRANCH_CONDITION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_INTERFACE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_OBJECT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT @@ -1520,6 +1521,10 @@ class FirDefaultErrorMessages { ) map.put(COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT, "Deprecated syntax. Use '||' instead of commas in when-condition for 'when' without argument") map.put(DUPLICATE_LABEL_IN_WHEN, "Duplicate label in when") + map.put( + CONFUSING_BRANCH_CONDITION, + "The logical expressions may be understood ambiguously in when with subject branches. Please wrap it with parenthesis" + ) // Context tracking map.put(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION, "Type parameter ''{0}'' is not an expression", SYMBOL) diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt index 35370f50200..0fbe132c400 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt @@ -10,6 +10,7 @@ import com.intellij.openapi.util.Ref import com.intellij.psi.TokenType import com.intellij.psi.tree.IElementType import com.intellij.util.diff.FlyweightCapableTreeStructure +import org.jetbrains.kotlin.ElementTypeUtils.isExpression import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.builder.BaseFirBuilder diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt index 56648716311..042b87e6938 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ConverterUtil.kt @@ -6,8 +6,6 @@ package org.jetbrains.kotlin.fir.lightTree.converter import com.intellij.lang.LighterASTNode -import com.intellij.psi.tree.IElementType -import org.jetbrains.kotlin.KtNodeType import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities @@ -20,25 +18,16 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.builder.* +import org.jetbrains.kotlin.fir.expressions.builder.FirCallBuilder +import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList +import org.jetbrains.kotlin.fir.expressions.builder.buildBlock +import org.jetbrains.kotlin.fir.expressions.builder.buildComponentCall import org.jetbrains.kotlin.fir.fakeElement import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol -import org.jetbrains.kotlin.lexer.KtSingleValueToken -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames -import org.jetbrains.kotlin.parsing.KotlinExpressionParsing import org.jetbrains.kotlin.psi.KtPsiUtil -import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType -import org.jetbrains.kotlin.psi.stubs.elements.KtStringTemplateExpressionElementType - -private val expressionSet = listOf( - REFERENCE_EXPRESSION, - DOT_QUALIFIED_EXPRESSION, - LAMBDA_EXPRESSION, - FUN -) fun String?.nameAsSafeName(defaultName: String = ""): Name { return when { @@ -48,28 +37,10 @@ fun String?.nameAsSafeName(defaultName: String = ""): Name { } } -fun String.getOperationSymbol(): IElementType { - KotlinExpressionParsing.ALL_OPERATIONS.types.forEach { - if (it is KtSingleValueToken && it.value == this) return it - } - if (this == "as?") return KtTokens.AS_SAFE - return KtTokens.IDENTIFIER -} - fun LighterASTNode.getAsStringWithoutBacktick(): String { return this.toString().replace("`", "") } -fun LighterASTNode.isExpression(): Boolean { - return when (this.tokenType) { - is KtNodeType, - is KtConstantExpressionElementType, - is KtStringTemplateExpressionElementType, - in expressionSet -> true - else -> false - } -} - fun T.extractArgumentsFrom(container: List): T { argumentList = buildArgumentList { arguments += container diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 251a510c14d..f969a30c6e9 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.lightTree.converter import com.intellij.lang.LighterASTNode import com.intellij.psi.TokenType import com.intellij.util.diff.FlyweightCapableTreeStructure +import org.jetbrains.kotlin.ElementTypeUtils.isExpression import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.builtins.StandardNames diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index 937752ea173..5dd53e5d675 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.lightTree.converter import com.intellij.lang.LighterASTNode import com.intellij.psi.TokenType import com.intellij.util.diff.FlyweightCapableTreeStructure +import org.jetbrains.kotlin.ElementTypeUtils.getOperationSymbol +import org.jetbrains.kotlin.ElementTypeUtils.isExpression import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities @@ -837,7 +839,7 @@ class ExpressionsConverter( it.tokenType == OPERATION_REFERENCE -> { conditionSource = it.toFirSourceElement() } - else -> if (it.isExpression()) firExpression = getAsFirExpression(it) + else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "No range in condition with range") } } diff --git a/compiler/psi/src/org/jetbrains/kotlin/ElementTypeUtils.kt b/compiler/psi/src/org/jetbrains/kotlin/ElementTypeUtils.kt index 86b0ecdccc1..8c71076b724 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/ElementTypeUtils.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/ElementTypeUtils.kt @@ -5,9 +5,16 @@ package org.jetbrains.kotlin +import com.intellij.lang.LighterASTNode +import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IErrorCounterReparseableElementType +import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.lexer.KotlinLexer +import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.parsing.KotlinExpressionParsing +import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType +import org.jetbrains.kotlin.psi.stubs.elements.KtStringTemplateExpressionElementType object ElementTypeUtils { @JvmStatic @@ -32,4 +39,29 @@ object ElementTypeUtils { } return balance } -} \ No newline at end of file + + fun String.getOperationSymbol(): IElementType { + KotlinExpressionParsing.ALL_OPERATIONS.types.forEach { + if (it is KtSingleValueToken && it.value == this) return it + } + if (this == "as?") return KtTokens.AS_SAFE + return KtTokens.IDENTIFIER + } + + private val expressionSet = listOf( + REFERENCE_EXPRESSION, + DOT_QUALIFIED_EXPRESSION, + LAMBDA_EXPRESSION, + FUN + ) + + fun LighterASTNode.isExpression(): Boolean { + return when (this.tokenType) { + is KtNodeType, + is KtConstantExpressionElementType, + is KtStringTemplateExpressionElementType, + in expressionSet -> true + else -> false + } + } +} diff --git a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.fir.kt b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.fir.kt index 96c0e239f4d..2110cc21c08 100644 --- a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.fir.kt +++ b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.fir.kt @@ -55,18 +55,18 @@ fun testWithSubject_ok(x: A, y: A?, any: Any, z: B) { fun testWithSubject_bad_1(x: A) { // bad when (x) { - x in x -> {} - x !in x -> {} - x is String -> {} - x !is String -> {} - x < x -> {} - x > x -> {} - x <= x -> {} - x >= x -> {} - x == x -> {} - x != x -> {} - x === x -> {} - x !== x -> {} + x in x -> {} + x !in x -> {} + x is String -> {} + x !is String -> {} + x < x -> {} + x > x -> {} + x <= x -> {} + x >= x -> {} + x == x -> {} + x != x -> {} + x === x -> {} + x !== x -> {} } // ok when (x) { @@ -88,8 +88,8 @@ fun testWithSubject_bad_1(x: A) { fun testWithSubject_bad_2(b: Boolean) { // bad when (b) { - b && b -> {} - b || b -> {} + b && b -> {} + b || b -> {} } // ok when (b) { @@ -159,18 +159,18 @@ fun testWithRange_ok(x: A, y: A?, any: Any, z: B) { fun testWithRange_bad_1(x: A) { // bad when (x) { - in x in x -> {} - in x !in x -> {} - in x is String -> {} - in x !is String -> {} - in x < x -> {} - in x > x -> {} - in x <= x -> {} - in x >= x -> {} - in x == x -> {} - in x != x -> {} - in x === x -> {} - in x !== x -> {} + in x in x -> {} + in x !in x -> {} + in x is String -> {} + in x !is String -> {} + in x < x -> {} + in x > x -> {} + in x <= x -> {} + in x >= x -> {} + in x == x -> {} + in x != x -> {} + in x === x -> {} + in x !== x -> {} } // ok when (x) { @@ -192,8 +192,8 @@ fun testWithRange_bad_1(x: A) { fun testWithRange_bad_2(b: Boolean) { // bad when (b) { - in b && b -> {} - in b || b -> {} + in b && b -> {} + in b || b -> {} } // ok when (b) { diff --git a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.fir.kt b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.fir.kt index 19dbfe2c7de..88158720f55 100644 --- a/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.fir.kt +++ b/compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.fir.kt @@ -55,18 +55,18 @@ fun testWithSubject_ok(x: A, y: A?, any: Any, z: B) { fun testWithSubject_bad_1(x: A) { // bad when (x) { - x in x -> {} - x !in x -> {} - x is String -> {} - x !is String -> {} - x < x -> {} - x > x -> {} - x <= x -> {} - x >= x -> {} - x == x -> {} - x != x -> {} - x === x -> {} - x !== x -> {} + x in x -> {} + x !in x -> {} + x is String -> {} + x !is String -> {} + x < x -> {} + x > x -> {} + x <= x -> {} + x >= x -> {} + x == x -> {} + x != x -> {} + x === x -> {} + x !== x -> {} } // ok when (x) { @@ -88,8 +88,8 @@ fun testWithSubject_bad_1(x: A) { fun testWithSubject_bad_2(b: Boolean) { // bad when (b) { - b && b -> {} - b || b -> {} + b && b -> {} + b || b -> {} } // ok when (b) { @@ -159,18 +159,18 @@ fun testWithRange_ok(x: A, y: A?, any: Any, z: B) { fun testWithRange_bad_1(x: A) { // bad when (x) { - in x in x -> {} - in x !in x -> {} - in x is String -> {} - in x !is String -> {} - in x < x -> {} - in x > x -> {} - in x <= x -> {} - in x >= x -> {} - in x == x -> {} - in x != x -> {} - in x === x -> {} - in x !== x -> {} + in x in x -> {} + in x !in x -> {} + in x is String -> {} + in x !is String -> {} + in x < x -> {} + in x > x -> {} + in x <= x -> {} + in x >= x -> {} + in x == x -> {} + in x != x -> {} + in x === x -> {} + in x !== x -> {} } // ok when (x) { @@ -192,8 +192,8 @@ fun testWithRange_bad_1(x: A) { fun testWithRange_bad_2(b: Boolean) { // bad when (b) { - in b && b -> {} - in b || b -> {} + in b && b -> {} + in b || b -> {} } // ok when (b) { diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.fir.kt index ac8c01f4382..caa230188d6 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/11.1.fir.kt @@ -29,7 +29,7 @@ fun case_3(value_1: Boolean?): Int = when(value_1) { } // TESTCASE NUMBER: 4 fun case_4(value_1: Boolean?): String = when (value_1) { - true && false && ((true || false)) || true && !!!false && !!!true -> "" - true && false && ((true || false)) || true && !!!false -> "" + true && false && ((true || false)) || true && !!!false && !!!true -> "" + true && false && ((true || false)) || true && !!!false -> "" null -> "" } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.fir.kt index d9d21146aa9..da8b37dc92a 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/neg/3.1.fir.kt @@ -48,6 +48,6 @@ fun case_5(value_1: Boolean): String { // TESTCASE NUMBER: 6 fun case_6(value_1: Boolean): String = when (value_1) { - true && false && ((true || false)) || true && !!!false && !!!true -> "" - true && false && ((true || false)) || true && !!!false -> "" + true && false && ((true || false)) || true && !!!false && !!!true -> "" + true && false && ((true || false)) || true && !!!false -> "" } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.fir.kt index a6bbd1d1652..f3cb6e14bf6 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/11.1.fir.kt @@ -18,7 +18,7 @@ fun case_1(value_1: Boolean?): String = when (value_1) { // TESTCASE NUMBER: 2 fun case_2(value_1: Boolean?): String = when (value_1) { - true && false && ((true || false)) || true && !!!false && !!!true -> "" - true && false && ((true || false)) || true && !!!false -> "" + true && false && ((true || false)) || true && !!!false && !!!true -> "" + true && false && ((true || false)) || true && !!!false -> "" null -> "" } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.fir.kt index 3c414d2fff5..e4b8cc48a35 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/exhaustive-when-expressions/p-2/pos/3.1.fir.kt @@ -17,6 +17,6 @@ fun case_1(value_1: Boolean): String = when (value_1) { // TESTCASE NUMBER: 2 fun case_2(value_1: Boolean): String = when (value_1) { - true && false && ((true || false)) || true && !!!false && !!!true -> "" - true && false && ((true || false)) || true && !!!false -> "" + true && false && ((true || false)) || true && !!!false && !!!true -> "" + true && false && ((true || false)) || true && !!!false -> "" } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-5/pos/1.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-5/pos/1.1.fir.kt index 270563b5d83..800e156eb4d 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-5/pos/1.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-5/pos/1.1.fir.kt @@ -47,13 +47,13 @@ fun case_4(value_1: Int, value_2: String, value_3: String) { fun case_5(value_1: Int, value_2: Int, value_3: Boolean?) { when (value_1) { 1 -> when (value_3) { - value_2 > 1000 -> "1" - value_2 > 100 -> "2" + value_2 > 1000 -> "1" + value_2 > 100 -> "2" else -> "3" } 2 -> when (value_3) { - value_2 > 1000 -> "1" - value_2 > 100 -> "2" + value_2 > 1000 -> "1" + value_2 > 100 -> "2" } 3 -> when (value_3) {} 4 -> when (value_3) { @@ -72,8 +72,8 @@ fun case_5(value_1: Int, value_2: Int, value_3: Boolean?) { // TESTCASE NUMBER: 6 fun case_6(value_1: Int, value_2: Int, value_3: Boolean?) = when (value_1) { 1 -> when (value_3) { - value_2 > 1000 -> 1 - value_2 > 100 -> 2 + value_2 > 1000 -> 1 + value_2 > 100 -> 2 else -> 3 } else -> when (value_3) { diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-6/pos/5.1.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-6/pos/5.1.fir.kt index 696b3985b82..694ef40ed35 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-6/pos/5.1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-6/pos/5.1.fir.kt @@ -27,10 +27,10 @@ fun case_3(value_1: Boolean, value_2: Boolean, value_3: Long) { when (value_1) { value_2 -> {} !value_2 -> {} - getBoolean() && value_2 -> {} - getChar() != 'a' -> {} - getList() === getAny() -> {} - value_3 <= 11 -> {} + getBoolean() && value_2 -> {} + getChar() != 'a' -> {} + getList() === getAny() -> {} + value_3 <= 11 -> {} } } diff --git a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-6/pos/5.2.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-6/pos/5.2.fir.kt index a938a70e4ba..96026587a6e 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-6/pos/5.2.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/expressions/when-expression/p-6/pos/5.2.fir.kt @@ -19,8 +19,8 @@ fun case_2(value_1: Number, value_2: Int) { // TESTCASE NUMBER: 3 fun case_3(value_1: Boolean, value_2: Boolean, value_3: Long) { when (value_1) { - value_2, !value_2, getBoolean() && value_2, getChar() != 'a' -> {} - getList() === getAny(), value_3 <= 11 -> {} + value_2, !value_2, getBoolean() && value_2, getChar() != 'a' -> {} + getList() === getAny(), value_3 <= 11 -> {} } }