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 ;
@@ -33,7 +35,7 @@ pub(super) fn register_hooks(handlers: &Handlers) {
33
35
Ok ( ( ) )
34
36
} ) ;
35
37
36
- let tx = handlers. pull_diagnostics . clone ( ) ;
38
+ let tx = handlers. pull_diagnostics_for_language_servers . clone ( ) ;
37
39
register_hook ! ( move |event: & mut DocumentDidChange <' _>| {
38
40
if event
39
41
. doc
@@ -47,106 +49,160 @@ 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_for_documents . clone ( ) ;
61
+ register_hook ! ( move |event: & mut DocumentDidOpen <' _>| {
62
+ if event
63
+ . doc
64
+ . has_language_server_with_feature( LanguageServerFeature :: PullDiagnostics )
65
+ {
66
+ send_blocking(
67
+ & tx,
68
+ PullDiagnosticsForDocumentsEvent {
69
+ document_id: event. doc. id( ) ,
70
+ } ,
71
+ ) ;
72
+ }
73
+
74
+ Ok ( ( ) )
75
+ } ) ;
76
+ }
60
77
61
78
#[ derive( Debug ) ]
62
- pub ( super ) struct PullDiagnosticsHandler {
63
- language_server_ids : Vec < LanguageServerId > ,
79
+ pub ( super ) struct PullDiagnosticsForLanguageServersHandler {
80
+ language_server_ids : HashSet < LanguageServerId > ,
64
81
}
65
82
66
- impl PullDiagnosticsHandler {
67
- pub fn new ( ) -> PullDiagnosticsHandler {
68
- PullDiagnosticsHandler {
69
- language_server_ids : vec ! [ ] ,
83
+ impl PullDiagnosticsForLanguageServersHandler {
84
+ pub fn new ( ) -> PullDiagnosticsForLanguageServersHandler {
85
+ PullDiagnosticsForLanguageServersHandler {
86
+ language_server_ids : [ ] . into ( ) ,
70
87
}
71
88
}
72
89
}
90
+ pub ( super ) struct PullDiagnosticsForDocumentsHandler {
91
+ document_ids : HashSet < DocumentId > ,
92
+ }
73
93
74
- impl helix_event:: AsyncHook for PullDiagnosticsHandler {
75
- type Event = PullDiagnosticsEvent ;
94
+ impl PullDiagnosticsForDocumentsHandler {
95
+ pub fn new ( ) -> PullDiagnosticsForDocumentsHandler {
96
+ PullDiagnosticsForDocumentsHandler {
97
+ document_ids : [ ] . into ( ) ,
98
+ }
99
+ }
100
+ }
101
+
102
+ impl helix_event:: AsyncHook for PullDiagnosticsForLanguageServersHandler {
103
+ type Event = PullDiagnosticsForLanguageServersEvent ;
76
104
77
105
fn handle_event (
78
106
& mut self ,
79
107
event : Self :: Event ,
80
108
_: Option < tokio:: time:: Instant > ,
81
109
) -> Option < tokio:: time:: Instant > {
82
110
self . language_server_ids = event. language_server_ids ;
83
- Some ( Instant :: now ( ) + Duration :: from_millis ( TIMEOUT ) )
111
+ Some ( Instant :: now ( ) + Duration :: from_millis ( 120 ) )
84
112
}
85
113
86
114
fn finish_debounce ( & mut self ) {
87
115
let language_servers = self . language_server_ids . clone ( ) ;
88
116
job:: dispatch_blocking ( move |editor, _| {
89
- pull_diagnostic_for_document (
90
- editor,
91
- language_servers,
92
- editor. documents ( ) . map ( |x| x. id ( ) ) . collect ( ) ,
93
- )
117
+ pull_diagnostic_for_language_servers ( editor, language_servers)
94
118
} )
95
119
}
96
120
}
97
121
98
- fn pull_diagnostic_for_document (
122
+ impl helix_event:: AsyncHook for PullDiagnosticsForDocumentsHandler {
123
+ type Event = PullDiagnosticsForDocumentsEvent ;
124
+
125
+ fn handle_event (
126
+ & mut self ,
127
+ event : Self :: Event ,
128
+ _: Option < tokio:: time:: Instant > ,
129
+ ) -> Option < tokio:: time:: Instant > {
130
+ self . document_ids . insert ( event. document_id ) ;
131
+ Some ( Instant :: now ( ) + Duration :: from_millis ( 50 ) )
132
+ }
133
+
134
+ fn finish_debounce ( & mut self ) {
135
+ let document_ids = self . document_ids . clone ( ) ;
136
+ job:: dispatch_blocking ( move |editor, _| {
137
+ pull_diagnostics_for_documents ( editor, document_ids)
138
+ } )
139
+ }
140
+ }
141
+
142
+ fn pull_diagnostics_for_documents ( editor : & mut Editor , document_ids : HashSet < DocumentId > ) {
143
+ for document_id in document_ids {
144
+ let doc = doc ! ( editor, & document_id) ;
145
+
146
+ let language_servers =
147
+ doc. language_servers_with_feature ( LanguageServerFeature :: PullDiagnostics ) ;
148
+
149
+ for language_server in language_servers {
150
+ pull_diagnostics_for_document ( doc, language_server) ;
151
+ }
152
+ }
153
+ }
154
+
155
+ fn pull_diagnostic_for_language_servers (
99
156
editor : & mut Editor ,
100
- language_server_ids : Vec < LanguageServerId > ,
101
- document_ids : Vec < helix_view:: DocumentId > ,
157
+ language_server_ids : HashSet < LanguageServerId > ,
102
158
) {
103
- for document_id in document_ids. clone ( ) {
159
+ let document_ids: Vec < _ > = editor. documents ( ) . map ( |x| x. id ( ) ) . collect ( ) ;
160
+
161
+ for document_id in document_ids {
104
162
let doc = doc_mut ! ( editor, & document_id) ;
105
163
let language_servers = doc
106
164
. language_servers ( )
107
165
. filter ( |x| language_server_ids. contains ( & x. id ( ) ) ) ;
108
166
109
167
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
- } ) ;
168
+ pull_diagnostics_for_document ( doc, language_server) ;
145
169
}
146
170
}
147
171
}
148
172
149
- fn show_pull_diagnostics (
173
+ fn pull_diagnostics_for_document ( doc : & helix_view:: Document , language_server : & helix_lsp:: Client ) {
174
+ let Some ( future) = language_server
175
+ . text_document_diagnostic ( doc. identifier ( ) , doc. previous_diagnostic_id . clone ( ) )
176
+ else {
177
+ return ;
178
+ } ;
179
+
180
+ let Some ( uri) = doc. uri ( ) else {
181
+ return ;
182
+ } ;
183
+
184
+ let server_id = language_server. id ( ) ;
185
+ let document_id = doc. id ( ) ;
186
+
187
+ tokio:: spawn ( async move {
188
+ match future. await {
189
+ Ok ( res) => {
190
+ job:: dispatch ( move |editor, _| {
191
+ let response = match serde_json:: from_value ( res) {
192
+ Ok ( result) => result,
193
+ Err ( _) => return ,
194
+ } ;
195
+
196
+ handle_pull_diagnostics_response ( editor, response, server_id, uri, & document_id)
197
+ } )
198
+ . await
199
+ }
200
+ Err ( err) => log:: error!( "Pull diagnostic request failed: {err}" ) ,
201
+ }
202
+ } ) ;
203
+ }
204
+
205
+ fn handle_pull_diagnostics_response (
150
206
editor : & mut Editor ,
151
207
response : lsp:: DocumentDiagnosticReport ,
152
208
server_id : LanguageServerId ,
@@ -157,7 +213,7 @@ fn show_pull_diagnostics(
157
213
match response {
158
214
lsp:: DocumentDiagnosticReport :: Full ( report) => {
159
215
// Original file diagnostic
160
- parse_diagnostic (
216
+ add_diagnostics_to_editor (
161
217
editor,
162
218
uri,
163
219
report. full_document_diagnostic_report . items ,
@@ -187,7 +243,7 @@ fn show_pull_diagnostics(
187
243
}
188
244
}
189
245
190
- fn parse_diagnostic (
246
+ fn add_diagnostics_to_editor (
191
247
editor : & mut Editor ,
192
248
uri : Uri ,
193
249
report : Vec < lsp:: Diagnostic > ,
@@ -213,7 +269,7 @@ fn handle_document_diagnostic_report_kind(
213
269
return ;
214
270
} ;
215
271
216
- parse_diagnostic ( editor, uri, report. items , report. result_id , server_id) ;
272
+ add_diagnostics_to_editor ( editor, uri, report. items , report. result_id , server_id) ;
217
273
}
218
274
lsp:: DocumentDiagnosticReportKind :: Unchanged ( report) => {
219
275
let doc = doc_mut ! ( editor, & document_id) ;
0 commit comments