Skip to content

Commit e07da87

Browse files
committed
refactor(language_server): improve file watching for different tools
1 parent 5858641 commit e07da87

File tree

4 files changed

+365
-406
lines changed

4 files changed

+365
-406
lines changed

crates/oxc_language_server/src/backend.rs

Lines changed: 9 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,17 @@ use std::{str::FromStr, sync::Arc};
33
use futures::future::join_all;
44
use log::{debug, info, warn};
55
use rustc_hash::FxBuildHasher;
6-
use serde_json::json;
76
use tokio::sync::{OnceCell, RwLock, SetError};
87
use tower_lsp_server::{
98
Client, LanguageServer,
109
jsonrpc::{Error, ErrorCode, Result},
1110
lsp_types::{
1211
CodeActionParams, CodeActionResponse, ConfigurationItem, Diagnostic,
1312
DidChangeConfigurationParams, DidChangeTextDocumentParams, DidChangeWatchedFilesParams,
14-
DidChangeWatchedFilesRegistrationOptions, DidChangeWorkspaceFoldersParams,
15-
DidCloseTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams,
16-
DocumentFormattingParams, ExecuteCommandParams, InitializeParams, InitializeResult,
17-
InitializedParams, Registration, ServerInfo, TextEdit, Unregistration, Uri, WorkspaceEdit,
13+
DidChangeWorkspaceFoldersParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams,
14+
DidSaveTextDocumentParams, DocumentFormattingParams, ExecuteCommandParams,
15+
InitializeParams, InitializeResult, InitializedParams, Registration, ServerInfo, TextEdit,
16+
Unregistration, Uri, WorkspaceEdit,
1817
},
1918
};
2019

@@ -204,13 +203,7 @@ impl LanguageServer for Backend {
204203
// init all file watchers
205204
if capabilities.dynamic_watchers {
206205
for worker in workers {
207-
registrations.push(Registration {
208-
id: format!("watcher-{}", worker.get_root_uri().as_str()),
209-
method: "workspace/didChangeWatchedFiles".to_string(),
210-
register_options: Some(json!(DidChangeWatchedFilesRegistrationOptions {
211-
watchers: worker.init_watchers().await
212-
})),
213-
});
206+
registrations.extend(worker.init_watchers().await);
214207
}
215208
}
216209

@@ -327,7 +320,7 @@ impl LanguageServer for Backend {
327320
continue;
328321
};
329322

330-
let (diagnostics, watchers, formatter_activated) =
323+
let (diagnostics, registrations, unregistrations, formatter_activated) =
331324
worker.did_change_configuration(&option.options).await;
332325

333326
if formatter_activated && self.capabilities.get().is_some_and(|c| c.dynamic_formatting)
@@ -344,23 +337,8 @@ impl LanguageServer for Backend {
344337
}
345338
}
346339

347-
if let Some(watchers) = watchers
348-
&& self.capabilities.get().is_some_and(|capabilities| capabilities.dynamic_watchers)
349-
{
350-
// remove the old watcher
351-
removing_registrations.push(Unregistration {
352-
id: format!("watcher-{}", worker.get_root_uri().as_str()),
353-
method: "workspace/didChangeWatchedFiles".to_string(),
354-
});
355-
// add the new watcher
356-
adding_registrations.push(Registration {
357-
id: format!("watcher-{}", worker.get_root_uri().as_str()),
358-
method: "workspace/didChangeWatchedFiles".to_string(),
359-
register_options: Some(json!(DidChangeWatchedFilesRegistrationOptions {
360-
watchers
361-
})),
362-
});
363-
}
340+
removing_registrations.extend(unregistrations);
341+
adding_registrations.extend(registrations);
364342
}
365343

