From c2b9fa84f7ffffca0ab173751f5dc2943e8b052d Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Fri, 21 Feb 2025 14:07:29 +0530 Subject: [PATCH] Refactor workspace logic into `workspace.rs` (#16295) ## Summary This is just a small refactor to move workspace related structs and impl out from `server.rs` where `Server` is defined and into a new `workspace.rs`. --- crates/ruff_server/src/lib.rs | 4 +- crates/ruff_server/src/server.rs | 126 +----------------------- crates/ruff_server/src/session.rs | 2 +- crates/ruff_server/src/session/index.rs | 2 +- crates/ruff_server/src/workspace.rs | 126 ++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 128 deletions(-) create mode 100644 crates/ruff_server/src/workspace.rs diff --git a/crates/ruff_server/src/lib.rs b/crates/ruff_server/src/lib.rs index acde201469..44d5e1bb52 100644 --- a/crates/ruff_server/src/lib.rs +++ b/crates/ruff_server/src/lib.rs @@ -2,8 +2,9 @@ pub use edit::{DocumentKey, NotebookDocument, PositionEncoding, TextDocument}; use lsp_types::CodeActionKind; -pub use server::{Server, Workspace, Workspaces}; +pub use server::Server; pub use session::{ClientSettings, DocumentQuery, DocumentSnapshot, Session}; +pub use workspace::{Workspace, Workspaces}; #[macro_use] mod message; @@ -16,6 +17,7 @@ mod logging; mod resolve; mod server; mod session; +mod workspace; pub(crate) const SERVER_NAME: &str = "ruff"; pub(crate) const DIAGNOSTIC_NAME: &str = "Ruff"; diff --git a/crates/ruff_server/src/server.rs b/crates/ruff_server/src/server.rs index feba047efa..88c0273fb6 100644 --- a/crates/ruff_server/src/server.rs +++ b/crates/ruff_server/src/server.rs @@ -3,14 +3,11 @@ use lsp_server as lsp; use lsp_types as types; use lsp_types::InitializeParams; -use lsp_types::WorkspaceFolder; use std::num::NonZeroUsize; -use std::ops::Deref; // The new PanicInfoHook name requires MSRV >= 1.82 #[allow(deprecated)] use std::panic::PanicInfo; use std::str::FromStr; -use thiserror::Error; use types::ClientCapabilities; use types::CodeActionKind; use types::CodeActionOptions; @@ -24,7 +21,6 @@ use types::OneOf; use types::TextDocumentSyncCapability; use types::TextDocumentSyncKind; use types::TextDocumentSyncOptions; -use types::Url; use types::WorkDoneProgressOptions; use types::WorkspaceFoldersServerCapabilities; @@ -34,9 +30,8 @@ use self::schedule::event_loop_thread; use self::schedule::Scheduler; use self::schedule::Task; use crate::session::AllSettings; -use crate::session::ClientSettings; use crate::session::Session; -use crate::session::WorkspaceSettingsMap; +use crate::workspace::Workspaces; use crate::PositionEncoding; mod api; @@ -447,122 +442,3 @@ impl FromStr for SupportedCommand { }) } } - -#[derive(Debug)] -pub struct Workspaces(Vec); - -impl Workspaces { - pub fn new(workspaces: Vec) -> Self { - Self(workspaces) - } - - /// Create the workspaces from the provided workspace folders as provided by the client during - /// initialization. - fn from_workspace_folders( - workspace_folders: Option>, - mut workspace_settings: WorkspaceSettingsMap, - ) -> std::result::Result { - let mut client_settings_for_url = |url: &Url| { - workspace_settings.remove(url).unwrap_or_else(|| { - tracing::info!( - "No workspace settings found for {}, using default settings", - url - ); - ClientSettings::default() - }) - }; - - let workspaces = - if let Some(folders) = workspace_folders.filter(|folders| !folders.is_empty()) { - folders - .into_iter() - .map(|folder| { - let settings = client_settings_for_url(&folder.uri); - Workspace::new(folder.uri).with_settings(settings) - }) - .collect() - } else { - let current_dir = std::env::current_dir().map_err(WorkspacesError::Io)?; - tracing::info!( - "No workspace(s) were provided during initialization. \ - Using the current working directory as a default workspace: {}", - current_dir.display() - ); - let uri = Url::from_file_path(current_dir) - .map_err(|()| WorkspacesError::InvalidCurrentDir)?; - let settings = client_settings_for_url(&uri); - vec![Workspace::default(uri).with_settings(settings)] - }; - - Ok(Workspaces(workspaces)) - } -} - -impl Deref for Workspaces { - type Target = [Workspace]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -#[derive(Error, Debug)] -enum WorkspacesError { - #[error(transparent)] - Io(#[from] std::io::Error), - #[error("Failed to create a URL from the current working directory")] - InvalidCurrentDir, -} - -#[derive(Debug)] -pub struct Workspace { - /// The [`Url`] pointing to the root of the workspace. - url: Url, - /// The client settings for this workspace. - settings: Option, - /// Whether this is the default workspace as created by the server. This will be the case when - /// no workspace folders were provided during initialization. - is_default: bool, -} - -impl Workspace { - /// Create a new workspace with the given root URL. - pub fn new(url: Url) -> Self { - Self { - url, - settings: None, - is_default: false, - } - } - - /// Create a new default workspace with the given root URL. - pub fn default(url: Url) -> Self { - Self { - url, - settings: None, - is_default: true, - } - } - - /// Set the client settings for this workspace. - #[must_use] - pub fn with_settings(mut self, settings: ClientSettings) -> Self { - self.settings = Some(settings); - self - } - - /// Returns the root URL of the workspace. - pub(crate) fn url(&self) -> &Url { - &self.url - } - - /// Returns the client settings for this workspace. - pub(crate) fn settings(&self) -> Option<&ClientSettings> { - self.settings.as_ref() - } - - /// Returns true if this is the default workspace. - pub(crate) fn is_default(&self) -> bool { - self.is_default - } -} diff --git a/crates/ruff_server/src/session.rs b/crates/ruff_server/src/session.rs index d79502dba9..00fd9d6013 100644 --- a/crates/ruff_server/src/session.rs +++ b/crates/ruff_server/src/session.rs @@ -7,7 +7,7 @@ use lsp_types::{ClientCapabilities, FileEvent, NotebookDocumentCellChange, Url}; use settings::ResolvedClientSettings; use crate::edit::{DocumentKey, DocumentVersion, NotebookDocument}; -use crate::server::Workspaces; +use crate::workspace::Workspaces; use crate::{PositionEncoding, TextDocument}; pub(crate) use self::capabilities::ResolvedClientCapabilities; diff --git a/crates/ruff_server/src/session/index.rs b/crates/ruff_server/src/session/index.rs index 3ca1ac5ba2..4f75a35fe6 100644 --- a/crates/ruff_server/src/session/index.rs +++ b/crates/ruff_server/src/session/index.rs @@ -11,7 +11,7 @@ use thiserror::Error; pub(crate) use ruff_settings::RuffSettings; use crate::edit::LanguageId; -use crate::server::{Workspace, Workspaces}; +use crate::workspace::{Workspace, Workspaces}; use crate::{ edit::{DocumentKey, DocumentVersion, NotebookDocument}, PositionEncoding, TextDocument, diff --git a/crates/ruff_server/src/workspace.rs b/crates/ruff_server/src/workspace.rs new file mode 100644 index 0000000000..b83a63b12f --- /dev/null +++ b/crates/ruff_server/src/workspace.rs @@ -0,0 +1,126 @@ +use std::ops::Deref; + +use lsp_types::{Url, WorkspaceFolder}; +use thiserror::Error; + +use crate::session::WorkspaceSettingsMap; +use crate::ClientSettings; + +#[derive(Debug)] +pub struct Workspaces(Vec); + +impl Workspaces { + pub fn new(workspaces: Vec) -> Self { + Self(workspaces) + } + + /// Create the workspaces from the provided workspace folders as provided by the client during + /// initialization. + pub(crate) fn from_workspace_folders( + workspace_folders: Option>, + mut workspace_settings: WorkspaceSettingsMap, + ) -> std::result::Result { + let mut client_settings_for_url = |url: &Url| { + workspace_settings.remove(url).unwrap_or_else(|| { + tracing::info!( + "No workspace settings found for {}, using default settings", + url + ); + ClientSettings::default() + }) + }; + + let workspaces = + if let Some(folders) = workspace_folders.filter(|folders| !folders.is_empty()) { + folders + .into_iter() + .map(|folder| { + let settings = client_settings_for_url(&folder.uri); + Workspace::new(folder.uri).with_settings(settings) + }) + .collect() + } else { + let current_dir = std::env::current_dir().map_err(WorkspacesError::Io)?; + tracing::info!( + "No workspace(s) were provided during initialization. \ + Using the current working directory as a default workspace: {}", + current_dir.display() + ); + let uri = Url::from_file_path(current_dir) + .map_err(|()| WorkspacesError::InvalidCurrentDir)?; + let settings = client_settings_for_url(&uri); + vec![Workspace::default(uri).with_settings(settings)] + }; + + Ok(Workspaces(workspaces)) + } +} + +impl Deref for Workspaces { + type Target = [Workspace]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Error, Debug)] +pub(crate) enum WorkspacesError { + #[error(transparent)] + Io(#[from] std::io::Error), + #[error("Failed to create a URL from the current working directory")] + InvalidCurrentDir, +} + +#[derive(Debug)] +pub struct Workspace { + /// The [`Url`] pointing to the root of the workspace. + url: Url, + /// The client settings for this workspace. + settings: Option, + /// Whether this is the default workspace as created by the server. This will be the case when + /// no workspace folders were provided during initialization. + is_default: bool, +} + +impl Workspace { + /// Create a new workspace with the given root URL. + pub fn new(url: Url) -> Self { + Self { + url, + settings: None, + is_default: false, + } + } + + /// Create a new default workspace with the given root URL. + pub fn default(url: Url) -> Self { + Self { + url, + settings: None, + is_default: true, + } + } + + /// Set the client settings for this workspace. + #[must_use] + pub fn with_settings(mut self, settings: ClientSettings) -> Self { + self.settings = Some(settings); + self + } + + /// Returns the root URL of the workspace. + pub(crate) fn url(&self) -> &Url { + &self.url + } + + /// Returns the client settings for this workspace. + pub(crate) fn settings(&self) -> Option<&ClientSettings> { + self.settings.as_ref() + } + + /// Returns true if this is the default workspace. + pub(crate) fn is_default(&self) -> bool { + self.is_default + } +}