From 0a6327418defd68af9a386dd5bf250f18c83f0d2 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Wed, 17 Apr 2024 09:14:45 -0700 Subject: [PATCH] `ruff server` refreshes diagnostics for open files when file configuration is changed (#10988) ## Summary The server now requests a [workspace diagnostic refresh](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnostic_refresh) when a configuration file gets changed. This means that diagnostics for all open files will be automatically re-requested by the client on a config change. ## Test Plan You can test this by opening several files in VS Code, setting `select` in your file configuration to `[]`, and observing that the diagnostics go away once the file is saved (besides any `Pylance` diagnostics). Restore it to what it was before, and you should see the diagnostics automatically return once a save happens. --- crates/ruff_server/src/server/api.rs | 4 ++-- .../src/server/api/notifications/cancel.rs | 3 ++- .../src/server/api/notifications/did_change.rs | 3 ++- .../notifications/did_change_configuration.rs | 3 ++- .../notifications/did_change_watched_files.rs | 13 +++++++++++-- .../api/notifications/did_change_workspace.rs | 3 ++- .../src/server/api/notifications/did_close.rs | 3 ++- .../src/server/api/notifications/did_open.rs | 3 ++- crates/ruff_server/src/server/api/traits.rs | 1 + crates/ruff_server/src/session/capabilities.rs | 16 ++++++++++++++++ 10 files changed, 42 insertions(+), 10 deletions(-) diff --git a/crates/ruff_server/src/server/api.rs b/crates/ruff_server/src/server/api.rs index e3ffde76c7..81e969a5a1 100644 --- a/crates/ruff_server/src/server/api.rs +++ b/crates/ruff_server/src/server/api.rs @@ -123,8 +123,8 @@ fn local_notification_task<'a, N: traits::SyncNotificationHandler>( notif: server::Notification, ) -> super::Result> { let (id, params) = cast_notification::(notif)?; - Ok(Task::local(move |session, notifier, _, _| { - if let Err(err) = N::run(session, notifier, params) { + Ok(Task::local(move |session, notifier, requester, _| { + if let Err(err) = N::run(session, notifier, requester, params) { tracing::error!("An error occurred while running {id}: {err}"); show_err_msg!("Ruff encountered a problem. Check the logs for more details."); } diff --git a/crates/ruff_server/src/server/api/notifications/cancel.rs b/crates/ruff_server/src/server/api/notifications/cancel.rs index bd7ecd943e..0011733569 100644 --- a/crates/ruff_server/src/server/api/notifications/cancel.rs +++ b/crates/ruff_server/src/server/api/notifications/cancel.rs @@ -1,4 +1,4 @@ -use crate::server::client::Notifier; +use crate::server::client::{Notifier, Requester}; use crate::server::Result; use crate::session::Session; use lsp_types as types; @@ -15,6 +15,7 @@ impl super::SyncNotificationHandler for Cancel { fn run( _session: &mut Session, _notifier: Notifier, + _requester: &mut Requester, _params: types::CancelParams, ) -> Result<()> { // TODO(jane): Handle this once we have task cancellation in the scheduler. diff --git a/crates/ruff_server/src/server/api/notifications/did_change.rs b/crates/ruff_server/src/server/api/notifications/did_change.rs index 7b1fada792..e35b1b3b12 100644 --- a/crates/ruff_server/src/server/api/notifications/did_change.rs +++ b/crates/ruff_server/src/server/api/notifications/did_change.rs @@ -1,5 +1,5 @@ use crate::server::api::LSPResult; -use crate::server::client::Notifier; +use crate::server::client::{Notifier, Requester}; use crate::server::Result; use crate::session::Session; use lsp_types as types; @@ -16,6 +16,7 @@ impl super::SyncNotificationHandler for DidChange { fn run( session: &mut Session, _notifier: Notifier, + _requester: &mut Requester, types::DidChangeTextDocumentParams { text_document: types::VersionedTextDocumentIdentifier { diff --git a/crates/ruff_server/src/server/api/notifications/did_change_configuration.rs b/crates/ruff_server/src/server/api/notifications/did_change_configuration.rs index c1998b777b..9a2e5af99c 100644 --- a/crates/ruff_server/src/server/api/notifications/did_change_configuration.rs +++ b/crates/ruff_server/src/server/api/notifications/did_change_configuration.rs @@ -1,4 +1,4 @@ -use crate::server::client::Notifier; +use crate::server::client::{Notifier, Requester}; use crate::server::Result; use crate::session::Session; use lsp_types as types; @@ -14,6 +14,7 @@ impl super::SyncNotificationHandler for DidChangeConfiguration { fn run( _session: &mut Session, _notifier: Notifier, + _requester: &mut Requester, _params: types::DidChangeConfigurationParams, ) -> Result<()> { // TODO(jane): get this wired up after the pre-release diff --git a/crates/ruff_server/src/server/api/notifications/did_change_watched_files.rs b/crates/ruff_server/src/server/api/notifications/did_change_watched_files.rs index 3c2f2e09ef..58eebe7292 100644 --- a/crates/ruff_server/src/server/api/notifications/did_change_watched_files.rs +++ b/crates/ruff_server/src/server/api/notifications/did_change_watched_files.rs @@ -1,5 +1,6 @@ use crate::server::api::LSPResult; -use crate::server::client::Notifier; +use crate::server::client::{Notifier, Requester}; +use crate::server::schedule::Task; use crate::server::Result; use crate::session::Session; use lsp_types as types; @@ -15,13 +16,21 @@ impl super::SyncNotificationHandler for DidChangeWatchedFiles { fn run( session: &mut Session, _notifier: Notifier, + requester: &mut Requester, params: types::DidChangeWatchedFilesParams, ) -> Result<()> { - for change in params.changes { + for change in ¶ms.changes { session .reload_settings(&change.uri) .with_failure_code(lsp_server::ErrorCode::InternalError)?; } + + if session.resolved_client_capabilities().workspace_refresh && !params.changes.is_empty() { + requester + .request::((), |()| Task::nothing()) + .with_failure_code(lsp_server::ErrorCode::InternalError)?; + } + Ok(()) } } diff --git a/crates/ruff_server/src/server/api/notifications/did_change_workspace.rs b/crates/ruff_server/src/server/api/notifications/did_change_workspace.rs index bb5226ef50..e5fe4768cc 100644 --- a/crates/ruff_server/src/server/api/notifications/did_change_workspace.rs +++ b/crates/ruff_server/src/server/api/notifications/did_change_workspace.rs @@ -1,5 +1,5 @@ use crate::server::api::LSPResult; -use crate::server::client::Notifier; +use crate::server::client::{Notifier, Requester}; use crate::server::Result; use crate::session::Session; use lsp_types as types; @@ -15,6 +15,7 @@ impl super::SyncNotificationHandler for DidChangeWorkspace { fn run( session: &mut Session, _notifier: Notifier, + _requester: &mut Requester, params: types::DidChangeWorkspaceFoldersParams, ) -> Result<()> { for new in params.event.added { diff --git a/crates/ruff_server/src/server/api/notifications/did_close.rs b/crates/ruff_server/src/server/api/notifications/did_close.rs index d8a1ac29d3..85dd51d5a1 100644 --- a/crates/ruff_server/src/server/api/notifications/did_close.rs +++ b/crates/ruff_server/src/server/api/notifications/did_close.rs @@ -1,5 +1,5 @@ use crate::server::api::LSPResult; -use crate::server::client::Notifier; +use crate::server::client::{Notifier, Requester}; use crate::server::Result; use crate::session::Session; use lsp_types as types; @@ -16,6 +16,7 @@ impl super::SyncNotificationHandler for DidClose { fn run( session: &mut Session, _notifier: Notifier, + _requester: &mut Requester, types::DidCloseTextDocumentParams { text_document: types::TextDocumentIdentifier { uri }, }: types::DidCloseTextDocumentParams, diff --git a/crates/ruff_server/src/server/api/notifications/did_open.rs b/crates/ruff_server/src/server/api/notifications/did_open.rs index ff76a80875..388706a13b 100644 --- a/crates/ruff_server/src/server/api/notifications/did_open.rs +++ b/crates/ruff_server/src/server/api/notifications/did_open.rs @@ -1,4 +1,4 @@ -use crate::server::client::Notifier; +use crate::server::client::{Notifier, Requester}; use crate::server::Result; use crate::session::Session; use lsp_types as types; @@ -15,6 +15,7 @@ impl super::SyncNotificationHandler for DidOpen { fn run( session: &mut Session, _notifier: Notifier, + _requester: &mut Requester, types::DidOpenTextDocumentParams { text_document: types::TextDocumentItem { diff --git a/crates/ruff_server/src/server/api/traits.rs b/crates/ruff_server/src/server/api/traits.rs index 59da1624e3..3c8e56b7a2 100644 --- a/crates/ruff_server/src/server/api/traits.rs +++ b/crates/ruff_server/src/server/api/traits.rs @@ -56,6 +56,7 @@ pub(super) trait SyncNotificationHandler: NotificationHandler { fn run( session: &mut Session, notifier: Notifier, + requester: &mut Requester, params: <::NotificationType as LSPNotification>::Params, ) -> super::Result<()>; } diff --git a/crates/ruff_server/src/session/capabilities.rs b/crates/ruff_server/src/session/capabilities.rs index 563737542c..4a83d92dd1 100644 --- a/crates/ruff_server/src/session/capabilities.rs +++ b/crates/ruff_server/src/session/capabilities.rs @@ -1,10 +1,12 @@ use lsp_types::ClientCapabilities; #[derive(Debug, Clone, PartialEq, Eq, Default)] +#[allow(clippy::struct_excessive_bools)] pub(crate) struct ResolvedClientCapabilities { pub(crate) code_action_deferred_edit_resolution: bool, pub(crate) apply_edit: bool, pub(crate) document_changes: bool, + pub(crate) workspace_refresh: bool, } impl ResolvedClientCapabilities { @@ -33,11 +35,25 @@ impl ResolvedClientCapabilities { .and_then(|workspace_edit| workspace_edit.document_changes) .unwrap_or_default(); + let workspace_refresh = true; + + // TODO(jane): Once the bug involving workspace.diagnostic(s) deserialization has been fixed, + // uncomment this. + /* + let workspace_refresh = client_capabilities + .workspace + .as_ref() + .and_then(|workspace| workspace.diagnostic.as_ref()) + .and_then(|diagnostic| diagnostic.refresh_support) + .unwrap_or_default(); + */ + Self { code_action_deferred_edit_resolution: code_action_data_support && code_action_edit_resolution, apply_edit, document_changes, + workspace_refresh, } } }