Respect LSP servers watch glob patterns

This commit is contained in:
Max Brunsfeld 2023-03-23 15:27:43 -07:00
parent 361b7c3a0c
commit 3ff5aee4a1
5 changed files with 218 additions and 21 deletions

View file

@ -1,5 +1,6 @@
mod ignore;
mod lsp_command;
mod lsp_glob_set;
pub mod search;
pub mod terminals;
pub mod worktree;
@ -33,10 +34,11 @@ use language::{
Transaction, Unclipped,
};
use lsp::{
DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer, LanguageString,
MarkedString,
DiagnosticSeverity, DiagnosticTag, DidChangeWatchedFilesRegistrationOptions,
DocumentHighlightKind, LanguageServer, LanguageString, MarkedString,
};
use lsp_command::*;
use lsp_glob_set::LspGlobSet;
use postage::watch;
use rand::prelude::*;
use search::SearchQuery;
@ -188,6 +190,7 @@ pub enum LanguageServerState {
language: Arc<Language>,
adapter: Arc<CachedLspAdapter>,
server: Arc<LanguageServer>,
watched_paths: LspGlobSet,
simulate_disk_based_diagnostics_completion: Option<Task<()>>,
},
}
@ -2046,8 +2049,26 @@ impl Project {
})
.detach();
language_server
.on_request::<lsp::request::RegisterCapability, _, _>(|_, _| async {
Ok(())
.on_request::<lsp::request::RegisterCapability, _, _>({
let this = this.downgrade();
move |params, mut cx| async move {
let this = this
.upgrade(&cx)
.ok_or_else(|| anyhow!("project dropped"))?;
for reg in params.registrations {
if reg.method == "workspace/didChangeWatchedFiles" {
if let Some(options) = reg.register_options {
let options = serde_json::from_value(options)?;
this.update(&mut cx, |this, cx| {
this.on_lsp_did_change_watched_files(
server_id, options, cx,
);
});
}
}
}
Ok(())
}
})
.detach();
@ -2117,6 +2138,7 @@ impl Project {
LanguageServerState::Running {
adapter: adapter.clone(),
language,
watched_paths: Default::default(),
server: language_server.clone(),
simulate_disk_based_diagnostics_completion: None,
},
@ -2509,6 +2531,23 @@ impl Project {
}
}
fn on_lsp_did_change_watched_files(
&mut self,
language_server_id: usize,
params: DidChangeWatchedFilesRegistrationOptions,
cx: &mut ModelContext<Self>,
) {
if let Some(LanguageServerState::Running { watched_paths, .. }) =
self.language_servers.get_mut(&language_server_id)
{
watched_paths.clear();
for watcher in params.watchers {
watched_paths.add_pattern(&watcher.glob_pattern).log_err();
}
cx.notify();
}
}
async fn on_lsp_workspace_edit(
this: WeakModelHandle<Self>,
params: lsp::ApplyWorkspaceEditParams,
@ -4592,15 +4631,20 @@ impl Project {
for ((server_worktree_id, _), server_id) in &self.language_server_ids {
if *server_worktree_id == worktree_id {
if let Some(server) = self.language_servers.get(server_id) {
if let LanguageServerState::Running { server, .. } = server {
server
.notify::<lsp::notification::DidChangeWatchedFiles>(
lsp::DidChangeWatchedFilesParams {
changes: changes
.iter()
.map(|(path, change)| lsp::FileEvent {
uri: lsp::Url::from_file_path(abs_path.join(path))
.unwrap(),
if let LanguageServerState::Running {
server,
watched_paths,
..
} = server
{
let params = lsp::DidChangeWatchedFilesParams {
changes: changes
.iter()
.filter_map(|(path, change)| {
let path = abs_path.join(path);
if watched_paths.matches(&path) {
Some(lsp::FileEvent {
uri: lsp::Url::from_file_path(path).unwrap(),
typ: match change {
PathChange::Added => lsp::FileChangeType::CREATED,
PathChange::Removed => lsp::FileChangeType::DELETED,
@ -4610,10 +4654,18 @@ impl Project {
}
},
})
.collect(),
},
)
.log_err();
} else {
None
}
})
.collect(),
};
if !params.changes.is_empty() {
server
.notify::<lsp::notification::DidChangeWatchedFiles>(params)
.log_err();
}
}
}
}