@@ -55,9 +55,9 @@ use language::{
use log::error;
use lsp::{
DiagnosticSeverity, DiagnosticTag, DidChangeWatchedFilesRegistrationOptions,
- DocumentHighlightKind, Edit, LanguageServer, LanguageServerBinary, LanguageServerId,
- LspRequestFuture, MessageActionItem, OneOf, ServerCapabilities, ServerHealthStatus,
- ServerStatus, TextEdit,
+ DocumentHighlightKind, Edit, FileSystemWatcher, LanguageServer, LanguageServerBinary,
+ LanguageServerId, LspRequestFuture, MessageActionItem, OneOf, ServerCapabilities,
+ ServerHealthStatus, ServerStatus, TextEdit,
};
use lsp_command::*;
use node_runtime::NodeRuntime;
@@ -167,6 +167,8 @@ pub struct Project {
last_formatting_failure: Option<String>,
last_workspace_edits_by_language_server: HashMap<LanguageServerId, ProjectTransaction>,
language_server_watched_paths: HashMap<LanguageServerId, HashMap<WorktreeId, GlobSet>>,
+ language_server_watcher_registrations:
+ HashMap<LanguageServerId, HashMap<String, Vec<FileSystemWatcher>>>,
client: Arc<client::Client>,
next_entry_id: Arc<AtomicUsize>,
join_project_response_message_id: u32,
@@ -725,6 +727,7 @@ impl Project {
last_formatting_failure: None,
last_workspace_edits_by_language_server: Default::default(),
language_server_watched_paths: HashMap::default(),
+ language_server_watcher_registrations: HashMap::default(),
buffers_being_formatted: Default::default(),
buffers_needing_diff: Default::default(),
git_diff_debouncer: DebouncedDelay::new(),
@@ -875,6 +878,7 @@ impl Project {
last_formatting_failure: None,
last_workspace_edits_by_language_server: Default::default(),
language_server_watched_paths: HashMap::default(),
+ language_server_watcher_registrations: HashMap::default(),
opened_buffers: Default::default(),
buffers_being_formatted: Default::default(),
buffers_needing_diff: Default::default(),
@@ -3471,7 +3475,7 @@ impl Project {
let options = serde_json::from_value(options)?;
this.update(&mut cx, |this, cx| {
this.on_lsp_did_change_watched_files(
- server_id, options, cx,
+ server_id, ®.id, options, cx,
);
})?;
}
@@ -3483,6 +3487,27 @@ impl Project {
})
.detach();
+ language_server
+ .on_request::<lsp::request::UnregisterCapability, _, _>({
+ let this = this.clone();
+ move |params, mut cx| {
+ let this = this.clone();
+ async move {
+ for unreg in params.unregisterations.iter() {
+ if unreg.method == "workspace/didChangeWatchedFiles" {
+ this.update(&mut cx, |this, cx| {
+ this.on_lsp_unregister_did_change_watched_files(
+ server_id, &unreg.id, cx,
+ );
+ })?;
+ }
+ }
+ Ok(())
+ }
+ }
+ })
+ .detach();
+
language_server
.on_request::<lsp::request::ApplyWorkspaceEdit, _, _>({
let adapter = adapter.clone();
@@ -4208,16 +4233,67 @@ impl Project {
fn on_lsp_did_change_watched_files(
&mut self,
language_server_id: LanguageServerId,
+ registration_id: &str,
params: DidChangeWatchedFilesRegistrationOptions,
cx: &mut ModelContext<Self>,
) {
+ let registrations = self
+ .language_server_watcher_registrations
+ .entry(language_server_id)
+ .or_default();
+
+ registrations.insert(registration_id.to_string(), params.watchers);
+
+ self.rebuild_watched_paths(language_server_id, cx);
+ }
+
+ fn on_lsp_unregister_did_change_watched_files(
+ &mut self,
+ language_server_id: LanguageServerId,
+ registration_id: &str,
+ cx: &mut ModelContext<Self>,
+ ) {
+ let registrations = self
+ .language_server_watcher_registrations
+ .entry(language_server_id)
+ .or_default();
+
+ if registrations.remove(registration_id).is_some() {
+ log::info!(
+ "language server {}: unregistered workspace/DidChangeWatchedFiles capability with id {}",
+ language_server_id,
+ registration_id
+ );
+ } else {
+ log::warn!(
+ "language server {}: failed to unregister workspace/DidChangeWatchedFiles capability with id {}. not registered.",
+ language_server_id,
+ registration_id
+ );
+ }
+
+ self.rebuild_watched_paths(language_server_id, cx);
+ }
+
+ fn rebuild_watched_paths(
+ &mut self,
+ language_server_id: LanguageServerId,
+ cx: &mut ModelContext<Self>,
+ ) {
+ let Some(watchers) = self
+ .language_server_watcher_registrations
+ .get(&language_server_id)
+ else {
+ return;
+ };
+
let watched_paths = self
.language_server_watched_paths
.entry(language_server_id)
.or_default();
let mut builders = HashMap::default();
- for watcher in params.watchers {
+ for watcher in watchers.values().flatten() {
for worktree in &self.worktrees {
if let Some(worktree) = worktree.upgrade() {
let glob_is_inside_worktree = worktree.update(cx, |tree, _| {