From 638a0d3b82c1044ffb8ccc69de7439e7f07478a3 Mon Sep 17 00:00:00 2001 From: vldf Date: Wed, 5 Aug 2020 17:39:43 +0300 Subject: [PATCH] [FIR] Checkers performance improvement and some refactoring --- .../kotlin/fir/analysis/CheckersComponent.kt | 5 +++ ...bstractFirPropertyInitializationChecker.kt | 10 ++++-- .../analysis/cfa/FirControlFlowAnalyzer.kt | 12 +++++-- .../cfa/FirPropertyInitializationAnalyzer.kt | 25 ++++++++++----- .../fir/analysis/checkers/FirHelpers.kt | 19 ++++++----- .../declaration/DeclarationCheckers.kt | 2 ++ .../ExtendedDeclarationCheckers.kt | 4 +-- ...BeReplacedWithOperatorAssignmentChecker.kt | 18 +++++++---- .../checkers/extended/EmptyRangeChecker.kt | 32 ++++++++++++++++--- .../RedundantCallOfConversionMethod.kt | 2 +- .../RedundantModalityModifierChecker.kt | 11 +++---- .../RedundantReturnUnitTypeChecker.kt | 5 ++- .../RedundantSetterParameterTypeChecker.kt | 1 + ...ntSingleExpressionStringTemplateChecker.kt | 3 +- .../extended/VariableAssignmentChecker.kt | 19 +++++------ 15 files changed, 112 insertions(+), 56 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt index 231c910a4a8..dd074dfd7ac 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSessionComponent +import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirCfaPropertyAssignmentChecker import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker import org.jetbrains.kotlin.fir.analysis.checkers.declaration.* import org.jetbrains.kotlin.fir.analysis.checkers.expression.* @@ -70,6 +71,8 @@ private class ComposedDeclarationCheckers : DeclarationCheckers() { get() = _constructorCheckers override val controlFlowAnalyserCheckers: List get() = _controlFlowAnalyserCheckers + override val variableAssignmentCfaBasedCheckers: List + get() = _variableAssignmentCfaBasedCheckers private val _fileCheckers: MutableList = mutableListOf() private val _declarationCheckers: MutableList = mutableListOf() @@ -77,6 +80,7 @@ private class ComposedDeclarationCheckers : DeclarationCheckers() { private val _regularClassCheckers: MutableList = mutableListOf() private val _constructorCheckers: MutableList = mutableListOf() private val _controlFlowAnalyserCheckers: MutableList = mutableListOf() + private val _variableAssignmentCfaBasedCheckers: MutableList = mutableListOf() fun register(checkers: DeclarationCheckers) { _fileCheckers += checkers.allFileCheckers @@ -85,6 +89,7 @@ private class ComposedDeclarationCheckers : DeclarationCheckers() { _regularClassCheckers += checkers.allRegularClassCheckers _constructorCheckers += checkers.allConstructorCheckers _controlFlowAnalyserCheckers += checkers.controlFlowAnalyserCheckers + _variableAssignmentCfaBasedCheckers += checkers.variableAssignmentCfaBasedCheckers } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/AbstractFirPropertyInitializationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/AbstractFirPropertyInitializationChecker.kt index 27ebedf4e88..021aa714038 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/AbstractFirPropertyInitializationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/AbstractFirPropertyInitializationChecker.kt @@ -8,14 +8,18 @@ package org.jetbrains.kotlin.fir.analysis.cfa import kotlinx.collections.immutable.PersistentMap import kotlinx.collections.immutable.persistentMapOf import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange -import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol -abstract class AbstractFirPropertyInitializationChecker : FirControlFlowChecker() { - abstract override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter) +abstract class AbstractFirCfaPropertyAssignmentChecker { + abstract fun analyze( + graph: ControlFlowGraph, + reporter: DiagnosticReporter, + data: Map, PropertyInitializationInfo>, + properties: Set + ) class PropertyInitializationInfo( map: PersistentMap = persistentMapOf() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirControlFlowAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirControlFlowAnalyzer.kt index a8643df6d60..0ff8ef5884d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirControlFlowAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirControlFlowAnalyzer.kt @@ -15,7 +15,8 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph class FirControlFlowAnalyzer(session: FirSession) { - private val checkers = session.checkersComponent.declarationCheckers.controlFlowAnalyserCheckers + private val cfaCheckers = session.checkersComponent.declarationCheckers.controlFlowAnalyserCheckers + private val variableAssignmentCheckers = session.checkersComponent.declarationCheckers.variableAssignmentCfaBasedCheckers fun analyzeClassInitializer(klass: FirClass<*>, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) { if (graph.owner != null) return @@ -24,7 +25,14 @@ class FirControlFlowAnalyzer(session: FirSession) { fun analyzeFunction(function: FirFunction<*>, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) { if (graph.owner != null) return - checkers.forEach { it.analyze(graph, reporter) } + + cfaCheckers.forEach { it.analyze(graph, reporter) } + + val properties = AbstractFirCfaPropertyAssignmentChecker.LocalPropertyCollector.collect(graph) + if (properties.isEmpty()) return + val data = AbstractFirCfaPropertyAssignmentChecker.DataCollector(properties).getData(graph) + + variableAssignmentCheckers.forEach { it.analyze(graph, reporter, data, properties) } } fun analyzePropertyInitializer(property: FirProperty, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt index 66de5563e93..47551c013ae 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt @@ -16,15 +16,24 @@ import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraphVisitorVoid import org.jetbrains.kotlin.fir.resolve.dfa.cfg.QualifiedAccessNode import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol -object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChecker() { - override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter) { - val localProperties = LocalPropertyCollector.collect(graph) - // we want to analyze only properties without initializers - localProperties.retainAll { it.fir.initializer == null && it.fir.delegate == null } - if (localProperties.isEmpty()) return - val data = DataCollector(localProperties).getData(graph) - val reporterVisitor = UninitializedPropertyReporter(data, localProperties, reporter) +object FirPropertyInitializationAnalyzer : AbstractFirCfaPropertyAssignmentChecker() { + override fun analyze( + graph: ControlFlowGraph, + reporter: DiagnosticReporter, + data: Map, PropertyInitializationInfo>, + properties: Set + ) { + // getting symbols of properties without initializers and non-variable symbols + val localData = data.filter { + val symbolFir = (it.key.fir as? FirVariableSymbol<*>)?.fir + symbolFir == null || symbolFir.initializer == null && symbolFir.delegate == null + } + + val localProperties = properties.filter { it.fir.initializer == null && it.fir.delegate == null }.toSet() + + val reporterVisitor = UninitializedPropertyReporter(localData, localProperties, reporter) graph.traverse(TraverseDirection.Forward, reporterVisitor) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index ef20cc795de..baa726a2c6e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef -import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtModifierList import org.jetbrains.kotlin.psi.psiUtil.toVisibility @@ -185,7 +184,7 @@ fun FirClassLikeDeclaration<*>.followAllAlias(session: FirSession): FirClassLike * or null if no such item could be found. */ fun CheckerContext.findClosestClassOrObject(): FirClass<*>? { - for (it in containingDeclarations.reversed()) { + for (it in containingDeclarations.asReversed()) { if ( it is FirRegularClass || it is FirAnonymousObject @@ -237,20 +236,20 @@ fun FirClass<*>.modality(): Modality? { /** * returns implicit modality by FirMemberDeclaration */ -fun FirMemberDeclaration.implicitModality(context: CheckerContext): KtModifierKeywordToken { +fun FirMemberDeclaration.implicitModality(context: CheckerContext): Modality { if (this is FirRegularClass && (this.classKind == ClassKind.CLASS || this.classKind == ClassKind.OBJECT)) { - if (this.classKind == ClassKind.INTERFACE) return KtTokens.ABSTRACT_KEYWORD - return KtTokens.FINAL_KEYWORD + if (this.classKind == ClassKind.INTERFACE) return Modality.ABSTRACT + return Modality.FINAL } - val klass = context.findClosestClassOrObject() ?: return KtTokens.FINAL_KEYWORD - val modifiers = this.modifierListOrNull() ?: return KtTokens.FINAL_KEYWORD + val klass = context.findClosestClassOrObject() ?: return Modality.FINAL + val modifiers = this.modifierListOrNull() ?: return Modality.FINAL if (modifiers.hasModifier(KtTokens.OVERRIDE_KEYWORD)) { val klassModifiers = klass.modifierListOrNull() if (klassModifiers != null && klassModifiers.run { hasModifier(KtTokens.ABSTRACT_KEYWORD) || hasModifier(KtTokens.OPEN_KEYWORD) || hasModifier(KtTokens.SEALED_KEYWORD) }) { - return KtTokens.OPEN_KEYWORD + return Modality.OPEN } } @@ -259,10 +258,10 @@ fun FirMemberDeclaration.implicitModality(context: CheckerContext): KtModifierKe && klass.classKind == ClassKind.INTERFACE && !modifiers.hasModifier(KtTokens.PRIVATE_KEYWORD) ) { - return if (this.hasBody()) KtTokens.OPEN_KEYWORD else KtTokens.ABSTRACT_KEYWORD + return if (this.hasBody()) Modality.OPEN else Modality.ABSTRACT } - return KtTokens.FINAL_KEYWORD + return Modality.FINAL } private fun FirDeclaration.modifierListOrNull() = (this.source.getModifierList() as? FirPsiModifierList)?.modifierList diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt index 822772cb403..e93050b625c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration +import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirCfaPropertyAssignmentChecker import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker abstract class DeclarationCheckers { @@ -18,6 +19,7 @@ abstract class DeclarationCheckers { open val regularClassCheckers: List = emptyList() open val constructorCheckers: List = emptyList() open val controlFlowAnalyserCheckers: List = emptyList() + open val variableAssignmentCfaBasedCheckers: List = emptyList() internal val allFileCheckers: List get() = fileCheckers + declarationCheckers internal val allMemberDeclarationCheckers: List get() = memberDeclarationCheckers + declarationCheckers diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ExtendedDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ExtendedDeclarationCheckers.kt index c23c1772aa3..f584010011f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ExtendedDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ExtendedDeclarationCheckers.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration -import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker +import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirCfaPropertyAssignmentChecker import org.jetbrains.kotlin.fir.analysis.checkers.extended.* object ExtendedDeclarationCheckers : DeclarationCheckers() { @@ -20,7 +20,7 @@ object ExtendedDeclarationCheckers : DeclarationCheckers() { RedundantSetterParameterTypeChecker ) - override val controlFlowAnalyserCheckers: List = listOf( + override val variableAssignmentCfaBasedCheckers: List = listOf( VariableAssignmentChecker ) } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt index 7fea895d4b2..6d99cb178d6 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt @@ -22,16 +22,19 @@ import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtNameReferenceExpression +import org.jetbrains.kotlin.psi.KtOperationReferenceExpression object CanBeReplacedWithOperatorAssignmentChecker : FirExpressionChecker() { - override fun check(functionCall: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) { - val lValue = functionCall.lValue + override fun check(assignment: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) { + val lValue = assignment.lValue if (lValue !is FirResolvedNamedReference) return - val operator = functionCall.psi?.children?.getOrNull(1) ?: return - if (operator.text != "=") return + + val operator = assignment.psi?.children?.getOrNull(1) ?: return + val operationSign = (operator as? KtOperationReferenceExpression)?.operationSignTokenType + if (operationSign != KtTokens.EQ) return val lValuePsi = lValue.psi as? KtNameReferenceExpression ?: return - val rValue = functionCall.rValue as? FirFunctionCall ?: return + val rValue = assignment.rValue as? FirFunctionCall ?: return val rValuePsi = rValue.psi as? KtBinaryExpression ?: return val rValueClassId = rValue.explicitReceiver?.typeRef?.coneType?.classId @@ -56,9 +59,12 @@ object CanBeReplacedWithOperatorAssignmentChecker : FirExpressionChecker) return if (functionCall !is FirFunctionCall) return - val range = functionCall.psi ?: return - val left = range.children.getOrNull(0)?.text?.toLongOrNull() ?: return - val right = range.children.getOrNull(2)?.text?.toLongOrNull() ?: return + val left = functionCall.rangeLeft ?: return + val right = functionCall.rangeRight ?: return val needReport = when (functionCall.calleeReference.name.asString()) { "rangeTo" -> { @@ -41,4 +41,28 @@ object EmptyRangeChecker : FirBasicExpresionChecker() { } } + private val FirFunctionCall.rangeLeft: Long? + get() { + return if (explicitReceiver is FirIntegerOperatorCall) { + (explicitReceiver as? FirIntegerOperatorCall)?.asLong + } else { + (explicitReceiver as? FirConstExpression<*>)?.value as? Long + } + } + + private val FirFunctionCall.rangeRight: Long? + get() { + val arg = argumentList.arguments.getOrNull(0) + return if (arg is FirIntegerOperatorCall) arg.asLong + else (arg as? FirConstExpression<*>)?.value as? Long + } + + private val FirIntegerOperatorCall.asLong: Long? + get() { + val value = (dispatchReceiver as? FirConstExpression<*>)?.value as Long? ?: return null + if (this.calleeReference.name.asString() == "unaryMinus") { + return -value + } + return value + } } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantCallOfConversionMethod.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantCallOfConversionMethod.kt index 410afc87589..25829bcbd4d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantCallOfConversionMethod.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantCallOfConversionMethod.kt @@ -37,7 +37,7 @@ object RedundantCallOfConversionMethod : FirQualifiedAccessChecker() { } } - private val targetClassMap = mapOf( + private val targetClassMap = hashMapOf( "toString" to StandardClassIds.String, "toDouble" to StandardClassIds.Double, "toFloat" to StandardClassIds.Float, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantModalityModifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantModalityModifierChecker.kt index 5d74ff8fed5..51ceeb73cb3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantModalityModifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantModalityModifierChecker.kt @@ -5,8 +5,8 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended -import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirFakeSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker @@ -15,10 +15,9 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration +import org.jetbrains.kotlin.fir.declarations.modality import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.toFirPsiSourceElement -import org.jetbrains.kotlin.lexer.KtModifierKeywordToken -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.psiUtil.modalityModifier @@ -26,10 +25,9 @@ object RedundantModalityModifierChecker : FirMemberDeclarationChecker() { override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration.source is FirFakeSourceElement<*>) return - val modalityModifier = (declaration.psi as? KtDeclaration)?.modalityModifier() ?: return - val modality = (modalityModifier as? LeafPsiElement)?.elementType as? KtModifierKeywordToken ?: return + val modality = declaration.modality ?: return if ( - modality == KtTokens.FINAL_KEYWORD + modality == Modality.FINAL && (context.containingDeclarations.last() as? FirClass<*>)?.classKind == ClassKind.INTERFACE ) return @@ -37,6 +35,7 @@ object RedundantModalityModifierChecker : FirMemberDeclarationChecker() { if (modality != implicitModality) return + val modalityModifier = (declaration.psi as? KtDeclaration)?.modalityModifier() ?: return reporter.report(modalityModifier.toFirPsiSourceElement(), REDUNDANT_MODALITY_MODIFIER) } } 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 e7e504c7a40..84f91968d89 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 @@ -19,10 +19,9 @@ object RedundantReturnUnitType : FirBasicDeclarationChecker() { override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { if (declaration !is FirSimpleFunction) return if (declaration.body is FirSingleExpressionBlock) return - if (declaration.returnTypeRef.source == null) return - if (declaration.source is FirFakeSourceElement<*>) return - val returnType = declaration.returnTypeRef + if (returnType.source == null) return + if (declaration.source is FirFakeSourceElement<*>) return if (returnType.annotations.isNotEmpty()) return if (returnType.isUnit) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSetterParameterTypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSetterParameterTypeChecker.kt index a68b158051a..90d49246675 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSetterParameterTypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSetterParameterTypeChecker.kt @@ -21,6 +21,7 @@ object RedundantSetterParameterTypeChecker : FirMemberDeclarationChecker() { val valueParameter = setter.valueParameters.firstOrNull() ?: return val propertyTypeSource = declaration.returnTypeRef.source val setterParameterTypeSource = valueParameter.returnTypeRef.source ?: return + if (setterParameterTypeSource != propertyTypeSource) { reporter.report(setterParameterTypeSource, REDUNDANT_SETTER_PARAMETER_TYPE) } 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 82e95c989ef..bffefdf308c 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 @@ -33,7 +33,6 @@ object RedundantSingleExpressionStringTemplateChecker : FirBasicExpresionChecker private fun PsiElement.findStringParent(): KtStringTemplateExpression? { if (this is KtStringTemplateExpression) return this - return if (this.parent != null) this.parent.findStringParent() - else null + return this.parent?.findStringParent() } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/VariableAssignmentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/VariableAssignmentChecker.kt index a8563ca2b8c..413dadf8b62 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/VariableAssignmentChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/VariableAssignmentChecker.kt @@ -9,7 +9,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange import org.jetbrains.kotlin.fir.FirFakeSourceElement import org.jetbrains.kotlin.fir.FirSourceElement -import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker +import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirCfaPropertyAssignmentChecker import org.jetbrains.kotlin.fir.analysis.cfa.TraverseDirection import org.jetbrains.kotlin.fir.analysis.cfa.traverse import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter @@ -22,16 +22,17 @@ import org.jetbrains.kotlin.fir.toFirPsiSourceElement import org.jetbrains.kotlin.psi.KtProperty -object VariableAssignmentChecker : AbstractFirPropertyInitializationChecker() { - override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter) { +object VariableAssignmentChecker : AbstractFirCfaPropertyAssignmentChecker() { + override fun analyze( + graph: ControlFlowGraph, + reporter: DiagnosticReporter, + data: Map, PropertyInitializationInfo>, + properties: Set + ) { val unprocessedProperties = mutableSetOf() val propertiesCharacteristics = mutableMapOf() - val localProperties = LocalPropertyCollector.collect(graph) - if (localProperties.isEmpty()) return - - val data = DataCollector(localProperties).getData(graph) - val reporterVisitor = UninitializedPropertyReporter(data, localProperties, unprocessedProperties, propertiesCharacteristics) + val reporterVisitor = UninitializedPropertyReporter(data, properties, unprocessedProperties, propertiesCharacteristics) graph.traverse(TraverseDirection.Forward, reporterVisitor) for (property in unprocessedProperties) { @@ -63,7 +64,7 @@ object VariableAssignmentChecker : AbstractFirPropertyInitializationChecker() { destructuringCanBeVal = false } lastDestructuredVariables-- - } else if (canBeVal(symbol, value) && symbol.fir.delegate == null ) { + } else if (canBeVal(symbol, value) && symbol.fir.delegate == null) { reporter.report(source, FirErrors.CAN_BE_VAL) } }