diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt index b2bb8942295..2dce8e57356 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt @@ -25,6 +25,12 @@ fun main(args: Array) { alias("ReturnExpressionChecker") alias("BlockChecker") alias("AnnotationCallChecker") + alias("CheckNotNullCallChecker") + alias("ElvisExpressionChecker") + alias("GetClassCallChecker") + alias("SafeCallExpressionChecker") + alias("EqualityOperatorCallChecker") + alias("AnonymousFunctionAsExpressionChecker") } val declarationPackage = "org.jetbrains.kotlin.fir.analysis.checkers.declaration" diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt index af8684e342c..41a726b6ba4 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt @@ -31,6 +31,18 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() { get() = _blockCheckers override val annotationCallCheckers: Set get() = _annotationCallCheckers + override val checkNotNullCallCheckers: Set + get() = _checkNotNullCallCheckers + override val elvisExpressionCheckers: Set + get() = _elvisExpressionCheckers + override val getClassCallCheckers: Set + get() = _getClassCallCheckers + override val safeCallExpressionCheckers: Set + get() = _safeCallExpressionCheckers + override val equalityOperatorCallCheckers: Set + get() = _equalityOperatorCallCheckers + override val anonymousFunctionAsExpressionCheckers: Set + get() = _anonymousFunctionAsExpressionCheckers private val _basicExpressionCheckers: MutableSet = mutableSetOf() private val _qualifiedAccessCheckers: MutableSet = mutableSetOf() @@ -41,6 +53,12 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() { private val _returnExpressionCheckers: MutableSet = mutableSetOf() private val _blockCheckers: MutableSet = mutableSetOf() private val _annotationCallCheckers: MutableSet = mutableSetOf() + private val _checkNotNullCallCheckers: MutableSet = mutableSetOf() + private val _elvisExpressionCheckers: MutableSet = mutableSetOf() + private val _getClassCallCheckers: MutableSet = mutableSetOf() + private val _safeCallExpressionCheckers: MutableSet = mutableSetOf() + private val _equalityOperatorCallCheckers: MutableSet = mutableSetOf() + private val _anonymousFunctionAsExpressionCheckers: MutableSet = mutableSetOf() @CheckersComponentInternal internal fun register(checkers: ExpressionCheckers) { @@ -53,5 +71,11 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() { _returnExpressionCheckers += checkers.returnExpressionCheckers _blockCheckers += checkers.blockCheckers _annotationCallCheckers += checkers.annotationCallCheckers + _checkNotNullCallCheckers += checkers.checkNotNullCallCheckers + _elvisExpressionCheckers += checkers.elvisExpressionCheckers + _getClassCallCheckers += checkers.getClassCallCheckers + _safeCallExpressionCheckers += checkers.safeCallExpressionCheckers + _equalityOperatorCallCheckers += checkers.equalityOperatorCallCheckers + _anonymousFunctionAsExpressionCheckers += checkers.anonymousFunctionAsExpressionCheckers } } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt index b3ec5405907..342b8244464 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt @@ -26,6 +26,12 @@ abstract class ExpressionCheckers { open val returnExpressionCheckers: Set = emptySet() open val blockCheckers: Set = emptySet() open val annotationCallCheckers: Set = emptySet() + open val checkNotNullCallCheckers: Set = emptySet() + open val elvisExpressionCheckers: Set = emptySet() + open val getClassCallCheckers: Set = emptySet() + open val safeCallExpressionCheckers: Set = emptySet() + open val equalityOperatorCallCheckers: Set = emptySet() + open val anonymousFunctionAsExpressionCheckers: Set = emptySet() @CheckersComponentInternal internal val allBasicExpressionCheckers: Set get() = basicExpressionCheckers @CheckersComponentInternal internal val allQualifiedAccessCheckers: Set get() = qualifiedAccessCheckers + basicExpressionCheckers @@ -36,4 +42,10 @@ abstract class ExpressionCheckers { @CheckersComponentInternal internal val allReturnExpressionCheckers: Set get() = returnExpressionCheckers + basicExpressionCheckers @CheckersComponentInternal internal val allBlockCheckers: Set get() = blockCheckers + basicExpressionCheckers @CheckersComponentInternal internal val allAnnotationCallCheckers: Set get() = annotationCallCheckers + basicExpressionCheckers + @CheckersComponentInternal internal val allCheckNotNullCallCheckers: Set get() = checkNotNullCallCheckers + basicExpressionCheckers + @CheckersComponentInternal internal val allElvisExpressionCheckers: Set get() = elvisExpressionCheckers + basicExpressionCheckers + @CheckersComponentInternal internal val allGetClassCallCheckers: Set get() = getClassCallCheckers + basicExpressionCheckers + @CheckersComponentInternal internal val allSafeCallExpressionCheckers: Set get() = safeCallExpressionCheckers + basicExpressionCheckers + @CheckersComponentInternal internal val allEqualityOperatorCallCheckers: Set get() = equalityOperatorCallCheckers + basicExpressionCheckers + @CheckersComponentInternal internal val allAnonymousFunctionAsExpressionCheckers: Set get() = anonymousFunctionAsExpressionCheckers + basicExpressionCheckers } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt index 36bf7a857bf..159f826cb87 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt @@ -10,11 +10,17 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression * DO NOT MODIFY IT MANUALLY */ +import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirBlock +import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall +import org.jetbrains.kotlin.fir.expressions.FirElvisExpression +import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.fir.expressions.FirGetClassCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirReturnExpression +import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.FirTryExpression import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment @@ -29,3 +35,9 @@ typealias FirWhenExpressionChecker = FirExpressionChecker typealias FirReturnExpressionChecker = FirExpressionChecker typealias FirBlockChecker = FirExpressionChecker typealias FirAnnotationCallChecker = FirExpressionChecker +typealias FirCheckNotNullCallChecker = FirExpressionChecker +typealias FirElvisExpressionChecker = FirExpressionChecker +typealias FirGetClassCallChecker = FirExpressionChecker +typealias FirSafeCallExpressionChecker = FirExpressionChecker +typealias FirEqualityOperatorCallChecker = FirExpressionChecker +typealias FirAnonymousFunctionAsExpressionChecker = FirExpressionChecker diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnonymousFunctionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnonymousFunctionChecker.kt index 75481e69a4a..3771acb1afe 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnonymousFunctionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnonymousFunctionChecker.kt @@ -8,14 +8,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.* import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction -import org.jetbrains.kotlin.fir.expressions.FirStatement -import org.jetbrains.kotlin.fir.toFirLightSourceElement -object FirAnonymousFunctionChecker : FirExpressionChecker() { - override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { - if (expression !is FirAnonymousFunction) { - return - } +object FirAnonymousFunctionChecker : FirAnonymousFunctionAsExpressionChecker() { + override fun check(expression: FirAnonymousFunction, context: CheckerContext, reporter: DiagnosticReporter) { for (valueParameter in expression.valueParameters) { val source = valueParameter.source ?: continue if (valueParameter.defaultValue != null) { @@ -30,7 +25,7 @@ object FirAnonymousFunctionChecker : FirExpressionChecker() { } private fun checkTypeParameters( - expression: FirStatement, + expression: FirAnonymousFunction, reporter: DiagnosticReporter, context: CheckerContext ) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirGetClassCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirClassLiteralChecker.kt similarity index 96% rename from compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirGetClassCallChecker.kt rename to compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirClassLiteralChecker.kt index d654b6b3fa0..9cd285715d7 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirGetClassCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirClassLiteralChecker.kt @@ -21,9 +21,8 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.lexer.KtTokens.QUEST -object FirGetClassCallChecker : FirBasicExpressionChecker() { - override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { - if (expression !is FirGetClassCall) return +object FirClassLiteralChecker : FirGetClassCallChecker() { + override fun check(expression: FirGetClassCall, context: CheckerContext, reporter: DiagnosticReporter) { val source = expression.source ?: return if (source.kind is FirFakeSourceElementKind) return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCheckNotNullCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNotNullAssertionChecker.kt similarity index 87% rename from compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCheckNotNullCallChecker.kt rename to compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNotNullAssertionChecker.kt index e4838f14639..022c767c9a3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCheckNotNullCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNotNullAssertionChecker.kt @@ -13,14 +13,11 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier -import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.types.* -object FirCheckNotNullCallChecker : FirBasicExpressionChecker() { - override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { - if (expression !is FirCheckNotNullCall) return - +object FirNotNullAssertionChecker : FirCheckNotNullCallChecker() { + override fun check(expression: FirCheckNotNullCall, context: CheckerContext, reporter: DiagnosticReporter) { val argument = expression.argumentList.arguments.singleOrNull() ?: return if (argument is FirAnonymousFunction && argument.isLambda) { reporter.reportOn(expression.source, FirErrors.NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION, context) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSafeCallExpressionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnnecessarySafeCallChecker.kt similarity index 80% rename from compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSafeCallExpressionChecker.kt rename to compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnnecessarySafeCallChecker.kt index 35ad6db06a5..2c0f1c9621c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSafeCallExpressionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnnecessarySafeCallChecker.kt @@ -10,16 +10,13 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression -import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.types.canBeNull import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.isUnit -object FirSafeCallExpressionChecker : FirBasicExpressionChecker() { - override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { - if (expression !is FirSafeCallExpression) return - +object FirUnnecessarySafeCallChecker : FirSafeCallExpressionChecker() { + override fun check(expression: FirSafeCallExpression, context: CheckerContext, reporter: DiagnosticReporter) { val receiverType = expression.receiver.typeRef.coneType.fullyExpandedType(context.session) if (receiverType.isUnit) { reporter.reportOn(expression.source, FirErrors.UNEXPECTED_SAFE_CALL, context) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirElvisExpressionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUselessElvisChecker.kt similarity index 84% rename from compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirElvisExpressionChecker.kt rename to compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUselessElvisChecker.kt index f2ac1f86467..48e8e4b1e16 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirElvisExpressionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUselessElvisChecker.kt @@ -10,15 +10,13 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.expressions.FirElvisExpression -import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType import org.jetbrains.kotlin.fir.types.canBeNull import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.isNullLiteral -object FirElvisExpressionChecker : FirBasicExpressionChecker() { - override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { - if (expression !is FirElvisExpression) return +object FirUselessElvisChecker : FirElvisExpressionChecker() { + override fun check(expression: FirElvisExpression, context: CheckerContext, reporter: DiagnosticReporter) { // If the overall expression is not resolved/completed, the corresponding error will be reported separately. // See [FirControlFlowStatementsResolveTransformer#transformElvisExpression], // where an error type is recorded as the expression's return type. diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/EmptyRangeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/EmptyRangeChecker.kt index 16b2894d716..94295409437 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/EmptyRangeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/EmptyRangeChecker.kt @@ -7,19 +7,17 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended import org.jetbrains.kotlin.fir.FirFakeSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker +import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.expressions.FirFunctionCall -import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall -object EmptyRangeChecker : FirBasicExpressionChecker() { - override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { +object EmptyRangeChecker : FirFunctionCallChecker() { + override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) { if (expression.source is FirFakeSourceElement<*>) return - if (expression !is FirFunctionCall) return val left = expression.rangeLeft ?: return val right = expression.rangeRight ?: return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantReturnUnitTypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantReturnUnitTypeChecker.kt index 3590da3ef4c..76cf8e26bac 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantReturnUnitTypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantReturnUnitTypeChecker.kt @@ -7,18 +7,16 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirSimpleFunctionChecker import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn -import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.types.isUnit -object RedundantReturnUnitType : FirBasicDeclarationChecker() { - override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { - if (declaration !is FirSimpleFunction) return +object RedundantReturnUnitType : FirSimpleFunctionChecker() { + override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration.body is FirSingleExpressionBlock) return val returnType = declaration.returnTypeRef if (returnType.source == null) return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSingleExpressionStringTemplateChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSingleExpressionStringTemplateChecker.kt index 997dc660cab..4267dc5a0de 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSingleExpressionStringTemplateChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSingleExpressionStringTemplateChecker.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirLightSourceElement import org.jetbrains.kotlin.fir.FirPsiSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker +import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker import org.jetbrains.kotlin.fir.analysis.checkers.getChildren import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE @@ -25,12 +25,10 @@ import org.jetbrains.kotlin.fir.types.classId import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.psi.KtStringTemplateExpression -object RedundantSingleExpressionStringTemplateChecker : FirBasicExpressionChecker() { - override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { +object RedundantSingleExpressionStringTemplateChecker : FirFunctionCallChecker() { + override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) { if (expression.source?.kind != FirFakeSourceElementKind.GeneratedToStringCallOnTemplateEntry) return - if (expression !is FirFunctionCall) return - if ( - expression.explicitReceiver?.typeRef?.coneType?.classId == StandardClassIds.String + if (expression.explicitReceiver?.typeRef?.coneType?.classId == StandardClassIds.String && expression.stringParentChildrenCount() == 1 // there is no more children in original string template ) { reporter.reportOn(expression.source, REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE, context) @@ -39,12 +37,8 @@ object RedundantSingleExpressionStringTemplateChecker : FirBasicExpressionChecke private fun FirStatement.stringParentChildrenCount(): Int? { return when (val source = source) { - is FirPsiSourceElement<*> -> { - source.psi.stringParentChildrenCount() - } - is FirLightSourceElement -> { - source.lighterASTNode.stringParentChildrenCount(source) - } + is FirPsiSourceElement<*> -> source.psi.stringParentChildrenCount() + is FirLightSourceElement -> source.lighterASTNode.stringParentChildrenCount(source) else -> null } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt index ae2b848c335..26f12b20cad 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt @@ -22,7 +22,7 @@ class ExpressionCheckersDiagnosticComponent( ) : AbstractDiagnosticCollectorComponent(collector) { override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) { - checkers.allBasicExpressionCheckers.check(anonymousFunction, data, reporter) + checkers.allAnonymousFunctionAsExpressionCheckers.check(anonymousFunction, data, reporter) } override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: CheckerContext) { @@ -74,15 +74,15 @@ class ExpressionCheckersDiagnosticComponent( } override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: CheckerContext) { - checkers.allBasicExpressionCheckers.check(checkNotNullCall, data, reporter) + checkers.allCheckNotNullCallCheckers.check(checkNotNullCall, data, reporter) } override fun visitElvisExpression(elvisExpression: FirElvisExpression, data: CheckerContext) { - checkers.allBasicExpressionCheckers.check(elvisExpression, data, reporter) + checkers.allElvisExpressionCheckers.check(elvisExpression, data, reporter) } override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: CheckerContext) { - checkers.basicExpressionCheckers.check(safeCallExpression, data, reporter) + checkers.allSafeCallExpressionCheckers.check(safeCallExpression, data, reporter) } override fun visitTryExpression(tryExpression: FirTryExpression, data: CheckerContext) { @@ -94,11 +94,11 @@ class ExpressionCheckersDiagnosticComponent( } override fun visitGetClassCall(getClassCall: FirGetClassCall, data: CheckerContext) { - checkers.allBasicExpressionCheckers.check(getClassCall, data, reporter) + checkers.allGetClassCallCheckers.check(getClassCall, data, reporter) } override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: CheckerContext) { - checkers.allBasicExpressionCheckers.check(equalityOperatorCall, data, reporter) + checkers.allEqualityOperatorCallCheckers.check(equalityOperatorCall, data, reporter) } override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) { diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt index 601fea04a1c..e387ec98150 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt @@ -15,11 +15,6 @@ object CommonExpressionCheckers : ExpressionCheckers() { override val basicExpressionCheckers: Set get() = setOf( - FirAnonymousFunctionChecker, - FirCheckNotNullCallChecker, - FirElvisExpressionChecker, - FirGetClassCallChecker, - FirSafeCallExpressionChecker, ) override val qualifiedAccessCheckers: Set @@ -71,4 +66,29 @@ object CommonExpressionCheckers : ExpressionCheckers() { get() = setOf( FirForLoopChecker ) + + override val checkNotNullCallCheckers: Set + get() = setOf( + FirNotNullAssertionChecker, + ) + + override val elvisExpressionCheckers: Set + get() = setOf( + FirUselessElvisChecker, + ) + + override val getClassCallCheckers: Set + get() = setOf( + FirClassLiteralChecker, + ) + + override val safeCallExpressionCheckers: Set + get() = setOf( + FirUnnecessarySafeCallChecker, + ) + + override val anonymousFunctionAsExpressionCheckers: Set + get() = setOf( + FirAnonymousFunctionChecker, + ) } diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/ExtendedDeclarationCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/ExtendedDeclarationCheckers.kt index 171e02b4a76..e3d478768ef 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/ExtendedDeclarationCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/ExtendedDeclarationCheckers.kt @@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.checkers import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDeclarationChecker -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.* import org.jetbrains.kotlin.fir.analysis.checkers.extended.* import org.jetbrains.kotlin.fir.declarations.FirDeclaration @@ -18,7 +15,6 @@ object ExtendedDeclarationCheckers : DeclarationCheckers() { override val basicDeclarationCheckers: Set get() = setOf( RedundantVisibilityModifierChecker, - RedundantReturnUnitType, ) override val memberDeclarationCheckers: Set @@ -37,4 +33,9 @@ object ExtendedDeclarationCheckers : DeclarationCheckers() { get() = setOf( UnusedChecker, ) + + override val simpleFunctionCheckers: Set + get() = setOf( + RedundantReturnUnitType, + ) } diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/ExtendedExpressionCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/ExtendedExpressionCheckers.kt index ce9fb134355..d82347c148f 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/ExtendedExpressionCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/ExtendedExpressionCheckers.kt @@ -5,18 +5,13 @@ package org.jetbrains.kotlin.fir.checkers -import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers -import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker -import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessChecker -import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirVariableAssignmentChecker +import org.jetbrains.kotlin.fir.analysis.checkers.expression.* import org.jetbrains.kotlin.fir.analysis.checkers.extended.* object ExtendedExpressionCheckers : ExpressionCheckers() { override val basicExpressionCheckers: Set get() = setOf( ArrayEqualityCanBeReplacedWithEquals, - RedundantSingleExpressionStringTemplateChecker, - EmptyRangeChecker, ) override val variableAssignmentCheckers: Set @@ -29,4 +24,10 @@ object ExtendedExpressionCheckers : ExpressionCheckers() { RedundantCallOfConversionMethod, UselessCallOnNotNullChecker, ) + + override val functionCallCheckers: Set + get() = setOf( + EmptyRangeChecker, + RedundantSingleExpressionStringTemplateChecker, + ) }