@@ -13,8 +13,10 @@ use tower_lsp_server::{
1313 DidChangeConfigurationParams , DidChangeTextDocumentParams , DidChangeWatchedFilesParams ,
1414 DidChangeWatchedFilesRegistrationOptions , DidChangeWorkspaceFoldersParams ,
1515 DidCloseTextDocumentParams , DidOpenTextDocumentParams , DidSaveTextDocumentParams ,
16- ExecuteCommandParams , InitializeParams , InitializeResult , InitializedParams , Registration ,
17- ServerInfo , Unregistration , Uri , WorkspaceEdit ,
16+ DocumentDiagnosticParams , DocumentDiagnosticReport , DocumentDiagnosticReportResult ,
17+ ExecuteCommandParams , FullDocumentDiagnosticReport , InitializeParams , InitializeResult ,
18+ InitializedParams , Registration , RelatedFullDocumentDiagnosticReport , ServerInfo ,
19+ Unregistration , Uri , WorkspaceEdit ,
1820 } ,
1921} ;
2022// #
@@ -464,14 +466,22 @@ impl LanguageServer for Backend {
464466 if !worker. should_lint_on_run_type ( Run :: OnSave ) . await {
465467 return ;
466468 }
467- if let Some ( diagnostics) = worker. lint_file ( uri, None ) . await {
468- self . client
469- . publish_diagnostics (
470- uri. clone ( ) ,
471- diagnostics. clone ( ) . into_iter ( ) . map ( |d| d. diagnostic ) . collect ( ) ,
472- None ,
473- )
474- . await ;
469+
470+ // we no longer need the cached document, as it is saved to disk
471+ worker. remove_cached_document ( uri) ;
472+
473+ // if the client supports pull diagnostics, we should not lint the file immediately,
474+ // instead wait for the client to request diagnostics
475+ if self . capabilities . get ( ) . is_some_and ( Capabilities :: use_push_diagnostics) {
476+ if let Some ( diagnostics) = worker. lint_file ( uri) . await {
477+ self . client
478+ . publish_diagnostics (
479+ uri. clone ( ) ,
480+ diagnostics. clone ( ) . into_iter ( ) . map ( |d| d. diagnostic ) . collect ( ) ,
481+ None ,
482+ )
483+ . await ;
484+ }
475485 }
476486 }
477487
@@ -487,14 +497,24 @@ impl LanguageServer for Backend {
487497 return ;
488498 }
489499 let content = params. content_changes . first ( ) . map ( |c| c. text . clone ( ) ) ;
490- if let Some ( diagnostics) = worker. lint_file ( uri, content) . await {
491- self . client
492- . publish_diagnostics (
493- uri. clone ( ) ,
494- diagnostics. clone ( ) . into_iter ( ) . map ( |d| d. diagnostic ) . collect ( ) ,
495- Some ( params. text_document . version ) ,
496- )
497- . await ;
500+
501+ if let Some ( content) = content {
502+ // cache the document content for later use
503+ worker. cache_document ( uri, content) ;
504+ }
505+
506+ // if the client supports pull diagnostics, we should not lint the file immediately,
507+ // instead wait for the client to request diagnostics
508+ if self . capabilities . get ( ) . is_some_and ( Capabilities :: use_push_diagnostics) {
509+ if let Some ( diagnostics) = worker. lint_file ( uri) . await {
510+ self . client
511+ . publish_diagnostics (
512+ uri. clone ( ) ,
513+ diagnostics. clone ( ) . into_iter ( ) . map ( |d| d. diagnostic ) . collect ( ) ,
514+ Some ( params. text_document . version ) ,
515+ )
516+ . await ;
517+ }
498518 }
499519 }
500520
@@ -505,15 +525,21 @@ impl LanguageServer for Backend {
505525 return ;
506526 } ;
507527
508- let content = params. text_document . text ;
509- if let Some ( diagnostics) = worker. lint_file ( uri, Some ( content) ) . await {
510- self . client
511- . publish_diagnostics (
512- uri. clone ( ) ,
513- diagnostics. clone ( ) . into_iter ( ) . map ( |d| d. diagnostic ) . collect ( ) ,
514- Some ( params. text_document . version ) ,
515- )
516- . await ;
528+ // cache the document content for later use
529+ worker. cache_document ( uri, params. text_document . text ) ;
530+
531+ // if the client supports pull diagnostics, we should not lint the file immediately,
532+ // instead wait for the client to request diagnostics
533+ if self . capabilities . get ( ) . is_some_and ( Capabilities :: use_push_diagnostics) {
534+ if let Some ( diagnostics) = worker. lint_file ( uri) . await {
535+ self . client
536+ . publish_diagnostics (
537+ uri. clone ( ) ,
538+ diagnostics. clone ( ) . into_iter ( ) . map ( |d| d. diagnostic ) . collect ( ) ,
539+ Some ( params. text_document . version ) ,
540+ )
541+ . await ;
542+ }
517543 }
518544 }
519545
@@ -523,7 +549,38 @@ impl LanguageServer for Backend {
523549 let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
524550 return ;
525551 } ;
526- worker. remove_diagnostics ( & params. text_document . uri ) ;
552+ worker. remove_cached_document ( uri) ;
553+ worker. remove_diagnostics ( uri) ;
554+ }
555+
556+ async fn diagnostic (
557+ & self ,
558+ params : DocumentDiagnosticParams ,
559+ ) -> Result < DocumentDiagnosticReportResult > {
560+ let uri = & params. text_document . uri ;
561+ let workers = self . workspace_workers . read ( ) . await ;
562+ let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
563+ return Ok ( DocumentDiagnosticReportResult :: Report ( DocumentDiagnosticReport :: Full (
564+ RelatedFullDocumentDiagnosticReport :: default ( ) ,
565+ ) ) ) ;
566+ } ;
567+ let diagnostics = worker. lint_file ( uri) . await ;
568+
569+ if let Some ( diagnostics) = diagnostics {
570+ Ok ( DocumentDiagnosticReportResult :: Report ( DocumentDiagnosticReport :: Full (
571+ RelatedFullDocumentDiagnosticReport {
572+ full_document_diagnostic_report : FullDocumentDiagnosticReport {
573+ items : diagnostics. into_iter ( ) . map ( |d| d. diagnostic ) . collect ( ) ,
574+ ..Default :: default ( )
575+ } ,
576+ ..Default :: default ( )
577+ } ,
578+ ) ) )
579+ } else {
580+ Ok ( DocumentDiagnosticReportResult :: Report ( DocumentDiagnosticReport :: Full (
581+ RelatedFullDocumentDiagnosticReport :: default ( ) ,
582+ ) ) )
583+ }
527584 }
528585
529586 async fn code_action ( & self , params : CodeActionParams ) -> Result < Option < CodeActionResponse > > {
0 commit comments