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>>()
@OptIn(PrivateForInline::class)
inline fun <DIAGNOSTIC_PSI : PsiElement, reified DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> registerPsiQuickFix(
quickFixFactory: QuickFixesPsiBasedFactory<DIAGNOSTIC_PSI>
fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> registerPsiQuickFixes(
diagnosticClass: KClass<DIAGNOSTIC>,
vararg quickFixFactories: QuickFixesPsiBasedFactory<in DIAGNOSTIC_PSI>
) {
registerPsiQuickFix(DIAGNOSTIC::class, quickFixFactory)
for (quickFixFactory in quickFixFactories) {
registerPsiQuickFix(diagnosticClass, quickFixFactory)
}
}
@OptIn(PrivateForInline::class)
@@ -72,7 +75,7 @@ class KtQuickFixesListBuilder private constructor() {
@PrivateForInline
fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> registerPsiQuickFix(
diagnosticClass: KClass<DIAGNOSTIC>,
quickFixFactory: QuickFixesPsiBasedFactory<DIAGNOSTIC_PSI>
quickFixFactory: QuickFixesPsiBasedFactory<in DIAGNOSTIC_PSI>
) {
quickFixes.getOrPut(diagnosticClass) { mutableListOf() }.add(HLQuickFixFactory.HLQuickFixesPsiBasedFactory(quickFixFactory))
}
@@ -118,4 +121,4 @@ private fun <K, V> List<Map<K, List<V>>>.merge(): Map<K, List<V>> {
}
@RequiresOptIn
annotation class ForKtQuickFixesListBuilder()
annotation class ForKtQuickFixesListBuilder()
@@ -5,24 +5,22 @@
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.KtQuickFixesList
import org.jetbrains.kotlin.idea.fir.api.fixes.KtQuickFixesListBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
import org.jetbrains.kotlin.idea.quickfix.fixes.ChangeTypeQuickFix
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.psi.KtParameter
class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
private val modifiers = KtQuickFixesListBuilder.registerPsiQuickFix {
registerPsiQuickFix<PsiElement, KtFirDiagnostic.RedundantModifier>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = true))
registerPsiQuickFix<PsiElement, KtFirDiagnostic.IncompatibleModifiers>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = false))
registerPsiQuickFix<PsiElement, KtFirDiagnostic.RepeatedModifier>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = false))
registerPsiQuickFix<PsiElement, KtFirDiagnostic.DeprecatedModifierPair>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = true))
registerPsiQuickFix<PsiElement, KtFirDiagnostic.TypeParametersInEnum>(RemoveModifierFix.createRemoveModifierFactory(isRedundant = true))
registerPsiQuickFix<KtModifierListOwner, KtFirDiagnostic.RedundantOpenInInterface>(
registerPsiQuickFixes(KtFirDiagnostic.RedundantModifier::class, RemoveModifierFix.removeRedundantModifier)
registerPsiQuickFixes(KtFirDiagnostic.IncompatibleModifiers::class, RemoveModifierFix.removeNonRedundantModifier)
registerPsiQuickFixes(KtFirDiagnostic.RepeatedModifier::class, RemoveModifierFix.removeNonRedundantModifier)
registerPsiQuickFixes(KtFirDiagnostic.DeprecatedModifierPair::class, RemoveModifierFix.removeRedundantModifier)
registerPsiQuickFixes(KtFirDiagnostic.TypeParametersInEnum::class, RemoveModifierFix.removeRedundantModifier)
registerPsiQuickFixes(
KtFirDiagnostic.RedundantOpenInInterface::class,
RemoveModifierFix.createRemoveModifierFromListOwnerFactoryByModifierListOwner(
modifier = KtTokens.OPEN_KEYWORD,
isRedundant = true
@@ -37,9 +35,9 @@ class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
}
private val mutability = KtQuickFixesListBuilder.registerPsiQuickFix {
registerPsiQuickFix<PsiElement, KtFirDiagnostic.VarOverriddenByVal>(ChangeVariableMutabilityFix.VAR_OVERRIDDEN_BY_VAL_FACTORY)
registerPsiQuickFix<KtParameter, KtFirDiagnostic.VarAnnotationParameter>(ChangeVariableMutabilityFix.VAR_ANNOTATION_PARAMETER_FACTORY)
registerPsiQuickFix<KtModifierListOwner, KtFirDiagnostic.InapplicableLateinitModifier>(ChangeVariableMutabilityFix.LATEINIT_VAL_FACTORY)
registerPsiQuickFixes(KtFirDiagnostic.VarOverriddenByVal::class, ChangeVariableMutabilityFix.VAR_OVERRIDDEN_BY_VAL_FACTORY)
registerPsiQuickFixes(KtFirDiagnostic.VarAnnotationParameter::class, ChangeVariableMutabilityFix.VAR_ANNOTATION_PARAMETER_FACTORY)
registerPsiQuickFixes(KtFirDiagnostic.InapplicableLateinitModifier::class, ChangeVariableMutabilityFix.LATEINIT_VAL_FACTORY)
}
override val list: KtQuickFixesList = KtQuickFixesList.createCombined(
@@ -47,4 +45,4 @@ class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
overrides,
mutability,
)
}
}
@@ -51,6 +51,9 @@ class RemoveModifierFix(
}
companion object {
val removeRedundantModifier = createRemoveModifierFactory(isRedundant = true)
val removeNonRedundantModifier = createRemoveModifierFactory(isRedundant = false)
@Deprecated(
"For binary compatibility",
replaceWith = ReplaceWith("createRemoveModifierFromListOwnerPsiBasedFactory(modifier, isRedundant)")
@@ -79,7 +82,7 @@ class RemoveModifierFix(
listOf(RemoveModifierFix(it, modifier, isRedundant))
}
fun createRemoveModifierFactory(isRedundant: Boolean = false): QuickFixesPsiBasedFactory<PsiElement> {
private fun createRemoveModifierFactory(isRedundant: Boolean = false): QuickFixesPsiBasedFactory<PsiElement> {
return quickFixesPsiBasedFactory { psiElement: PsiElement ->
val elementType = psiElement.node.elementType as? KtModifierKeywordToken ?: return@quickFixesPsiBasedFactory emptyList()
val modifierListOwner = psiElement.getStrictParentOfType<KtModifierListOwner>()
@@ -116,14 +116,14 @@ class QuickFixRegistrar : QuickFixContributor {
USELESS_ELVIS.registerFactory(RemoveUselessElvisFix)
USELESS_ELVIS_RIGHT_IS_NULL.registerFactory(RemoveUselessElvisFix)
val removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true)
val removeRedundantModifierFactory = RemoveModifierFix.removeRedundantModifier
REDUNDANT_MODIFIER.registerFactory(removeRedundantModifierFactory)
REDUNDANT_OPEN_IN_INTERFACE.registerFactory(RemoveModifierFix.createRemoveModifierFromListOwnerPsiBasedFactory(OPEN_KEYWORD, true))
REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE.registerFactory(RemoveModifierFix.createRemoveSuspendFactory())
UNNECESSARY_LATEINIT.registerFactory(RemoveModifierFix.createRemoveModifierFromListOwnerPsiBasedFactory(LATEINIT_KEYWORD))
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())
val removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerPsiBasedFactory(OPEN_KEYWORD)
@@ -133,27 +133,26 @@ class QuickFixRegistrar : QuickFixContributor {
)
NON_FINAL_MEMBER_IN_OBJECT.registerFactory(removeOpenModifierFactory)
val removeModifierFactory = RemoveModifierFix.createRemoveModifierFactory()
GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.registerFactory(removeModifierFactory)
SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY.registerFactory(removeModifierFactory)
PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY.registerFactory(removeModifierFactory)
GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
PRIVATE_SETTER_FOR_OPEN_PROPERTY.registerFactory(
AddModifierFixMpp.createFactory(FINAL_KEYWORD, KtProperty::class.java),
removeModifierFactory
RemoveModifierFix.removeNonRedundantModifier
)
REDUNDANT_MODIFIER_IN_GETTER.registerFactory(removeRedundantModifierFactory)
WRONG_MODIFIER_TARGET.registerFactory(removeModifierFactory, ConstValFactory)
WRONG_MODIFIER_TARGET.registerFactory(RemoveModifierFix.removeNonRedundantModifier, ConstValFactory)
DEPRECATED_MODIFIER.registerFactory(ReplaceModifierFix)
REDUNDANT_MODIFIER_FOR_TARGET.registerFactory(removeModifierFactory)
WRONG_MODIFIER_CONTAINING_DECLARATION.registerFactory(removeModifierFactory)
REPEATED_MODIFIER.registerFactory(removeModifierFactory)
NON_PRIVATE_CONSTRUCTOR_IN_ENUM.registerFactory(removeModifierFactory)
NON_PRIVATE_CONSTRUCTOR_IN_SEALED.registerFactory(removeModifierFactory)
NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED.registerFactory(removeModifierFactory)
TYPE_CANT_BE_USED_FOR_CONST_VAL.registerFactory(removeModifierFactory)
DEPRECATED_BINARY_MOD.registerFactory(removeModifierFactory)
REDUNDANT_MODIFIER_FOR_TARGET.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
WRONG_MODIFIER_CONTAINING_DECLARATION.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
REPEATED_MODIFIER.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
NON_PRIVATE_CONSTRUCTOR_IN_ENUM.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
NON_PRIVATE_CONSTRUCTOR_IN_SEALED.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
TYPE_CANT_BE_USED_FOR_CONST_VAL.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
DEPRECATED_BINARY_MOD.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
DEPRECATED_BINARY_MOD.registerFactory(RenameModToRemFix.Factory)
FORBIDDEN_BINARY_MOD.registerFactory(removeModifierFactory)
FORBIDDEN_BINARY_MOD.registerFactory(RemoveModifierFix.removeNonRedundantModifier)
FORBIDDEN_BINARY_MOD.registerFactory(RenameModToRemFix.Factory)
NO_EXPLICIT_VISIBILITY_IN_API_MODE.registerFactory(ChangeVisibilityFix.SetExplicitVisibilityFactory)
@@ -604,7 +603,7 @@ class QuickFixRegistrar : QuickFixContributor {
CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT.registerFactory(
MoveMemberToCompanionObjectIntention,
RemoveModifierFix.createRemoveModifierFactory()
RemoveModifierFix.removeNonRedundantModifier
)
NO_COMPANION_OBJECT.registerFactory(AddIsToWhenConditionFix)
@@ -614,7 +613,7 @@ class QuickFixRegistrar : QuickFixContributor {
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)
@@ -141,7 +141,7 @@ private val errorsFixingDiagnosticBasedPostProcessingGroup =
Errors.INVISIBLE_MEMBER
),
diagnosticBasedProcessing(
RemoveModifierFix.createRemoveModifierFactory(),
RemoveModifierFix.removeNonRedundantModifier,
Errors.WRONG_MODIFIER_TARGET
),
diagnosticBasedProcessing(
@@ -302,4 +302,4 @@ private val processings: List<NamedPostProcessingGroup> = listOf(
FormatCodeProcessing()
)
)
)
)