diff options
Diffstat (limited to 'crates/ra_flycheck/src/lib.rs')
-rw-r--r-- | crates/ra_flycheck/src/lib.rs | 108 |
1 files changed, 35 insertions, 73 deletions
diff --git a/crates/ra_flycheck/src/lib.rs b/crates/ra_flycheck/src/lib.rs index b54a30ab8..041e38a9f 100644 --- a/crates/ra_flycheck/src/lib.rs +++ b/crates/ra_flycheck/src/lib.rs | |||
@@ -1,11 +1,9 @@ | |||
1 | //! cargo_check provides the functionality needed to run `cargo check` or | 1 | //! cargo_check provides the functionality needed to run `cargo check` or |
2 | //! another compatible command (f.x. clippy) in a background thread and provide | 2 | //! another compatible command (f.x. clippy) in a background thread and provide |
3 | //! LSP diagnostics based on the output of the command. | 3 | //! LSP diagnostics based on the output of the command. |
4 | mod conv; | ||
5 | 4 | ||
6 | use std::{ | 5 | use std::{ |
7 | env, | 6 | io::{self, BufReader}, |
8 | io::{self, BufRead, BufReader}, | ||
9 | path::PathBuf, | 7 | path::PathBuf, |
10 | process::{Command, Stdio}, | 8 | process::{Command, Stdio}, |
11 | time::Instant, | 9 | time::Instant, |
@@ -13,18 +11,14 @@ use std::{ | |||
13 | 11 | ||
14 | use cargo_metadata::Message; | 12 | use cargo_metadata::Message; |
15 | use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender}; | 13 | use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender}; |
16 | use lsp_types::{ | ||
17 | CodeAction, CodeActionOrCommand, Diagnostic, Url, WorkDoneProgress, WorkDoneProgressBegin, | ||
18 | WorkDoneProgressEnd, WorkDoneProgressReport, | ||
19 | }; | ||
20 | |||
21 | use crate::conv::{map_rust_diagnostic_to_lsp, MappedRustDiagnostic}; | ||
22 | 14 | ||
23 | pub use crate::conv::url_from_path_with_drive_lowercasing; | 15 | pub use cargo_metadata::diagnostic::{ |
16 | Applicability, Diagnostic, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion, | ||
17 | }; | ||
24 | 18 | ||
25 | #[derive(Clone, Debug, PartialEq, Eq)] | 19 | #[derive(Clone, Debug, PartialEq, Eq)] |
26 | pub enum FlycheckConfig { | 20 | pub enum FlycheckConfig { |
27 | CargoCommand { command: String, all_targets: bool, extra_args: Vec<String> }, | 21 | CargoCommand { command: String, all_targets: bool, all_features: bool, extra_args: Vec<String> }, |
28 | CustomCommand { command: String, args: Vec<String> }, | 22 | CustomCommand { command: String, args: Vec<String> }, |
29 | } | 23 | } |
30 | 24 | ||
@@ -62,10 +56,17 @@ pub enum CheckTask { | |||
62 | ClearDiagnostics, | 56 | ClearDiagnostics, |
63 | 57 | ||
64 | /// Request adding a diagnostic with fixes included to a file | 58 | /// Request adding a diagnostic with fixes included to a file |
65 | AddDiagnostic { url: Url, diagnostic: Diagnostic, fixes: Vec<CodeActionOrCommand> }, | 59 | AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic }, |
66 | 60 | ||
67 | /// Request check progress notification to client | 61 | /// Request check progress notification to client |
68 | Status(WorkDoneProgress), | 62 | Status(Status), |
63 | } | ||
64 | |||
65 | #[derive(Debug)] | ||
66 | pub enum Status { | ||
67 | Being, | ||
68 | Progress(String), | ||
69 | End, | ||
69 | } | 70 | } |
70 | 71 | ||
71 | pub enum CheckCommand { | 72 | pub enum CheckCommand { |
@@ -132,9 +133,7 @@ impl FlycheckThread { | |||
132 | 133 | ||
133 | fn clean_previous_results(&self, task_send: &Sender<CheckTask>) { | 134 | fn clean_previous_results(&self, task_send: &Sender<CheckTask>) { |
134 | task_send.send(CheckTask::ClearDiagnostics).unwrap(); | 135 | task_send.send(CheckTask::ClearDiagnostics).unwrap(); |
135 | task_send | 136 | task_send.send(CheckTask::Status(Status::End)).unwrap(); |
136 | .send(CheckTask::Status(WorkDoneProgress::End(WorkDoneProgressEnd { message: None }))) | ||
137 | .unwrap(); | ||
138 | } | 137 | } |
139 | 138 | ||
140 | fn should_recheck(&mut self) -> bool { | 139 | fn should_recheck(&mut self) -> bool { |
@@ -156,55 +155,29 @@ impl FlycheckThread { | |||
156 | fn handle_message(&self, msg: CheckEvent, task_send: &Sender<CheckTask>) { | 155 | fn handle_message(&self, msg: CheckEvent, task_send: &Sender<CheckTask>) { |
157 | match msg { | 156 | match msg { |
158 | CheckEvent::Begin => { | 157 | CheckEvent::Begin => { |
159 | task_send | 158 | task_send.send(CheckTask::Status(Status::Being)).unwrap(); |
160 | .send(CheckTask::Status(WorkDoneProgress::Begin(WorkDoneProgressBegin { | ||
161 | title: "Running 'cargo check'".to_string(), | ||
162 | cancellable: Some(false), | ||
163 | message: None, | ||
164 | percentage: None, | ||
165 | }))) | ||
166 | .unwrap(); | ||
167 | } | 159 | } |
168 | 160 | ||
169 | CheckEvent::End => { | 161 | CheckEvent::End => { |
170 | task_send | 162 | task_send.send(CheckTask::Status(Status::End)).unwrap(); |
171 | .send(CheckTask::Status(WorkDoneProgress::End(WorkDoneProgressEnd { | ||
172 | message: None, | ||
173 | }))) | ||
174 | .unwrap(); | ||
175 | } | 163 | } |
176 | 164 | ||
177 | CheckEvent::Msg(Message::CompilerArtifact(msg)) => { | 165 | CheckEvent::Msg(Message::CompilerArtifact(msg)) => { |
178 | task_send | 166 | task_send.send(CheckTask::Status(Status::Progress(msg.target.name))).unwrap(); |
179 | .send(CheckTask::Status(WorkDoneProgress::Report(WorkDoneProgressReport { | ||
180 | cancellable: Some(false), | ||
181 | message: Some(msg.target.name), | ||
182 | percentage: None, | ||
183 | }))) | ||
184 | .unwrap(); | ||
185 | } | 167 | } |
186 | 168 | ||
187 | CheckEvent::Msg(Message::CompilerMessage(msg)) => { | 169 | CheckEvent::Msg(Message::CompilerMessage(msg)) => { |
188 | let map_result = map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root); | 170 | task_send |
189 | if map_result.is_empty() { | 171 | .send(CheckTask::AddDiagnostic { |
190 | return; | 172 | workspace_root: self.workspace_root.clone(), |
191 | } | 173 | diagnostic: msg.message, |
192 | 174 | }) | |
193 | for MappedRustDiagnostic { location, diagnostic, fixes } in map_result { | 175 | .unwrap(); |
194 | let fixes = fixes | ||
195 | .into_iter() | ||
196 | .map(|fix| { | ||
197 | CodeAction { diagnostics: Some(vec![diagnostic.clone()]), ..fix }.into() | ||
198 | }) | ||
199 | .collect(); | ||
200 | |||
201 | task_send | ||
202 | .send(CheckTask::AddDiagnostic { url: location.uri, diagnostic, fixes }) | ||
203 | .unwrap(); | ||
204 | } | ||
205 | } | 176 | } |
206 | 177 | ||
207 | CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} | 178 | CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} |
179 | CheckEvent::Msg(Message::BuildFinished(_)) => {} | ||
180 | CheckEvent::Msg(Message::TextLine(_)) => {} | ||
208 | CheckEvent::Msg(Message::Unknown) => {} | 181 | CheckEvent::Msg(Message::Unknown) => {} |
209 | } | 182 | } |
210 | } | 183 | } |
@@ -215,14 +188,17 @@ impl FlycheckThread { | |||
215 | self.check_process = None; | 188 | self.check_process = None; |
216 | 189 | ||
217 | let mut cmd = match &self.config { | 190 | let mut cmd = match &self.config { |
218 | FlycheckConfig::CargoCommand { command, all_targets, extra_args } => { | 191 | FlycheckConfig::CargoCommand { command, all_targets, all_features, extra_args } => { |
219 | let mut cmd = Command::new(cargo_binary()); | 192 | let mut cmd = Command::new(ra_toolchain::cargo()); |
220 | cmd.arg(command); | 193 | cmd.arg(command); |
221 | cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]); | 194 | cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]) |
222 | cmd.arg(self.workspace_root.join("Cargo.toml")); | 195 | .arg(self.workspace_root.join("Cargo.toml")); |
223 | if *all_targets { | 196 | if *all_targets { |
224 | cmd.arg("--all-targets"); | 197 | cmd.arg("--all-targets"); |
225 | } | 198 | } |
199 | if *all_features { | ||
200 | cmd.arg("--all-features"); | ||
201 | } | ||
226 | cmd.args(extra_args); | 202 | cmd.args(extra_args); |
227 | cmd | 203 | cmd |
228 | } | 204 | } |
@@ -267,12 +243,6 @@ impl FlycheckThread { | |||
267 | } | 243 | } |
268 | } | 244 | } |
269 | 245 | ||
270 | #[derive(Debug)] | ||
271 | pub struct DiagnosticWithFixes { | ||
272 | diagnostic: Diagnostic, | ||
273 | fixes: Vec<CodeAction>, | ||
274 | } | ||
275 | |||
276 | enum CheckEvent { | 246 | enum CheckEvent { |
277 | Begin, | 247 | Begin, |
278 | Msg(cargo_metadata::Message), | 248 | Msg(cargo_metadata::Message), |
@@ -296,15 +266,11 @@ fn run_cargo( | |||
296 | // erroneus output. | 266 | // erroneus output. |
297 | let stdout = BufReader::new(child.stdout.take().unwrap()); | 267 | let stdout = BufReader::new(child.stdout.take().unwrap()); |
298 | let mut read_at_least_one_message = false; | 268 | let mut read_at_least_one_message = false; |
299 | 269 | for message in cargo_metadata::Message::parse_stream(stdout) { | |
300 | for line in stdout.lines() { | ||
301 | let line = line?; | ||
302 | |||
303 | let message = serde_json::from_str::<cargo_metadata::Message>(&line); | ||
304 | let message = match message { | 270 | let message = match message { |
305 | Ok(message) => message, | 271 | Ok(message) => message, |
306 | Err(err) => { | 272 | Err(err) => { |
307 | log::error!("Invalid json from cargo check, ignoring ({}): {:?} ", err, line); | 273 | log::error!("Invalid json from cargo check, ignoring ({})", err); |
308 | continue; | 274 | continue; |
309 | } | 275 | } |
310 | }; | 276 | }; |
@@ -334,7 +300,3 @@ fn run_cargo( | |||
334 | 300 | ||
335 | Ok(()) | 301 | Ok(()) |
336 | } | 302 | } |
337 | |||
338 | fn cargo_binary() -> String { | ||
339 | env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()) | ||
340 | } | ||