4
4
use cargo_metadata:: Message ;
5
5
use crossbeam_channel:: { never, select, unbounded, Receiver , RecvError , Sender } ;
6
6
use lsp_types:: {
7
- Diagnostic , Url , WorkDoneProgress , WorkDoneProgressBegin , WorkDoneProgressEnd ,
8
- WorkDoneProgressReport ,
7
+ CodeAction , CodeActionOrCommand , Diagnostic , Url , WorkDoneProgress , WorkDoneProgressBegin ,
8
+ WorkDoneProgressEnd , WorkDoneProgressReport ,
9
9
} ;
10
10
use std:: {
11
- collections:: HashMap ,
12
11
io:: { BufRead , BufReader } ,
13
12
path:: PathBuf ,
14
13
process:: { Command , Stdio } ,
15
- sync:: Arc ,
16
14
thread:: JoinHandle ,
17
15
time:: Instant ,
18
16
} ;
19
17
20
18
mod conv;
21
19
22
- use crate :: conv:: { map_rust_diagnostic_to_lsp, MappedRustDiagnostic , SuggestedFix } ;
20
+ use crate :: conv:: { map_rust_diagnostic_to_lsp, MappedRustDiagnostic } ;
23
21
24
22
pub use crate :: conv:: url_from_path_with_drive_lowercasing;
25
23
@@ -38,29 +36,26 @@ pub struct CheckOptions {
38
36
#[ derive( Debug ) ]
39
37
pub struct CheckWatcher {
40
38
pub task_recv : Receiver < CheckTask > ,
41
- pub state : Arc < CheckState > ,
42
39
cmd_send : Option < Sender < CheckCommand > > ,
43
40
handle : Option < JoinHandle < ( ) > > ,
44
41
}
45
42
46
43
impl CheckWatcher {
47
44
pub fn new ( options : & CheckOptions , workspace_root : PathBuf ) -> CheckWatcher {
48
45
let options = options. clone ( ) ;
49
- let state = Arc :: new ( CheckState :: new ( ) ) ;
50
46
51
47
let ( task_send, task_recv) = unbounded :: < CheckTask > ( ) ;
52
48
let ( cmd_send, cmd_recv) = unbounded :: < CheckCommand > ( ) ;
53
49
let handle = std:: thread:: spawn ( move || {
54
50
let mut check = CheckWatcherThread :: new ( options, workspace_root) ;
55
51
check. run ( & task_send, & cmd_recv) ;
56
52
} ) ;
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) }
58
54
}
59
55
60
56
/// Returns a CheckWatcher that doesn't actually do anything
61
57
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 }
64
59
}
65
60
66
61
/// Schedule a re-start of the cargo check worker.
@@ -87,84 +82,13 @@ impl std::ops::Drop for CheckWatcher {
87
82
}
88
83
}
89
84
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
-
161
85
#[ derive( Debug ) ]
162
86
pub enum CheckTask {
163
87
/// Request a clearing of all cached diagnostics from the check watcher
164
88
ClearDiagnostics ,
165
89
166
90
/// Request adding a diagnostic with fixes included to a file
167
- AddDiagnostic ( Url , DiagnosticWithFixes ) ,
91
+ AddDiagnostic { url : Url , diagnostic : Diagnostic , fixes : Vec < CodeActionOrCommand > } ,
168
92
169
93
/// Request check progress notification to client
170
94
Status ( WorkDoneProgress ) ,
@@ -279,10 +203,17 @@ impl CheckWatcherThread {
279
203
None => return ,
280
204
} ;
281
205
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 ( ) ;
283
213
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 ( ) ;
286
217
}
287
218
288
219
CheckEvent :: Msg ( Message :: BuildScriptExecuted ( _msg) ) => { }
@@ -294,7 +225,7 @@ impl CheckWatcherThread {
294
225
#[ derive( Debug ) ]
295
226
pub struct DiagnosticWithFixes {
296
227
diagnostic : Diagnostic ,
297
- suggested_fixes : Vec < SuggestedFix > ,
228
+ fixes : Vec < CodeAction > ,
298
229
}
299
230
300
231
/// WatchThread exists to wrap around the communication needed to be able to
@@ -429,10 +360,3 @@ impl std::ops::Drop for WatchThread {
429
360
}
430
361
}
431
362
}
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