44use cargo_metadata:: Message ;
55use crossbeam_channel:: { never, select, unbounded, Receiver , RecvError , Sender } ;
66use lsp_types:: {
7- Diagnostic , Url , WorkDoneProgress , WorkDoneProgressBegin , WorkDoneProgressEnd ,
8- WorkDoneProgressReport ,
7+ CodeAction , CodeActionOrCommand , Diagnostic , Url , WorkDoneProgress , WorkDoneProgressBegin ,
8+ WorkDoneProgressEnd , WorkDoneProgressReport ,
99} ;
1010use std:: {
11- collections:: HashMap ,
1211 io:: { BufRead , BufReader } ,
1312 path:: PathBuf ,
1413 process:: { Command , Stdio } ,
15- sync:: Arc ,
1614 thread:: JoinHandle ,
1715 time:: Instant ,
1816} ;
1917
2018mod conv;
2119
22- use crate :: conv:: { map_rust_diagnostic_to_lsp, MappedRustDiagnostic , SuggestedFix } ;
20+ use crate :: conv:: { map_rust_diagnostic_to_lsp, MappedRustDiagnostic } ;
2321
2422pub use crate :: conv:: url_from_path_with_drive_lowercasing;
2523
@@ -38,29 +36,26 @@ pub struct CheckOptions {
3836#[ derive( Debug ) ]
3937pub struct CheckWatcher {
4038 pub task_recv : Receiver < CheckTask > ,
41- pub state : Arc < CheckState > ,
4239 cmd_send : Option < Sender < CheckCommand > > ,
4340 handle : Option < JoinHandle < ( ) > > ,
4441}
4542
4643impl CheckWatcher {
4744 pub fn new ( options : & CheckOptions , workspace_root : PathBuf ) -> CheckWatcher {
4845 let options = options. clone ( ) ;
49- let state = Arc :: new ( CheckState :: new ( ) ) ;
5046
5147 let ( task_send, task_recv) = unbounded :: < CheckTask > ( ) ;
5248 let ( cmd_send, cmd_recv) = unbounded :: < CheckCommand > ( ) ;
5349 let handle = std:: thread:: spawn ( move || {
5450 let mut check = CheckWatcherThread :: new ( options, workspace_root) ;
5551 check. run ( & task_send, & cmd_recv) ;
5652 } ) ;
57- CheckWatcher { task_recv, cmd_send : Some ( cmd_send) , handle : Some ( handle) , state }
53+ CheckWatcher { task_recv, cmd_send : Some ( cmd_send) , handle : Some ( handle) }
5854 }
5955
6056 /// Returns a CheckWatcher that doesn't actually do anything
6157 pub fn dummy ( ) -> CheckWatcher {
62- let state = Arc :: new ( CheckState :: new ( ) ) ;
63- CheckWatcher { task_recv : never ( ) , cmd_send : None , handle : None , state }
58+ CheckWatcher { task_recv : never ( ) , cmd_send : None , handle : None }
6459 }
6560
6661 /// Schedule a re-start of the cargo check worker.
@@ -87,84 +82,13 @@ impl std::ops::Drop for CheckWatcher {
8782 }
8883}
8984
90- #[ derive( Clone , Debug ) ]
91- pub struct CheckState {
92- diagnostic_collection : HashMap < Url , Vec < Diagnostic > > ,
93- suggested_fix_collection : HashMap < Url , Vec < SuggestedFix > > ,
94- }
95-
96- impl CheckState {
97- fn new ( ) -> CheckState {
98- CheckState {
99- diagnostic_collection : HashMap :: new ( ) ,
100- suggested_fix_collection : HashMap :: new ( ) ,
101- }
102- }
103-
104- /// Clear the cached diagnostics, and schedule updating diagnostics by the
105- /// server, to clear stale results.
106- pub fn clear ( & mut self ) -> Vec < Url > {
107- let cleared_files: Vec < Url > = self . diagnostic_collection . keys ( ) . cloned ( ) . collect ( ) ;
108- self . diagnostic_collection . clear ( ) ;
109- self . suggested_fix_collection . clear ( ) ;
110- cleared_files
111- }
112-
113- pub fn diagnostics_for ( & self , uri : & Url ) -> Option < & [ Diagnostic ] > {
114- self . diagnostic_collection . get ( uri) . map ( |d| d. as_slice ( ) )
115- }
116-
117- pub fn fixes_for ( & self , uri : & Url ) -> Option < & [ SuggestedFix ] > {
118- self . suggested_fix_collection . get ( uri) . map ( |d| d. as_slice ( ) )
119- }
120-
121- pub fn add_diagnostic_with_fixes ( & mut self , file_uri : Url , diagnostic : DiagnosticWithFixes ) {
122- for fix in diagnostic. suggested_fixes {
123- self . add_suggested_fix_for_diagnostic ( fix, & diagnostic. diagnostic ) ;
124- }
125- self . add_diagnostic ( file_uri, diagnostic. diagnostic ) ;
126- }
127-
128- fn add_diagnostic ( & mut self , file_uri : Url , diagnostic : Diagnostic ) {
129- let diagnostics = self . diagnostic_collection . entry ( file_uri) . or_default ( ) ;
130-
131- // If we're building multiple targets it's possible we've already seen this diagnostic
132- let is_duplicate = diagnostics. iter ( ) . any ( |d| are_diagnostics_equal ( d, & diagnostic) ) ;
133- if is_duplicate {
134- return ;
135- }
136-
137- diagnostics. push ( diagnostic) ;
138- }
139-
140- fn add_suggested_fix_for_diagnostic (
141- & mut self ,
142- mut suggested_fix : SuggestedFix ,
143- diagnostic : & Diagnostic ,
144- ) {
145- let file_uri = suggested_fix. location . uri . clone ( ) ;
146- let file_suggestions = self . suggested_fix_collection . entry ( file_uri) . or_default ( ) ;
147-
148- let existing_suggestion: Option < & mut SuggestedFix > =
149- file_suggestions. iter_mut ( ) . find ( |s| s == & & suggested_fix) ;
150- if let Some ( existing_suggestion) = existing_suggestion {
151- // The existing suggestion also applies to this new diagnostic
152- existing_suggestion. diagnostics . push ( diagnostic. clone ( ) ) ;
153- } else {
154- // We haven't seen this suggestion before
155- suggested_fix. diagnostics . push ( diagnostic. clone ( ) ) ;
156- file_suggestions. push ( suggested_fix) ;
157- }
158- }
159- }
160-
16185#[ derive( Debug ) ]
16286pub enum CheckTask {
16387 /// Request a clearing of all cached diagnostics from the check watcher
16488 ClearDiagnostics ,
16589
16690 /// Request adding a diagnostic with fixes included to a file
167- AddDiagnostic ( Url , DiagnosticWithFixes ) ,
91+ AddDiagnostic { url : Url , diagnostic : Diagnostic , fixes : Vec < CodeActionOrCommand > } ,
16892
16993 /// Request check progress notification to client
17094 Status ( WorkDoneProgress ) ,
@@ -279,10 +203,17 @@ impl CheckWatcherThread {
279203 None => return ,
280204 } ;
281205
282- let MappedRustDiagnostic { location, diagnostic, suggested_fixes } = map_result;
206+ let MappedRustDiagnostic { location, diagnostic, fixes } = map_result;
207+ let fixes = fixes
208+ . into_iter ( )
209+ . map ( |fix| {
210+ CodeAction { diagnostics : Some ( vec ! [ diagnostic. clone( ) ] ) , ..fix } . into ( )
211+ } )
212+ . collect ( ) ;
283213
284- let diagnostic = DiagnosticWithFixes { diagnostic, suggested_fixes } ;
285- task_send. send ( CheckTask :: AddDiagnostic ( location. uri , diagnostic) ) . unwrap ( ) ;
214+ task_send
215+ . send ( CheckTask :: AddDiagnostic { url : location. uri , diagnostic, fixes } )
216+ . unwrap ( ) ;
286217 }
287218
288219 CheckEvent :: Msg ( Message :: BuildScriptExecuted ( _msg) ) => { }
@@ -294,7 +225,7 @@ impl CheckWatcherThread {
294225#[ derive( Debug ) ]
295226pub struct DiagnosticWithFixes {
296227 diagnostic : Diagnostic ,
297- suggested_fixes : Vec < SuggestedFix > ,
228+ fixes : Vec < CodeAction > ,
298229}
299230
300231/// WatchThread exists to wrap around the communication needed to be able to
@@ -429,10 +360,3 @@ impl std::ops::Drop for WatchThread {
429360 }
430361 }
431362}
432-
433- fn are_diagnostics_equal ( left : & Diagnostic , right : & Diagnostic ) -> bool {
434- left. source == right. source
435- && left. severity == right. severity
436- && left. range == right. range
437- && left. message == right. message
438- }
0 commit comments