Skip to content

Commit 573facd

Browse files
authored
Fix automatic configuration reloading for text and notebook documents (#11492)
## Summary Recent changes made in the [Jupyter Notebook feature PR](#11206) caused automatic configuration reloading to stop working. This was because we would check for paths to reload using the changed path, when we should have been using the parent path of the changed path (to get the directory it was changed in). Additionally, this PR fixes an issue where `ruff.toml` and `.ruff.toml` files were not being automatically reloaded. Finally, this PR improves configuration reloading by actively publishing diagnostics for notebook documents (which won't be affected by the workspace refresh since they don't use pull diagnostics). It will also publish diagnostics for text documents if pull diagnostics aren't supported. ## Test Plan To test this, open an existing configuration file in a codebase, and make modifications that will affect one or more open Python / Jupyter Notebook files. You should observe that the diagnostics for both kinds of files update automatically when the file changes are saved. Here's a test video showing what a successful test should look like: https://github.com/astral-sh/ruff/assets/19577865/7172b598-d6de-4965-b33c-6cb8b911ef6c
1 parent 3cb2e67 commit 573facd

File tree

4 files changed

+61
-7
lines changed

4 files changed

+61
-7
lines changed

crates/ruff_server/src/server.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,14 @@ impl Server {
173173
watchers: vec![
174174
FileSystemWatcher {
175175
glob_pattern: types::GlobPattern::String(
176-
"**/.?ruff.toml".into(),
176+
"**/.ruff.toml".into(),
177177
),
178178
kind: None,
179179
},
180+
FileSystemWatcher {
181+
glob_pattern: types::GlobPattern::String("**/ruff.toml".into()),
182+
kind: None,
183+
},
180184
FileSystemWatcher {
181185
glob_pattern: types::GlobPattern::String(
182186
"**/pyproject.toml".into(),

crates/ruff_server/src/server/api/notifications/did_change_watched_files.rs

+24-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::server::api::diagnostics::publish_diagnostics_for_document;
12
use crate::server::api::LSPResult;
23
use crate::server::client::{Notifier, Requester};
34
use crate::server::schedule::Task;
@@ -15,18 +16,36 @@ impl super::NotificationHandler for DidChangeWatchedFiles {
1516
impl super::SyncNotificationHandler for DidChangeWatchedFiles {
1617
fn run(
1718
session: &mut Session,
18-
_notifier: Notifier,
19+
notifier: Notifier,
1920
requester: &mut Requester,
2021
params: types::DidChangeWatchedFilesParams,
2122
) -> Result<()> {
2223
for change in &params.changes {
2324
session.reload_settings(&change.uri.to_file_path().unwrap());
2425
}
2526

26-
if session.resolved_client_capabilities().workspace_refresh && !params.changes.is_empty() {
27-
requester
28-
.request::<types::request::WorkspaceDiagnosticRefresh>((), |()| Task::nothing())
29-
.with_failure_code(lsp_server::ErrorCode::InternalError)?;
27+
if !params.changes.is_empty() {
28+
if session.resolved_client_capabilities().workspace_refresh {
29+
requester
30+
.request::<types::request::WorkspaceDiagnosticRefresh>((), |()| Task::nothing())
31+
.with_failure_code(lsp_server::ErrorCode::InternalError)?;
32+
} else {
33+
// publish diagnostics for text documents
34+
for url in session.text_document_urls() {
35+
let snapshot = session
36+
.take_snapshot(&url)
37+
.expect("snapshot should be available");
38+
publish_diagnostics_for_document(&snapshot, &notifier)?;
39+
}
40+
}
41+
42+
// always publish diagnostics for notebook files (since they don't use pull diagnostics)
43+
for url in session.notebook_document_urls() {
44+
let snapshot = session
45+
.take_snapshot(&url)
46+
.expect("snapshot should be available");
47+
publish_diagnostics_for_document(&snapshot, &notifier)?;
48+
}
3049
}
3150

3251
Ok(())

crates/ruff_server/src/session.rs

+10
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ impl Session {
7272
})
7373
}
7474

75+
/// Iterates over the LSP URLs for all open text documents. These URLs are valid file paths.
76+
pub(super) fn text_document_urls(&self) -> impl Iterator<Item = lsp_types::Url> + '_ {
77+
self.index.text_document_urls()
78+
}
79+
80+
/// Iterates over the LSP URLs for all open notebook documents. These URLs are valid file paths.
81+
pub(super) fn notebook_document_urls(&self) -> impl Iterator<Item = lsp_types::Url> + '_ {
82+
self.index.notebook_document_urls()
83+
}
84+
7585
/// Updates a text document at the associated `key`.
7686
///
7787
/// The document key must point to a text document, or this will throw an error.

crates/ruff_server/src/session/index.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,24 @@ impl Index {
8888
}
8989
}
9090

91+
pub(super) fn text_document_urls(&self) -> impl Iterator<Item = lsp_types::Url> + '_ {
92+
self.documents
93+
.iter()
94+
.filter(|(_, doc)| doc.as_text().is_some())
95+
.map(|(path, _)| {
96+
lsp_types::Url::from_file_path(path).expect("valid file path should convert to URL")
97+
})
98+
}
99+
100+
pub(super) fn notebook_document_urls(&self) -> impl Iterator<Item = lsp_types::Url> + '_ {
101+
self.documents
102+
.iter()
103+
.filter(|(_, doc)| doc.as_notebook().is_some())
104+
.map(|(path, _)| {
105+
lsp_types::Url::from_file_path(path).expect("valid file path should convert to URL")
106+
})
107+
}
108+
91109
pub(super) fn update_text_document(
92110
&mut self,
93111
key: &DocumentKey,
@@ -234,11 +252,14 @@ impl Index {
234252
Some(controller.make_ref(cell_uri, path, document_settings))
235253
}
236254

255+
/// Reloads relevant existing settings files based on a changed settings file path.
256+
/// This does not currently register new settings files.
237257
pub(super) fn reload_settings(&mut self, changed_path: &PathBuf) {
258+
let search_path = changed_path.parent().unwrap_or(changed_path);
238259
for (root, settings) in self
239260
.settings
240261
.iter_mut()
241-
.filter(|(path, _)| path.starts_with(changed_path))
262+
.filter(|(path, _)| path.starts_with(search_path))
242263
{
243264
settings.workspace_settings_index = ruff_settings::RuffSettingsIndex::new(
244265
root,

0 commit comments

Comments
 (0)