@@ -5,6 +5,7 @@ use std::{
55 sync:: { Arc , Mutex } ,
66} ;
77
8+ use ariadne:: ReportKind ;
89use crossbeam_channel:: Sender ;
910
1011use lsp_server:: { Connection , IoThreads , Message , Request , Response } ;
@@ -249,6 +250,40 @@ impl LspServer {
249250 Ok ( ( ) )
250251 }
251252
253+ /// Convert `VerifyResult::Todo` and `VerifyResult::Verifying` statuses to `VerifyResult::Timeout`, send the results to the client and emit diagnostics for them.
254+ fn handle_timeout_for_results ( & mut self ) -> Result < ( ) , ServerError > {
255+ let mut diagnostics: Vec < Diagnostic > = Vec :: new ( ) ;
256+
257+ // Transform results and collect diagnostics for timed out procedures
258+ for ( span, status) in & mut self . statuses {
259+ match status {
260+ VerifyResult :: Ongoing => {
261+ diagnostics. push (
262+ Diagnostic :: new ( ReportKind :: Error , * span)
263+ . with_message ( "Timed out while verifying this procedure" ) ,
264+ ) ;
265+ * status = VerifyResult :: Timeout ;
266+ }
267+ VerifyResult :: Todo => {
268+ diagnostics. push (
269+ Diagnostic :: new ( ReportKind :: Warning , * span)
270+ . with_message ( "Skipped this procedure due to timeout" ) ,
271+ ) ;
272+ * status = VerifyResult :: Timeout ;
273+ }
274+ _ => { }
275+ }
276+ }
277+
278+ // Add the collected diagnostics to the server
279+ for diagnostic in diagnostics {
280+ self . add_diagnostic ( diagnostic) ?;
281+ }
282+
283+ self . publish_verify_statuses ( ) ?;
284+ Ok ( ( ) )
285+ }
286+
252287 fn clear_file_information ( & mut self , file_id : & FileId ) -> Result < ( ) , ServerError > {
253288 if let Some ( diag) = self . diagnostics . get_mut ( file_id) {
254289 diag. clear ( ) ;
@@ -317,6 +352,15 @@ impl Server for LspServer {
317352
318353 fn register_source_unit ( & mut self , span : Span ) -> Result < ( ) , VerifyError > {
319354 self . statuses . insert ( span, VerifyResult :: Todo ) ;
355+ self . publish_verify_statuses ( )
356+ . map_err ( VerifyError :: ServerError ) ?;
357+ Ok ( ( ) )
358+ }
359+
360+ fn set_ongoing_unit ( & mut self , span : Span ) -> Result < ( ) , VerifyError > {
361+ self . statuses . insert ( span, VerifyResult :: Ongoing ) ;
362+ self . publish_verify_statuses ( )
363+ . map_err ( VerifyError :: ServerError ) ?;
320364 Ok ( ( ) )
321365 }
322366
@@ -335,13 +379,6 @@ impl Server for LspServer {
335379 self . publish_verify_statuses ( ) ?;
336380 Ok ( ( ) )
337381 }
338-
339- fn handle_not_checked ( & mut self , span : Span ) -> Result < ( ) , ServerError > {
340- let prev = self . statuses . insert ( span, VerifyResult :: Unknown ) ;
341- assert ! ( prev. is_some( ) ) ;
342- self . publish_verify_statuses ( ) ?;
343- Ok ( ( ) )
344- }
345382}
346383
347384/// A type alias representing an asynchronous closure that returns a `Result<(), VerifyError>`.
@@ -440,29 +477,29 @@ async fn handle_verify_request(
440477 } ;
441478
442479 let result = verify ( & [ file_id] ) . await ;
443- let res = match & result {
444- Ok ( _) => Response :: new_ok ( id, Value :: Null ) ,
445- Err ( err) => Response :: new_err ( id, 0 , format ! ( "{}" , err) ) ,
480+
481+ let response = match result {
482+ Ok ( ( ) ) => Response :: new_ok ( id. clone ( ) , Value :: Null ) ,
483+ Err ( err) => match err {
484+ VerifyError :: Diagnostic ( diagnostic) => {
485+ server. lock ( ) . unwrap ( ) . add_diagnostic ( diagnostic) ?;
486+ Response :: new_ok ( id. clone ( ) , Value :: Null )
487+ }
488+ VerifyError :: Interrupted | VerifyError :: LimitError ( _) => {
489+ server
490+ . lock ( )
491+ . unwrap ( )
492+ . handle_timeout_for_results ( )
493+ . map_err ( VerifyError :: ServerError ) ?;
494+ Response :: new_ok ( id. clone ( ) , Value :: Null )
495+ }
496+ _ => Response :: new_err ( id, 0 , format ! ( "{}" , err) ) ,
497+ } ,
446498 } ;
499+
447500 sender
448- . send ( Message :: Response ( res ) )
501+ . send ( Message :: Response ( response ) )
449502 . map_err ( |e| VerifyError :: ServerError ( e. into ( ) ) ) ?;
450- match result {
451- Ok ( ( ) ) => { }
452- Err ( VerifyError :: Diagnostic ( diagnostic) ) => {
453- server. lock ( ) . unwrap ( ) . add_diagnostic ( diagnostic) ?;
454- }
455- Err ( VerifyError :: Interrupted ) | Err ( VerifyError :: LimitError ( _) ) => {
456- // If the verification is interrupted or a limit is reached before the verification starts, no verification statuses are published yet.
457- // In this case, the client needs to be notified about the registered source units that are not checked yet (marked with VerifyResult::Todo).
458- // This acts as a fallback mechanism for this case.
459- server
460- . lock ( )
461- . unwrap ( )
462- . publish_verify_statuses ( )
463- . map_err ( VerifyError :: ServerError ) ?;
464- }
465- Err ( err) => Err ( err) ?,
466- }
503+
467504 Ok ( ( ) )
468505}
0 commit comments