FIR: use more precise checkers when possible
This commit is contained in:
+6
@@ -25,6 +25,12 @@ fun main(args: Array<String>) {
|
|||||||
alias<FirReturnExpression>("ReturnExpressionChecker")
|
alias<FirReturnExpression>("ReturnExpressionChecker")
|
||||||
alias<FirBlock>("BlockChecker")
|
alias<FirBlock>("BlockChecker")
|
||||||
alias<FirAnnotationCall>("AnnotationCallChecker")
|
alias<FirAnnotationCall>("AnnotationCallChecker")
|
||||||
|
alias<FirCheckNotNullCall>("CheckNotNullCallChecker")
|
||||||
|
alias<FirElvisExpression>("ElvisExpressionChecker")
|
||||||
|
alias<FirGetClassCall>("GetClassCallChecker")
|
||||||
|
alias<FirSafeCallExpression>("SafeCallExpressionChecker")
|
||||||
|
alias<FirEqualityOperatorCall>("EqualityOperatorCallChecker")
|
||||||
|
alias<FirAnonymousFunction>("AnonymousFunctionAsExpressionChecker")
|
||||||
}
|
}
|
||||||
|
|
||||||
val declarationPackage = "org.jetbrains.kotlin.fir.analysis.checkers.declaration"
|
val declarationPackage = "org.jetbrains.kotlin.fir.analysis.checkers.declaration"
|
||||||
|
|||||||
+24
@@ -31,6 +31,18 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() {
|
|||||||
get() = _blockCheckers
|
get() = _blockCheckers
|
||||||
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
|
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
|
||||||
get() = _annotationCallCheckers
|
get() = _annotationCallCheckers
|
||||||
|
override val checkNotNullCallCheckers: Set<FirCheckNotNullCallChecker>
|
||||||
|
get() = _checkNotNullCallCheckers
|
||||||
|
override val elvisExpressionCheckers: Set<FirElvisExpressionChecker>
|
||||||
|
get() = _elvisExpressionCheckers
|
||||||
|
override val getClassCallCheckers: Set<FirGetClassCallChecker>
|
||||||
|
get() = _getClassCallCheckers
|
||||||
|
override val safeCallExpressionCheckers: Set<FirSafeCallExpressionChecker>
|
||||||
|
get() = _safeCallExpressionCheckers
|
||||||
|
override val equalityOperatorCallCheckers: Set<FirEqualityOperatorCallChecker>
|
||||||
|
get() = _equalityOperatorCallCheckers
|
||||||
|
override val anonymousFunctionAsExpressionCheckers: Set<FirAnonymousFunctionAsExpressionChecker>
|
||||||
|
get() = _anonymousFunctionAsExpressionCheckers
|
||||||
|
|
||||||
private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf()
|
private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf()
|
||||||
private val _qualifiedAccessCheckers: MutableSet<FirQualifiedAccessChecker> = mutableSetOf()
|
private val _qualifiedAccessCheckers: MutableSet<FirQualifiedAccessChecker> = mutableSetOf()
|
||||||
@@ -41,6 +53,12 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() {
|
|||||||
private val _returnExpressionCheckers: MutableSet<FirReturnExpressionChecker> = mutableSetOf()
|
private val _returnExpressionCheckers: MutableSet<FirReturnExpressionChecker> = mutableSetOf()
|
||||||
private val _blockCheckers: MutableSet<FirBlockChecker> = mutableSetOf()
|
private val _blockCheckers: MutableSet<FirBlockChecker> = mutableSetOf()
|
||||||
private val _annotationCallCheckers: MutableSet<FirAnnotationCallChecker> = mutableSetOf()
|
private val _annotationCallCheckers: MutableSet<FirAnnotationCallChecker> = mutableSetOf()
|
||||||
|
private val _checkNotNullCallCheckers: MutableSet<FirCheckNotNullCallChecker> = mutableSetOf()
|
||||||
|
private val _elvisExpressionCheckers: MutableSet<FirElvisExpressionChecker> = mutableSetOf()
|
||||||
|
private val _getClassCallCheckers: MutableSet<FirGetClassCallChecker> = mutableSetOf()
|
||||||
|
private val _safeCallExpressionCheckers: MutableSet<FirSafeCallExpressionChecker> = mutableSetOf()
|
||||||
|
private val _equalityOperatorCallCheckers: MutableSet<FirEqualityOperatorCallChecker> = mutableSetOf()
|
||||||
|
private val _anonymousFunctionAsExpressionCheckers: MutableSet<FirAnonymousFunctionAsExpressionChecker> = mutableSetOf()
|
||||||
|
|
||||||
@CheckersComponentInternal
|
@CheckersComponentInternal
|
||||||
internal fun register(checkers: ExpressionCheckers) {
|
internal fun register(checkers: ExpressionCheckers) {
|
||||||
@@ -53,5 +71,11 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() {
|
|||||||
_returnExpressionCheckers += checkers.returnExpressionCheckers
|
_returnExpressionCheckers += checkers.returnExpressionCheckers
|
||||||
_blockCheckers += checkers.blockCheckers
|
_blockCheckers += checkers.blockCheckers
|
||||||
_annotationCallCheckers += checkers.annotationCallCheckers
|
_annotationCallCheckers += checkers.annotationCallCheckers
|
||||||
|
_checkNotNullCallCheckers += checkers.checkNotNullCallCheckers
|
||||||
|
_elvisExpressionCheckers += checkers.elvisExpressionCheckers
|
||||||
|
_getClassCallCheckers += checkers.getClassCallCheckers
|
||||||
|
_safeCallExpressionCheckers += checkers.safeCallExpressionCheckers
|
||||||
|
_equalityOperatorCallCheckers += checkers.equalityOperatorCallCheckers
|
||||||
|
_anonymousFunctionAsExpressionCheckers += checkers.anonymousFunctionAsExpressionCheckers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -26,6 +26,12 @@ abstract class ExpressionCheckers {
|
|||||||
open val returnExpressionCheckers: Set<FirReturnExpressionChecker> = emptySet()
|
open val returnExpressionCheckers: Set<FirReturnExpressionChecker> = emptySet()
|
||||||
open val blockCheckers: Set<FirBlockChecker> = emptySet()
|
open val blockCheckers: Set<FirBlockChecker> = emptySet()
|
||||||
open val annotationCallCheckers: Set<FirAnnotationCallChecker> = emptySet()
|
open val annotationCallCheckers: Set<FirAnnotationCallChecker> = emptySet()
|
||||||
|
open val checkNotNullCallCheckers: Set<FirCheckNotNullCallChecker> = emptySet()
|
||||||
|
open val elvisExpressionCheckers: Set<FirElvisExpressionChecker> = emptySet()
|
||||||
|
open val getClassCallCheckers: Set<FirGetClassCallChecker> = emptySet()
|
||||||
|
open val safeCallExpressionCheckers: Set<FirSafeCallExpressionChecker> = emptySet()
|
||||||
|
open val equalityOperatorCallCheckers: Set<FirEqualityOperatorCallChecker> = emptySet()
|
||||||
|
open val anonymousFunctionAsExpressionCheckers: Set<FirAnonymousFunctionAsExpressionChecker> = emptySet()
|
||||||
|
|
||||||
@CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> get() = basicExpressionCheckers
|
@CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> get() = basicExpressionCheckers
|
||||||
@CheckersComponentInternal internal val allQualifiedAccessCheckers: Set<FirQualifiedAccessChecker> get() = qualifiedAccessCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allQualifiedAccessCheckers: Set<FirQualifiedAccessChecker> get() = qualifiedAccessCheckers + basicExpressionCheckers
|
||||||
@@ -36,4 +42,10 @@ abstract class ExpressionCheckers {
|
|||||||
@CheckersComponentInternal internal val allReturnExpressionCheckers: Set<FirReturnExpressionChecker> get() = returnExpressionCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allReturnExpressionCheckers: Set<FirReturnExpressionChecker> get() = returnExpressionCheckers + basicExpressionCheckers
|
||||||
@CheckersComponentInternal internal val allBlockCheckers: Set<FirBlockChecker> get() = blockCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allBlockCheckers: Set<FirBlockChecker> get() = blockCheckers + basicExpressionCheckers
|
||||||
@CheckersComponentInternal internal val allAnnotationCallCheckers: Set<FirAnnotationCallChecker> get() = annotationCallCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allAnnotationCallCheckers: Set<FirAnnotationCallChecker> get() = annotationCallCheckers + basicExpressionCheckers
|
||||||
|
@CheckersComponentInternal internal val allCheckNotNullCallCheckers: Set<FirCheckNotNullCallChecker> get() = checkNotNullCallCheckers + basicExpressionCheckers
|
||||||
|
@CheckersComponentInternal internal val allElvisExpressionCheckers: Set<FirElvisExpressionChecker> get() = elvisExpressionCheckers + basicExpressionCheckers
|
||||||
|
@CheckersComponentInternal internal val allGetClassCallCheckers: Set<FirGetClassCallChecker> get() = getClassCallCheckers + basicExpressionCheckers
|
||||||
|
@CheckersComponentInternal internal val allSafeCallExpressionCheckers: Set<FirSafeCallExpressionChecker> get() = safeCallExpressionCheckers + basicExpressionCheckers
|
||||||
|
@CheckersComponentInternal internal val allEqualityOperatorCallCheckers: Set<FirEqualityOperatorCallChecker> get() = equalityOperatorCallCheckers + basicExpressionCheckers
|
||||||
|
@CheckersComponentInternal internal val allAnonymousFunctionAsExpressionCheckers: Set<FirAnonymousFunctionAsExpressionChecker> get() = anonymousFunctionAsExpressionCheckers + basicExpressionCheckers
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -10,11 +10,17 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
|||||||
* DO NOT MODIFY IT MANUALLY
|
* 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.FirAnnotationCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
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.FirFunctionCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
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.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirTryExpression
|
import org.jetbrains.kotlin.fir.expressions.FirTryExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||||
@@ -29,3 +35,9 @@ typealias FirWhenExpressionChecker = FirExpressionChecker<FirWhenExpression>
|
|||||||
typealias FirReturnExpressionChecker = FirExpressionChecker<FirReturnExpression>
|
typealias FirReturnExpressionChecker = FirExpressionChecker<FirReturnExpression>
|
||||||
typealias FirBlockChecker = FirExpressionChecker<FirBlock>
|
typealias FirBlockChecker = FirExpressionChecker<FirBlock>
|
||||||
typealias FirAnnotationCallChecker = FirExpressionChecker<FirAnnotationCall>
|
typealias FirAnnotationCallChecker = FirExpressionChecker<FirAnnotationCall>
|
||||||
|
typealias FirCheckNotNullCallChecker = FirExpressionChecker<FirCheckNotNullCall>
|
||||||
|
typealias FirElvisExpressionChecker = FirExpressionChecker<FirElvisExpression>
|
||||||
|
typealias FirGetClassCallChecker = FirExpressionChecker<FirGetClassCall>
|
||||||
|
typealias FirSafeCallExpressionChecker = FirExpressionChecker<FirSafeCallExpression>
|
||||||
|
typealias FirEqualityOperatorCallChecker = FirExpressionChecker<FirEqualityOperatorCall>
|
||||||
|
typealias FirAnonymousFunctionAsExpressionChecker = FirExpressionChecker<FirAnonymousFunction>
|
||||||
|
|||||||
+3
-8
@@ -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.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
|
||||||
import org.jetbrains.kotlin.fir.toFirLightSourceElement
|
|
||||||
|
|
||||||
object FirAnonymousFunctionChecker : FirExpressionChecker<FirStatement>() {
|
object FirAnonymousFunctionChecker : FirAnonymousFunctionAsExpressionChecker() {
|
||||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirAnonymousFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (expression !is FirAnonymousFunction) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for (valueParameter in expression.valueParameters) {
|
for (valueParameter in expression.valueParameters) {
|
||||||
val source = valueParameter.source ?: continue
|
val source = valueParameter.source ?: continue
|
||||||
if (valueParameter.defaultValue != null) {
|
if (valueParameter.defaultValue != null) {
|
||||||
@@ -30,7 +25,7 @@ object FirAnonymousFunctionChecker : FirExpressionChecker<FirStatement>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkTypeParameters(
|
private fun checkTypeParameters(
|
||||||
expression: FirStatement,
|
expression: FirAnonymousFunction,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
context: CheckerContext
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
|
|||||||
+2
-3
@@ -21,9 +21,8 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
|||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens.QUEST
|
import org.jetbrains.kotlin.lexer.KtTokens.QUEST
|
||||||
|
|
||||||
object FirGetClassCallChecker : FirBasicExpressionChecker() {
|
object FirClassLiteralChecker : FirGetClassCallChecker() {
|
||||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirGetClassCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (expression !is FirGetClassCall) return
|
|
||||||
val source = expression.source ?: return
|
val source = expression.source ?: return
|
||||||
if (source.kind is FirFakeSourceElementKind) return
|
if (source.kind is FirFakeSourceElementKind) return
|
||||||
|
|
||||||
+2
-5
@@ -13,14 +13,11 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall
|
import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
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.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
|
||||||
object FirCheckNotNullCallChecker : FirBasicExpressionChecker() {
|
object FirNotNullAssertionChecker : FirCheckNotNullCallChecker() {
|
||||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirCheckNotNullCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (expression !is FirCheckNotNullCall) return
|
|
||||||
|
|
||||||
val argument = expression.argumentList.arguments.singleOrNull() ?: return
|
val argument = expression.argumentList.arguments.singleOrNull() ?: return
|
||||||
if (argument is FirAnonymousFunction && argument.isLambda) {
|
if (argument is FirAnonymousFunction && argument.isLambda) {
|
||||||
reporter.reportOn(expression.source, FirErrors.NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION, context)
|
reporter.reportOn(expression.source, FirErrors.NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION, context)
|
||||||
+2
-5
@@ -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.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
|
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.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.types.canBeNull
|
import org.jetbrains.kotlin.fir.types.canBeNull
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.types.isUnit
|
import org.jetbrains.kotlin.fir.types.isUnit
|
||||||
|
|
||||||
object FirSafeCallExpressionChecker : FirBasicExpressionChecker() {
|
object FirUnnecessarySafeCallChecker : FirSafeCallExpressionChecker() {
|
||||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirSafeCallExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (expression !is FirSafeCallExpression) return
|
|
||||||
|
|
||||||
val receiverType = expression.receiver.typeRef.coneType.fullyExpandedType(context.session)
|
val receiverType = expression.receiver.typeRef.coneType.fullyExpandedType(context.session)
|
||||||
if (receiverType.isUnit) {
|
if (receiverType.isUnit) {
|
||||||
reporter.reportOn(expression.source, FirErrors.UNEXPECTED_SAFE_CALL, context)
|
reporter.reportOn(expression.source, FirErrors.UNEXPECTED_SAFE_CALL, context)
|
||||||
+2
-4
@@ -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.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirElvisExpression
|
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.ConeKotlinErrorType
|
||||||
import org.jetbrains.kotlin.fir.types.canBeNull
|
import org.jetbrains.kotlin.fir.types.canBeNull
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.types.isNullLiteral
|
import org.jetbrains.kotlin.fir.types.isNullLiteral
|
||||||
|
|
||||||
object FirElvisExpressionChecker : FirBasicExpressionChecker() {
|
object FirUselessElvisChecker : FirElvisExpressionChecker() {
|
||||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirElvisExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (expression !is FirElvisExpression) return
|
|
||||||
// If the overall expression is not resolved/completed, the corresponding error will be reported separately.
|
// If the overall expression is not resolved/completed, the corresponding error will be reported separately.
|
||||||
// See [FirControlFlowStatementsResolveTransformer#transformElvisExpression],
|
// See [FirControlFlowStatementsResolveTransformer#transformElvisExpression],
|
||||||
// where an error type is recorded as the expression's return type.
|
// where an error type is recorded as the expression's return type.
|
||||||
+3
-5
@@ -7,19 +7,17 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElement
|
import org.jetbrains.kotlin.fir.FirFakeSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
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.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
|
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
|
||||||
|
|
||||||
object EmptyRangeChecker : FirBasicExpressionChecker() {
|
object EmptyRangeChecker : FirFunctionCallChecker() {
|
||||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (expression.source is FirFakeSourceElement<*>) return
|
if (expression.source is FirFakeSourceElement<*>) return
|
||||||
if (expression !is FirFunctionCall) return
|
|
||||||
val left = expression.rangeLeft ?: return
|
val left = expression.rangeLeft ?: return
|
||||||
val right = expression.rangeRight ?: return
|
val right = expression.rangeRight ?: return
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -7,18 +7,16 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
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.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
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.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
||||||
import org.jetbrains.kotlin.fir.types.isUnit
|
import org.jetbrains.kotlin.fir.types.isUnit
|
||||||
|
|
||||||
object RedundantReturnUnitType : FirBasicDeclarationChecker() {
|
object RedundantReturnUnitType : FirSimpleFunctionChecker() {
|
||||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (declaration !is FirSimpleFunction) return
|
|
||||||
if (declaration.body is FirSingleExpressionBlock) return
|
if (declaration.body is FirSingleExpressionBlock) return
|
||||||
val returnType = declaration.returnTypeRef
|
val returnType = declaration.returnTypeRef
|
||||||
if (returnType.source == null) return
|
if (returnType.source == null) return
|
||||||
|
|||||||
+6
-12
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
|||||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
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.checkers.getChildren
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE
|
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.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
||||||
|
|
||||||
object RedundantSingleExpressionStringTemplateChecker : FirBasicExpressionChecker() {
|
object RedundantSingleExpressionStringTemplateChecker : FirFunctionCallChecker() {
|
||||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (expression.source?.kind != FirFakeSourceElementKind.GeneratedToStringCallOnTemplateEntry) return
|
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
|
&& expression.stringParentChildrenCount() == 1 // there is no more children in original string template
|
||||||
) {
|
) {
|
||||||
reporter.reportOn(expression.source, REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE, context)
|
reporter.reportOn(expression.source, REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE, context)
|
||||||
@@ -39,12 +37,8 @@ object RedundantSingleExpressionStringTemplateChecker : FirBasicExpressionChecke
|
|||||||
|
|
||||||
private fun FirStatement.stringParentChildrenCount(): Int? {
|
private fun FirStatement.stringParentChildrenCount(): Int? {
|
||||||
return when (val source = source) {
|
return when (val source = source) {
|
||||||
is FirPsiSourceElement<*> -> {
|
is FirPsiSourceElement<*> -> source.psi.stringParentChildrenCount()
|
||||||
source.psi.stringParentChildrenCount()
|
is FirLightSourceElement -> source.lighterASTNode.stringParentChildrenCount(source)
|
||||||
}
|
|
||||||
is FirLightSourceElement -> {
|
|
||||||
source.lighterASTNode.stringParentChildrenCount(source)
|
|
||||||
}
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -22,7 +22,7 @@ class ExpressionCheckersDiagnosticComponent(
|
|||||||
) : AbstractDiagnosticCollectorComponent(collector) {
|
) : AbstractDiagnosticCollectorComponent(collector) {
|
||||||
|
|
||||||
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) {
|
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) {
|
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: CheckerContext) {
|
||||||
@@ -74,15 +74,15 @@ class ExpressionCheckersDiagnosticComponent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: CheckerContext) {
|
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) {
|
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) {
|
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) {
|
override fun visitTryExpression(tryExpression: FirTryExpression, data: CheckerContext) {
|
||||||
@@ -94,11 +94,11 @@ class ExpressionCheckersDiagnosticComponent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitGetClassCall(getClassCall: FirGetClassCall, data: CheckerContext) {
|
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) {
|
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) {
|
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) {
|
||||||
|
|||||||
+25
-5
@@ -15,11 +15,6 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
|
|
||||||
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirAnonymousFunctionChecker,
|
|
||||||
FirCheckNotNullCallChecker,
|
|
||||||
FirElvisExpressionChecker,
|
|
||||||
FirGetClassCallChecker,
|
|
||||||
FirSafeCallExpressionChecker,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
|
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
|
||||||
@@ -71,4 +66,29 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirForLoopChecker
|
FirForLoopChecker
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val checkNotNullCallCheckers: Set<FirCheckNotNullCallChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirNotNullAssertionChecker,
|
||||||
|
)
|
||||||
|
|
||||||
|
override val elvisExpressionCheckers: Set<FirElvisExpressionChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirUselessElvisChecker,
|
||||||
|
)
|
||||||
|
|
||||||
|
override val getClassCallCheckers: Set<FirGetClassCallChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirClassLiteralChecker,
|
||||||
|
)
|
||||||
|
|
||||||
|
override val safeCallExpressionCheckers: Set<FirSafeCallExpressionChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirUnnecessarySafeCallChecker,
|
||||||
|
)
|
||||||
|
|
||||||
|
override val anonymousFunctionAsExpressionCheckers: Set<FirAnonymousFunctionAsExpressionChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirAnonymousFunctionChecker,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.checkers
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
|
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
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.*
|
||||||
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.extended.*
|
import org.jetbrains.kotlin.fir.analysis.checkers.extended.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
|
||||||
@@ -18,7 +15,6 @@ object ExtendedDeclarationCheckers : DeclarationCheckers() {
|
|||||||
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
RedundantVisibilityModifierChecker,
|
RedundantVisibilityModifierChecker,
|
||||||
RedundantReturnUnitType,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker>
|
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker>
|
||||||
@@ -37,4 +33,9 @@ object ExtendedDeclarationCheckers : DeclarationCheckers() {
|
|||||||
get() = setOf(
|
get() = setOf(
|
||||||
UnusedChecker,
|
UnusedChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
|
||||||
|
get() = setOf(
|
||||||
|
RedundantReturnUnitType,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -5,18 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.checkers
|
package org.jetbrains.kotlin.fir.checkers
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
|
||||||
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.extended.*
|
import org.jetbrains.kotlin.fir.analysis.checkers.extended.*
|
||||||
|
|
||||||
object ExtendedExpressionCheckers : ExpressionCheckers() {
|
object ExtendedExpressionCheckers : ExpressionCheckers() {
|
||||||
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
ArrayEqualityCanBeReplacedWithEquals,
|
ArrayEqualityCanBeReplacedWithEquals,
|
||||||
RedundantSingleExpressionStringTemplateChecker,
|
|
||||||
EmptyRangeChecker,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
override val variableAssignmentCheckers: Set<FirVariableAssignmentChecker>
|
override val variableAssignmentCheckers: Set<FirVariableAssignmentChecker>
|
||||||
@@ -29,4 +24,10 @@ object ExtendedExpressionCheckers : ExpressionCheckers() {
|
|||||||
RedundantCallOfConversionMethod,
|
RedundantCallOfConversionMethod,
|
||||||
UselessCallOnNotNullChecker,
|
UselessCallOnNotNullChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val functionCallCheckers: Set<FirFunctionCallChecker>
|
||||||
|
get() = setOf(
|
||||||
|
EmptyRangeChecker,
|
||||||
|
RedundantSingleExpressionStringTemplateChecker,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user