Skip to content

Commit ac7aabf

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

File tree

7 files changed

+142
-28
lines changed

7 files changed

+142
-28
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: 123 additions & 25 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,16 +49,26 @@ 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 {
@@ -70,37 +82,119 @@ impl PullDiagnosticsHandler {
7082
}
7183
}
7284
}
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(),
93+
}
94+
}
95+
}
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+
127+
Some(Instant::now() + Duration::from_millis(50))
128+
}
129+
130+
fn finish_debounce(&mut self) {
131+
let document_ids = self.document_ids.clone();
132+
job::dispatch_blocking(move |editor, _| {
133+
pull_diagnostics_for_documents(editor, document_ids)
94134
})
95135
}
96136
}
97137

98-
fn pull_diagnostic_for_document(
138+
fn pull_diagnostics_for_documents(editor: &mut Editor, document_ids: HashSet<DocumentId>) {
139+
for document_id in document_ids {
140+
let doc = doc_mut!(editor, &document_id);
141+
142+
log::error!("Pulling for {:?}", doc.path());
143+
144+
let language_servers =
145+
doc.language_servers_with_feature(LanguageServerFeature::PullDiagnostics);
146+
147+
for language_server in language_servers {
148+
let Some(future) = language_server
149+
.text_document_diagnostic(doc.identifier(), doc.previous_diagnostic_id.clone())
150+
else {
151+
return;
152+
};
153+
154+
let Some(uri) = doc.uri() else {
155+
return;
156+
};
157+
158+
let server_id = language_server.id();
159+
160+
tokio::spawn(async move {
161+
match future.await {
162+
Ok(res) => {
163+
job::dispatch(move |editor, _| {
164+
let parsed_response: Option<lsp::DocumentDiagnosticReport> =
165+
match serde_json::from_value(res) {
166+
Ok(result) => Some(result),
167+
Err(_) => None,
168+
};
169+
170+
let Some(response) = parsed_response else {
171+
return;
172+
};
173+
174+
handle_pull_diagnostics_response(
175+
editor,
176+
response,
177+
server_id,
178+
uri,
179+
&document_id,
180+
)
181+
})
182+
.await
183+
}
184+
Err(err) => log::error!("Pull diagnostic request failed: {err}"),
185+
}
186+
});
187+
}
188+
}
189+
}
190+
191+
fn pull_diagnostic_for_language_servers(
99192
editor: &mut Editor,
100193
language_server_ids: Vec<LanguageServerId>,
101-
document_ids: Vec<helix_view::DocumentId>,
102194
) {
103-
for document_id in document_ids.clone() {
195+
let document_ids: Vec<_> = editor.documents().map(|x| x.id()).collect();
196+
197+
for document_id in document_ids {
104198
let doc = doc_mut!(editor, &document_id);
105199
let language_servers = doc
106200
.language_servers()
@@ -123,8 +217,6 @@ fn pull_diagnostic_for_document(
123217
match future.await {
124218
Ok(res) => {
125219
job::dispatch(move |editor, _| {
126-
log::error!("{}", res);
127-
128220
let parsed_response: Option<lsp::DocumentDiagnosticReport> =
129221
match serde_json::from_value(res) {
130222
Ok(result) => Some(result),
@@ -135,18 +227,24 @@ fn pull_diagnostic_for_document(
135227
return;
136228
};
137229

138-
show_pull_diagnostics(editor, response, server_id, uri, &document_id)
230+
handle_pull_diagnostics_response(
231+
editor,
232+
response,
233+
server_id,
234+
uri,
235+
&document_id,
236+
)
139237
})
140238
.await
141239
}
142-
Err(err) => log::error!("signature help request failed: {err}"),
240+
Err(err) => log::error!("Pull diagnostic request failed: {err}"),
143241
}
144242
});
145243
}
146244
}
147245
}
148246

149-
fn show_pull_diagnostics(
247+
fn handle_pull_diagnostics_response(
150248
editor: &mut Editor,
151249
response: lsp::DocumentDiagnosticReport,
152250
server_id: LanguageServerId,
@@ -157,7 +255,7 @@ fn show_pull_diagnostics(
157255
match response {
158256
lsp::DocumentDiagnosticReport::Full(report) => {
159257
// Original file diagnostic
160-
parse_diagnostic(
258+
add_diagnostic(
161259
editor,
162260
uri,
163261
report.full_document_diagnostic_report.items,
@@ -187,7 +285,7 @@ fn show_pull_diagnostics(
187285
}
188286
}
189287

190-
fn parse_diagnostic(
288+
fn add_diagnostic(
191289
editor: &mut Editor,
192290
uri: Uri,
193291
report: Vec<lsp::Diagnostic>,
@@ -213,7 +311,7 @@ fn handle_document_diagnostic_report_kind(
213311
return;
214312
};
215313

216-
parse_diagnostic(editor, uri, report.items, report.result_id, server_id);
314+
add_diagnostic(editor, uri, report.items, report.result_id, server_id);
217315
}
218316
lsp::DocumentDiagnosticReportKind::Unchanged(report) => {
219317
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,
@@ -1717,6 +1718,8 @@ impl Editor {
17171718
let id = self.new_document(doc);
17181719
self.launch_language_servers(id);
17191720

1721+
helix_event::dispatch(DocumentDidOpen { doc: id });
1722+
17201723
id
17211724
};
17221725

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: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,14 @@ pub enum SignatureHelpEvent {
4747
RequestComplete { open: bool },
4848
}
4949

50-
pub struct PullDiagnosticsEvent {
50+
pub struct PullDiagnosticsForLanguageServersEvent {
5151
pub language_server_ids: Vec<helix_lsp::LanguageServerId>,
5252
}
5353

54+
pub struct PullDiagnosticsForDocumentsEvent {
55+
pub document_id: DocumentId,
56+
}
57+
5458
#[derive(Debug)]
5559
pub struct ApplyEditError {
5660
pub kind: ApplyEditErrorKind,

0 commit comments

Comments
 (0)