Persist sdk associate path change, so it could be seen in other places; PY-70145; PY-72692

(cherry picked from commit 4b74266cd7aa3af2f2475b51ca3a91116704f394)

IJ-MR-140372

GitOrigin-RevId: 75f918b7340cd082f86aad0e3ba2fe28d3f5efb1
This commit is contained in:
Aleksandr Sorotskii
2024-07-18 22:28:52 +02:00
committed by intellij-monorepo-bot
parent c4f981882a
commit e044767d68
5 changed files with 24 additions and 77 deletions

View File

@@ -178,6 +178,7 @@ fun showSdkExecutionException(sdk: Sdk?, e: ExecutionException, @NlsContexts.Dia
}
}
@Deprecated("It doesn't persist changes", ReplaceWith("setAssociationToModule"))
fun Sdk.associateWithModule(module: Module?, newProjectPath: String?) {
getOrCreateAdditionalData().apply {
when {
@@ -187,6 +188,21 @@ fun Sdk.associateWithModule(module: Module?, newProjectPath: String?) {
}
}
fun Sdk.setAssociationToModule(module: Module) {
val data = getOrCreateAdditionalData().apply {
associateWithModule(module)
}
val modificator = sdkModificator
modificator.sdkAdditionalData = data
runInEdt {
ApplicationManager.getApplication().runWriteAction() {
modificator.commitChanges()
}
}
}
fun Sdk.isAssociatedWithModule(module: Module?): Boolean {
val basePath = module?.basePath
val associatedPath = associatedModulePath

View File

@@ -47,7 +47,7 @@ class PyPipEnvSdkProvider : PySdkProvider {
else -> PyPsiBundle.message("INSP.interpreter.pipenv.interpreter.not.associated.with.any.module")
}
}
return PyInterpreterInspectionQuickFixData(UsePipEnvQuickFix(sdk, module), message)
return PyInterpreterInspectionQuickFixData(PipEnvAssociationQuickFix(), message)
}
return null
}

View File

@@ -6,7 +6,6 @@ import com.google.gson.JsonSyntaxException
import com.google.gson.annotations.SerializedName
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.util.IntentionName
import com.intellij.execution.ExecutionException
import com.intellij.execution.RunCanceledByUserException
import com.intellij.execution.configurations.GeneralCommandLine
@@ -35,8 +34,6 @@ import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.NlsContexts.ProgressTitle
import com.intellij.openapi.util.NlsSafe
@@ -236,46 +233,15 @@ val Sdk.pipFileLockRequirements: List<PyRequirement>?
/**
* A quick-fix for setting up the pipenv for the module of the current PSI element.
*/
class UsePipEnvQuickFix(sdk: Sdk?, module: Module) : LocalQuickFix {
@IntentionName
private val quickFixName = when {
sdk != null && sdk.isAssociatedWithAnotherModule(module) -> PyBundle.message("python.sdk.pipenv.quickfix.fix.pipenv.name")
else -> PyBundle.message("python.sdk.pipenv.quickfix.use.pipenv.name")
}
companion object {
fun isApplicable(module: Module): Boolean = module.pipFile != null
fun setUpPipEnv(project: Project, module: Module) {
val sdksModel = ProjectSdksModel().apply {
reset(project)
}
val existingSdks = sdksModel.sdks.filter { it.sdkType is PythonSdkType }
// XXX: Should we show an error message on exceptions and on null?
val newSdk = setupPipEnvSdkUnderProgress(project, module, existingSdks, null, null, false) ?: return
val existingSdk = existingSdks.find { it.isPipEnv && it.homePath == newSdk.homePath }
val sdk = existingSdk ?: newSdk
if (sdk == newSdk) {
SdkConfigurationUtil.addSdk(newSdk)
}
else {
sdk.associateWithModule(module, null)
}
project.pythonSdk = sdk
module.pythonSdk = sdk
}
}
class PipEnvAssociationQuickFix : LocalQuickFix {
private val quickFixName = PyBundle.message("python.sdk.pipenv.quickfix.use.pipenv.name")
override fun getFamilyName() = quickFixName
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.psiElement ?: return
val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return
// Invoke the setup later to escape the write action of the quick fix in order to show the modal progress dialog
ApplicationManager.getApplication().invokeLater {
if (project.isDisposed || module.isDisposed) return@invokeLater
setUpPipEnv(project, module)
}
module.pythonSdk?.setAssociationToModule(module)
}
}

View File

@@ -32,7 +32,7 @@ class PoetrySdkProvider : PySdkProvider {
PyBundle.message("python.sdk.inspection.message.poetry.interpreter.associated.with.another.project", projectUnit, associatedModulePath)
else -> PyBundle.message("python.sdk.inspection.message.poetry.interpreter.not.associated.with.any.project", projectUnit)
}
return PyInterpreterInspectionQuickFixData(UsePoetryQuickFix(sdk, module), message)
return PyInterpreterInspectionQuickFixData(PoetryAssociationQuickFix(), message)
}
return null
}

View File

@@ -32,8 +32,6 @@ import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel
import com.intellij.openapi.ui.ValidationInfo
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.NlsSafe
@@ -332,48 +330,15 @@ val Sdk.poetrySources: List<String>
/**
* A quick-fix for setting up the poetry for the module of the current PSI element.
*/
class UsePoetryQuickFix(sdk: Sdk?, module: Module) : LocalQuickFix {
private val quickFixName = when {
sdk != null && sdk.isAssociatedWithAnotherModule(module) -> PyBundle.message("python.sdk.poetry.quickfix.fix.pipenv.name")
else -> PyBundle.message("python.sdk.poetry.quickfix.use.pipenv.name")
}
companion object {
fun isApplicable(module: Module): Boolean = module.pyProjectToml != null
fun setUpPoetry(project: Project, module: Module) {
val sdksModel = ProjectSdksModel().apply {
reset(project)
}
val existingSdks = sdksModel.sdks.filter { it.sdkType is PythonSdkType }
// XXX: Should we show an error message on exceptions and on null?
val newSdk = setupPoetrySdkUnderProgress(project, module, existingSdks, null, null, false)
?: return
val existingSdk = existingSdks.find { it.isPoetry && it.homePath == newSdk.homePath }
val sdk = existingSdk ?: newSdk
if (sdk == newSdk) {
SdkConfigurationUtil.addSdk(newSdk)
}
else {
sdk.associateWithModule(module, null)
}
project.pythonSdk = sdk
module.pythonSdk = sdk
PoetryConfigService.getInstance(project).poetryVirtualenvPaths.add(sdk.homePath!!)
}
}
class PoetryAssociationQuickFix: LocalQuickFix {
private val quickFixName = PyBundle.message("python.sdk.poetry.quickfix.use.pipenv.name")
override fun getFamilyName() = quickFixName
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val element = descriptor.psiElement ?: return
val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return
// Invoke the setup later to escape the write action of the quick fix in order to show the modal progress dialog
ApplicationManager.getApplication().invokeLater {
if (project.isDisposed || module.isDisposed) return@invokeLater
setUpPoetry(project, module)
}
module.pythonSdk?.setAssociationToModule(module)
}
}