FIR IDE: Simplify registerPsiQuickFixes

This change makes it possible to register multiple fixes for a
diagnostic. Also, the previous registerPsiQuickFix that relies compiler
to infer the KtFirDiagnostic type parameter is dangerous since it
can silently register fixes on interface `KtDiagnosticWithPsi` if caller
doesn't specify it explicitly.
This commit is contained in:
Tianyu Geng
2021-02-17 15:29:57 -08:00
committed by Ilya Kirillov
parent cacd84390e
commit 51da54ce66
5 changed files with 43 additions and 40 deletions
@@ -56,10 +56,13 @@ class KtQuickFixesListBuilder private constructor() {
private val quickFixes = mutableMapOf<KClass<out KtDiagnosticWithPsi<*>>, MutableList<HLQuickFixFactory>>() private val quickFixes = mutableMapOf<KClass<out KtDiagnosticWithPsi<*>>, MutableList<HLQuickFixFactory>>()
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
inline fun <DIAGNOSTIC_PSI : PsiElement, reified DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> registerPsiQuickFix( fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> registerPsiQuickFixes(
quickFixFactory: QuickFixesPsiBasedFactory<DIAGNOSTIC_PSI> diagnosticClass: KClass<DIAGNOSTIC>,
vararg quickFixFactories: QuickFixesPsiBasedFactory<in DIAGNOSTIC_PSI>
) { ) {
registerPsiQuickFix(DIAGNOSTIC::class, quickFixFactory) for (quickFixFactory in quickFixFactories) {
registerPsiQuickFix(diagnosticClass, quickFixFactory)
}
} }
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
@@ -72,7 +75,7 @@ class KtQuickFixesListBuilder private constructor() {
@PrivateForInline @PrivateForInline
fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> registerPsiQuickFix( fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> registerPsiQuickFix(
diagnosticClass: KClass<DIAGNOSTIC>, diagnosticClass: KClass<DIAGNOSTIC>,
quickFixFactory: QuickFixesPsiBasedFactory<DIAGNOSTIC_PSI> quickFixFactory: QuickFixesPsiBasedFactory<in DIAGNOSTIC_PSI>
) { ) {
quickFixes.getOrPut(diagnosticClass) { mutableListOf() }.add(HLQuickFixFactory.HLQuickFixesPsiBasedFactory(quickFixFactory)) quickFixes.getOrPut(diagnosticClass) { mutableListOf() }.add(HLQuickFixFactory.HLQuickFixesPsiBasedFactory(quickFixFactory))
} }
@@ -5,24 +5,22 @@
package org.jetbrains.kotlin.idea.quickfix package org.jetbrains.kotlin.idea.quickfix
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.fir.api.fixes.KtQuickFixRegistrar import org.jetbrains.kotlin.idea.fir.api.fixes.KtQuickFixRegistrar
import org.jetbrains.kotlin.idea.fir.api.fixes.KtQuickFixesList import org.jetbrains.kotlin.idea.fir.api.fixes.KtQuickFixesList
import org.jetbrains.kotlin.idea.fir.api.fixes.KtQuickFixesListBuilder import org.jetbrains.kotlin.idea.fir.api.fixes.KtQuickFixesListBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
import org.jetbrains.kotlin.idea.quickfix.fixes.ChangeTypeQuickFix import org.jetbrains.kotlin.idea.quickfix.fixes.ChangeTypeQuickFix
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.psi.KtParameter
class MainKtQuickFixRegistrar : KtQuickFixRegistrar() { class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
private val modifiers = KtQuickFixesListBuilder.registerPsiQuickFix { private val modifiers = KtQuickFixesListBuilder.registerPsiQuickFix {
registerPsiQuickFix<PsiElement, KtFirDiagnostic.RedundantModifier>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = true)) registerPsiQuickFixes(KtFirDiagnostic.RedundantModifier::class, RemoveModifierFix.removeRedundantModifier)
registerPsiQuickFix<PsiElement, KtFirDiagnostic.IncompatibleModifiers>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = false)) registerPsiQuickFixes(KtFirDiagnostic.IncompatibleModifiers::class, RemoveModifierFix.removeNonRedundantModifier)
registerPsiQuickFix<PsiElement, KtFirDiagnostic.RepeatedModifier>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = false)) registerPsiQuickFixes(KtFirDiagnostic.RepeatedModifier::class, RemoveModifierFix.removeNonRedundantModifier)
registerPsiQuickFix<PsiElement, KtFirDiagnostic.DeprecatedModifierPair>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = true)) registerPsiQuickFixes(KtFirDiagnostic.DeprecatedModifierPair::class, RemoveModifierFix.removeRedundantModifier)
registerPsiQuickFix<PsiElement, KtFirDiagnostic.TypeParametersInEnum>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = true)) registerPsiQuickFixes(KtFirDiagnostic.TypeParametersInEnum::class, RemoveModifierFix.removeRedundantModifier)
registerPsiQuickFix<KtModifierListOwner, KtFirDiagnostic.RedundantOpenInInterface>( registerPsiQuickFixes(
KtFirDiagnostic.RedundantOpenInInterface::class,
RemoveModifierFix.createRemoveModifierFromListOwnerFactoryByModifierListOwner( RemoveModifierFix.createRemoveModifierFromListOwnerFactoryByModifierListOwner(
modifier = KtTokens.OPEN_KEYWORD, modifier = KtTokens.OPEN_KEYWORD,
isRedundant = true isRedundant = true
@@ -37,9 +35,9 @@ class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
} }
private val mutability = KtQuickFixesListBuilder.registerPsiQuickFix { private val mutability = KtQuickFixesListBuilder.registerPsiQuickFix {
registerPsiQuickFix<PsiElement, KtFirDiagnostic.VarOverriddenByVal>(ChangeVariableMutabilityFix.VAR_OVERRIDDEN_BY_VAL_FACTORY) registerPsiQuickFixes(KtFirDiagnostic.VarOverriddenByVal::class, ChangeVariableMutabilityFix.VAR_OVERRIDDEN_BY_VAL_FACTORY)
registerPsiQuickFix<KtParameter, KtFirDiagnostic.VarAnnotationParameter>(ChangeVariableMutabilityFix.VAR_ANNOTATION_PARAMETER_FACTORY) registerPsiQuickFixes(KtFirDiagnostic.VarAnnotationParameter::class, ChangeVariableMutabilityFix.VAR_ANNOTATION_PARAMETER_FACTORY)
registerPsiQuickFix<KtModifierListOwner, KtFirDiagnostic.InapplicableLateinitModifier>(ChangeVariableMutabilityFix.LATEINIT_VAL_FACTORY) registerPsiQuickFixes(KtFirDiagnostic.InapplicableLateinitModifier::class, ChangeVariableMutabilityFix.LATEINIT_VAL_FACTORY)
} }
override val list: KtQuickFixesList = KtQuickFixesList.createCombined( override val list: KtQuickFixesList = KtQuickFixesList.createCombined(
@@ -51,6 +51,9 @@ class RemoveModifierFix(
} }
companion object { companion object {
val removeRedundantModifier = createRemoveModifierFactory(isRedundant = true)
val removeNonRedundantModifier = createRemoveModifierFactory(isRedundant = false)
@Deprecated( @Deprecated(
"For binary compatibility", "For binary compatibility",
replaceWith = ReplaceWith("createRemoveModifierFromListOwnerPsiBasedFactory(modifier, isRedundant)") replaceWith = ReplaceWith("createRemoveModifierFromListOwnerPsiBasedFactory(modifier, isRedundant)")
@@ -79,7 +82,7 @@ class RemoveModifierFix(
listOf(RemoveModifierFix(it, modifier, isRedundant)) listOf(RemoveModifierFix(it, modifier, isRedundant))
} }
fun createRemoveModifierFactory(isRedundant: Boolean = false): QuickFixesPsiBasedFactory<PsiElement> { private fun createRemoveModifierFactory(isRedundant: Boolean = false): QuickFixesPsiBasedFactory<PsiElement> {
return quickFixesPsiBasedFactory { psiElement: PsiElement -> return quickFixesPsiBasedFactory { psiElement: PsiElement ->
val elementType = psiElement.node.elementType as? KtModifierKeywordToken ?: return@quickFixesPsiBasedFactory emptyList() val elementType = psiElement.node.elementType as? KtModifierKeywordToken ?: return@quickFixesPsiBasedFactory emptyList()
val modifierListOwner = psiElement.getStrictParentOfType<KtModifierListOwner>() val modifierListOwner = psiElement.getStrictParentOfType<KtModifierListOwner>()
@@ -116,14 +116,14 @@ class QuickFixRegistrar : QuickFixContributor {
USELESS_ELVIS.registerFactory(RemoveUselessElvisFix) USELESS_ELVIS.registerFactory(RemoveUselessElvisFix)
USELESS_ELVIS_RIGHT_IS_NULL.registerFactory(RemoveUselessElvisFix) USELESS_ELVIS_RIGHT_IS_NULL.registerFactory(RemoveUselessElvisFix)
val removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true) val removeRedundantModifierFactory = RemoveModifierFix.removeRedundantModifier
REDUNDANT_MODIFIER.registerFactory(removeRedundantModifierFactory) REDUNDANT_MODIFIER.registerFactory(removeRedundantModifierFactory)
REDUNDANT_OPEN_IN_INTERFACE.registerFactory(RemoveModifierFix.createRemoveModifierFromListOwnerPsiBasedFactory(OPEN_KEYWORD, true)) REDUNDANT_OPEN_IN_INTERFACE.registerFactory(RemoveModifierFix.createRemoveModifierFromListOwnerPsiBasedFactory(OPEN_KEYWORD, true))
REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE.registerFactory(RemoveModifierFix.createRemoveSuspendFactory()) REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE.registerFactory(RemoveModifierFix.createRemoveSuspendFactory())
UNNECESSARY_LATEINIT.registerFactory(RemoveModifierFix.createRemoveModifierFromListOwnerPsiBasedFactory(LATEINIT_KEYWORD)) UNNECESSARY_LATEINIT.registerFactory(RemoveModifierFix.createRemoveModifierFromListOwnerPsiBasedFactory(LATEINIT_KEYWORD))
REDUNDANT_PROJECTION.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(true)) REDUNDANT_PROJECTION.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(true))
INCOMPATIBLE_MODIFIERS.registerFactory(RemoveModifierFix.createRemoveModifierFactory(false)) INCOMPATIBLE_MODIFIERS.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED.registerFactory(RemoveModifierFix.createRemoveVarianceFactory()) VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED.registerFactory(RemoveModifierFix.createRemoveVarianceFactory())
val removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerPsiBasedFactory(OPEN_KEYWORD) val removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerPsiBasedFactory(OPEN_KEYWORD)
@@ -133,27 +133,26 @@ class QuickFixRegistrar : QuickFixContributor {
) )
NON_FINAL_MEMBER_IN_OBJECT.registerFactory(removeOpenModifierFactory) NON_FINAL_MEMBER_IN_OBJECT.registerFactory(removeOpenModifierFactory)
val removeModifierFactory = RemoveModifierFix.createRemoveModifierFactory() GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.registerFactory(removeModifierFactory) SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY.registerFactory(removeModifierFactory) PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY.registerFactory(removeModifierFactory)
PRIVATE_SETTER_FOR_OPEN_PROPERTY.registerFactory( PRIVATE_SETTER_FOR_OPEN_PROPERTY.registerFactory(
AddModifierFixMpp.createFactory(FINAL_KEYWORD, KtProperty::class.java), AddModifierFixMpp.createFactory(FINAL_KEYWORD, KtProperty::class.java),
removeModifierFactory RemoveModifierFix.removeNonRedundantModifier
) )
REDUNDANT_MODIFIER_IN_GETTER.registerFactory(removeRedundantModifierFactory) REDUNDANT_MODIFIER_IN_GETTER.registerFactory(removeRedundantModifierFactory)
WRONG_MODIFIER_TARGET.registerFactory(removeModifierFactory, ConstValFactory) WRONG_MODIFIER_TARGET.registerFactory(RemoveModifierFix.removeNonRedundantModifier, ConstValFactory)
DEPRECATED_MODIFIER.registerFactory(ReplaceModifierFix) DEPRECATED_MODIFIER.registerFactory(ReplaceModifierFix)
REDUNDANT_MODIFIER_FOR_TARGET.registerFactory(removeModifierFactory) REDUNDANT_MODIFIER_FOR_TARGET.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
WRONG_MODIFIER_CONTAINING_DECLARATION.registerFactory(removeModifierFactory) WRONG_MODIFIER_CONTAINING_DECLARATION.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
REPEATED_MODIFIER.registerFactory(removeModifierFactory) REPEATED_MODIFIER.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
NON_PRIVATE_CONSTRUCTOR_IN_ENUM.registerFactory(removeModifierFactory) NON_PRIVATE_CONSTRUCTOR_IN_ENUM.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
NON_PRIVATE_CONSTRUCTOR_IN_SEALED.registerFactory(removeModifierFactory) NON_PRIVATE_CONSTRUCTOR_IN_SEALED.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED.registerFactory(removeModifierFactory) NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
TYPE_CANT_BE_USED_FOR_CONST_VAL.registerFactory(removeModifierFactory) TYPE_CANT_BE_USED_FOR_CONST_VAL.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
DEPRECATED_BINARY_MOD.registerFactory(removeModifierFactory) DEPRECATED_BINARY_MOD.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
DEPRECATED_BINARY_MOD.registerFactory(RenameModToRemFix.Factory) DEPRECATED_BINARY_MOD.registerFactory(RenameModToRemFix.Factory)
FORBIDDEN_BINARY_MOD.registerFactory(removeModifierFactory) FORBIDDEN_BINARY_MOD.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
FORBIDDEN_BINARY_MOD.registerFactory(RenameModToRemFix.Factory) FORBIDDEN_BINARY_MOD.registerFactory(RenameModToRemFix.Factory)
NO_EXPLICIT_VISIBILITY_IN_API_MODE.registerFactory(ChangeVisibilityFix.SetExplicitVisibilityFactory) NO_EXPLICIT_VISIBILITY_IN_API_MODE.registerFactory(ChangeVisibilityFix.SetExplicitVisibilityFactory)
@@ -604,7 +603,7 @@ class QuickFixRegistrar : QuickFixContributor {
CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT.registerFactory( CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT.registerFactory(
MoveMemberToCompanionObjectIntention, MoveMemberToCompanionObjectIntention,
RemoveModifierFix.createRemoveModifierFactory() RemoveModifierFix.removeNonRedundantModifier
) )
NO_COMPANION_OBJECT.registerFactory(AddIsToWhenConditionFix) NO_COMPANION_OBJECT.registerFactory(AddIsToWhenConditionFix)
@@ -614,7 +613,7 @@ class QuickFixRegistrar : QuickFixContributor {
RESOLUTION_TO_CLASSIFIER.registerFactory(ConvertToAnonymousObjectFix) RESOLUTION_TO_CLASSIFIER.registerFactory(ConvertToAnonymousObjectFix)
NOTHING_TO_INLINE.registerFactory(RemoveModifierFix.createRemoveModifierFactory(isRedundant = false)) NOTHING_TO_INLINE.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
DECLARATION_CANT_BE_INLINED.registerFactory(DeclarationCantBeInlinedFactory) DECLARATION_CANT_BE_INLINED.registerFactory(DeclarationCantBeInlinedFactory)
@@ -141,7 +141,7 @@ private val errorsFixingDiagnosticBasedPostProcessingGroup =
Errors.INVISIBLE_MEMBER Errors.INVISIBLE_MEMBER
), ),
diagnosticBasedProcessing( diagnosticBasedProcessing(
RemoveModifierFix.createRemoveModifierFactory(), RemoveModifierFix.removeNonRedundantModifier,
Errors.WRONG_MODIFIER_TARGET Errors.WRONG_MODIFIER_TARGET
), ),
diagnosticBasedProcessing( diagnosticBasedProcessing(