提交 0d9991eb 编写于 作者: T Tianyu Geng 提交者: Ilya Kirillov

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.
上级 56096451
...@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession ...@@ -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 ...@@ -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 ...@@ -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)
...@@ -5,15 +5,10 @@ ...@@ -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 ...@@ -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 { ...@@ -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()
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册