[FIR] Prohibit confusing syntax inside when branches
^KT-48385
This commit is contained in:
committed by
teamcityserver
parent
bf453674b9
commit
94664694df
+12
-51
@@ -5,64 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.analysis.api.fir.diagnostics
|
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.FirPsiSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
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.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.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.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
|
* This file was generated automatically
|
||||||
@@ -3157,6 +3106,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
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 ->
|
add(FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION) { firDiagnostic ->
|
||||||
TypeParameterIsNotAnExpressionImpl(
|
TypeParameterIsNotAnExpressionImpl(
|
||||||
firSymbolBuilder.classifierBuilder.buildTypeParameterSymbol(firDiagnostic.a.fir),
|
firSymbolBuilder.classifierBuilder.buildTypeParameterSymbol(firDiagnostic.a.fir),
|
||||||
|
|||||||
+10
-50
@@ -8,13 +8,7 @@ package org.jetbrains.kotlin.analysis.api.fir.diagnostics
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnosticWithPsi
|
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnosticWithPsi
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
|
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||||
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.types.KtType
|
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
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.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.*
|
||||||
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.resolve.ForbiddenNamedArgumentsTarget
|
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo
|
import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||||
@@ -2203,6 +2155,14 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = DuplicateLabelInWhen::class
|
override val diagnosticClass get() = DuplicateLabelInWhen::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class ConfusingBranchConditionError : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = ConfusingBranchConditionError::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ConfusingBranchConditionWarning : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = ConfusingBranchConditionWarning::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class TypeParameterIsNotAnExpression : KtFirDiagnostic<KtSimpleNameExpression>() {
|
abstract class TypeParameterIsNotAnExpression : KtFirDiagnostic<KtSimpleNameExpression>() {
|
||||||
override val diagnosticClass get() = TypeParameterIsNotAnExpression::class
|
override val diagnosticClass get() = TypeParameterIsNotAnExpression::class
|
||||||
abstract val typeParameter: KtTypeParameterSymbol
|
abstract val typeParameter: KtTypeParameterSymbol
|
||||||
|
|||||||
+12
-50
@@ -7,13 +7,7 @@ package org.jetbrains.kotlin.analysis.api.fir.diagnostics
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
|
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||||
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.tokens.ValidityToken
|
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
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.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.*
|
||||||
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.resolve.ForbiddenNamedArgumentsTarget
|
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo
|
import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible
|
||||||
@@ -2655,6 +2607,16 @@ internal class DuplicateLabelInWhenImpl(
|
|||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
) : KtFirDiagnostic.DuplicateLabelInWhen(), KtAbstractFirDiagnostic<KtElement>
|
) : KtFirDiagnostic.DuplicateLabelInWhen(), KtAbstractFirDiagnostic<KtElement>
|
||||||
|
|
||||||
|
internal class ConfusingBranchConditionErrorImpl(
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ConfusingBranchConditionError(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
|
internal class ConfusingBranchConditionWarningImpl(
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ConfusingBranchConditionWarning(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
internal class TypeParameterIsNotAnExpressionImpl(
|
internal class TypeParameterIsNotAnExpressionImpl(
|
||||||
override val typeParameter: KtTypeParameterSymbol,
|
override val typeParameter: KtTypeParameterSymbol,
|
||||||
override val firDiagnostic: FirPsiDiagnostic,
|
override val firDiagnostic: FirPsiDiagnostic,
|
||||||
|
|||||||
+1
@@ -1117,6 +1117,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
}
|
}
|
||||||
val COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT by error<PsiElement>(PositioningStrategy.COMMAS)
|
val COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT by error<PsiElement>(PositioningStrategy.COMMAS)
|
||||||
val DUPLICATE_LABEL_IN_WHEN by warning<KtElement>()
|
val DUPLICATE_LABEL_IN_WHEN by warning<KtElement>()
|
||||||
|
val CONFUSING_BRANCH_CONDITION by deprecationError<PsiElement>(LanguageFeature.ProhibitConfusingSyntaxInWhenBranches)
|
||||||
}
|
}
|
||||||
|
|
||||||
val CONTEXT_TRACKING by object : DiagnosticGroup("Context tracking") {
|
val CONTEXT_TRACKING by object : DiagnosticGroup("Context tracking") {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitAssigningSingleElementsToVarargsInNamedForm
|
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.ProhibitInvisibleAbstractMethodsInSuperclasses
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments
|
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitUseSiteTargetAnnotationsOnSuperTypes
|
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitUseSiteTargetAnnotationsOnSuperTypes
|
||||||
@@ -596,6 +597,7 @@ object FirErrors {
|
|||||||
val ILLEGAL_DECLARATION_IN_WHEN_SUBJECT by error1<KtElement, String>()
|
val ILLEGAL_DECLARATION_IN_WHEN_SUBJECT by error1<KtElement, String>()
|
||||||
val COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT by error0<PsiElement>(SourceElementPositioningStrategies.COMMAS)
|
val COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT by error0<PsiElement>(SourceElementPositioningStrategies.COMMAS)
|
||||||
val DUPLICATE_LABEL_IN_WHEN by warning0<KtElement>()
|
val DUPLICATE_LABEL_IN_WHEN by warning0<KtElement>()
|
||||||
|
val CONFUSING_BRANCH_CONDITION by deprecationError0<PsiElement>(ProhibitConfusingSyntaxInWhenBranches)
|
||||||
|
|
||||||
// Context tracking
|
// Context tracking
|
||||||
val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION by error1<KtSimpleNameExpression, FirTypeParameterSymbol>()
|
val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION by error1<KtSimpleNameExpression, FirTypeParameterSymbol>()
|
||||||
|
|||||||
+2
@@ -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.expression.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirCommaInWhenConditionChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirCommaInWhenConditionChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirConfusingWhenBranchSyntaxChecker
|
||||||
|
|
||||||
object CommonExpressionCheckers : ExpressionCheckers() {
|
object CommonExpressionCheckers : ExpressionCheckers() {
|
||||||
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
|
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
|
||||||
@@ -77,6 +78,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
FirWhenConditionChecker,
|
FirWhenConditionChecker,
|
||||||
FirWhenSubjectChecker,
|
FirWhenSubjectChecker,
|
||||||
FirCommaInWhenConditionChecker,
|
FirCommaInWhenConditionChecker,
|
||||||
|
FirConfusingWhenBranchSyntaxChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val loopExpressionCheckers: Set<FirLoopExpressionChecker>
|
override val loopExpressionCheckers: Set<FirLoopExpressionChecker>
|
||||||
|
|||||||
+118
@@ -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<FirWhenExpression, PsiElement>() {
|
||||||
|
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<LighterASTNode>,
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -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
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION
|
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.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_INTERFACE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_OBJECT
|
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
|
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(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(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
|
// Context tracking
|
||||||
map.put(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION, "Type parameter ''{0}'' is not an expression", SYMBOL)
|
map.put(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION, "Type parameter ''{0}'' is not an expression", SYMBOL)
|
||||||
|
|||||||
+1
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.Ref
|
|||||||
import com.intellij.psi.TokenType
|
import com.intellij.psi.TokenType
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
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.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.builder.BaseFirBuilder
|
import org.jetbrains.kotlin.fir.builder.BaseFirBuilder
|
||||||
|
|||||||
+4
-33
@@ -6,8 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.fir.lightTree.converter
|
package org.jetbrains.kotlin.fir.lightTree.converter
|
||||||
|
|
||||||
import com.intellij.lang.LighterASTNode
|
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.KtNodeTypes.*
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
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.declarations.impl.FirDeclarationStatusImpl
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
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.fakeElement
|
||||||
import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration
|
import org.jetbrains.kotlin.fir.lightTree.fir.DestructuringDeclaration
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
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.Name
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.parsing.KotlinExpressionParsing
|
|
||||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
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 {
|
fun String?.nameAsSafeName(defaultName: String = ""): Name {
|
||||||
return when {
|
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 {
|
fun LighterASTNode.getAsStringWithoutBacktick(): String {
|
||||||
return this.toString().replace("`", "")
|
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 : FirCallBuilder> T.extractArgumentsFrom(container: List<FirExpression>): T {
|
fun <T : FirCallBuilder> T.extractArgumentsFrom(container: List<FirExpression>): T {
|
||||||
argumentList = buildArgumentList {
|
argumentList = buildArgumentList {
|
||||||
arguments += container
|
arguments += container
|
||||||
|
|||||||
+1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.lightTree.converter
|
|||||||
import com.intellij.lang.LighterASTNode
|
import com.intellij.lang.LighterASTNode
|
||||||
import com.intellij.psi.TokenType
|
import com.intellij.psi.TokenType
|
||||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
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.KtNodeTypes.*
|
import org.jetbrains.kotlin.KtNodeTypes.*
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
|
|||||||
+3
-1
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.lightTree.converter
|
|||||||
import com.intellij.lang.LighterASTNode
|
import com.intellij.lang.LighterASTNode
|
||||||
import com.intellij.psi.TokenType
|
import com.intellij.psi.TokenType
|
||||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
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.KtNodeTypes.*
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
@@ -837,7 +839,7 @@ class ExpressionsConverter(
|
|||||||
it.tokenType == OPERATION_REFERENCE -> {
|
it.tokenType == OPERATION_REFERENCE -> {
|
||||||
conditionSource = it.toFirSourceElement()
|
conditionSource = it.toFirSourceElement()
|
||||||
}
|
}
|
||||||
else -> if (it.isExpression()) firExpression = getAsFirExpression(it)
|
else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "No range in condition with range")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,16 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin
|
package org.jetbrains.kotlin
|
||||||
|
|
||||||
|
import com.intellij.lang.LighterASTNode
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
import com.intellij.psi.tree.IErrorCounterReparseableElementType
|
import com.intellij.psi.tree.IErrorCounterReparseableElementType
|
||||||
|
import org.jetbrains.kotlin.KtNodeTypes.*
|
||||||
import org.jetbrains.kotlin.lexer.KotlinLexer
|
import org.jetbrains.kotlin.lexer.KotlinLexer
|
||||||
|
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
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 {
|
object ElementTypeUtils {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@@ -32,4 +39,29 @@ object ElementTypeUtils {
|
|||||||
}
|
}
|
||||||
return balance
|
return balance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+28
-28
@@ -55,18 +55,18 @@ fun testWithSubject_ok(x: A, y: A?, any: Any, z: B) {
|
|||||||
fun testWithSubject_bad_1(x: A) {
|
fun testWithSubject_bad_1(x: A) {
|
||||||
// bad
|
// bad
|
||||||
when (x) {
|
when (x) {
|
||||||
x in x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x in x<!> -> {}
|
||||||
x !in x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x !in x<!> -> {}
|
||||||
x is String -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x is String<!> -> {}
|
||||||
x !is String -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x !is String<!> -> {}
|
||||||
x < x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x < x<!> -> {}
|
||||||
x > x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x > x<!> -> {}
|
||||||
x <= x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x <= x<!> -> {}
|
||||||
x >= x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x >= x<!> -> {}
|
||||||
x == x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x == x<!> -> {}
|
||||||
x != x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x != x<!> -> {}
|
||||||
x === x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x === x<!> -> {}
|
||||||
x !== x -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>x !== x<!> -> {}
|
||||||
}
|
}
|
||||||
// ok
|
// ok
|
||||||
when (x) {
|
when (x) {
|
||||||
@@ -88,8 +88,8 @@ fun testWithSubject_bad_1(x: A) {
|
|||||||
fun testWithSubject_bad_2(b: Boolean) {
|
fun testWithSubject_bad_2(b: Boolean) {
|
||||||
// bad
|
// bad
|
||||||
when (b) {
|
when (b) {
|
||||||
b && b -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>b && b<!> -> {}
|
||||||
b || b -> {}
|
<!CONFUSING_BRANCH_CONDITION_ERROR!>b || b<!> -> {}
|
||||||
}
|
}
|
||||||
// ok
|
// ok
|
||||||
when (b) {
|
when (b) {
|
||||||
@@ -159,18 +159,18 @@ fun testWithRange_ok(x: A, y: A?, any: Any, z: B) {
|
|||||||
fun testWithRange_bad_1(x: A) {
|
fun testWithRange_bad_1(x: A) {
|
||||||
// bad
|
// bad
|
||||||
when (x) {
|
when (x) {
|
||||||
in x in x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x in x<!> -> {}
|
||||||
in x !in x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x !in x<!> -> {}
|
||||||
in x is String -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x is String<!> -> {}
|
||||||
in x !is String -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x !is String<!> -> {}
|
||||||
in x < x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x < x<!> -> {}
|
||||||
in x > x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x > x<!> -> {}
|
||||||
in x <= x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x <= x<!> -> {}
|
||||||
in x >= x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x >= x<!> -> {}
|
||||||
in x == x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x == x<!> -> {}
|
||||||
in x != x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x != x<!> -> {}
|
||||||
in x === x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x === x<!> -> {}
|
||||||
in x !== x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x !== x<!> -> {}
|
||||||
}
|
}
|
||||||
// ok
|
// ok
|
||||||
when (x) {
|
when (x) {
|
||||||
@@ -192,8 +192,8 @@ fun testWithRange_bad_1(x: A) {
|
|||||||
fun testWithRange_bad_2(b: Boolean) {
|
fun testWithRange_bad_2(b: Boolean) {
|
||||||
// bad
|
// bad
|
||||||
when (b) {
|
when (b) {
|
||||||
in b && b -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>b && b<!> -> {}
|
||||||
in b || b -> {}
|
in <!CONFUSING_BRANCH_CONDITION_ERROR!>b || b<!> -> {}
|
||||||
}
|
}
|
||||||
// ok
|
// ok
|
||||||
when (b) {
|
when (b) {
|
||||||
|
|||||||
+28
-28
@@ -55,18 +55,18 @@ fun testWithSubject_ok(x: A, y: A?, any: Any, z: B) {
|
|||||||
fun testWithSubject_bad_1(x: A) {
|
fun testWithSubject_bad_1(x: A) {
|
||||||
// bad
|
// bad
|
||||||
when (x) {
|
when (x) {
|
||||||
x in x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x in x<!> -> {}
|
||||||
x !in x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x !in x<!> -> {}
|
||||||
x is String -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x is String<!> -> {}
|
||||||
x !is String -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x !is String<!> -> {}
|
||||||
x < x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x < x<!> -> {}
|
||||||
x > x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x > x<!> -> {}
|
||||||
x <= x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x <= x<!> -> {}
|
||||||
x >= x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x >= x<!> -> {}
|
||||||
x == x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x == x<!> -> {}
|
||||||
x != x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x != x<!> -> {}
|
||||||
x === x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x === x<!> -> {}
|
||||||
x !== x -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>x !== x<!> -> {}
|
||||||
}
|
}
|
||||||
// ok
|
// ok
|
||||||
when (x) {
|
when (x) {
|
||||||
@@ -88,8 +88,8 @@ fun testWithSubject_bad_1(x: A) {
|
|||||||
fun testWithSubject_bad_2(b: Boolean) {
|
fun testWithSubject_bad_2(b: Boolean) {
|
||||||
// bad
|
// bad
|
||||||
when (b) {
|
when (b) {
|
||||||
b && b -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>b && b<!> -> {}
|
||||||
b || b -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>b || b<!> -> {}
|
||||||
}
|
}
|
||||||
// ok
|
// ok
|
||||||
when (b) {
|
when (b) {
|
||||||
@@ -159,18 +159,18 @@ fun testWithRange_ok(x: A, y: A?, any: Any, z: B) {
|
|||||||
fun testWithRange_bad_1(x: A) {
|
fun testWithRange_bad_1(x: A) {
|
||||||
// bad
|
// bad
|
||||||
when (x) {
|
when (x) {
|
||||||
in x in x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x in x<!> -> {}
|
||||||
in x !in x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x !in x<!> -> {}
|
||||||
in x is String -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x is String<!> -> {}
|
||||||
in x !is String -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x !is String<!> -> {}
|
||||||
in x < x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x < x<!> -> {}
|
||||||
in x > x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x > x<!> -> {}
|
||||||
in x <= x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x <= x<!> -> {}
|
||||||
in x >= x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x >= x<!> -> {}
|
||||||
in x == x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x == x<!> -> {}
|
||||||
in x != x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x != x<!> -> {}
|
||||||
in x === x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x === x<!> -> {}
|
||||||
in x !== x -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x !== x<!> -> {}
|
||||||
}
|
}
|
||||||
// ok
|
// ok
|
||||||
when (x) {
|
when (x) {
|
||||||
@@ -192,8 +192,8 @@ fun testWithRange_bad_1(x: A) {
|
|||||||
fun testWithRange_bad_2(b: Boolean) {
|
fun testWithRange_bad_2(b: Boolean) {
|
||||||
// bad
|
// bad
|
||||||
when (b) {
|
when (b) {
|
||||||
in b && b -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>b && b<!> -> {}
|
||||||
in b || b -> {}
|
in <!CONFUSING_BRANCH_CONDITION_WARNING!>b || b<!> -> {}
|
||||||
}
|
}
|
||||||
// ok
|
// ok
|
||||||
when (b) {
|
when (b) {
|
||||||
|
|||||||
+2
-2
@@ -29,7 +29,7 @@ fun case_3(value_1: Boolean?): Int = <!NO_ELSE_IN_WHEN!>when<!>(value_1) { }
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 4
|
// TESTCASE NUMBER: 4
|
||||||
fun case_4(value_1: Boolean?): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
fun case_4(value_1: Boolean?): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
||||||
true && false && ((true || false)) || true && !!!false && !!!true -> ""
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||||
true && false && ((true || false)) || true && !!!false -> ""
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||||
null -> ""
|
null -> ""
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -48,6 +48,6 @@ fun case_5(value_1: Boolean): String {
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 6
|
// TESTCASE NUMBER: 6
|
||||||
fun case_6(value_1: Boolean): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
fun case_6(value_1: Boolean): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
||||||
true && false && ((true || false)) || true && !!!false && !!!true -> ""
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||||
true && false && ((true || false)) || true && !!!false -> ""
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -18,7 +18,7 @@ fun case_1(value_1: Boolean?): String = when (value_1) {
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 2
|
// TESTCASE NUMBER: 2
|
||||||
fun case_2(value_1: Boolean?): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
fun case_2(value_1: Boolean?): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
||||||
true && false && ((true || false)) || true && !!!false && !!!true -> ""
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||||
true && false && ((true || false)) || true && !!!false -> ""
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||||
null -> ""
|
null -> ""
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -17,6 +17,6 @@ fun case_1(value_1: Boolean): String = when (value_1) {
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 2
|
// TESTCASE NUMBER: 2
|
||||||
fun case_2(value_1: Boolean): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
fun case_2(value_1: Boolean): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
||||||
true && false && ((true || false)) || true && !!!false && !!!true -> ""
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||||
true && false && ((true || false)) || true && !!!false -> ""
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+6
-6
@@ -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?) {
|
fun case_5(value_1: Int, value_2: Int, value_3: Boolean?) {
|
||||||
when (value_1) {
|
when (value_1) {
|
||||||
1 -> when (value_3) {
|
1 -> when (value_3) {
|
||||||
value_2 > 1000 -> "1"
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 1000<!> -> "1"
|
||||||
value_2 > 100 -> "2"
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 100<!> -> "2"
|
||||||
else -> "3"
|
else -> "3"
|
||||||
}
|
}
|
||||||
2 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {
|
2 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {
|
||||||
value_2 > 1000 -> "1"
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 1000<!> -> "1"
|
||||||
value_2 > 100 -> "2"
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 100<!> -> "2"
|
||||||
}
|
}
|
||||||
3 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {}
|
3 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {}
|
||||||
4 -> 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
|
// TESTCASE NUMBER: 6
|
||||||
fun case_6(value_1: Int, value_2: Int, value_3: Boolean?) = when (value_1) {
|
fun case_6(value_1: Int, value_2: Int, value_3: Boolean?) = when (value_1) {
|
||||||
1 -> when (value_3) {
|
1 -> when (value_3) {
|
||||||
value_2 > 1000 -> 1
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 1000<!> -> 1
|
||||||
value_2 > 100 -> 2
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 100<!> -> 2
|
||||||
else -> 3
|
else -> 3
|
||||||
}
|
}
|
||||||
else -> when (value_3) {
|
else -> when (value_3) {
|
||||||
|
|||||||
Vendored
+4
-4
@@ -27,10 +27,10 @@ fun case_3(value_1: Boolean, value_2: Boolean, value_3: Long) {
|
|||||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
||||||
value_2 -> {}
|
value_2 -> {}
|
||||||
!value_2 -> {}
|
!value_2 -> {}
|
||||||
getBoolean() && value_2 -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>getBoolean() && value_2<!> -> {}
|
||||||
getChar() != 'a' -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>getChar() != 'a'<!> -> {}
|
||||||
getList() === getAny() -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>getList() === getAny()<!> -> {}
|
||||||
value_3 <= 11 -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_3 <= 11<!> -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-2
@@ -19,8 +19,8 @@ fun case_2(value_1: Number, value_2: Int) {
|
|||||||
// TESTCASE NUMBER: 3
|
// TESTCASE NUMBER: 3
|
||||||
fun case_3(value_1: Boolean, value_2: Boolean, value_3: Long) {
|
fun case_3(value_1: Boolean, value_2: Boolean, value_3: Long) {
|
||||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
||||||
value_2, !value_2, getBoolean() && value_2, getChar() != 'a' -> {}
|
value_2, !value_2, <!CONFUSING_BRANCH_CONDITION_WARNING!>getBoolean() && value_2<!>, <!CONFUSING_BRANCH_CONDITION_WARNING!>getChar() != 'a'<!> -> {}
|
||||||
getList() === getAny(), value_3 <= 11 -> {}
|
<!CONFUSING_BRANCH_CONDITION_WARNING!>getList() === getAny()<!>, <!CONFUSING_BRANCH_CONDITION_WARNING!>value_3 <= 11<!> -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user