diff --git a/python/python-sdk-configurator/backend/resources/intellij.python.sdkConfigurator.backend.xml b/python/python-sdk-configurator/backend/resources/intellij.python.sdkConfigurator.backend.xml index 09ccc3c3b20d..1ee5941f00c6 100644 --- a/python/python-sdk-configurator/backend/resources/intellij.python.sdkConfigurator.backend.xml +++ b/python/python-sdk-configurator/backend/resources/intellij.python.sdkConfigurator.backend.xml @@ -16,10 +16,6 @@ - - - diff --git a/python/python-sdk-configurator/backend/src/impl/backendLib.kt b/python/python-sdk-configurator/backend/src/impl/backendLib.kt index a395f5e66a6a..4646fb7a3c5f 100644 --- a/python/python-sdk-configurator/backend/src/impl/backendLib.kt +++ b/python/python-sdk-configurator/backend/src/impl/backendLib.kt @@ -30,9 +30,20 @@ import kotlinx.coroutines.withContext private val askUserMutex = Mutex() -// TODO: DOC -internal fun configureSdkAskingUser(project: Project) { +/** + * Same as [configureSdkAutomatically] but in a separate coroutine + */ +internal fun configureSdkAskingUserBg(project: Project) { project.service().scope.launch(Dispatchers.Default) { + configureSdkAskingUser(project) + } +} + +/** + * Ask user for list of modules and configure them + */ +internal suspend fun configureSdkAskingUser(project: Project) { + withContext(Dispatchers.Default) { askUserMutex.withLock { val moduleToSuggestedSdk = getModulesWithoutSDK(project) if (moduleToSuggestedSdk.modules.isNotEmpty()) { diff --git a/python/python-sdk-configurator/backend/src/impl/platformBridge/ConfigureSDKAction.kt b/python/python-sdk-configurator/backend/src/impl/platformBridge/ConfigureSDKAction.kt index fc39d7effc3e..ebc8fd653827 100644 --- a/python/python-sdk-configurator/backend/src/impl/platformBridge/ConfigureSDKAction.kt +++ b/python/python-sdk-configurator/backend/src/impl/platformBridge/ConfigureSDKAction.kt @@ -4,6 +4,7 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.python.sdkConfigurator.backend.impl.configureSdkAskingUser +import com.intellij.python.sdkConfigurator.backend.impl.configureSdkAskingUserBg import com.intellij.python.sdkConfigurator.common.enableSDKAutoConfigurator internal class ConfigureSDKAction : AnAction() { @@ -13,7 +14,7 @@ internal class ConfigureSDKAction : AnAction() { if (!enableSDKAutoConfigurator) { return } - configureSdkAskingUser(project) + configureSdkAskingUserBg(project) } override fun update(e: AnActionEvent) { diff --git a/python/python-sdk-configurator/backend/src/impl/platformBridge/ModelRebuiltListenerImpl.kt b/python/python-sdk-configurator/backend/src/impl/platformBridge/ModelRebuiltListenerImpl.kt index 520157dedc04..41a9fdde637f 100644 --- a/python/python-sdk-configurator/backend/src/impl/platformBridge/ModelRebuiltListenerImpl.kt +++ b/python/python-sdk-configurator/backend/src/impl/platformBridge/ModelRebuiltListenerImpl.kt @@ -3,9 +3,8 @@ package com.intellij.python.sdkConfigurator.backend.impl.platformBridge import com.intellij.openapi.extensions.ExtensionNotApplicableException import com.intellij.openapi.project.Project import com.intellij.python.pyproject.model.api.ModelRebuiltListener -import com.intellij.python.sdkConfigurator.backend.impl.configureSdkAskingUser +import com.intellij.python.sdkConfigurator.backend.impl.configureSdkAskingUserBg import com.intellij.python.sdkConfigurator.common.enableSDKAutoConfigurator -import kotlinx.coroutines.sync.Mutex internal class ModelRebuiltListenerImpl : ModelRebuiltListener { init { @@ -15,7 +14,7 @@ internal class ModelRebuiltListenerImpl : ModelRebuiltListener { } override fun modelRebuilt(project: Project) { - configureSdkAskingUser(project) + configureSdkAskingUserBg(project) } } diff --git a/python/python-sdk-configurator/backend/src/impl/rpcBridge/BackendTopicListener.kt b/python/python-sdk-configurator/backend/src/impl/rpcBridge/BackendTopicListener.kt deleted file mode 100644 index ed9bb9e76efd..000000000000 --- a/python/python-sdk-configurator/backend/src/impl/rpcBridge/BackendTopicListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.intellij.python.sdkConfigurator.backend.impl.rpcBridge - -import com.intellij.openapi.project.Project -import com.intellij.platform.rpc.topics.ProjectRemoteTopic -import com.intellij.platform.rpc.topics.ProjectRemoteTopicListener -import com.intellij.python.sdkConfigurator.backend.impl.configureSdkAskingUser -import com.intellij.python.sdkConfigurator.common.impl.DETECT_SDK_FOR_MODULES - -internal class BackendTopicListener : ProjectRemoteTopicListener { - override val topic: ProjectRemoteTopic = DETECT_SDK_FOR_MODULES - - override fun handleEvent(project: Project, event: Unit) { - configureSdkAskingUser(project) - } -} diff --git a/python/python-sdk-configurator/backend/src/impl/rpcBridge/SdkConfiguratorApiImpl.kt b/python/python-sdk-configurator/backend/src/impl/rpcBridge/SdkConfiguratorApiImpl.kt index 66dada0bf9c4..d5666cda6184 100644 --- a/python/python-sdk-configurator/backend/src/impl/rpcBridge/SdkConfiguratorApiImpl.kt +++ b/python/python-sdk-configurator/backend/src/impl/rpcBridge/SdkConfiguratorApiImpl.kt @@ -2,6 +2,7 @@ package com.intellij.python.sdkConfigurator.backend.impl.rpcBridge import com.intellij.platform.project.ProjectId import com.intellij.platform.project.findProject +import com.intellij.python.sdkConfigurator.backend.impl.configureSdkAskingUser import com.intellij.python.sdkConfigurator.backend.impl.configureSdkAutomatically import com.intellij.python.sdkConfigurator.common.impl.ModuleName import com.intellij.python.sdkConfigurator.common.impl.SdkConfiguratorBackEndApi @@ -10,4 +11,8 @@ internal object SdkConfiguratorApiImpl : SdkConfiguratorBackEndApi { override suspend fun configureSdkAutomatically(projectId: ProjectId, onlyModules: Set) { configureSdkAutomatically(projectId.findProject(), onlyModules) } + + override suspend fun configureAskingUser(projectId: ProjectId) { + configureSdkAskingUser(projectId.findProject()) + } } \ No newline at end of file diff --git a/python/python-sdk-configurator/common/resources/intellij.python.sdkConfigurator.common.xml b/python/python-sdk-configurator/common/resources/intellij.python.sdkConfigurator.common.xml index f7b2a6632b72..22c04e273843 100644 --- a/python/python-sdk-configurator/common/resources/intellij.python.sdkConfigurator.common.xml +++ b/python/python-sdk-configurator/common/resources/intellij.python.sdkConfigurator.common.xml @@ -1,5 +1,5 @@ - + diff --git a/python/python-sdk-configurator/common/src/impl/SdkConfiguratorBackEndApi.kt b/python/python-sdk-configurator/common/src/impl/SdkConfiguratorBackEndApi.kt index ed834bda66c5..cc678e90d641 100644 --- a/python/python-sdk-configurator/common/src/impl/SdkConfiguratorBackEndApi.kt +++ b/python/python-sdk-configurator/common/src/impl/SdkConfiguratorBackEndApi.kt @@ -1,9 +1,11 @@ package com.intellij.python.sdkConfigurator.common.impl import com.intellij.platform.project.ProjectId +import com.intellij.platform.rpc.RemoteApiProviderService import com.intellij.platform.rpc.topics.ProjectRemoteTopic import fleet.rpc.RemoteApi import fleet.rpc.Rpc +import fleet.rpc.remoteApiDescriptor import kotlinx.serialization.Serializable /** @@ -12,9 +14,14 @@ import kotlinx.serialization.Serializable @Rpc interface SdkConfiguratorBackEndApi : RemoteApi { /*** - * Configure SDK for all modules in [projectId] if their names in [onlyModules] + * Configure SDK for all modules in [projectId] if their names in [onlyModules] unconditionally */ suspend fun configureSdkAutomatically(projectId: ProjectId, onlyModules: Set) + + /** + * Ask user about modules, then call [configureSdkAutomatically] + */ + suspend fun configureAskingUser(projectId: ProjectId) } typealias ModuleName = String @@ -29,4 +36,9 @@ val SHOW_SDK_CONFIG_UI_TOPIC: ProjectRemoteTopic = ProjectRemoteTopi */ @Serializable data class ModulesDTO(val modules: Map) { -} \ No newline at end of file +} + +/** + * [SdkConfiguratorBackEndApi] instance + */ +suspend fun SdkConfiguratorBackEndApi(): SdkConfiguratorBackEndApi = RemoteApiProviderService.resolve(remoteApiDescriptor()) \ No newline at end of file diff --git a/python/python-sdk-configurator/common/src/impl/detectModulesImpl.kt b/python/python-sdk-configurator/common/src/impl/detectModulesImpl.kt deleted file mode 100644 index f6f8a0f3b16f..000000000000 --- a/python/python-sdk-configurator/common/src/impl/detectModulesImpl.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.intellij.python.sdkConfigurator.common.impl - -import com.intellij.platform.rpc.topics.ProjectRemoteTopic -import kotlinx.serialization.builtins.serializer - -/** - * Backend listens for this topic to start SDK detection process - */ -val DETECT_SDK_FOR_MODULES: ProjectRemoteTopic = ProjectRemoteTopic("PySDKConfigurationDetectSDKTopic", Unit.serializer()) - diff --git a/python/python-sdk-configurator/common/src/publicApi.kt b/python/python-sdk-configurator/common/src/publicApi.kt index 059d91956a12..76689c4f8acf 100644 --- a/python/python-sdk-configurator/common/src/publicApi.kt +++ b/python/python-sdk-configurator/common/src/publicApi.kt @@ -2,8 +2,8 @@ package com.intellij.python.sdkConfigurator.common import com.intellij.openapi.project.Project import com.intellij.openapi.util.registry.Registry -import com.intellij.platform.rpc.topics.sendToClient -import com.intellij.python.sdkConfigurator.common.impl.DETECT_SDK_FOR_MODULES +import com.intellij.platform.project.projectId +import com.intellij.python.sdkConfigurator.common.impl.SdkConfiguratorBackEndApi /** @@ -11,14 +11,10 @@ import com.intellij.python.sdkConfigurator.common.impl.DETECT_SDK_FOR_MODULES */ val enableSDKAutoConfigurator: Boolean get() = Registry.`is`("intellij.python.sdkConfigurator.auto") + /** - * Check if [enableSDKAutoConfigurator] (return `false` if not) and start detecting process. - * it might ask user for list of modules and then detect them + * it might ask user for list of modules and then detect SDK for them */ -fun detectSdkForModulesIn(project: Project): Boolean { - if (!enableSDKAutoConfigurator) { - return false - } - DETECT_SDK_FOR_MODULES.sendToClient(project, Unit) - return true +suspend fun detectSdkForModulesIn(project: Project) { + SdkConfiguratorBackEndApi().configureAskingUser(project.projectId()) } diff --git a/python/python-sdk-configurator/frontend/resources/messages/PySdkConfiguratorFrontendBundle.properties b/python/python-sdk-configurator/frontend/resources/messages/PySdkConfiguratorFrontendBundle.properties index c9c6b99e6560..64ca45526a7e 100644 --- a/python/python-sdk-configurator/frontend/resources/messages/PySdkConfiguratorFrontendBundle.properties +++ b/python/python-sdk-configurator/frontend/resources/messages/PySdkConfiguratorFrontendBundle.properties @@ -1 +1,4 @@ -python.sdk.configurator.frontend.choose.modules.title=Choose Modules to Configure SDK For \ No newline at end of file +python.sdk.configurator.frontend.choose.modules.title=Configure Modules Environment +python.sdk.configurator.frontend.choose.modules.text=Pick the ones you want to use to run code and set up environment for them +python.sdk.configurator.frontend.choose.modules.project.structure=Project Structure +python.sdk.configurator.frontend.choose.modules.environment=Environment diff --git a/python/python-sdk-configurator/frontend/src/components/ModuleList.kt b/python/python-sdk-configurator/frontend/src/components/ModuleList.kt index ac261354a404..d1a0a68320cd 100644 --- a/python/python-sdk-configurator/frontend/src/components/ModuleList.kt +++ b/python/python-sdk-configurator/frontend/src/components/ModuleList.kt @@ -1,17 +1,18 @@ package com.intellij.python.sdkConfigurator.frontend.components -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableIntState -import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.snapshots.SnapshotStateSet import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.intellij.python.sdkConfigurator.frontend.ModuleInfo import kotlinx.collections.immutable.ImmutableMap -import org.jetbrains.jewel.ui.component.Checkbox +import org.jetbrains.annotations.Nls +import org.jetbrains.jewel.foundation.theme.JewelTheme +import org.jetbrains.jewel.ui.component.CheckboxRow import org.jetbrains.jewel.ui.component.Text import org.jetbrains.jewel.ui.component.VerticallyScrollableContainer @@ -21,23 +22,42 @@ internal fun ModuleList( moduleItems: ImmutableMap, checked: SnapshotStateSet, onCheckChange: (String, Boolean) -> Unit, + topLabel: @Nls String, + projectStructureLabel: @Nls String, + environmentLabel: @Nls String, ) { - VerticallyScrollableContainer { - Column(Modifier.width(500.dp)) { - for ((moduleName, moduleInfo) in moduleItems) { - val (parent, pythons) = moduleInfo - Row(Modifier.padding(2.dp), verticalAlignment = Alignment.CenterVertically) { - val checked = moduleName in checked - val elementToChange = parent ?: moduleName - Checkbox( - checked = checked, - onCheckedChange = { - onCheckChange(elementToChange, it) - }, - ) - Text(moduleName, Modifier.padding(start = 1.dp).clickable(true, onClick = { onCheckChange(elementToChange, !checked) })) - Spacer(Modifier.weight(1f)) - PythonsDropDown(pythons, Modifier.width(200.dp)) + val ts = JewelTheme.defaultTextStyle + val padding = 2.dp + val longestItemChars = remember { (listOf(projectStructureLabel) + moduleItems.keys).maxBy { it.length } } + val leftColumnMinSize = measureText(longestItemChars, ts) + val spaceBetweenCols = 16.dp + Column(Modifier.padding(padding), verticalArrangement = Arrangement.spacedBy(padding)) { + Text(topLabel, Modifier.padding(bottom = 10.dp)) + Row(Modifier, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween) { + Text(projectStructureLabel, Modifier.width(leftColumnMinSize + spaceBetweenCols + padding + 26.dp)) //~ checkbox size + Text(environmentLabel, textAlign = TextAlign.End) + } + val moduleItems = remember { moduleItems.entries.sortedBy { it.key } } + VerticallyScrollableContainer { + Column(Modifier, horizontalAlignment = Alignment.Start, verticalArrangement = Arrangement.spacedBy(padding)) { + for ((moduleName, moduleInfo) in moduleItems) { + val (parent, pythons) = moduleInfo + Row(Modifier.padding(padding), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(spaceBetweenCols)) { + val checked = moduleName in checked + val elementToChange = parent ?: moduleName // TODO: move logic out of UI + CheckboxRow( + moduleName, + checked = checked, + onCheckedChange = { + onCheckChange(elementToChange, it) + }, + textStyle = ts, + textModifier = Modifier.width(leftColumnMinSize) + ) + if (parent == null) { + PythonsDropDown(pythons) + } + } } } } diff --git a/python/python-sdk-configurator/frontend/src/components/PythonsDropDown.kt b/python/python-sdk-configurator/frontend/src/components/PythonsDropDown.kt index 007e7f491d93..a499bf0951d2 100644 --- a/python/python-sdk-configurator/frontend/src/components/PythonsDropDown.kt +++ b/python/python-sdk-configurator/frontend/src/components/PythonsDropDown.kt @@ -1,13 +1,40 @@ package com.intellij.python.sdkConfigurator.frontend.components +import androidx.compose.foundation.layout.widthIn import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.unit.dp import kotlinx.collections.immutable.ImmutableList import org.jetbrains.jewel.foundation.ExperimentalJewelApi +import org.jetbrains.jewel.foundation.theme.JewelTheme import org.jetbrains.jewel.ui.component.ListComboBox +import org.jetbrains.jewel.ui.component.SimpleListItem +import org.jetbrains.jewel.ui.icons.AllIconsKeys.Language.Python +@OptIn(ExperimentalJewelApi::class) @Composable -internal fun PythonsDropDown(pythons: ImmutableList, modifier: Modifier = Modifier) { +internal fun PythonsDropDown(pythons: ImmutableList, grayedOut: Boolean = false, modifier: Modifier = Modifier) { + val ts = JewelTheme.defaultTextStyle + val longestPython = remember { pythons.maxBy { it.length } } + val padding = 100.dp + val width = measureText(longestPython, ts) + padding // Padding var i by remember { mutableIntStateOf(0) } - ListComboBox(pythons, i, { i = it }, modifier) + ListComboBox( + items = pythons, + selectedIndex = i, + modifier = modifier.widthIn(min = width, max = width + padding), + onSelectedItemChange = { i = it }, + itemKeys = { index, _ -> index }, + itemContent = { item, isSelected, isActive -> + SimpleListItem( + text = item, + selected = isSelected, + active = isActive, + icon = Python, + colorFilter = if (grayedOut) ColorFilter.tint(Color.Gray) else null, + ) + }, + ) } \ No newline at end of file diff --git a/python/python-sdk-configurator/frontend/src/components/tools.kt b/python/python-sdk-configurator/frontend/src/components/tools.kt new file mode 100644 index 000000000000..0a65e1c4fc5e --- /dev/null +++ b/python/python-sdk-configurator/frontend/src/components/tools.kt @@ -0,0 +1,15 @@ +package com.intellij.python.sdkConfigurator.frontend.components + +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.rememberTextMeasurer +import androidx.compose.ui.unit.Dp + +@Composable +internal fun measureText(text: String, textStyle: TextStyle): Dp { + val textMeasurer = rememberTextMeasurer() + return with(LocalDensity.current) { + textMeasurer.measure(text, textStyle).size.width.toDp() + } +} \ No newline at end of file diff --git a/python/python-sdk-configurator/frontend/src/package-info.java b/python/python-sdk-configurator/frontend/src/package-info.java index 73502c3f5af2..19baa5e9a068 100644 --- a/python/python-sdk-configurator/frontend/src/package-info.java +++ b/python/python-sdk-configurator/frontend/src/package-info.java @@ -1,3 +1,6 @@ +/** + * Front-end implementation, do not access directly + */ @ApiStatus.Internal package com.intellij.python.sdkConfigurator.frontend; diff --git a/python/python-sdk-configurator/frontend/src/rpcBridge/FrontendTopicListener.kt b/python/python-sdk-configurator/frontend/src/rpcBridge/FrontendTopicListener.kt index 1c3746efe4d2..7bebcced34cc 100644 --- a/python/python-sdk-configurator/frontend/src/rpcBridge/FrontendTopicListener.kt +++ b/python/python-sdk-configurator/frontend/src/rpcBridge/FrontendTopicListener.kt @@ -9,6 +9,7 @@ import com.intellij.platform.rpc.topics.ProjectRemoteTopic import com.intellij.platform.rpc.topics.ProjectRemoteTopicListener import com.intellij.python.sdkConfigurator.common.impl.ModulesDTO import com.intellij.python.sdkConfigurator.common.impl.SHOW_SDK_CONFIG_UI_TOPIC +import com.intellij.python.sdkConfigurator.common.impl.SdkConfiguratorBackEndApi import com.intellij.python.sdkConfigurator.frontend.askUser import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -22,7 +23,7 @@ internal class FrontendTopicListener : ProjectRemoteTopicListener { // Ask user to choose modules, then ask backend to configure it askUser(project, event) { modulesChosenByUser -> scope.launch { - getBackendApi().configureSdkAutomatically(project.projectId(), modulesChosenByUser) + SdkConfiguratorBackEndApi().configureSdkAutomatically(project.projectId(), modulesChosenByUser) } } } diff --git a/python/python-sdk-configurator/frontend/src/rpcBridge/apiObtainer.kt b/python/python-sdk-configurator/frontend/src/rpcBridge/apiObtainer.kt deleted file mode 100644 index 491afe7a8e3a..000000000000 --- a/python/python-sdk-configurator/frontend/src/rpcBridge/apiObtainer.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.intellij.python.sdkConfigurator.frontend.rpcBridge - -import com.intellij.platform.rpc.RemoteApiProviderService -import com.intellij.python.sdkConfigurator.common.impl.SdkConfiguratorBackEndApi -import fleet.rpc.remoteApiDescriptor - - -internal suspend fun getBackendApi() = RemoteApiProviderService.resolve(remoteApiDescriptor()) - diff --git a/python/python-sdk-configurator/frontend/src/swingBridge.kt b/python/python-sdk-configurator/frontend/src/swingBridge.kt index dd2952f78fde..1dffc18e2ba9 100644 --- a/python/python-sdk-configurator/frontend/src/swingBridge.kt +++ b/python/python-sdk-configurator/frontend/src/swingBridge.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogWrapper import com.intellij.python.sdkConfigurator.common.impl.ModuleName import com.intellij.python.sdkConfigurator.common.impl.ModulesDTO +import com.intellij.python.sdkConfigurator.frontend.PySdkConfiguratorFrontendBundle.message import com.intellij.python.sdkConfigurator.frontend.components.ModuleList import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -28,7 +29,8 @@ internal suspend fun askUser(project: Project, modules: ModulesDTO, onResult: (S private class MyDialog(project: Project, private val viewModel: ModulesViewModel) : DialogWrapper(project) { init { - title = PySdkConfiguratorFrontendBundle.message("python.sdk.configurator.frontend.choose.modules.title") + title = message("python.sdk.configurator.frontend.choose.modules.title") + isResizable = false init() } @@ -36,7 +38,10 @@ private class MyDialog(project: Project, private val viewModel: ModulesViewModel override fun createCenterPanel(): JComponent { enableNewSwingCompositing() return compose(focusOnClickInside = true, content = { - ModuleList(viewModel.checkBoxItems, viewModel.checked, viewModel::clicked) + ModuleList(viewModel.checkBoxItems, viewModel.checked, viewModel::clicked, + topLabel = message("python.sdk.configurator.frontend.choose.modules.text"), + projectStructureLabel = message("python.sdk.configurator.frontend.choose.modules.project.structure"), + environmentLabel = message("python.sdk.configurator.frontend.choose.modules.environment")) }) } } \ 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 b0766eaaf1b5..38ad254f80e2 100644 --- a/python/src/com/jetbrains/python/inspections/PyInterpreterInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyInterpreterInspection.java @@ -58,7 +58,7 @@ import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.intellij.python.sdkConfigurator.common.PublicApiKt.detectSdkForModulesIn; +import static com.jetbrains.python.inspections.PyInterpreterInspectionExKt.detectSdkForModulesForJvmIn; import static com.jetbrains.python.inspections.PyInterpreterInspectionExKt.findAllSortedForModuleForJvm; @@ -343,7 +343,7 @@ public final class PyInterpreterInspection extends PyInspection { @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - if (!detectSdkForModulesIn(project)) { + if (!detectSdkForModulesForJvmIn(project)) { PyProjectSdkConfiguration.INSTANCE.configureSdkUsingCreateSdkInfo(myModule, myCreateSdkInfo); } } diff --git a/python/src/com/jetbrains/python/inspections/PyInterpreterInspectionEx.kt b/python/src/com/jetbrains/python/inspections/PyInterpreterInspectionEx.kt index 5c7b1ab208b9..b3bc445a5a82 100644 --- a/python/src/com/jetbrains/python/inspections/PyInterpreterInspectionEx.kt +++ b/python/src/com/jetbrains/python/inspections/PyInterpreterInspectionEx.kt @@ -1,13 +1,37 @@ // 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.inspections +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.service import com.intellij.openapi.module.Module import com.intellij.openapi.progress.runBlockingMaybeCancellable +import com.intellij.openapi.project.Project +import com.intellij.python.sdkConfigurator.common.detectSdkForModulesIn +import com.intellij.python.sdkConfigurator.common.enableSDKAutoConfigurator import com.intellij.util.concurrency.annotations.RequiresBackgroundThread import com.jetbrains.python.sdk.configuration.CreateSdkInfo import com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import org.jetbrains.annotations.ApiStatus +/** + * To be used by [PyInterpreterInspection] only + */ +@ApiStatus.Internal +internal fun detectSdkForModulesForJvmIn(project: Project): Boolean { + if (!enableSDKAutoConfigurator) { + return false + } + project.service().scope.launch { + detectSdkForModulesIn(project) + } + return true +} + +@Service(Service.Level.PROJECT) +private class MyService(val scope: CoroutineScope) + /** * To be used by [PyInterpreterInspection] only */