mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-88280 Extract autoConfigureSdkIfNeeded and simplify SDK auto-configuration
- Add autoConfigureSdkIfNeeded to sdkSuggestionTools that waits for project model and uses the global mutex - Add early return in getModuleInfo when SDK is already configured - Simplify ModulesSdkConfigurator to use autoConfigureSdkIfNeeded - Simplify InterpreterSettingsQuickFix to use autoConfigureSdkIfNeeded - Remove SDK-configured notification from PyProjectSdkConfiguration (cherry picked from commit f1423427eeb433d379519e3b9d1af00b46fc869d) GitOrigin-RevId: b81353d3af62f2d1f694d8c0d470d4495a01c989
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4bf4e78ab1
commit
17c8522684
+53
-1
@@ -2,13 +2,23 @@ package com.intellij.python.pyproject.model.api
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.guessModuleDir
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.python.common.tools.ToolId
|
||||
import com.intellij.python.pyproject.model.internal.suggestSdkImpl
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.onSuccess
|
||||
import com.jetbrains.python.sdk.configuration.CreateSdkInfo
|
||||
import com.jetbrains.python.sdk.configuration.CreateSdkInfoWithTool
|
||||
import com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension
|
||||
import com.jetbrains.python.sdk.configuration.findPythonVirtualEnvironments
|
||||
import com.jetbrains.python.sdk.configuration.getSdkCreator
|
||||
import com.jetbrains.python.sdk.findPythonSdk
|
||||
import com.jetbrains.python.sdk.legacy.PythonSdkUtil
|
||||
import com.jetbrains.python.sdk.pythonSdk
|
||||
import com.jetbrains.python.sdk.pythonSdkConfigurationMutex
|
||||
import com.jetbrains.python.sdk.setAssociationToModule
|
||||
import com.jetbrains.python.venvReader.Directory
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
|
||||
sealed interface SuggestedSdk {
|
||||
@@ -33,11 +43,19 @@ suspend fun Module.suggestSdk(): SuggestedSdk? = suggestSdkImpl(this)
|
||||
|
||||
|
||||
/**
|
||||
* For multiple calls, pull [configuratorsByTool] up not to create it each time
|
||||
* Suggests an [ModuleCreateInfo] for this module, or returns `null` if the module
|
||||
* already has a Python SDK or is not a Python module.
|
||||
*
|
||||
* Suspends until the project model is fully loaded (via [findPythonSdk]) before checking,
|
||||
* so it is safe to call during startup without risking a false positive from a stale SDK table.
|
||||
*
|
||||
* For multiple calls, pull [configuratorsByTool] up not to create it each time.
|
||||
*/
|
||||
suspend fun Module.getModuleInfo(
|
||||
configuratorsByTool: Map<ToolId, PyProjectSdkConfigurationExtension> = PyProjectSdkConfigurationExtension.createMap(),
|
||||
): ModuleCreateInfo? { // Save on module level
|
||||
findPythonSdk()?.let { return null }
|
||||
|
||||
val venvsInModule = findPythonVirtualEnvironments()
|
||||
val bestProposalFromTools = PyProjectSdkConfigurationExtension.findAllSortedForModule(this, venvsInModule).firstOrNull()
|
||||
|
||||
@@ -76,3 +94,37 @@ sealed interface ModuleCreateInfo {
|
||||
|
||||
private fun CreateSdkInfoWithTool.asDTO(moduleDir: Directory?): ModuleCreateInfo =
|
||||
ModuleCreateInfo.CreateSdkInfoWrapper(createSdkInfo, toolId, moduleDir)
|
||||
|
||||
|
||||
/**
|
||||
* Auto-configures a Python SDK for the module if one doesn't already exist.
|
||||
*
|
||||
* Waits for the SDK table to load (to avoid overwriting a persisted SDK that hasn't resolved yet),
|
||||
* then detects the best SDK using [getModuleInfo] and assigns it to the module.
|
||||
*
|
||||
* Returns the configured SDK, or `null` if no SDK could be configured.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
suspend fun Module.autoConfigureSdkIfNeeded(): PyResult<Sdk>? = pythonSdkConfigurationMutex.withLock {
|
||||
val moduleInfo = getModuleInfo() ?: return@withLock null
|
||||
|
||||
when (moduleInfo) {
|
||||
is ModuleCreateInfo.CreateSdkInfoWrapper -> {
|
||||
when (moduleInfo.createSdkInfo) {
|
||||
is CreateSdkInfo.ExistingEnv -> {
|
||||
moduleInfo.createSdkInfo.getSdkCreator(this).createSdk().onSuccess {sdk ->
|
||||
pythonSdk = sdk
|
||||
sdk.setAssociationToModule(this)
|
||||
}
|
||||
}
|
||||
is CreateSdkInfo.WillCreateEnv, is CreateSdkInfo.WillInstallTool -> null
|
||||
}
|
||||
}
|
||||
is ModuleCreateInfo.SameAs -> {
|
||||
moduleInfo.parentModule.findPythonSdk()?.let { parentSdk ->
|
||||
pythonSdk = parentSdk
|
||||
PyResult.success(parentSdk)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.intellij.openapi.util.removeUserData
|
||||
import com.intellij.platform.ide.progress.withBackgroundProgress
|
||||
import com.intellij.python.pyproject.model.api.ModuleCreateInfo
|
||||
import com.intellij.python.pyproject.model.api.SuggestedSdk
|
||||
import com.intellij.python.pyproject.model.api.autoConfigureSdkIfNeeded
|
||||
import com.intellij.python.pyproject.model.api.getModuleInfo
|
||||
import com.intellij.python.pyproject.model.api.suggestSdk
|
||||
import com.intellij.python.sdkConfigurator.backend.impl.ModulesSdkConfigurator.Companion.create
|
||||
@@ -24,9 +25,10 @@ import com.jetbrains.python.orLogException
|
||||
import com.jetbrains.python.sdk.configuration.CreateSdkInfo
|
||||
import com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension
|
||||
import com.jetbrains.python.sdk.configuration.createSdk
|
||||
import com.jetbrains.python.sdk.configuration.getSdkCreator
|
||||
import com.jetbrains.python.sdk.findPythonSdk
|
||||
import com.jetbrains.python.sdk.getOrCreateAdditionalData
|
||||
import com.jetbrains.python.sdk.legacy.PythonSdkUtil
|
||||
import com.jetbrains.python.sdk.pythonSdkConfigurationMutex
|
||||
import com.jetbrains.python.sdk.pythonSdk
|
||||
import com.jetbrains.python.sdk.setAssociationToPath
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
@@ -111,7 +113,7 @@ internal class ModulesSdkConfigurator private constructor(
|
||||
withBackgroundProgress(project, PySdkConfiguratorBundle.message("intellij.python.sdk.looking")) {
|
||||
val tools = PyProjectSdkConfigurationExtension.createMap()
|
||||
val now = System.currentTimeMillis()
|
||||
val resultDef = project.modules.filter { PythonSdkUtil.findPythonSdk(it) == null }.map { module ->
|
||||
val resultDef = project.modules.filter { it.findPythonSdk() != null }.map { module ->
|
||||
async {
|
||||
val moduleInfo = module.getModuleInfo(tools) ?: return@async null
|
||||
Pair(module, moduleInfo)
|
||||
@@ -136,7 +138,7 @@ internal class ModulesSdkConfigurator private constructor(
|
||||
* Errors are logged.
|
||||
*
|
||||
*/
|
||||
suspend fun configureSdks(modulesOnly: Set<ModuleName>) {
|
||||
suspend fun configureSdks(modulesOnly: Set<ModuleName>) = pythonSdkConfigurationMutex.withLock {
|
||||
withContext(Dispatchers.Default) {
|
||||
val modulesMap = project.modules.associateBy { it.name }
|
||||
val modulesWithSameSdk = mutableMapOf<Module, Module>()
|
||||
@@ -190,78 +192,28 @@ internal class ModulesSdkConfigurator private constructor(
|
||||
@ApiStatus.Internal // Opened for tests only: we can't put tests here because configurators are in communuty.impl
|
||||
suspend fun configureSdkAutomatically(project: Project): Unit = withContext(Dispatchers.Default) {
|
||||
val moduleService = PyModuleService.getInstance(project)
|
||||
val modules = project.modules.filter { moduleService.isPythonModule(it) }
|
||||
val pythonModules = project.modules.filter { moduleService.isPythonModule(it) }
|
||||
|
||||
when (modules.size) {
|
||||
when (pythonModules.size) {
|
||||
0 -> return@withContext
|
||||
1 -> { // Single-module project, associate first module only
|
||||
val module = modules.first()
|
||||
if (PythonSdkUtil.findPythonSdk(module) != null) return@withContext // Already has SDK
|
||||
configureSdkForModuleAutomatically(module, createEnvIfNeeded = false)
|
||||
}
|
||||
else -> { // Multi-module project, only associate workspace members
|
||||
val modulesToSdk = modules.filter { PythonSdkUtil.findPythonSdk(it) == null }.associateWith { it.suggestSdk() }
|
||||
for ((module, sdkSuggestion) in modulesToSdk) {
|
||||
1 -> pythonModules.first().autoConfigureSdkIfNeeded()?.orLogException(logger)
|
||||
else -> pythonSdkConfigurationMutex.withLock {
|
||||
for (module in pythonModules) {
|
||||
if (module.findPythonSdk() != null) continue
|
||||
val sdkSuggestion = module.suggestSdk()
|
||||
when (sdkSuggestion) {
|
||||
is SuggestedSdk.SameAs -> {
|
||||
val parentSdk = PythonSdkUtil.findPythonSdk(sdkSuggestion.parentModule) ?: continue
|
||||
module.pythonSdk = parentSdk
|
||||
}
|
||||
is SuggestedSdk.PyProjectIndependent, null -> {
|
||||
logger.trace { "${module.name} skipped in multimodule project autoconfig" }
|
||||
}
|
||||
is SuggestedSdk.SameAs -> {
|
||||
setModuleSdkAsParent(parentModule = sdkSuggestion.parentModule, module = module)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun configureSdkForModuleAutomatically(module: Module, createEnvIfNeeded: Boolean) {
|
||||
when (val moduleInfo = module.getModuleInfo()) {
|
||||
is ModuleCreateInfo.CreateSdkInfoWrapper -> {
|
||||
when (val info = moduleInfo.createSdkInfo) {
|
||||
is CreateSdkInfo.ExistingEnv -> {
|
||||
info.createAndSetToModule(module)
|
||||
}
|
||||
is CreateSdkInfo.WillCreateEnv -> {
|
||||
if (createEnvIfNeeded) {
|
||||
info.createAndSetToModule(module)
|
||||
}
|
||||
else {
|
||||
logger.trace { "${module.name} can't be configured automatically: no venv for ${moduleInfo.toolId}" }
|
||||
}
|
||||
}
|
||||
is CreateSdkInfo.WillInstallTool -> logger.trace { "${module.name} can't be configured automatically: no tool installed - ${moduleInfo.toolId}" }
|
||||
}
|
||||
}
|
||||
is ModuleCreateInfo.SameAs -> {
|
||||
val parentModule = moduleInfo.parentModule
|
||||
setModuleSdkAsParent(parentModule = parentModule, module = module)
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun CreateSdkInfo.createAndSetToModule(module: Module) {
|
||||
when (val r = getSdkCreator(module).createSdk()) {
|
||||
is Result.Failure -> {
|
||||
logger.trace { "Failed to create sdk for ${module.name} : ${r.error}" }
|
||||
}
|
||||
is Result.Success -> {
|
||||
val sdk = r.result
|
||||
module.pythonSdk = sdk
|
||||
logger.trace { "SDK creation result for ${module.name} : $sdk" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setModuleSdkAsParent(
|
||||
parentModule: Module,
|
||||
module: Module,
|
||||
) {
|
||||
val parentSdk = PythonSdkUtil.findPythonSdk(parentModule) ?: return
|
||||
logger.trace { "${module.name} seeds the same sdk as ${parentModule} : ${parentSdk}" }
|
||||
module.pythonSdk = parentSdk
|
||||
}
|
||||
|
||||
|
||||
private val logger = fileLogger()
|
||||
|
||||
+45
-76
@@ -18,37 +18,34 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import com.intellij.openapi.vfs.newvfs.RefreshQueue
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService
|
||||
import com.intellij.openapi.ui.popup.JBPopup
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.openapi.util.use
|
||||
import com.intellij.openapi.vfs.newvfs.RefreshQueue
|
||||
import com.intellij.platform.ide.progress.withBackgroundProgress
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.python.common.tools.ToolId
|
||||
import com.intellij.python.pyproject.model.api.ModuleCreateInfo
|
||||
import com.intellij.python.pyproject.model.api.autoConfigureSdkIfNeeded
|
||||
import com.intellij.python.pyproject.model.api.getModuleInfo
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.ui.components.ActionLink
|
||||
import com.intellij.ui.components.DropDownLink
|
||||
import com.intellij.util.PlatformUtils
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.inspections.InspectionRunnerResult
|
||||
import com.intellij.openapi.ui.popup.JBPopup
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.ui.components.ActionLink
|
||||
import com.intellij.ui.components.DropDownLink
|
||||
import com.jetbrains.python.orLogException
|
||||
import com.jetbrains.python.sdk.ModuleOrProject
|
||||
import com.jetbrains.python.sdk.collectAddInterpreterActions
|
||||
import com.intellij.openapi.util.use
|
||||
import com.intellij.platform.ide.progress.withBackgroundProgress
|
||||
import com.jetbrains.python.sdk.configuration.CreateSdkInfo
|
||||
import com.jetbrains.python.sdk.configuration.CreateSdkInfoWithTool
|
||||
import com.jetbrains.python.sdk.configuration.PyProjectSdkConfiguration
|
||||
import com.jetbrains.python.sdk.configuration.createSdk
|
||||
import com.jetbrains.python.sdk.pythonSdk
|
||||
import com.jetbrains.python.sdk.switchToSdk
|
||||
import com.jetbrains.python.sdk.service.PySdkService.Companion.pySdkService
|
||||
import com.jetbrains.python.sdk.setAssociationToModule
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
* Executor that accepts at most one concurrent task.
|
||||
@@ -76,6 +73,12 @@ interface BusyGuardExecutor {
|
||||
* and rendered inside [PyInterpreterNotificationProvider].
|
||||
* Long-running work (SDK creation, tool installation) must be submitted through the supplied [BusyGuardExecutor]
|
||||
* so that all notification panels share the same busy state.
|
||||
*
|
||||
* **WARNING:** Implementations must NOT hold strong references to [Module] or [Project] in their fields.
|
||||
* Instances are cached by [PyAsyncFileInspectionRunner] with the Module as a weak key.
|
||||
* A strong reference from the fix back to the Module prevents the weak key from being collected,
|
||||
* causing a project leak after the project is closed. Use the [module] and [project] parameters
|
||||
* passed to [createActionLink] instead.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
interface InterpreterFix {
|
||||
@@ -128,7 +131,7 @@ internal fun createInterpreterCacheLoader(): suspend (Module) -> InspectionRunne
|
||||
val moduleCreateInfo = module.getModuleInfo()
|
||||
val fixes = buildList {
|
||||
getSuitableSdkFix(module, moduleCreateInfo)?.let { add(it) }
|
||||
add(ConfigureInterpreterFix())
|
||||
moduleCreateInfo?.let { add(ConfigureInterpreterFix()) }
|
||||
}
|
||||
val shouldCache = when (moduleCreateInfo) {
|
||||
is ModuleCreateInfo.SameAs -> false
|
||||
@@ -150,19 +153,14 @@ internal class ConfigureInterpreterFix : InterpreterFix {
|
||||
override fun createActionLink(module: Module, project: Project, psiFile: PsiFile, executor: BusyGuardExecutor): ActionLink {
|
||||
return DropDownLink(PyBundle.message("python.sdk.custom.environment")) {
|
||||
val context = DataManager.getInstance().getDataContext(it)
|
||||
createAddInterpreterPopup(module, context, executor)
|
||||
createAddInterpreterPopup(module, context)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun createAddInterpreterPopup(module: Module, context: DataContext, executor: BusyGuardExecutor): JBPopup {
|
||||
val currentSdk = module.pythonSdk
|
||||
fun createAddInterpreterPopup(module: Module, context: DataContext): JBPopup {
|
||||
val group = DefaultActionGroup()
|
||||
group.addAll(collectAddInterpreterActions(ModuleOrProject.ModuleAndProject(module)) { sdk ->
|
||||
executor.execute {
|
||||
withContext(Dispatchers.IO) { switchToSdk(module, sdk, currentSdk) }
|
||||
}
|
||||
})
|
||||
group.addAll(collectAddInterpreterActions(ModuleOrProject.ModuleAndProject(module)) { })
|
||||
ActionManager.getInstance().getAction("Python.NewInterpreter.Extra")?.let {
|
||||
group.add(it)
|
||||
}
|
||||
@@ -177,15 +175,18 @@ internal class ConfigureInterpreterFix : InterpreterFix {
|
||||
}
|
||||
}
|
||||
|
||||
private class UseProvidedInterpreterFix(private val myModule: Module, private val myCreateSdkInfo: CreateSdkInfoWithTool) : InterpreterFix {
|
||||
private class UseProvidedInterpreterFix(
|
||||
private val myCreateSdkInfo: CreateSdkInfoWithTool,
|
||||
private val modulePath: Path?,
|
||||
) : InterpreterFix {
|
||||
override fun createActionLink(module: Module, project: Project, psiFile: PsiFile, executor: BusyGuardExecutor): ActionLink {
|
||||
return ActionLink(myCreateSdkInfo.createSdkInfo.intentionName) {
|
||||
executor.execute {
|
||||
val lifetime = PyProjectSdkConfiguration.suppressTipAndInspectionsFor(myModule, myCreateSdkInfo.toolId.id)
|
||||
val lifetime = PyProjectSdkConfiguration.suppressTipAndInspectionsFor(module, myCreateSdkInfo.toolId.id)
|
||||
withBackgroundProgress(project, myCreateSdkInfo.createSdkInfo.intentionName, false) {
|
||||
lifetime.use { PyProjectSdkConfiguration.setSdkUsingCreateSdkInfo(myModule, myCreateSdkInfo) }
|
||||
lifetime.use { PyProjectSdkConfiguration.setSdkUsingCreateSdkInfo(module, myCreateSdkInfo) }
|
||||
}
|
||||
RefreshQueue.getInstance().refresh(recursive = false, files = ModuleRootManager.getInstance(myModule).contentRoots.toList())
|
||||
RefreshQueue.getInstance().refresh(recursive = false, files = ModuleRootManager.getInstance(module).contentRoots.toList())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,59 +209,27 @@ private class SuggestToolInstallationFix(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun Module.getQuickFixBySdkSuggestion(i: ModuleCreateInfo?): FindQuickFixResult = when (i) {
|
||||
is ModuleCreateInfo.CreateSdkInfoWrapper -> {
|
||||
when (val createSdkInfo = i.createSdkInfo) {
|
||||
is CreateSdkInfo.ExistingEnv -> {
|
||||
logger.trace { "$this: Files already exist, just create sn SDK" }
|
||||
when (val creationResult = createSdkInfo.createSdk(module = this)) {
|
||||
is Result.Failure -> {
|
||||
logger.warn("Can't create SDK for $this : ${creationResult.error}")
|
||||
FindQuickFixResult.NoSuggestion
|
||||
}
|
||||
is Result.Success -> {
|
||||
val sdk = creationResult.result
|
||||
logger.trace { "$this: sdk $sdk created" }
|
||||
pythonSdk = sdk // SDK can't be null
|
||||
project.pySdkService.persistSdk(sdk)
|
||||
sdk.setAssociationToModule(this)
|
||||
FindQuickFixResult.SdkAppliedAutomatically(sdk)
|
||||
}
|
||||
private suspend fun Module.getQuickFixBySdkSuggestion(i: ModuleCreateInfo?): FindQuickFixResult {
|
||||
// Try auto-configure (waits for SDK table, handles ExistingEnv and SameAs)
|
||||
autoConfigureSdkIfNeeded()?.orLogException(logger)?.let { return FindQuickFixResult.SdkAppliedAutomatically(it) }
|
||||
|
||||
// No existing env — show user fix for WillCreateEnv / WillInstallTool
|
||||
return when (i) {
|
||||
is ModuleCreateInfo.CreateSdkInfoWrapper -> {
|
||||
when (val createSdkInfo = i.createSdkInfo) {
|
||||
is CreateSdkInfo.ExistingEnv -> FindQuickFixResult.NoSuggestion // already handled by autoConfigureSdkIfNeeded
|
||||
is CreateSdkInfo.WillCreateEnv -> {
|
||||
logger.trace { "$this: Ask user as it is a heavy operation" }
|
||||
FindQuickFixResult.ShowUserFix(UseProvidedInterpreterFix(CreateSdkInfoWithTool(createSdkInfo, i.toolId), i.moduleDir))
|
||||
}
|
||||
is CreateSdkInfo.WillInstallTool -> {
|
||||
logger.trace { "$this: Tool installation will be suggested to the user" }
|
||||
FindQuickFixResult.ShowUserFix(SuggestToolInstallationFix(this, createSdkInfo, i.toolId))
|
||||
}
|
||||
}
|
||||
is CreateSdkInfo.WillCreateEnv -> {
|
||||
logger.trace { "$this: Ask user as it is a heavy operation" }
|
||||
val tool = CreateSdkInfoWithTool(createSdkInfo, i.toolId)
|
||||
FindQuickFixResult.ShowUserFix(UseProvidedInterpreterFix(this, tool))
|
||||
}
|
||||
is CreateSdkInfo.WillInstallTool -> {
|
||||
logger.trace { "$this: Tool installation will be suggested to the user" }
|
||||
FindQuickFixResult.ShowUserFix(SuggestToolInstallationFix(this, createSdkInfo, i.toolId))
|
||||
}
|
||||
}
|
||||
is ModuleCreateInfo.SameAs, null -> FindQuickFixResult.NoSuggestion // SameAs already handled by autoConfigureSdkIfNeeded
|
||||
}
|
||||
is ModuleCreateInfo.SameAs -> {
|
||||
logger.trace { "$this: Same as parent" }
|
||||
i.parentModule.pythonSdk?.let { parentModuleSdk ->
|
||||
logger.trace { "$this: Parent has SDK $parentModuleSdk" }
|
||||
pythonSdk = parentModuleSdk
|
||||
FindQuickFixResult.SdkAppliedAutomatically(parentModuleSdk)
|
||||
} ?:
|
||||
// Try to find SDK for parent otherwise
|
||||
when (val parentResult = i.parentModule.getQuickFixBySdkSuggestion(i.parentModule.getModuleInfo())) {
|
||||
is FindQuickFixResult.SdkAppliedAutomatically -> {
|
||||
val parentModuleSdk = parentResult.sdk
|
||||
logger.trace { "$this: Parent has SDK $parentModuleSdk" }
|
||||
pythonSdk = parentModuleSdk
|
||||
FindQuickFixResult.SdkAppliedAutomatically(parentModuleSdk)
|
||||
}
|
||||
FindQuickFixResult.NoSuggestion, is FindQuickFixResult.ShowUserFix -> {
|
||||
logger.trace { "$this: Parent SDK can't be created ($parentResult), so is ours" }
|
||||
parentResult
|
||||
}
|
||||
}
|
||||
}
|
||||
null -> FindQuickFixResult.NoSuggestion
|
||||
}
|
||||
|
||||
private sealed interface FindQuickFixResult {
|
||||
|
||||
@@ -1,36 +1,25 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.sdk.configuration
|
||||
|
||||
import com.intellij.notification.NotificationAction
|
||||
import com.intellij.notification.NotificationGroupManager
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.EDT
|
||||
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.isNotificationSilentMode
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.util.Disposer
|
||||
|
||||
import com.intellij.openapi.wm.ex.WelcomeScreenProjectProvider
|
||||
|
||||
import com.intellij.python.community.services.systemPython.SystemPythonService
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.PythonPluginDisposable
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.errorProcessing.emit
|
||||
import com.jetbrains.python.sdk.PySdkPopupFactory
|
||||
import com.jetbrains.python.sdk.configuration.suppressors.PyPackageRequirementsInspectionSuppressor
|
||||
import com.jetbrains.python.sdk.configuration.suppressors.TipOfTheDaySuppressor
|
||||
import com.jetbrains.python.sdk.configurePythonSdk
|
||||
import com.jetbrains.python.sdk.impl.PySdkBundle
|
||||
import com.jetbrains.python.sdk.installExecutableViaPythonScript
|
||||
import com.jetbrains.python.statistics.ConfiguredPythonInterpreterIdsHolder.Companion.SDK_HAS_BEEN_CONFIGURED_AS_THE_PROJECT_INTERPRETER
|
||||
import com.jetbrains.python.util.ShowingMessageErrorSync
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.nio.file.Path
|
||||
|
||||
object PyProjectSdkConfiguration {
|
||||
@@ -56,20 +45,18 @@ object PyProjectSdkConfiguration {
|
||||
return@withContext true
|
||||
}
|
||||
|
||||
setReadyToUseSdk(module.project, module, sdk)
|
||||
configurePythonSdk(module.project, module, sdk)
|
||||
thisLogger().debug("Successfully configured sdk using ${createSdkInfoWithTool.toolId}")
|
||||
true
|
||||
}
|
||||
|
||||
suspend fun setReadyToUseSdk(project: Project, module: Module, sdk: Sdk) {
|
||||
@ApiStatus.Obsolete
|
||||
fun setReadyToUseSdk(project: Project, module: Module, sdk: Sdk) {
|
||||
if (module.isDisposed) {
|
||||
return
|
||||
}
|
||||
|
||||
configurePythonSdk(project, module, sdk)
|
||||
withContext(Dispatchers.EDT) {
|
||||
notifyAboutConfiguredSdk(project, module, sdk)
|
||||
}
|
||||
}
|
||||
|
||||
fun suppressTipAndInspectionsFor(module: Module, toolName: String): Disposable {
|
||||
@@ -86,22 +73,4 @@ object PyProjectSdkConfiguration {
|
||||
PythonSdkCreationWaiter.register(module, lifetime)
|
||||
return lifetime
|
||||
}
|
||||
|
||||
private fun notifyAboutConfiguredSdk(project: Project, module: Module, sdk: Sdk) {
|
||||
if (isNotificationSilentMode(project) || WelcomeScreenProjectProvider.isWelcomeScreenProject(project)) return
|
||||
NotificationGroupManager.getInstance().getNotificationGroup("ConfiguredPythonInterpreter")
|
||||
.createNotification(
|
||||
content = PyBundle.message("sdk.has.been.configured.as.the.project.interpreter", sdk.name),
|
||||
type = NotificationType.INFORMATION
|
||||
)
|
||||
.setDisplayId(SDK_HAS_BEEN_CONFIGURED_AS_THE_PROJECT_INTERPRETER)
|
||||
.apply {
|
||||
val configureSdkAction = NotificationAction.createSimpleExpiring(PySdkBundle.message("python.configure.interpreter.action")) {
|
||||
PySdkPopupFactory.createAndShow(module)
|
||||
}
|
||||
|
||||
addAction(configureSdkAction)
|
||||
notify(project)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user