diff --git a/crates/languages/src/lib.rs b/crates/languages/src/lib.rs index f5fbe66e26..3a140e4ae1 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 c81eb178ff..e070ee67a3 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -4,13 +4,13 @@ use async_trait::async_trait; use collections::HashMap; use gpui::{App, Task}; use gpui::{AsyncApp, SharedString}; -use language::LanguageName; use language::LanguageToolchainStore; use language::Toolchain; use language::ToolchainList; use language::ToolchainLister; use language::language_settings::language_settings; use language::{ContextProvider, LspAdapter, LspAdapterDelegate}; +use language::{LanguageName, ManifestName, ManifestProvider, ManifestQuery}; use lsp::LanguageServerBinary; use lsp::LanguageServerName; use node_runtime::NodeRuntime; @@ -38,6 +38,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"; @@ -301,6 +327,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( @@ -1142,6 +1171,9 @@ impl LspAdapter for PyLspAdapter { user_settings }) } + fn manifest_name(&self) -> Option { + Some(SharedString::new_static("pyproject.toml").into()) + } } #[cfg(test)]