1
- use std:: collections:: HashMap ;
1
+ use std:: collections:: { HashMap , HashSet } ;
2
2
use std:: time:: Duration ;
3
3
4
4
use helix_core:: syntax:: LanguageServerFeature ;
@@ -7,11 +7,13 @@ use helix_event::{register_hook, send_blocking};
7
7
use helix_lsp:: lsp:: { self , Diagnostic } ;
8
8
use helix_lsp:: LanguageServerId ;
9
9
use helix_view:: document:: Mode ;
10
- use helix_view:: events:: { DiagnosticsDidChange , DocumentDidChange } ;
10
+ use helix_view:: events:: { DiagnosticsDidChange , DocumentDidChange , DocumentDidOpen } ;
11
11
use helix_view:: handlers:: diagnostics:: DiagnosticEvent ;
12
- use helix_view:: handlers:: lsp:: PullDiagnosticsEvent ;
12
+ use helix_view:: handlers:: lsp:: {
13
+ PullDiagnosticsForDocumentsEvent , PullDiagnosticsForLanguageServersEvent ,
14
+ } ;
13
15
use helix_view:: handlers:: Handlers ;
14
- use helix_view:: Editor ;
16
+ use helix_view:: { DocumentId , Editor } ;
15
17
use tokio:: time:: Instant ;
16
18
17
19
use crate :: events:: OnModeSwitch ;
@@ -47,16 +49,26 @@ pub(super) fn register_hooks(handlers: &Handlers) {
47
49
48
50
send_blocking(
49
51
& tx,
50
- PullDiagnosticsEvent {
52
+ PullDiagnosticsForLanguageServersEvent {
51
53
language_server_ids,
52
54
} ,
53
55
) ;
54
56
}
55
57
Ok ( ( ) )
56
58
} ) ;
57
- }
58
59
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
+ }
60
72
61
73
#[ derive( Debug ) ]
62
74
pub ( super ) struct PullDiagnosticsHandler {
@@ -70,37 +82,119 @@ impl PullDiagnosticsHandler {
70
82
}
71
83
}
72
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 ( ) ,
93
+ }
94
+ }
95
+ }
73
96
74
97
impl helix_event:: AsyncHook for PullDiagnosticsHandler {
75
- type Event = PullDiagnosticsEvent ;
98
+ type Event = PullDiagnosticsForLanguageServersEvent ;
76
99
77
100
fn handle_event (
78
101
& mut self ,
79
102
event : Self :: Event ,
80
103
_: Option < tokio:: time:: Instant > ,
81
104
) -> Option < tokio:: time:: Instant > {
82
105
self . language_server_ids = event. language_server_ids ;
83
- Some ( Instant :: now ( ) + Duration :: from_millis ( TIMEOUT ) )
106
+ Some ( Instant :: now ( ) + Duration :: from_millis ( 120 ) )
84
107
}
85
108
86
109
fn finish_debounce ( & mut self ) {
87
110
let language_servers = self . language_server_ids . clone ( ) ;
88
111
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)
94
134
} )
95
135
}
96
136
}
97
137
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 (
99
192
editor : & mut Editor ,
100
193
language_server_ids : Vec < LanguageServerId > ,
101
- document_ids : Vec < helix_view:: DocumentId > ,
102
194
) {
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 {
104
198
let doc = doc_mut ! ( editor, & document_id) ;
105
199
let language_servers = doc
106
200
. language_servers ( )
@@ -123,8 +217,6 @@ fn pull_diagnostic_for_document(
123
217
match future. await {
124
218
Ok ( res) => {
125
219
job:: dispatch ( move |editor, _| {
126
- log:: error!( "{}" , res) ;
127
-
128
220
let parsed_response: Option < lsp:: DocumentDiagnosticReport > =
129
221
match serde_json:: from_value ( res) {
130
222
Ok ( result) => Some ( result) ,
@@ -135,18 +227,24 @@ fn pull_diagnostic_for_document(
135
227
return ;
136
228
} ;
137
229
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
+ )
139
237
} )
140
238
. await
141
239
}
142
- Err ( err) => log:: error!( "signature help request failed: {err}" ) ,
240
+ Err ( err) => log:: error!( "Pull diagnostic request failed: {err}" ) ,
143
241
}
144
242
} ) ;
145
243
}
146
244
}
147
245
}
148
246
149
- fn show_pull_diagnostics (
247
+ fn handle_pull_diagnostics_response (
150
248
editor : & mut Editor ,
151
249
response : lsp:: DocumentDiagnosticReport ,
152
250
server_id : LanguageServerId ,
@@ -157,7 +255,7 @@ fn show_pull_diagnostics(
157
255
match response {
158
256
lsp:: DocumentDiagnosticReport :: Full ( report) => {
159
257
// Original file diagnostic
160
- parse_diagnostic (
258
+ add_diagnostic (
161
259
editor,
162
260
uri,
163
261
report. full_document_diagnostic_report . items ,
@@ -187,7 +285,7 @@ fn show_pull_diagnostics(
187
285
}
188
286
}
189
287
190
- fn parse_diagnostic (
288
+ fn add_diagnostic (
191
289
editor : & mut Editor ,
192
290
uri : Uri ,
193
291
report : Vec < lsp:: Diagnostic > ,
@@ -213,7 +311,7 @@ fn handle_document_diagnostic_report_kind(
213
311
return ;
214
312
} ;
215
313
216
- parse_diagnostic ( editor, uri, report. items , report. result_id , server_id) ;
314
+ add_diagnostic ( editor, uri, report. items , report. result_id , server_id) ;
217
315
}
218
316
lsp:: DocumentDiagnosticReportKind :: Unchanged ( report) => {
219
317
let doc = doc_mut ! ( editor, & document_id) ;
0 commit comments