From fb7e5d64147e83e5c7dbf8c50f474f16860b9e1f Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Thu, 28 Jan 2021 01:54:39 +0300 Subject: [PATCH] Refactor quickfix to clean API No need to have two methods and break nullable safety. Poetry plugin could be broken by this change, but Semyon.Proshev will send them a patch) GitOrigin-RevId: 024cd4861ff1cb65e34e5c2e6c5032ad86205b60 --- .../jetbrains/python/PythonSdkConfigurator.kt | 2 +- .../PyEnvironmentYmlSdkConfiguration.kt | 8 ++--- .../PyPipfileSdkConfiguration.kt | 10 +++--- ...equirementsTxtOrSetupPySdkConfiguration.kt | 9 ++---- .../PyProjectSdkConfigurationExtension.kt | 31 ++++++++++--------- .../inspections/PyInterpreterInspection.java | 17 +++++++--- 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/python/ide/impl/src/com/jetbrains/python/PythonSdkConfigurator.kt b/python/ide/impl/src/com/jetbrains/python/PythonSdkConfigurator.kt index 8af0c1409dcf7..8faf4c09db1e7 100644 --- a/python/ide/impl/src/com/jetbrains/python/PythonSdkConfigurator.kt +++ b/python/ide/impl/src/com/jetbrains/python/PythonSdkConfigurator.kt @@ -80,7 +80,7 @@ internal class PythonSdkConfigurator : DirectoryProjectConfigurator { private fun findExtension(module: Module): PyProjectSdkConfigurationExtension? { return if (ApplicationManager.getApplication().let { it.isHeadlessEnvironment || it.isUnitTestMode }) null - else PyProjectSdkConfigurationExtension.EP_NAME.findFirstSafe { it.isApplicable(module) } + else PyProjectSdkConfigurationExtension.EP_NAME.findFirstSafe { it.getIntention(module) != null } } private fun configureSdk(project: Project, diff --git a/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt b/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt index 01a2aeeff5721..665d33f68cd72 100644 --- a/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt +++ b/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyEnvironmentYmlSdkConfiguration.kt @@ -41,12 +41,10 @@ class PyEnvironmentYmlSdkConfiguration : PyProjectSdkConfigurationExtension { private val LOGGER = Logger.getInstance(PyEnvironmentYmlSdkConfiguration::class.java) - override fun isApplicable(module: Module): Boolean = getEnvironmentYml(module) != null - override fun createAndAddSdkForConfigurator(module: Module): Sdk? = createAndAddSdk(module, Source.CONFIGURATOR) - override fun getIntentionName(module: Module): @IntentionName String { - return PyCharmCommunityCustomizationBundle.message("sdk.create.condaenv.suggestion") + override fun getIntention(module: Module): @IntentionName String? = getEnvironmentYml(module)?.let { + PyCharmCommunityCustomizationBundle.message("sdk.create.condaenv.suggestion") } override fun createAndAddSdkForInspection(module: Module): Sdk? = createAndAddSdk(module, Source.INSPECTION) @@ -215,4 +213,4 @@ class PyEnvironmentYmlSdkConfiguration : PyProjectSdkConfigurationExtension { override fun doValidateAll(): List = panel.validateAll() } -} \ No newline at end of file +} diff --git a/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyPipfileSdkConfiguration.kt b/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyPipfileSdkConfiguration.kt index 0458885f6a1c6..d09804e81f5da 100644 --- a/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyPipfileSdkConfiguration.kt +++ b/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyPipfileSdkConfiguration.kt @@ -1,6 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.sdk.configuration +import com.intellij.codeInspection.util.IntentionName import com.intellij.execution.ExecutionException import com.intellij.ide.util.PropertiesComponent import com.intellij.openapi.application.ApplicationManager @@ -33,13 +34,10 @@ class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension { private val LOGGER = Logger.getInstance(PyPipfileSdkConfiguration::class.java) - override fun isApplicable(module: Module): Boolean = module.pipFile != null - override fun createAndAddSdkForConfigurator(module: Module): Sdk? = createAndAddSDk(module, Source.CONFIGURATOR) - override fun getIntentionName(module: Module): String { - return PyCharmCommunityCustomizationBundle.message("sdk.create.pipenv.suggestion", module.pipFile?.name) - } + override fun getIntention(module: Module): @IntentionName String? = + module.pipFile?.let { PyCharmCommunityCustomizationBundle.message("sdk.create.pipenv.suggestion", it.name) } override fun createAndAddSdkForInspection(module: Module): Sdk? = createAndAddSDk(module, Source.INSPECTION) @@ -158,4 +156,4 @@ class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension { override fun doValidateAll(): List = panel.validateAll() } -} \ No newline at end of file +} diff --git a/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt b/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt index ac20a6c133f3f..079019fea3c8b 100644 --- a/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt +++ b/python/ide/impl/src/com/jetbrains/python/sdk/configuration/PyRequirementsTxtOrSetupPySdkConfiguration.kt @@ -44,13 +44,10 @@ class PyRequirementsTxtOrSetupPySdkConfiguration : PyProjectSdkConfigurationExte private val LOGGER = Logger.getInstance(PyRequirementsTxtOrSetupPySdkConfiguration::class.java) - override fun isApplicable(module: Module): Boolean = getRequirementsTxtOrSetupPy(module) != null - override fun createAndAddSdkForConfigurator(module: Module) = createAndAddSdk(module, Source.CONFIGURATOR) - override fun getIntentionName(module: Module): @IntentionName String { - return PyCharmCommunityCustomizationBundle.message("sdk.create.venv.suggestion", getRequirementsTxtOrSetupPy(module)?.name) - } + override fun getIntention(module: Module): @IntentionName String? = + getRequirementsTxtOrSetupPy(module)?.let { PyCharmCommunityCustomizationBundle.message("sdk.create.venv.suggestion", it.name)} override fun createAndAddSdkForInspection(module: Module) = createAndAddSdk(module, Source.INSPECTION) @@ -209,4 +206,4 @@ class PyRequirementsTxtOrSetupPySdkConfiguration : PyProjectSdkConfigurationExte override fun doValidateAll(): List = panel.validateAll(CommonBundle.getOkButtonText()) } -} \ No newline at end of file +} diff --git a/python/python-sdk/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfigurationExtension.kt b/python/python-sdk/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfigurationExtension.kt index 2a25a80c19a82..6a0946b4dab74 100644 --- a/python/python-sdk/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfigurationExtension.kt +++ b/python/python-sdk/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfigurationExtension.kt @@ -20,18 +20,11 @@ interface PyProjectSdkConfigurationExtension { companion object { @JvmStatic val EP_NAME = ExtensionPointName.create("Pythonid.projectSdkConfigurationExtension") - } - /** - * Called by sdk configurator and interpreter inspection - * to determine if an extension could configure or suggest an interpreter for the passed [module]. - * - * First applicable extension is processed, others are ignored. - * If there is no applicable extension, configurator and inspection guess a suitable interpreter. - * - * Could be called from AWT hence should be as fast as possible. - */ - fun isApplicable(module: Module): Boolean + @JvmStatic + fun findForModule(module: Module): Pair<@IntentionName String, PyProjectSdkConfigurationExtension>? = + EP_NAME.computeSafeIfAny { ext -> ext.getIntention(module)?.let { Pair(it, ext) } } + } /** * An implementation is responsible for interpreter setup and registration in IDE. @@ -43,11 +36,21 @@ interface PyProjectSdkConfigurationExtension { fun createAndAddSdkForConfigurator(module: Module): Sdk? /** - * Returned string is used as a quick fix name. + * Called by sdk configurator and interpreter inspection + * to determine if an extension could configure or suggest an interpreter for the passed [module]. + * + * First applicable extension is processed, others are ignored. + * If there is no applicable extension, configurator and inspection guess a suitable interpreter. + * + * Could be called from AWT hence should be as fast as possible. + * + * If returned value is `null`, then the extension can't be used to configure an interpreter (not applicable). + * Otherwise returned string is used as a quick fix name. + * * Example: `Create a virtual environment using requirements.txt`. */ @IntentionName - fun getIntentionName(module: Module): String + fun getIntention(module: Module): String? /** * An implementation is responsible for interpreter setup and registration in IDE. @@ -57,4 +60,4 @@ interface PyProjectSdkConfigurationExtension { */ @RequiresBackgroundThread fun createAndAddSdkForInspection(module: Module): Sdk? -} \ No newline at end of file +} diff --git a/python/src/com/jetbrains/python/inspections/PyInterpreterInspection.java b/python/src/com/jetbrains/python/inspections/PyInterpreterInspection.java index ef5d783af79e1..8ff26399b882d 100644 --- a/python/src/com/jetbrains/python/inspections/PyInterpreterInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyInterpreterInspection.java @@ -38,6 +38,7 @@ import com.jetbrains.python.sdk.configuration.PyProjectSdkConfiguration; import com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension; import com.jetbrains.python.ui.PyUiUtil; +import kotlin.Pair; import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -166,8 +167,9 @@ private static LocalQuickFix getSuitableSdkFix(@Nullable String name, @NotNull M if (detectedAssociatedSdk != null) return new UseDetectedInterpreterFix(detectedAssociatedSdk, existingSdks, true, module); - final var extension = PyProjectSdkConfigurationExtension.getEP_NAME().findFirstSafe(e -> e.isApplicable(module)); - if (extension != null) return new UseProvidedInterpreterFix(module, extension); + final Pair<@IntentionName String, PyProjectSdkConfigurationExtension> textAndExtension + = PyProjectSdkConfigurationExtension.findForModule(module); + if (textAndExtension != null) return new UseProvidedInterpreterFix(module, textAndExtension.getSecond(), textAndExtension.getFirst()); if (name == null) return null; @@ -357,9 +359,16 @@ private static final class UseProvidedInterpreterFix implements LocalQuickFix { @NotNull private final PyProjectSdkConfigurationExtension myExtension; - private UseProvidedInterpreterFix(@NotNull Module module, @NotNull PyProjectSdkConfigurationExtension extension) { + @NotNull + @IntentionName + private final String myName; + + private UseProvidedInterpreterFix(@NotNull Module module, + @NotNull PyProjectSdkConfigurationExtension extension, + @NotNull @IntentionName String name) { myModule = module; myExtension = extension; + myName = name; } @Override @@ -369,7 +378,7 @@ private UseProvidedInterpreterFix(@NotNull Module module, @NotNull PyProjectSdkC @Override public @IntentionName @NotNull String getName() { - return myExtension.getIntentionName(myModule); + return myName; } @Override