FIR IDE: allow HLDiagnosticFixFactory creating any intention
It seems unnecessary to force all quickfixes to fit the `HLQuickfix` API, especially for those existing trivial fixes that simply modifies PSI tree. This change further loosen the API of `HLDiagnosticFixFactory` to allow it to create arbitrary `IntentionAction` objects. This also avoids code duplication (for example, specify the family name again in `ReplaceCallFixFactories`). `HLQuickfix` and the input/target paradighm can still be used where applicable.
This commit is contained in:
committed by
Ilya Kirillov
parent
5609645156
commit
0d9991ebcd
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
|
||||
|
||||
sealed class HLDiagnosticFixFactory<in DIAGNOSTIC : KtDiagnosticWithPsi<*>> {
|
||||
abstract fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<HLQuickFix<*, *>>
|
||||
abstract fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<IntentionAction>
|
||||
}
|
||||
|
||||
private class HLDiagnosticFixFactoryWithFixedApplicator<DIAGNOSTIC : KtDiagnosticWithPsi<*>, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput>(
|
||||
@@ -25,9 +25,9 @@ private class HLDiagnosticFixFactoryWithFixedApplicator<DIAGNOSTIC : KtDiagnosti
|
||||
}
|
||||
|
||||
private class HLDiagnosticFixFactoryWithVariableApplicator<DIAGNOSTIC : KtDiagnosticWithPsi<*>>(
|
||||
private val createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<HLQuickFix<*, *>>
|
||||
private val createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<IntentionAction>
|
||||
) : HLDiagnosticFixFactory<DIAGNOSTIC>() {
|
||||
override fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<HLQuickFix<*, *>> =
|
||||
override fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<IntentionAction> =
|
||||
createQuickFixes.invoke(this, diagnostic)
|
||||
}
|
||||
|
||||
@@ -50,6 +50,6 @@ fun <DIAGNOSTIC : KtDiagnosticWithPsi<*>, TARGET_PSI : PsiElement, INPUT : HLApp
|
||||
* Returns a [HLDiagnosticFixFactory] that creates [HLQuickFix]es from a diagnostic.
|
||||
*/
|
||||
fun <DIAGNOSTIC : KtDiagnosticWithPsi<*>> diagnosticFixFactory(
|
||||
createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<HLQuickFix<*, *>>
|
||||
createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<IntentionAction>
|
||||
): HLDiagnosticFixFactory<DIAGNOSTIC> =
|
||||
HLDiagnosticFixFactoryWithVariableApplicator(createQuickFixes)
|
||||
|
||||
+2
-24
@@ -5,15 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix.fixes
|
||||
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.fir.api.applicator.HLApplicatorInput
|
||||
import org.jetbrains.kotlin.idea.fir.api.applicator.applicatorByQuickFix
|
||||
import org.jetbrains.kotlin.idea.fir.api.fixes.HLQuickFix
|
||||
import org.jetbrains.kotlin.idea.fir.api.fixes.diagnosticFixFactory
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeWithNullability
|
||||
import org.jetbrains.kotlin.idea.quickfix.ReplaceCallFix
|
||||
import org.jetbrains.kotlin.idea.quickfix.ReplaceImplicitReceiverCallFix
|
||||
import org.jetbrains.kotlin.idea.quickfix.ReplaceWithSafeCallFix
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
@@ -21,23 +16,6 @@ import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
|
||||
object ReplaceCallFixFactories {
|
||||
private val replaceWithSafeCallFixApplicator =
|
||||
applicatorByQuickFix<KtExpression, Input, ReplaceCallFix>(
|
||||
getFamilyName = KotlinBundle.lazyMessage("replace.with.safe.call"),
|
||||
isApplicableByPsi = { psi -> psi is KtDotQualifiedExpression }
|
||||
) { psi, input ->
|
||||
ReplaceWithSafeCallFix(psi as KtDotQualifiedExpression, input.notNullNeeded)
|
||||
}
|
||||
|
||||
private val replaceImplicitReceiverCallFixApplicator =
|
||||
applicatorByQuickFix<KtExpression, Input, ReplaceImplicitReceiverCallFix>(
|
||||
getFamilyName = KotlinBundle.lazyMessage("replace.with.safe.this.call")
|
||||
) { psi, input ->
|
||||
ReplaceImplicitReceiverCallFix(psi, input.notNullNeeded)
|
||||
}
|
||||
|
||||
class Input(val notNullNeeded: Boolean) : HLApplicatorInput
|
||||
|
||||
val unsafeCallFactory =
|
||||
diagnosticFixFactory<KtFirDiagnostic.UnsafeCall> { diagnostic ->
|
||||
fun KtExpression.shouldHaveNotNullType(): Boolean {
|
||||
@@ -48,13 +26,13 @@ object ReplaceCallFixFactories {
|
||||
}
|
||||
|
||||
when (val psi = diagnostic.psi) {
|
||||
is KtDotQualifiedExpression -> listOf(HLQuickFix(psi, Input(psi.shouldHaveNotNullType()), replaceWithSafeCallFixApplicator))
|
||||
is KtDotQualifiedExpression -> listOf(ReplaceWithSafeCallFix(psi, psi.shouldHaveNotNullType()))
|
||||
is KtNameReferenceExpression -> {
|
||||
// TODO: As a safety precaution, resolve the expression to determine if it is a call with an implicit receiver.
|
||||
// This is a defensive check to ensure that the diagnostic was reported on such a call and not some other name reference.
|
||||
// This isn't strictly needed because FIR checkers aren't reporting on wrong elements, but ReplaceWithSafeCallFixFactory
|
||||
// in FE1.0 does so.
|
||||
listOf(HLQuickFix(psi, Input(psi.shouldHaveNotNullType()), replaceImplicitReceiverCallFixApplicator))
|
||||
listOf(ReplaceImplicitReceiverCallFix(psi, psi.shouldHaveNotNullType()))
|
||||
}
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user