FIR IDE: remove type parameter TARGET_PSI and INPUT
The factory does not need to care about what target PSI and input a quick fix should need. We only need to ensure these two types match when an `HLQuickfix` is created. With this constraint loosened, now one factory can register multiple quickfixes applied on different targets and different input. This makes it much more flexible when implementing quickfixes.
This commit is contained in:
committed by
Ilya Kirillov
parent
a5e445492f
commit
6c52d95342
+12
-12
@@ -12,28 +12,28 @@ import org.jetbrains.kotlin.idea.fir.api.applicator.HLApplicatorInput
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
|
||||
|
||||
sealed class HLDiagnosticFixFactory<DIAGNOSTIC_PSI : PsiElement, in DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput> {
|
||||
abstract fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<HLQuickFix<TARGET_PSI, INPUT>>
|
||||
sealed class HLDiagnosticFixFactory<DIAGNOSTIC_PSI : PsiElement, in DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> {
|
||||
abstract fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<HLQuickFix<*, *>>
|
||||
}
|
||||
|
||||
private class HLDiagnosticFixFactoryWithFixedApplicator<DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput>(
|
||||
private val applicator: HLApplicator<TARGET_PSI, INPUT>,
|
||||
private val createTargets: KtAnalysisSession.(DIAGNOSTIC) -> List<HLApplicatorTargetWithInput<TARGET_PSI, INPUT>>
|
||||
) : HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC, TARGET_PSI, INPUT>() {
|
||||
) : HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC>() {
|
||||
override fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<HLQuickFix<TARGET_PSI, INPUT>> =
|
||||
createTargets.invoke(this, diagnostic).map { (target, input) -> HLQuickFix(target, input, applicator) }
|
||||
}
|
||||
|
||||
private class HLDiagnosticFixFactoryWithVariableApplicator<DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput>(
|
||||
private val createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<HLQuickFix<TARGET_PSI, INPUT>>
|
||||
) : HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC, TARGET_PSI, INPUT>() {
|
||||
override fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<HLQuickFix<TARGET_PSI, INPUT>> =
|
||||
private class HLDiagnosticFixFactoryWithVariableApplicator<DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>>(
|
||||
private val createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<HLQuickFix<*, *>>
|
||||
) : HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC>() {
|
||||
override fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<HLQuickFix<*, *>> =
|
||||
createQuickFixes.invoke(this, diagnostic)
|
||||
}
|
||||
|
||||
internal fun <DIAGNOSTIC : KtDiagnosticWithPsi<PsiElement>> KtAnalysisSession.createPlatformQuickFixes(
|
||||
diagnostic: DIAGNOSTIC,
|
||||
factory: HLDiagnosticFixFactory<PsiElement, DIAGNOSTIC, PsiElement, HLApplicatorInput>
|
||||
factory: HLDiagnosticFixFactory<PsiElement, DIAGNOSTIC>
|
||||
): List<IntentionAction> = with(factory) { createQuickFixes(diagnostic) }
|
||||
|
||||
/**
|
||||
@@ -43,13 +43,13 @@ internal fun <DIAGNOSTIC : KtDiagnosticWithPsi<PsiElement>> KtAnalysisSession.cr
|
||||
fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput> diagnosticFixFactory(
|
||||
applicator: HLApplicator<TARGET_PSI, INPUT>,
|
||||
createTargets: KtAnalysisSession.(DIAGNOSTIC) -> List<HLApplicatorTargetWithInput<TARGET_PSI, INPUT>>
|
||||
): HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC, TARGET_PSI, INPUT> =
|
||||
): HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC> =
|
||||
HLDiagnosticFixFactoryWithFixedApplicator(applicator, createTargets)
|
||||
|
||||
/**
|
||||
* Returns a [HLDiagnosticFixFactory] that creates [HLQuickFix]es from a diagnostic.
|
||||
*/
|
||||
fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput> diagnosticFixFactory(
|
||||
createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<HLQuickFix<TARGET_PSI, INPUT>>
|
||||
): HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC, TARGET_PSI, INPUT> =
|
||||
fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> diagnosticFixFactory(
|
||||
createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<HLQuickFix<*, *>>
|
||||
): HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC> =
|
||||
HLDiagnosticFixFactoryWithVariableApplicator(createQuickFixes)
|
||||
|
||||
@@ -30,7 +30,7 @@ class KtQuickFixesList @ForKtQuickFixesListBuilder @OptIn(PrivateForInline::clas
|
||||
is HLQuickFixFactory.HLApplicatorBasedFactory -> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val factory = quickFixFactory.applicatorFactory
|
||||
as HLDiagnosticFixFactory<PsiElement, KtDiagnosticWithPsi<PsiElement>, PsiElement, HLApplicatorInput>
|
||||
as HLDiagnosticFixFactory<PsiElement, KtDiagnosticWithPsi<PsiElement>>
|
||||
createPlatformQuickFixes(diagnostic, factory)
|
||||
}
|
||||
is HLQuickFixFactory.HLQuickFixesPsiBasedFactory -> quickFixFactory.psiFactory.createQuickFix(diagnostic.psi)
|
||||
@@ -66,8 +66,8 @@ class KtQuickFixesListBuilder private constructor() {
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <DIAGNOSTIC_PSI : PsiElement, reified DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput> registerApplicator(
|
||||
quickFixFactory: HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC, TARGET_PSI, INPUT>
|
||||
inline fun <DIAGNOSTIC_PSI : PsiElement, reified DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> registerApplicator(
|
||||
quickFixFactory: HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC>
|
||||
) {
|
||||
registerApplicator(DIAGNOSTIC::class, quickFixFactory)
|
||||
}
|
||||
@@ -82,9 +82,9 @@ class KtQuickFixesListBuilder private constructor() {
|
||||
|
||||
|
||||
@PrivateForInline
|
||||
fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput> registerApplicator(
|
||||
fun <DIAGNOSTIC_PSI : PsiElement, DIAGNOSTIC : KtDiagnosticWithPsi<DIAGNOSTIC_PSI>> registerApplicator(
|
||||
diagnosticClass: KClass<DIAGNOSTIC>,
|
||||
quickFixFactory: HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC, TARGET_PSI, INPUT>
|
||||
quickFixFactory: HLDiagnosticFixFactory<DIAGNOSTIC_PSI, DIAGNOSTIC>
|
||||
) {
|
||||
quickFixes.getOrPut(diagnosticClass) { mutableListOf() }
|
||||
.add(HLQuickFixFactory.HLApplicatorBasedFactory(quickFixFactory))
|
||||
@@ -105,7 +105,7 @@ sealed class HLQuickFixFactory {
|
||||
) : HLQuickFixFactory()
|
||||
|
||||
class HLApplicatorBasedFactory(
|
||||
val applicatorFactory: HLDiagnosticFixFactory<*, *, *, *>
|
||||
val applicatorFactory: HLDiagnosticFixFactory<*, *>
|
||||
) : HLQuickFixFactory()
|
||||
}
|
||||
|
||||
@@ -121,4 +121,4 @@ private fun <K, V> List<Map<K, List<V>>>.merge(): Map<K, List<V>> {
|
||||
}
|
||||
|
||||
@RequiresOptIn
|
||||
annotation class ForKtQuickFixesListBuilder()
|
||||
annotation class ForKtQuickFixesListBuilder
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ object ReplaceCallFixFactories {
|
||||
class Input(val notNullNeeded: Boolean) : HLApplicatorInput
|
||||
|
||||
val unsafeCallFactory =
|
||||
diagnosticFixFactory<PsiElement, KtFirDiagnostic.UnsafeCall, KtExpression, Input> { diagnostic ->
|
||||
diagnosticFixFactory<PsiElement, KtFirDiagnostic.UnsafeCall> { diagnostic ->
|
||||
fun KtExpression.shouldHaveNotNullType(): Boolean {
|
||||
// This function is used to determine if we may need to add an elvis operator after the safe call. For example, to replace
|
||||
// `s.length` in `val x: Int = s.length` with a safe call, it should be replaced with `s.length ?: <caret>`.
|
||||
|
||||
Reference in New Issue
Block a user