366344
if !new_diagnostics.is_empty() {
@@ -487,13 +465,7 @@ impl LanguageServer for Backend {
487465

488466
worker.start_worker(options).await;
489467

490-
added_registrations.push(Registration {
491-
id: format!("watcher-{}", worker.get_root_uri().as_str()),
492-
method: "workspace/didChangeWatchedFiles".to_string(),
493-
register_options: Some(json!(DidChangeWatchedFilesRegistrationOptions {
494-
watchers: worker.init_watchers().await
495-
})),
496-
});
468+
added_registrations.extend(worker.init_watchers().await);
497469
workers.push(worker);
498470
}
499471
// client does not support the request

crates/oxc_language_server/src/formatter/server_formatter.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use oxc_formatter::{
99
use oxc_parser::{ParseOptions, Parser};
1010
use tower_lsp_server::{
1111
UriExt,
12-
lsp_types::{Position, Range, TextEdit, Uri},
12+
lsp_types::{Pattern, Position, Range, TextEdit, Uri},
1313
};
1414

1515
use crate::formatter::options::FormatOptions as LSPFormatOptions;
@@ -103,6 +103,23 @@ impl ServerFormatter {
103103
}
104104
}
105105
}
106+
107+
#[expect(clippy::unused_self)]
108+
pub fn get_watcher_patterns(&self, options: &LSPFormatOptions) -> Pattern {
109+
options.config_path.as_ref().map_or(FORMAT_CONFIG_FILE, |v| v).to_owned()
110+
}
111+
112+
pub fn get_changed_watch_patterns(
113+
&self,
114+
old_options: &LSPFormatOptions,
115+
new_options: &LSPFormatOptions,
116+
) -> Option<Pattern> {
117+
if old_options != new_options && new_options.experimental {
118+
return Some(self.get_watcher_patterns(new_options));
119+
}
120+
121+
None
122+
}
106123
}
107124

108125
/// Returns the minimal text edit (start, end, replacement) to transform `source_text` into `formatted_text`

crates/oxc_language_server/src/linter/server_linter.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use log::{debug, warn};
77
use oxc_linter::{AllowWarnDeny, LintIgnoreMatcher};
88
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
99
use tokio::sync::Mutex;
10-
use tower_lsp_server::lsp_types::Uri;
10+
use tower_lsp_server::lsp_types::{Pattern, Uri};
1111

1212
use oxc_linter::{
1313
Config, ConfigStore, ConfigStoreBuilder, ExternalPluginStore, LintOptions, Oxlintrc,
@@ -40,7 +40,7 @@ pub struct ServerLinter {
4040
gitignore_glob: Vec<Gitignore>,
4141
lint_on_run: Run,
4242
diagnostics: ServerLinterDiagnostics,
43-
pub extended_paths: FxHashSet<PathBuf>,
43+
extended_paths: FxHashSet<PathBuf>,
4444
}
4545

4646
#[derive(Debug, Default)]
@@ -376,6 +376,39 @@ impl ServerLinter {
376376
// TODO: only the TsgoLinter needs to be dropped or created
377377
|| old_options.type_aware != new_options.type_aware
378378
}
379+
380+
pub fn get_watch_patterns(&self, options: &LSPLintOptions, root_path: &Path) -> Vec<Pattern> {
381+
let mut watchers = vec![
382+
options.config_path.as_ref().unwrap_or(&"**/.oxlintrc.json".to_string()).to_owned(),
383+
];
384+
385+
for path in &self.extended_paths {
386+
// ignore .oxlintrc.json files when using nested configs
387+
if path.ends_with(".oxlintrc.json") && options.use_nested_configs() {
388+
continue;
389+
}
390+
391+
let pattern = path.strip_prefix(root_path).unwrap_or(path);
392+
393+
watchers.push(normalize_path(pattern).to_string_lossy().to_string());
394+
}
395+
watchers
396+
}
397+
398+
pub fn get_changed_watch_patterns(
399+
&self,
400+
old_options: &LSPLintOptions,
401+
new_options: &LSPLintOptions,
402+
root_path: &Path,
403+
) -> Option<Vec<Pattern>> {
404+
if old_options.config_path == new_options.config_path
405+
&& old_options.use_nested_configs() == new_options.use_nested_configs()
406+
{
407+
return None;
408+
}
409+
410+
Some(self.get_watch_patterns(new_options, root_path))
411+
}
379412
}
380413

381414
#[cfg(test)]

0 commit comments

Comments
 (0)