From 4cde27882c56fd59247e718e904ee54637707f13 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Mon, 10 Jun 2024 12:21:47 -0700 Subject: [PATCH 1/2] Implement debug command --- .../server/api/requests/execute_command.rs | 37 +++++++++++++++++++ crates/ruff_server/src/session.rs | 12 ++++++ .../ruff_server/src/session/capabilities.rs | 18 +++++++++ crates/ruff_server/src/session/index.rs | 15 ++++++++ .../src/session/index/ruff_settings.rs | 19 +++++++++- 5 files changed, 99 insertions(+), 2 deletions(-) diff --git a/crates/ruff_server/src/server/api/requests/execute_command.rs b/crates/ruff_server/src/server/api/requests/execute_command.rs index 1cf06cf1024b0..8c1034c9bbecd 100644 --- a/crates/ruff_server/src/server/api/requests/execute_command.rs +++ b/crates/ruff_server/src/server/api/requests/execute_command.rs @@ -13,6 +13,7 @@ use serde::Deserialize; #[derive(Debug)] enum Command { + Debug, Format, FixAll, OrganizeImports, @@ -40,6 +41,15 @@ impl super::SyncRequestHandler for ExecuteCommand { let command = Command::from_str(¶ms.command).with_failure_code(ErrorCode::InvalidParams)?; + if let Command::Debug = command { + let output = debug_information(session); + #[allow(clippy::print_stderr)] + { + eprintln!("Debug information:\n{output}"); + } + return Ok(None); + } + // check if we can apply a workspace edit if !session.resolved_client_capabilities().apply_edit { return Err(anyhow::anyhow!("Cannot execute the '{}' command: the client does not support `workspace/applyEdit`", command.label())).with_failure_code(ErrorCode::InternalError); @@ -87,6 +97,9 @@ impl super::SyncRequestHandler for ExecuteCommand { .set_fixes_for_document(fixes, snapshot.query().version()) .with_failure_code(ErrorCode::InternalError)?; } + Command::Debug => { + unreachable!("The debug command should have already been handled") + } } } @@ -109,6 +122,7 @@ impl Command { Self::FixAll => "Fix all auto-fixable problems", Self::Format => "Format document", Self::OrganizeImports => "Format imports", + Self::Debug => "Print debug information", } } } @@ -121,6 +135,7 @@ impl FromStr for Command { "ruff.applyAutofix" => Self::FixAll, "ruff.applyFormat" => Self::Format, "ruff.applyOrganizeImports" => Self::OrganizeImports, + "ruff.printDebugInformation" => Self::Debug, _ => return Err(anyhow::anyhow!("Invalid command `{name}`")), }) } @@ -148,3 +163,25 @@ fn apply_edit( }, ) } + +fn debug_information(session: &Session) -> String { + let path = std::env::current_exe() + .map(|path| format!("{}", path.display())) + .unwrap_or_else(|_| "".to_string()); + format!( + r#"path = {path} +version = {version} +encoding = {encoding:?} +open_document_count = {doc_count} +active_workspace_count = {workspace_count} +configuration_files = {config_files:?} +{client_capabilities} + "#, + version = crate::version(), + encoding = session.encoding(), + client_capabilities = session.resolved_client_capabilities(), + doc_count = session.count_documents(), + workspace_count = session.count_workspaces(), + config_files = session.list_config_files() + ) +} diff --git a/crates/ruff_server/src/session.rs b/crates/ruff_server/src/session.rs index d1327bb8e3a48..74846a492ff69 100644 --- a/crates/ruff_server/src/session.rs +++ b/crates/ruff_server/src/session.rs @@ -145,6 +145,18 @@ impl Session { Ok(()) } + pub(crate) fn count_documents(&self) -> usize { + self.index.count_documents() + } + + pub(crate) fn count_workspaces(&self) -> usize { + self.index.count_workspaces() + } + + pub(crate) fn list_config_files(&self) -> Vec<&std::path::Path> { + self.index.list_config_files() + } + pub(crate) fn resolved_client_capabilities(&self) -> &ResolvedClientCapabilities { &self.resolved_client_capabilities } diff --git a/crates/ruff_server/src/session/capabilities.rs b/crates/ruff_server/src/session/capabilities.rs index 27d5d09ce7adc..001931f9e8bae 100644 --- a/crates/ruff_server/src/session/capabilities.rs +++ b/crates/ruff_server/src/session/capabilities.rs @@ -1,4 +1,5 @@ use lsp_types::ClientCapabilities; +use ruff_linter::display_settings; #[derive(Debug, Clone, PartialEq, Eq, Default)] #[allow(clippy::struct_excessive_bools)] @@ -65,3 +66,20 @@ impl ResolvedClientCapabilities { } } } + +impl std::fmt::Display for ResolvedClientCapabilities { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "capabilities", + fields = [ + self.code_action_deferred_edit_resolution, + self.apply_edit, + self.document_changes, + self.workspace_refresh, + self.pull_diagnostics, + ] + }; + Ok(()) + } +} diff --git a/crates/ruff_server/src/session/index.rs b/crates/ruff_server/src/session/index.rs index 2b68e282d3558..140aa723e5160 100644 --- a/crates/ruff_server/src/session/index.rs +++ b/crates/ruff_server/src/session/index.rs @@ -187,6 +187,21 @@ impl Index { Self::register_workspace_settings(&mut self.settings, url, None, global_settings) } + pub(super) fn count_documents(&self) -> usize { + self.documents.len() + } + + pub(super) fn count_workspaces(&self) -> usize { + self.settings.len() + } + + pub(super) fn list_config_files(&self) -> Vec<&Path> { + self.settings + .values() + .flat_map(|WorkspaceSettings { ruff_settings, .. }| ruff_settings.list_files()) + .collect() + } + fn register_workspace_settings( settings_index: &mut SettingsIndex, workspace_url: &Url, diff --git a/crates/ruff_server/src/session/index/ruff_settings.rs b/crates/ruff_server/src/session/index/ruff_settings.rs index 1939a91aca3c0..abb02a463e606 100644 --- a/crates/ruff_server/src/session/index/ruff_settings.rs +++ b/crates/ruff_server/src/session/index/ruff_settings.rs @@ -19,6 +19,9 @@ use walkdir::WalkDir; use crate::session::settings::{ConfigurationPreference, ResolvedEditorSettings}; pub(crate) struct RuffSettings { + /// The path to this configuration file, used for debugging. + /// The default fallback configuration does not have a file path. + path: Option, /// Settings used to manage file inclusion and exclusion. file_resolver: ruff_workspace::FileResolverSettings, /// Settings to pass into the Ruff linter. @@ -48,14 +51,17 @@ impl std::fmt::Display for RuffSettings { impl RuffSettings { pub(crate) fn fallback(editor_settings: &ResolvedEditorSettings, root: &Path) -> RuffSettings { + let mut path = None; let fallback = find_user_settings_toml() .and_then(|user_settings| { - ruff_workspace::resolver::resolve_root_settings( + let settings = ruff_workspace::resolver::resolve_root_settings( &user_settings, Relativity::Cwd, &EditorConfigurationTransformer(editor_settings, root), ) - .ok() + .ok(); + path = Some(user_settings); + settings }) .unwrap_or_else(|| { let default_configuration = Configuration::default(); @@ -68,6 +74,7 @@ impl RuffSettings { }); RuffSettings { + path, file_resolver: fallback.file_resolver, formatter: fallback.formatter, linter: fallback.linter, @@ -108,6 +115,7 @@ impl RuffSettingsIndex { index.insert( directory.to_path_buf(), Arc::new(RuffSettings { + path: Some(pyproject), file_resolver: settings.file_resolver, linter: settings.linter, formatter: settings.formatter, @@ -176,6 +184,7 @@ impl RuffSettingsIndex { index.insert( directory, Arc::new(RuffSettings { + path: Some(pyproject), file_resolver: settings.file_resolver, linter: settings.linter, formatter: settings.formatter, @@ -198,6 +207,12 @@ impl RuffSettingsIndex { .clone() } + pub(crate) fn list_files(&self) -> impl Iterator { + self.index + .values() + .filter_map(|settings| settings.path.as_deref()) + } + pub(super) fn fallback(&self) -> Arc { self.fallback.clone() } From 38d3d1f486ab8bb69524479d8e395b9a4925ff8d Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Tue, 11 Jun 2024 11:35:55 -0700 Subject: [PATCH 2/2] Address suggestions --- .../server/api/requests/execute_command.rs | 24 ++++++++++--------- crates/ruff_server/src/session.rs | 8 +++---- crates/ruff_server/src/session/index.rs | 4 ++-- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/crates/ruff_server/src/server/api/requests/execute_command.rs b/crates/ruff_server/src/server/api/requests/execute_command.rs index 8c1034c9bbecd..570b16cba012b 100644 --- a/crates/ruff_server/src/server/api/requests/execute_command.rs +++ b/crates/ruff_server/src/server/api/requests/execute_command.rs @@ -11,7 +11,7 @@ use lsp_server::ErrorCode; use lsp_types::{self as types, request as req}; use serde::Deserialize; -#[derive(Debug)] +#[derive(Debug, PartialEq)] enum Command { Debug, Format, @@ -34,19 +34,21 @@ impl super::RequestHandler for ExecuteCommand { impl super::SyncRequestHandler for ExecuteCommand { fn run( session: &mut Session, - _notifier: client::Notifier, + notifier: client::Notifier, requester: &mut client::Requester, params: types::ExecuteCommandParams, ) -> server::Result> { let command = Command::from_str(¶ms.command).with_failure_code(ErrorCode::InvalidParams)?; - if let Command::Debug = command { + if command == Command::Debug { let output = debug_information(session); - #[allow(clippy::print_stderr)] - { - eprintln!("Debug information:\n{output}"); - } + notifier + .notify::(types::LogMessageParams { + message: output, + typ: types::MessageType::INFO, + }) + .with_failure_code(ErrorCode::InternalError)?; return Ok(None); } @@ -165,11 +167,11 @@ fn apply_edit( } fn debug_information(session: &Session) -> String { - let path = std::env::current_exe() + let executable = std::env::current_exe() .map(|path| format!("{}", path.display())) .unwrap_or_else(|_| "".to_string()); format!( - r#"path = {path} + r#"executable = {executable} version = {version} encoding = {encoding:?} open_document_count = {doc_count} @@ -180,8 +182,8 @@ configuration_files = {config_files:?} version = crate::version(), encoding = session.encoding(), client_capabilities = session.resolved_client_capabilities(), - doc_count = session.count_documents(), - workspace_count = session.count_workspaces(), + doc_count = session.num_documents(), + workspace_count = session.num_workspaces(), config_files = session.list_config_files() ) } diff --git a/crates/ruff_server/src/session.rs b/crates/ruff_server/src/session.rs index 74846a492ff69..a6072fb6c1f59 100644 --- a/crates/ruff_server/src/session.rs +++ b/crates/ruff_server/src/session.rs @@ -145,12 +145,12 @@ impl Session { Ok(()) } - pub(crate) fn count_documents(&self) -> usize { - self.index.count_documents() + pub(crate) fn num_documents(&self) -> usize { + self.index.num_documents() } - pub(crate) fn count_workspaces(&self) -> usize { - self.index.count_workspaces() + pub(crate) fn num_workspaces(&self) -> usize { + self.index.num_workspaces() } pub(crate) fn list_config_files(&self) -> Vec<&std::path::Path> { diff --git a/crates/ruff_server/src/session/index.rs b/crates/ruff_server/src/session/index.rs index 140aa723e5160..6d60f148953a6 100644 --- a/crates/ruff_server/src/session/index.rs +++ b/crates/ruff_server/src/session/index.rs @@ -187,11 +187,11 @@ impl Index { Self::register_workspace_settings(&mut self.settings, url, None, global_settings) } - pub(super) fn count_documents(&self) -> usize { + pub(super) fn num_documents(&self) -> usize { self.documents.len() } - pub(super) fn count_workspaces(&self) -> usize { + pub(super) fn num_workspaces(&self) -> usize { self.settings.len() }