diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-21 22:56:54 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-04-21 22:56:54 +0100 |
commit | 32491c09787fa3b386d067f0ce95d744c1480e0b (patch) | |
tree | b34adf250a8f7b43b7bfc2ecda2fb1f8f5614917 /crates | |
parent | b21701c5ee77f30d3d5f2e69980c6d03618390d6 (diff) | |
parent | b3a7953cae4f14f74934cc64ba7ccf7b3eb6cd08 (diff) |
Merge #8570
8570: Flycheck tries to parse both Cargo and Rustc messages. r=rickvanprim a=rickvanprim
This change allows non-Cargo build systems to be used for Flycheck provided they call `rustc` with `--error-format=json` and emit those JSON messages to `stdout`.
Co-authored-by: James Leitch <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/flycheck/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/flycheck/src/lib.rs | 68 |
2 files changed, 47 insertions, 22 deletions
diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml index 2a1a21b28..18b9ce7df 100644 --- a/crates/flycheck/Cargo.toml +++ b/crates/flycheck/Cargo.toml | |||
@@ -13,6 +13,7 @@ doctest = false | |||
13 | crossbeam-channel = "0.5.0" | 13 | crossbeam-channel = "0.5.0" |
14 | log = "0.4.8" | 14 | log = "0.4.8" |
15 | cargo_metadata = "0.13" | 15 | cargo_metadata = "0.13" |
16 | serde = { version = "1.0.106", features = ["derive"] } | ||
16 | serde_json = "1.0.48" | 17 | serde_json = "1.0.48" |
17 | jod-thread = "0.1.1" | 18 | jod-thread = "0.1.1" |
18 | 19 | ||
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index e2a59497a..1682d8bde 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs | |||
@@ -4,13 +4,14 @@ | |||
4 | 4 | ||
5 | use std::{ | 5 | use std::{ |
6 | fmt, | 6 | fmt, |
7 | io::{self, BufReader}, | 7 | io::{self, BufRead, BufReader}, |
8 | path::PathBuf, | 8 | path::PathBuf, |
9 | process::{self, Command, Stdio}, | 9 | process::{self, Command, Stdio}, |
10 | time::Duration, | 10 | time::Duration, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; | 13 | use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; |
14 | use serde::Deserialize; | ||
14 | use stdx::JodChild; | 15 | use stdx::JodChild; |
15 | 16 | ||
16 | pub use cargo_metadata::diagnostic::{ | 17 | pub use cargo_metadata::diagnostic::{ |
@@ -128,7 +129,7 @@ struct FlycheckActor { | |||
128 | 129 | ||
129 | enum Event { | 130 | enum Event { |
130 | Restart(Restart), | 131 | Restart(Restart), |
131 | CheckEvent(Option<cargo_metadata::Message>), | 132 | CheckEvent(Option<CargoMessage>), |
132 | } | 133 | } |
133 | 134 | ||
134 | impl FlycheckActor { | 135 | impl FlycheckActor { |
@@ -180,21 +181,16 @@ impl FlycheckActor { | |||
180 | self.progress(Progress::DidFinish(res)); | 181 | self.progress(Progress::DidFinish(res)); |
181 | } | 182 | } |
182 | Event::CheckEvent(Some(message)) => match message { | 183 | Event::CheckEvent(Some(message)) => match message { |
183 | cargo_metadata::Message::CompilerArtifact(msg) => { | 184 | CargoMessage::CompilerArtifact(msg) => { |
184 | self.progress(Progress::DidCheckCrate(msg.target.name)); | 185 | self.progress(Progress::DidCheckCrate(msg.target.name)); |
185 | } | 186 | } |
186 | 187 | ||
187 | cargo_metadata::Message::CompilerMessage(msg) => { | 188 | CargoMessage::Diagnostic(msg) => { |
188 | self.send(Message::AddDiagnostic { | 189 | self.send(Message::AddDiagnostic { |
189 | workspace_root: self.workspace_root.clone(), | 190 | workspace_root: self.workspace_root.clone(), |
190 | diagnostic: msg.message, | 191 | diagnostic: msg, |
191 | }); | 192 | }); |
192 | } | 193 | } |
193 | |||
194 | cargo_metadata::Message::BuildScriptExecuted(_) | ||
195 | | cargo_metadata::Message::BuildFinished(_) | ||
196 | | cargo_metadata::Message::TextLine(_) | ||
197 | | _ => {} | ||
198 | }, | 194 | }, |
199 | } | 195 | } |
200 | } | 196 | } |
@@ -261,7 +257,7 @@ struct CargoHandle { | |||
261 | child: JodChild, | 257 | child: JodChild, |
262 | #[allow(unused)] | 258 | #[allow(unused)] |
263 | thread: jod_thread::JoinHandle<io::Result<bool>>, | 259 | thread: jod_thread::JoinHandle<io::Result<bool>>, |
264 | receiver: Receiver<cargo_metadata::Message>, | 260 | receiver: Receiver<CargoMessage>, |
265 | } | 261 | } |
266 | 262 | ||
267 | impl CargoHandle { | 263 | impl CargoHandle { |
@@ -294,14 +290,11 @@ impl CargoHandle { | |||
294 | 290 | ||
295 | struct CargoActor { | 291 | struct CargoActor { |
296 | child_stdout: process::ChildStdout, | 292 | child_stdout: process::ChildStdout, |
297 | sender: Sender<cargo_metadata::Message>, | 293 | sender: Sender<CargoMessage>, |
298 | } | 294 | } |
299 | 295 | ||
300 | impl CargoActor { | 296 | impl CargoActor { |
301 | fn new( | 297 | fn new(child_stdout: process::ChildStdout, sender: Sender<CargoMessage>) -> CargoActor { |
302 | child_stdout: process::ChildStdout, | ||
303 | sender: Sender<cargo_metadata::Message>, | ||
304 | ) -> CargoActor { | ||
305 | CargoActor { child_stdout, sender } | 298 | CargoActor { child_stdout, sender } |
306 | } | 299 | } |
307 | fn run(self) -> io::Result<bool> { | 300 | fn run(self) -> io::Result<bool> { |
@@ -315,7 +308,7 @@ impl CargoActor { | |||
315 | // erroneus output. | 308 | // erroneus output. |
316 | let stdout = BufReader::new(self.child_stdout); | 309 | let stdout = BufReader::new(self.child_stdout); |
317 | let mut read_at_least_one_message = false; | 310 | let mut read_at_least_one_message = false; |
318 | for message in cargo_metadata::Message::parse_stream(stdout) { | 311 | for message in stdout.lines() { |
319 | let message = match message { | 312 | let message = match message { |
320 | Ok(message) => message, | 313 | Ok(message) => message, |
321 | Err(err) => { | 314 | Err(err) => { |
@@ -326,13 +319,44 @@ impl CargoActor { | |||
326 | 319 | ||
327 | read_at_least_one_message = true; | 320 | read_at_least_one_message = true; |
328 | 321 | ||
329 | // Skip certain kinds of messages to only spend time on what's useful | 322 | // Try to deserialize a message from Cargo or Rustc. |
330 | match &message { | 323 | let mut deserializer = serde_json::Deserializer::from_str(&message); |
331 | cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (), | 324 | deserializer.disable_recursion_limit(); |
332 | cargo_metadata::Message::BuildScriptExecuted(_) => (), | 325 | if let Ok(message) = JsonMessage::deserialize(&mut deserializer) { |
333 | _ => self.sender.send(message).unwrap(), | 326 | match message { |
327 | // Skip certain kinds of messages to only spend time on what's useful | ||
328 | JsonMessage::Cargo(message) => match message { | ||
329 | cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => { | ||
330 | self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap() | ||
331 | } | ||
332 | cargo_metadata::Message::CompilerMessage(msg) => { | ||
333 | self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap() | ||
334 | } | ||
335 | |||
336 | cargo_metadata::Message::CompilerArtifact(_) | ||
337 | | cargo_metadata::Message::BuildScriptExecuted(_) | ||
338 | | cargo_metadata::Message::BuildFinished(_) | ||
339 | | cargo_metadata::Message::TextLine(_) | ||
340 | | _ => (), | ||
341 | }, | ||
342 | JsonMessage::Rustc(message) => { | ||
343 | self.sender.send(CargoMessage::Diagnostic(message)).unwrap() | ||
344 | } | ||
345 | } | ||
334 | } | 346 | } |
335 | } | 347 | } |
336 | Ok(read_at_least_one_message) | 348 | Ok(read_at_least_one_message) |
337 | } | 349 | } |
338 | } | 350 | } |
351 | |||
352 | enum CargoMessage { | ||
353 | CompilerArtifact(cargo_metadata::Artifact), | ||
354 | Diagnostic(Diagnostic), | ||
355 | } | ||
356 | |||
357 | #[derive(Deserialize)] | ||
358 | #[serde(untagged)] | ||
359 | enum JsonMessage { | ||
360 | Cargo(cargo_metadata::Message), | ||
361 | Rustc(Diagnostic), | ||
362 | } | ||