Skip to content

Commit 97a7124

Browse files
committed
Pull diagnostics on open
1 parent 96a984c commit 97a7124

File tree

7 files changed

+131
-63
lines changed

7 files changed

+131
-63
lines changed

helix-term/src/events.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use helix_event::{events, register_event};
22
use helix_view::document::Mode;
3-
use helix_view::events::{DiagnosticsDidChange, DocumentDidChange, SelectionDidChange};
3+
use helix_view::events::{
4+
DiagnosticsDidChange, DocumentDidChange, DocumentDidOpen, SelectionDidChange,
5+
};
46

57
use crate::commands;
68
use crate::keymap::MappableCommand;
@@ -16,6 +18,7 @@ pub fn register() {
1618
register_event::<PostInsertChar>();
1719
register_event::<PostCommand>();
1820
register_event::<DocumentDidChange>();
21+
register_event::<DocumentDidOpen>();
1922
register_event::<SelectionDidChange>();
2023
register_event::<DiagnosticsDidChange>();
2124
}

helix-term/src/handlers.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use crate::handlers::signature_help::SignatureHelpHandler;
1414
pub use completion::trigger_auto_completion;
1515
pub use helix_view::handlers::Handlers;
1616

17+
use self::diagnostics::PullDiagnosticsForDocumentsHandler;
18+
1719
mod auto_save;
1820
pub mod completion;
1921
mod diagnostics;
@@ -26,12 +28,14 @@ pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers {
2628
let signature_hints = SignatureHelpHandler::new().spawn();
2729
let auto_save = AutoSaveHandler::new().spawn();
2830
let pull_diagnostics = PullDiagnosticsHandler::new().spawn();
31+
let pull_diagnostics_document = PullDiagnosticsForDocumentsHandler::new().spawn();
2932

3033
let handlers = Handlers {
3134
completions,
3235
signature_hints,
3336
auto_save,
3437
pull_diagnostics,
38+
pull_diagnostics_document,
3539
};
3640

3741
completion::register_hooks(&handlers);

helix-term/src/handlers/diagnostics.rs

Lines changed: 110 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::collections::{HashMap, HashSet};
22
use std::time::Duration;
33

44
use helix_core::syntax::LanguageServerFeature;
@@ -7,11 +7,13 @@ use helix_event::{register_hook, send_blocking};
77
use helix_lsp::lsp::{self, Diagnostic};
88
use helix_lsp::LanguageServerId;
99
use helix_view::document::Mode;
10-
use helix_view::events::{DiagnosticsDidChange, DocumentDidChange};
10+
use helix_view::events::{DiagnosticsDidChange, DocumentDidChange, DocumentDidOpen};
1111
use helix_view::handlers::diagnostics::DiagnosticEvent;
12-
use helix_view::handlers::lsp::PullDiagnosticsEvent;
12+
use helix_view::handlers::lsp::{
13+
PullDiagnosticsForDocumentsEvent, PullDiagnosticsForLanguageServersEvent,
14+
};
1315
use helix_view::handlers::Handlers;
14-
use helix_view::Editor;
16+
use helix_view::{DocumentId, Editor};
1517
use tokio::time::Instant;
1618

1719
use crate::events::OnModeSwitch;
@@ -47,106 +49,155 @@ pub(super) fn register_hooks(handlers: &Handlers) {
4749

4850
send_blocking(
4951
&tx,
50-
PullDiagnosticsEvent {
52+
PullDiagnosticsForLanguageServersEvent {
5153
language_server_ids,
5254
},
5355
);
5456
}
5557
Ok(())
5658
});
57-
}
5859

59-
const TIMEOUT: u64 = 120;
60+
let tx = handlers.pull_diagnostics_document.clone();
61+
register_hook!(move |event: &mut DocumentDidOpen| {
62+
send_blocking(
63+
&tx,
64+
PullDiagnosticsForDocumentsEvent {
65+
document_id: event.doc,
66+
},
67+
);
68+
69+
Ok(())
70+
});
71+
}
6072

6173
#[derive(Debug)]
6274
pub(super) struct PullDiagnosticsHandler {
63-
language_server_ids: Vec<LanguageServerId>,
75+
language_server_ids: HashSet<LanguageServerId>,
6476
}
6577

6678
impl PullDiagnosticsHandler {
6779
pub fn new() -> PullDiagnosticsHandler {
6880
PullDiagnosticsHandler {
69-
language_server_ids: vec![],
81+
language_server_ids: [].into(),
82+
}
83+
}
84+
}
85+
pub(super) struct PullDiagnosticsForDocumentsHandler {
86+
document_ids: HashSet<DocumentId>,
87+
}
88+
89+
impl PullDiagnosticsForDocumentsHandler {
90+
pub fn new() -> PullDiagnosticsForDocumentsHandler {
91+
PullDiagnosticsForDocumentsHandler {
92+
document_ids: [].into(),
7093
}
7194
}
7295
}
7396

