From 3ebdfa3850a7ff28a1ec42675d7e80519eb8f7d7 Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Tue, 9 Mar 2021 23:08:41 +0000 Subject: [PATCH] FIR IDE: Implement applicatorByQuickFix() to re-use quick fix actions from idea-frontend-independent. --- .../idea/fir/api/applicator/HLApplicator.kt | 17 +++++++++ .../fixes/HLApplicatorWithTargetAndInput.kt | 19 ++++++++++ .../fir/api/fixes/HLDiagnosticFixFactory.kt | 38 ++++++++++++++----- 3 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/fixes/HLApplicatorWithTargetAndInput.kt diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/applicator/HLApplicator.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/applicator/HLApplicator.kt index a89468bf2b5..7548cb889e0 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/applicator/HLApplicator.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/applicator/HLApplicator.kt @@ -10,6 +10,7 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.PrivateForInline import org.jetbrains.kotlin.idea.frontend.api.ForbidKtResolve +import org.jetbrains.kotlin.idea.quickfix.KotlinPsiOnlyQuickFixAction import kotlin.experimental.ExperimentalTypeInference import kotlin.reflect.KClass @@ -194,3 +195,19 @@ fun applicator( init: HLApplicatorBuilder.() -> Unit, ): HLApplicator = HLApplicatorBuilder().apply(init).build() + +/** + * Builds a new applicator that uses a [KotlinPsiOnlyQuickFixAction] to apply the fix to the PSI + * + * @see HLApplicator + */ +fun > applicatorByQuickFix( + getFamilyName: () -> String, + isApplicableByPsi: (PSI) -> Boolean = { true }, + quickFixByInput: (PSI, INPUT) -> QUICK_FIX, +): HLApplicator = HLApplicatorImpl( + applyTo = { psi, input, project, editor -> quickFixByInput(psi, input).invoke(project ?: psi.project, editor, psi.containingFile) }, + isApplicableByPsi = isApplicableByPsi, + getActionName = { psi, input -> quickFixByInput(psi, input).text }, + getFamilyName = getFamilyName +) diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/fixes/HLApplicatorWithTargetAndInput.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/fixes/HLApplicatorWithTargetAndInput.kt new file mode 100644 index 00000000000..aa5dd0163b4 --- /dev/null +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/fixes/HLApplicatorWithTargetAndInput.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.fir.api.fixes + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.idea.fir.api.applicator.HLApplicator +import org.jetbrains.kotlin.idea.fir.api.applicator.HLApplicatorInput + +class HLApplicatorWithTargetAndInput( + val applicator: HLApplicator, + private val targetAndInput: HLApplicatorTargetWithInput, +) { + operator fun component1() = applicator + operator fun component2() = targetAndInput.target + operator fun component3() = targetAndInput.input +} diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/fixes/HLDiagnosticFixFactory.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/fixes/HLDiagnosticFixFactory.kt index 7ee87cd22ba..5c37c0d6b07 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/fixes/HLDiagnosticFixFactory.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/api/fixes/HLDiagnosticFixFactory.kt @@ -12,17 +12,22 @@ 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, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput>( - val applicator: HLApplicator -) { - abstract fun KtAnalysisSession.createTargets(diagnostic: DIAGNOSTIC): List> +sealed class HLDiagnosticFixFactory, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput> { + abstract fun KtAnalysisSession.createTargets(diagnostic: DIAGNOSTIC): List> } -private class HLDiagnosticFixFactoryImpl, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput>( - applicator: HLApplicator, +private class HLDiagnosticFixFactoryWithFixedApplicator, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput>( + private val applicator: HLApplicator, private val createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List> -) : HLDiagnosticFixFactory(applicator) { - override fun KtAnalysisSession.createTargets(diagnostic: DIAGNOSTIC): List> = +) : HLDiagnosticFixFactory() { + override fun KtAnalysisSession.createTargets(diagnostic: DIAGNOSTIC): List> = + createQuickFixes.invoke(this, diagnostic).map { targetAndInput -> HLApplicatorWithTargetAndInput(applicator, targetAndInput) } +} + +private class HLDiagnosticFixFactoryWithVariableApplicator, TARGET_PSI : PsiElement, INPUT : HLApplicatorInput>( + private val createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List> +) : HLDiagnosticFixFactory() { + override fun KtAnalysisSession.createTargets(diagnostic: DIAGNOSTIC): List> = createQuickFixes.invoke(this, diagnostic) } @@ -30,11 +35,24 @@ internal fun > KtAnalysisSession.cr diagnostic: DIAGNOSTIC, factory: HLDiagnosticFixFactory ): List = with(factory) { - createTargets(diagnostic).map { (target, input) -> HLQuickFix(target, input, factory.applicator) } + createTargets(diagnostic).map { (applicator, target, input) -> HLQuickFix(target, input, applicator) } } +/** + * Returns a [HLDiagnosticFixFactory] that creates targets and inputs ([HLApplicatorTargetWithInput]) from a diagnostic. + * The targets and inputs are consumed by the given applicator to apply fixes. + */ fun , TARGET_PSI : PsiElement, INPUT : HLApplicatorInput> diagnosticFixFactory( applicator: HLApplicator, createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List> ): HLDiagnosticFixFactory = - HLDiagnosticFixFactoryImpl(applicator, createQuickFixes) \ No newline at end of file + HLDiagnosticFixFactoryWithFixedApplicator(applicator, createQuickFixes) + +/** + * Returns a [HLDiagnosticFixFactory] that creates applicators, targets, and inputs ([HLApplicatorWithTargetAndInput]) from a diagnostic. + * The targets and inputs are consumed by the corresponding applicator to apply fixes. + */ +fun , TARGET_PSI : PsiElement, INPUT : HLApplicatorInput> diagnosticFixFactory( + createQuickFixes: KtAnalysisSession.(DIAGNOSTIC) -> List> +): HLDiagnosticFixFactory = + HLDiagnosticFixFactoryWithVariableApplicator(createQuickFixes)