From e661a0afd64e3e6e1e51c981cb7bda4e0af724fd Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 24 Mar 2025 18:56:18 +0100 Subject: [PATCH] python: Enable subroot detection for pylsp and pyright (#27364) This is not going to fully fix the multi-root story, as we still need to weave venvs through. Hence, no release note just yet. Release Notes: - N/A --- crates/languages/src/lib.rs | 9 ++++++++- crates/languages/src/python.rs | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/crates/languages/src/lib.rs b/crates/languages/src/lib.rs index d80ad2bf36..ed8a1fc5b8 100644 --- a/crates/languages/src/lib.rs +++ b/crates/languages/src/lib.rs @@ -2,6 +2,7 @@ use anyhow::Context as _; use gpui::{App, UpdateGlobal}; use json::json_task_context; use node_runtime::NodeRuntime; +use python::PyprojectTomlManifestProvider; use rust::CargoManifestProvider; use rust_embed::RustEmbed; use settings::SettingsStore; @@ -302,7 +303,13 @@ pub fn init(languages: Arc, node: NodeRuntime, cx: &mut App) { anyhow::Ok(()) }) .detach(); - project::ManifestProviders::global(cx).register(Arc::from(CargoManifestProvider)); + let manifest_providers: [Arc; 2] = [ + Arc::from(CargoManifestProvider), + Arc::from(PyprojectTomlManifestProvider), + ]; + for provider in manifest_providers { + project::ManifestProviders::global(cx).register(provider); + } } #[derive(Default)] diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index 1219083b0c..825b11db2d 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -5,12 +5,12 @@ use collections::HashMap; use gpui::{App, Task}; use gpui::{AsyncApp, SharedString}; use language::language_settings::language_settings; -use language::LanguageName; use language::LanguageToolchainStore; use language::Toolchain; use language::ToolchainList; use language::ToolchainLister; use language::{ContextProvider, LspAdapter, LspAdapterDelegate}; +use language::{LanguageName, ManifestName, ManifestProvider, ManifestQuery}; use lsp::LanguageServerBinary; use lsp::LanguageServerName; use node_runtime::NodeRuntime; @@ -35,6 +35,32 @@ use std::{ use task::{TaskTemplate, TaskTemplates, VariableName}; use util::ResultExt; +pub(crate) struct PyprojectTomlManifestProvider; + +impl ManifestProvider for PyprojectTomlManifestProvider { + fn name(&self) -> ManifestName { + SharedString::new_static("pyproject.toml").into() + } + + fn search( + &self, + ManifestQuery { + path, + depth, + delegate, + }: ManifestQuery, + ) -> Option> { + for path in path.ancestors().take(depth) { + let p = path.join("pyproject.toml"); + if delegate.exists(&p, Some(false)) { + return Some(path.into()); + } + } + + None + } +} + const SERVER_PATH: &str = "node_modules/pyright/langserver.index.js"; const NODE_MODULE_RELATIVE_SERVER_PATH: &str = "pyright/langserver.index.js"; @@ -293,6 +319,9 @@ impl LspAdapter for PythonLspAdapter { user_settings }) } + fn manifest_name(&self) -> Option { + Some(SharedString::new_static("pyproject.toml").into()) + } } async fn get_cached_server_binary( @@ -1010,6 +1039,9 @@ impl LspAdapter for PyLspAdapter { user_settings }) } + fn manifest_name(&self) -> Option { + Some(SharedString::new_static("pyproject.toml").into()) + } } #[cfg(test)]