7497
impl helix_event::AsyncHook for PullDiagnosticsHandler {
75-
type Event = PullDiagnosticsEvent;
98+
type Event = PullDiagnosticsForLanguageServersEvent;
7699

77100
fn handle_event(
78101
&mut self,
79102
event: Self::Event,
80103
_: Option<tokio::time::Instant>,
81104
) -> Option<tokio::time::Instant> {
82105
self.language_server_ids = event.language_server_ids;
83-
Some(Instant::now() + Duration::from_millis(TIMEOUT))
106+
Some(Instant::now() + Duration::from_millis(120))
84107
}
85108

86109
fn finish_debounce(&mut self) {
87110
let language_servers = self.language_server_ids.clone();
88111
job::dispatch_blocking(move |editor, _| {
89-
pull_diagnostic_for_document(
90-
editor,
91-
language_servers,
92-
editor.documents().map(|x| x.id()).collect(),
93-
)
112+
pull_diagnostic_for_language_servers(editor, language_servers)
113+
})
114+
}
115+
}
116+
117+
impl helix_event::AsyncHook for PullDiagnosticsForDocumentsHandler {
118+
type Event = PullDiagnosticsForDocumentsEvent;
119+
120+
fn handle_event(
121+
&mut self,
122+
event: Self::Event,
123+
_: Option<tokio::time::Instant>,
124+
) -> Option<tokio::time::Instant> {
125+
self.document_ids.insert(event.document_id);
126+
Some(Instant::now() + Duration::from_millis(50))
127+
}
128+
129+
fn finish_debounce(&mut self) {
130+
let document_ids = self.document_ids.clone();
131+
job::dispatch_blocking(move |editor, _| {
132+
pull_diagnostics_for_documents(editor, document_ids)
94133
})
95134
}
96135
}
97136

