Skip to content

Commit a09d9f7

Browse files
committed
feat(language_server): watch for fmt.configPath file content change
1 parent f977700 commit a09d9f7

File tree

2 files changed

+56
-28
lines changed

2 files changed

+56
-28
lines changed

crates/oxc_language_server/src/backend.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ impl LanguageServer for Backend {
327327
continue;
328328
};
329329

330-
let (diagnostics, watcher, formatter_activated) =
330+
let (diagnostics, watchers, formatter_activated) =
331331
worker.did_change_configuration(&option.options).await;
332332

333333
if formatter_activated && self.capabilities.get().is_some_and(|c| c.dynamic_formatting)
@@ -344,9 +344,7 @@ impl LanguageServer for Backend {
344344
}
345345
}
346346

347-
if let Some(watcher) = watcher
348-
&& self.capabilities.get().is_some_and(|capabilities| capabilities.dynamic_watchers)
349-
{
347+
if self.capabilities.get().is_some_and(|capabilities| capabilities.dynamic_watchers) {
350348
// remove the old watcher
351349
removing_registrations.push(Unregistration {
352350
id: format!("watcher-{}", worker.get_root_uri().as_str()),
@@ -357,7 +355,7 @@ impl LanguageServer for Backend {
357355
id: format!("watcher-{}", worker.get_root_uri().as_str()),
358356
method: "workspace/didChangeWatchedFiles".to_string(),
359357
register_options: Some(json!(DidChangeWatchedFilesRegistrationOptions {
360-
watchers: vec![watcher]
358+
watchers
361359
})),
362360
});
363361
}

crates/oxc_language_server/src/worker.rs

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use tower_lsp_server::{
1111
};
1212

1313
use crate::{
14-
ConcurrentHashMap,
14+
ConcurrentHashMap, FORMAT_CONFIG_FILE,
1515
code_actions::{apply_all_fix_code_action, apply_fix_code_actions, fix_all_text_edit},
1616
formatter::server_formatter::ServerFormatter,
1717
linter::{
@@ -104,6 +104,19 @@ impl WorkspaceWorker {
104104
kind: Some(WatchKind::all()), // created, deleted, changed
105105
});
106106

107+
watchers.push(FileSystemWatcher {
108+
glob_pattern: GlobPattern::Relative(RelativePattern {
109+
base_uri: OneOf::Right(self.root_uri.clone()),
110+
pattern: options
111+
.lint
112+
.config_path
113+
.as_ref()
114+
.map_or(FORMAT_CONFIG_FILE, |v| v)
115+
.to_owned(),
116+
}),
117+
kind: Some(WatchKind::all()), // created, deleted, changed
118+
});
119+
107120
let Some(root_path) = &self.root_uri.to_file_path() else {
108121
return watchers;
109122
};
@@ -296,6 +309,7 @@ impl WorkspaceWorker {
296309
&self,
297310
_file_event: &FileEvent,
298311
) -> Option<ConcurrentHashMap<String, Vec<DiagnosticReport>>> {
312+
// TODO: the tools should implement a helper function to detect if the changed file is relevant
299313
let files = {
300314
let server_linter_guard = self.server_linter.read().await;
301315
let server_linter = server_linter_guard.as_ref()?;
@@ -320,8 +334,8 @@ impl WorkspaceWorker {
320334
) -> (
321335
// Diagnostic reports that need to be revalidated
322336
Option<ConcurrentHashMap<String, Vec<DiagnosticReport>>>,
323-
// File system watcher for lint config changes
324-
Option<FileSystemWatcher>,
337+
// File system watcher for lint/fmt config changes
338+
Vec<FileSystemWatcher>,
325339
// Is true, when the formatter was added to the workspace worker
326340
bool,
327341
) {
@@ -346,13 +360,35 @@ impl WorkspaceWorker {
346360
}
347361

348362
let mut formatting = false;
363+
364+
// create all watchers again, because maybe one tool configuration is changed
365+
// and we unregister the workspace watcher and register a new one.
366+
// Without adding the old watchers back, the client would not watch them anymore.
367+
//
368+
// TODO: create own watcher for each tool with its own id,
369+
// so we can unregister only the watcher that changed.
370+
let mut watchers = Vec::new();
371+
349372
if current_option.format != changed_options.format {
350373
if changed_options.format.experimental {
351374
debug!("experimental formatter enabled/restarted");
352375
// restart the formatter
353376
*self.server_formatter.write().await =
354377
Some(ServerFormatter::new(&self.root_uri, &changed_options.format));
355378
formatting = true;
379+
380+
watchers.push(FileSystemWatcher {
381+
glob_pattern: GlobPattern::Relative(RelativePattern {
382+
base_uri: OneOf::Right(self.root_uri.clone()),
383+
pattern: current_option
384+
.format
385+
.config_path
386+
.as_ref()
387+
.map_or(FORMAT_CONFIG_FILE, |v| v)
388+
.to_owned(),
389+
}),
390+
kind: Some(WatchKind::all()), // created, deleted, changed
391+
});
356392
} else {
357393
debug!("experimental formatter disabled");
358394
*self.server_formatter.write().await = None;
@@ -371,29 +407,23 @@ impl WorkspaceWorker {
371407
};
372408
self.refresh_server_linter(&changed_options.lint).await;
373409

374-
if current_option.lint.config_path != changed_options.lint.config_path {
375-
return (
376-
Some(self.revalidate_diagnostics(files).await),
377-
Some(FileSystemWatcher {
378-
glob_pattern: GlobPattern::Relative(RelativePattern {
379-
base_uri: OneOf::Right(self.root_uri.clone()),
380-
pattern: changed_options
381-
.lint
382-
.config_path
383-
.as_ref()
384-
.unwrap_or(&"**/.oxlintrc.json".to_string())
385-
.to_owned(),
386-
}),
387-
kind: Some(WatchKind::all()), // created, deleted, changed
388-
}),
389-
formatting,
390-
);
391-
}
410+
watchers.push(FileSystemWatcher {
411+
glob_pattern: GlobPattern::Relative(RelativePattern {
412+
base_uri: OneOf::Right(self.root_uri.clone()),
413+
pattern: current_option
414+
.lint
415+
.config_path
416+
.as_ref()
417+
.unwrap_or(&"**/.oxlintrc.json".to_string())
418+
.to_owned(),
419+
}),
420+
kind: Some(WatchKind::all()), // created, deleted, changed
421+
});
392422

393-
return (Some(self.revalidate_diagnostics(files).await), None, formatting);
423+
return (Some(self.revalidate_diagnostics(files).await), watchers, formatting);
394424
}
395425

396-
(None, None, formatting)
426+
(None, watchers, formatting)
397427
}
398428
}
399429

0 commit comments

Comments
 (0)