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
|
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
|
||||||
|
|
||||||
sealed class HLDiagnosticFixFactory<in DIAGNOSTIC : 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>(
|
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 class HLDiagnosticFixFactoryWithVariableApplicator<DIAGNOSTIC : KtDiagnosticWithPsi<*>>(
|
||||||
private val createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<HLQuickFix<*, *>>
|
private val createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<IntentionAction>
|
||||||
) : HLDiagnosticFixFactory<DIAGNOSTIC>() {
|
) : HLDiagnosticFixFactory<DIAGNOSTIC>() {
|
||||||
override fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<HLQuickFix<*, *>> =
|
override fun KtAnalysisSession.createQuickFixes(diagnostic: DIAGNOSTIC): List<IntentionAction> =
|
||||||
createQuickFixes.invoke(this, diagnostic)
|
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.
|
* Returns a [HLDiagnosticFixFactory] that creates [HLQuickFix]es from a diagnostic.
|
||||||
*/
|
*/
|
||||||
fun <DIAGNOSTIC : KtDiagnosticWithPsi<*>> diagnosticFixFactory(
|
fun <DIAGNOSTIC : KtDiagnosticWithPsi<*>> diagnosticFixFactory(
|
||||||
createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<HLQuickFix<*, *>>
|
createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List<IntentionAction>
|
||||||
): HLDiagnosticFixFactory<DIAGNOSTIC> =
|
): HLDiagnosticFixFactory<DIAGNOSTIC> =
|
||||||
HLDiagnosticFixFactoryWithVariableApplicator(createQuickFixes)
|
HLDiagnosticFixFactoryWithVariableApplicator(createQuickFixes)
|
||||||
|
|||||||
+2
-24
@@ -5,15 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.quickfix.fixes
|
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.fir.api.fixes.diagnosticFixFactory
|
||||||
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.frontend.api.types.KtTypeNullability
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeWithNullability
|
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.ReplaceImplicitReceiverCallFix
|
||||||
import org.jetbrains.kotlin.idea.quickfix.ReplaceWithSafeCallFix
|
import org.jetbrains.kotlin.idea.quickfix.ReplaceWithSafeCallFix
|
||||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||||
@@ -21,23 +16,6 @@ import org.jetbrains.kotlin.psi.KtExpression
|
|||||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
|
|
||||||
object ReplaceCallFixFactories {
|
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 =
|
val unsafeCallFactory =
|
||||||
diagnosticFixFactory<KtFirDiagnostic.UnsafeCall> { diagnostic ->
|
diagnosticFixFactory<KtFirDiagnostic.UnsafeCall> { diagnostic ->
|
||||||
fun KtExpression.shouldHaveNotNullType(): Boolean {
|
fun KtExpression.shouldHaveNotNullType(): Boolean {
|
||||||
@@ -48,13 +26,13 @@ object ReplaceCallFixFactories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
when (val psi = diagnostic.psi) {
|
when (val psi = diagnostic.psi) {
|
||||||
is KtDotQualifiedExpression -> listOf(HLQuickFix(psi, Input(psi.shouldHaveNotNullType()), replaceWithSafeCallFixApplicator))
|
is KtDotQualifiedExpression -> listOf(ReplaceWithSafeCallFix(psi, psi.shouldHaveNotNullType()))
|
||||||
is KtNameReferenceExpression -> {
|
is KtNameReferenceExpression -> {
|
||||||
// TODO: As a safety precaution, resolve the expression to determine if it is a call with an implicit receiver.
|
// 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 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
|
// This isn't strictly needed because FIR checkers aren't reporting on wrong elements, but ReplaceWithSafeCallFixFactory
|
||||||
// in FE1.0 does so.
|
// in FE1.0 does so.
|
||||||
listOf(HLQuickFix(psi, Input(psi.shouldHaveNotNullType()), replaceImplicitReceiverCallFixApplicator))
|
listOf(ReplaceImplicitReceiverCallFix(psi, psi.shouldHaveNotNullType()))
|
||||||
}
|
}
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user