1- use std:: collections:: HashMap ;
1+ use std:: collections:: { HashMap , HashSet } ;
22use std:: time:: Duration ;
33
44use helix_core:: syntax:: LanguageServerFeature ;
@@ -7,11 +7,13 @@ use helix_event::{register_hook, send_blocking};
77use helix_lsp:: lsp:: { self , Diagnostic } ;
88use helix_lsp:: LanguageServerId ;
99use helix_view:: document:: Mode ;
10- use helix_view:: events:: { DiagnosticsDidChange , DocumentDidChange } ;
10+ use helix_view:: events:: { DiagnosticsDidChange , DocumentDidChange , DocumentDidOpen } ;
1111use helix_view:: handlers:: diagnostics:: DiagnosticEvent ;
12- use helix_view:: handlers:: lsp:: PullDiagnosticsEvent ;
12+ use helix_view:: handlers:: lsp:: {
13+ PullDiagnosticsForDocumentsEvent , PullDiagnosticsForLanguageServersEvent ,
14+ } ;
1315use helix_view:: handlers:: Handlers ;
14- use helix_view:: Editor ;
16+ use helix_view:: { DocumentId , Editor } ;
1517use tokio:: time:: Instant ;
1618
1719use crate :: events:: OnModeSwitch ;
@@ -33,7 +35,7 @@ pub(super) fn register_hooks(handlers: &Handlers) {
3335 Ok ( ( ) )
3436 } ) ;
3537
36- let tx = handlers. pull_diagnostics . clone ( ) ;
38+ let tx = handlers. pull_diagnostics_for_language_servers . clone ( ) ;
3739 register_hook ! ( move |event: & mut DocumentDidChange <' _>| {
3840 if event
3941 . doc
@@ -47,106 +49,160 @@ 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_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+ }
6077
6178#[ derive( Debug ) ]
62- pub ( super ) struct PullDiagnosticsHandler {
63- language_server_ids : Vec < LanguageServerId > ,
79+ pub ( super ) struct PullDiagnosticsForLanguageServersHandler {
80+ language_server_ids : HashSet < LanguageServerId > ,
6481}
6582
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 ( ) ,
7087 }
7188 }
7289}
90+ pub ( super ) struct PullDiagnosticsForDocumentsHandler {
91+ document_ids : HashSet < DocumentId > ,
92+ }
7393
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 ;
76104
77105 fn handle_event (
78106 & mut self ,
79107 event : Self :: Event ,
80108 _: Option < tokio:: time:: Instant > ,
81109 ) -> Option < tokio:: time:: Instant > {
82110 self . language_server_ids = event. language_server_ids ;
83- Some ( Instant :: now ( ) + Duration :: from_millis ( TIMEOUT ) )
111+ Some ( Instant :: now ( ) + Duration :: from_millis ( 120 ) )
84112 }
85113
86114 fn finish_debounce ( & mut self ) {
87115 let language_servers = self . language_server_ids . clone ( ) ;
88116 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)
94118 } )
95119 }
96120}
97121
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 (
99156 editor : & mut Editor ,
100- language_server_ids : Vec < LanguageServerId > ,
101- document_ids : Vec < helix_view:: DocumentId > ,
157+ language_server_ids : HashSet < LanguageServerId > ,
102158) {
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 {
104162 let doc = doc_mut ! ( editor, & document_id) ;
105163 let language_servers = doc
106164 . language_servers ( )
107165 . filter ( |x| language_server_ids. contains ( & x. id ( ) ) ) ;
108166
109167 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) ;
145169 }
146170 }
147171}
148172
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 (
150206 editor : & mut Editor ,
151207 response : lsp:: DocumentDiagnosticReport ,
152208 server_id : LanguageServerId ,
@@ -157,7 +213,7 @@ fn show_pull_diagnostics(
157213 match response {
158214 lsp:: DocumentDiagnosticReport :: Full ( report) => {
159215 // Original file diagnostic
160- parse_diagnostic (
216+ add_diagnostics_to_editor (
161217 editor,
162218 uri,
163219 report. full_document_diagnostic_report . items ,
@@ -187,7 +243,7 @@ fn show_pull_diagnostics(
187243 }
188244}
189245
190- fn parse_diagnostic (
246+ fn add_diagnostics_to_editor (
191247 editor : & mut Editor ,
192248 uri : Uri ,
193249 report : Vec < lsp:: Diagnostic > ,
@@ -213,7 +269,7 @@ fn handle_document_diagnostic_report_kind(
213269 return ;
214270 } ;
215271
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) ;
217273 }
218274 lsp:: DocumentDiagnosticReportKind :: Unchanged ( report) => {
219275 let doc = doc_mut ! ( editor, & document_id) ;
0 commit comments