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,106 +49,155 @@ 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 {
63
- language_server_ids : Vec < LanguageServerId > ,
75
+ language_server_ids : HashSet < LanguageServerId > ,
64
76
}
65
77
66
78
impl PullDiagnosticsHandler {
67
79
pub fn new ( ) -> PullDiagnosticsHandler {
68
80
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 ( ) ,
70
93
}
71
94
}
72
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
+ 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)
94
133
} )
95
134
}
96
135
}
97
136
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 (
99
151
editor : & mut Editor ,
100
- language_server_ids : Vec < LanguageServerId > ,
101
- document_ids : Vec < helix_view:: DocumentId > ,
152
+ language_server_ids : HashSet < LanguageServerId > ,
102
153
) {
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 {
104
157
let doc = doc_mut ! ( editor, & document_id) ;
105
158
let language_servers = doc
106
159
. language_servers ( )
107
160
. filter ( |x| language_server_ids. contains ( & x. id ( ) ) ) ;
108
161
109
162
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) ;
145
164
}
146
165
}
147
166
}
148
167
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 (
150
201
editor : & mut Editor ,
151
202
response : lsp:: DocumentDiagnosticReport ,
152
203
server_id : LanguageServerId ,
@@ -157,7 +208,7 @@ fn show_pull_diagnostics(
157
208
match response {
158
209
lsp:: DocumentDiagnosticReport :: Full ( report) => {
159
210
// Original file diagnostic
160
- parse_diagnostic (
211
+ add_diagnostics_to_editor (
161
212
editor,
162
213
uri,
163
214
report. full_document_diagnostic_report . items ,
@@ -187,7 +238,7 @@ fn show_pull_diagnostics(
187
238
}
188
239
}
189
240
190
- fn parse_diagnostic (
241
+ fn add_diagnostics_to_editor (
191
242
editor : & mut Editor ,
192
243
uri : Uri ,
193
244
report : Vec < lsp:: Diagnostic > ,
@@ -213,7 +264,7 @@ fn handle_document_diagnostic_report_kind(
213
264
return ;
214
265
} ;
215
266
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) ;
217
268
}
218
269
lsp:: DocumentDiagnosticReportKind :: Unchanged ( report) => {
219
270
let doc = doc_mut ! ( editor, & document_id) ;
0 commit comments