98-
fn pull_diagnostic_for_document(
137+
fn pull_diagnostics_for_documents(editor: &mut Editor, document_ids: HashSet<DocumentId>) {
138+
for document_id in document_ids {
139+
let doc = doc!(editor, &document_id);
140+
141+
let language_servers =
142+
doc.language_servers_with_feature(LanguageServerFeature::PullDiagnostics);
143+
144+
for language_server in language_servers {
145+
pull_diagnostics_for_document(doc, language_server);
146+
}
147+
}
148+
}
149+
150+
fn pull_diagnostic_for_language_servers(
99151
editor: &mut Editor,
100-
language_server_ids: Vec<LanguageServerId>,
101-
document_ids: Vec<helix_view::DocumentId>,
152+
language_server_ids: HashSet<LanguageServerId>,
102153
) {
103-
for document_id in document_ids.clone() {
154+
let document_ids: Vec<_> = editor.documents().map(|x| x.id()).collect();
155+
156+
for document_id in document_ids {
104157
let doc = doc_mut!(editor, &document_id);
105158
let language_servers = doc
106159
.language_servers()
107160
.filter(|x| language_server_ids.contains(&x.id()));
108161

109162
for language_server in language_servers {
110-
let Some(future) = language_server
111-
.text_document_diagnostic(doc.identifier(), doc.previous_diagnostic_id.clone())
112-
else {
113-
return;
114-
};
115-
116-
let Some(uri) = doc.uri() else {
117-
return;
118-
};
119-
120-
let server_id = language_server.id();
121-
122-
tokio::spawn(async move {
123-
match future.await {
124-
Ok(res) => {
125-
job::dispatch(move |editor, _| {
126-
log::error!("{}", res);
127-
128-
let parsed_response: Option<lsp::DocumentDiagnosticReport> =
129-
match serde_json::from_value(res) {
130-
Ok(result) => Some(result),
131-
Err(_) => None,
132-
};
133-
134-
let Some(response) = parsed_response else {
135-
return;
136-
};
137-
138-
show_pull_diagnostics(editor, response, server_id, uri, &document_id)
139-
})
140-
.await
141-
}
142-
Err(err) => log::error!("signature help request failed: {err}"),
143-
}
144-
});
163+
pull_diagnostics_for_document(doc, language_server);
145164
}
146165
}
147166
}
148167

149-
fn show_pull_diagnostics(
168+
fn pull_diagnostics_for_document(doc: &helix_view::Document, language_server: &helix_lsp::Client) {
169+
let Some(future) = language_server
170+
.text_document_diagnostic(doc.identifier(), doc.previous_diagnostic_id.clone())
171+
else {
172+
return;
173+
};
174+
175+
let Some(uri) = doc.uri() else {
176+
return;
177+
};
178+
179+
let server_id = language_server.id();
180+
let document_id = doc.id();
181+
182+
tokio::spawn(async move {
183+
match future.await {
184+
Ok(res) => {
185+
job::dispatch(move |editor, _| {
186+
let response = match serde_json::from_value(res) {
187+
Ok(result) => result,
188+
Err(_) => return,
189+
};
190+
191+
handle_pull_diagnostics_response(editor, response, server_id, uri, &document_id)
192+
})
193+
.await
194+
}
195+
Err(err) => log::error!("Pull diagnostic request failed: {err}"),
196+
}
197+
});
198+
}
199+
200+
fn handle_pull_diagnostics_response(
150201
editor: &mut Editor,
151202
response: lsp::DocumentDiagnosticReport,
152203
server_id: LanguageServerId,
@@ -157,7 +208,7 @@ fn show_pull_diagnostics(
157208
match response {
158209
lsp::DocumentDiagnosticReport::Full(report) => {
159210
// Original file diagnostic
160-
parse_diagnostic(
211+
add_diagnostics_to_editor(
161212
editor,
162213
uri,
163214
report.full_document_diagnostic_report.items,
@@ -187,7 +238,7 @@ fn show_pull_diagnostics(
187238
}
188239
}
189240

190-
fn parse_diagnostic(
241+
fn add_diagnostics_to_editor(
191242
editor: &mut Editor,
192243
uri: Uri,
193244
report: Vec<lsp::Diagnostic>,
@@ -213,7 +264,7 @@ fn handle_document_diagnostic_report_kind(
213264
return;
214265
};
215266

216-
parse_diagnostic(editor, uri, report.items, report.result_id, server_id);
267+
add_diagnostics_to_editor(editor, uri, report.items, report.result_id, server_id);
217268
}
218269
lsp::DocumentDiagnosticReportKind::Unchanged(report) => {
219270
let doc = doc_mut!(editor, &document_id);

helix-view/src/editor.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::{
33
document::{
44
DocumentOpenError, DocumentSavedEventFuture, DocumentSavedEventResult, Mode, SavePoint,
55
},
6+
events::DocumentDidOpen,
67
graphics::{CursorKind, Rect},
78
handlers::Handlers,
89
info::Info,
@@ -1721,6 +1722,8 @@ impl Editor {
17211722
};
17221723

17231724
self.switch(id, action);
1725+
1726+
helix_event::dispatch(DocumentDidOpen { doc: id });
17241727
Ok(id)
17251728
}
17261729

helix-view/src/events.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{Document, DocumentId, Editor, ViewId};
55

66
events! {
77
DocumentDidChange<'a> { doc: &'a mut Document, view: ViewId, old_text: &'a Rope }
8+
DocumentDidOpen { doc: DocumentId}
89
SelectionDidChange<'a> { doc: &'a mut Document, view: ViewId }
910
DiagnosticsDidChange<'a> { editor: &'a mut Editor, doc: DocumentId }
1011
}

helix-view/src/handlers.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ pub struct Handlers {
1919
pub completions: Sender<lsp::CompletionEvent>,
2020
pub signature_hints: Sender<lsp::SignatureHelpEvent>,
2121
pub auto_save: Sender<AutoSaveEvent>,
22-
pub pull_diagnostics: Sender<lsp::PullDiagnosticsEvent>,
22+
pub pull_diagnostics: Sender<lsp::PullDiagnosticsForLanguageServersEvent>,
23+
pub pull_diagnostics_document: Sender<lsp::PullDiagnosticsForDocumentsEvent>,
2324
}
2425

2526
impl Handlers {

helix-view/src/handlers/lsp.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashSet;
12
use std::fmt::Display;
23

34
use crate::editor::Action;
@@ -47,8 +48,12 @@ pub enum SignatureHelpEvent {
4748
RequestComplete { open: bool },
4849
}
4950

50-
pub struct PullDiagnosticsEvent {
51-
pub language_server_ids: Vec<helix_lsp::LanguageServerId>,
51+
pub struct PullDiagnosticsForLanguageServersEvent {
52+
pub language_server_ids: HashSet<helix_lsp::LanguageServerId>,
53+
}
54+
55+
pub struct PullDiagnosticsForDocumentsEvent {
56+
pub document_id: DocumentId,
5257
}
5358

5459
#[derive(Debug)]

0 commit comments

Comments
 (0)