Skip to content

Commit

Permalink
Refactor quickfix to clean API
Browse files Browse the repository at this point in the history
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
  • Loading branch information
throwable-one authored and intellij-monorepo-bot committed Jan 28, 2021
1 parent 3724696 commit fb7e5d6
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 36 deletions.
Expand Up @@ -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,
Expand Down
Expand Up @@ -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)
Expand Down Expand Up @@ -215,4 +213,4 @@ class PyEnvironmentYmlSdkConfiguration : PyProjectSdkConfigurationExtension {

override fun doValidateAll(): List<ValidationInfo> = panel.validateAll()
}
}
}
@@ -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
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -158,4 +156,4 @@ class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension {

override fun doValidateAll(): List<ValidationInfo> = panel.validateAll()
}
}
}
Expand Up @@ -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)

Expand Down Expand Up @@ -209,4 +206,4 @@ class PyRequirementsTxtOrSetupPySdkConfiguration : PyProjectSdkConfigurationExte

override fun doValidateAll(): List<ValidationInfo> = panel.validateAll(CommonBundle.getOkButtonText())
}
}
}
Expand Up @@ -20,18 +20,11 @@ interface PyProjectSdkConfigurationExtension {
companion object {
@JvmStatic
val EP_NAME = ExtensionPointName.create<PyProjectSdkConfigurationExtension>("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.
Expand All @@ -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.
Expand All @@ -57,4 +60,4 @@ interface PyProjectSdkConfigurationExtension {
*/
@RequiresBackgroundThread
fun createAndAddSdkForInspection(module: Module): Sdk?
}
}
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand All @@ -369,7 +378,7 @@ private UseProvidedInterpreterFix(@NotNull Module module, @NotNull PyProjectSdkC

@Override
public @IntentionName @NotNull String getName() {
return myExtension.getIntentionName(myModule);
return myName;
}

@Override
Expand Down

0 comments on commit fb7e5d6

Please sign in to comment.