From b5c194f3f7c1dd38d4743ca65d5a55dfb5b648fc Mon Sep 17 00:00:00 2001 From: James Leitch Date: Sun, 18 Apr 2021 16:36:29 -0700 Subject: [PATCH] Flycheck tries to parse both Cargo and Rustc messages. --- Cargo.lock | 1 + crates/flycheck/Cargo.toml | 1 + crates/flycheck/src/lib.rs | 67 +++++++++++++++++++++++++------------- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1bb66c66e0..ebd20404c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -396,6 +396,7 @@ dependencies = [ "crossbeam-channel", "jod-thread", "log", + "serde", "serde_json", "stdx", "toolchain", diff --git a/crates/flycheck/Cargo.toml b/crates/flycheck/Cargo.toml index 2a1a21b28b..18b9ce7dfc 100644 --- a/crates/flycheck/Cargo.toml +++ b/crates/flycheck/Cargo.toml @@ -13,6 +13,7 @@ doctest = false crossbeam-channel = "0.5.0" log = "0.4.8" cargo_metadata = "0.13" +serde = { version = "1.0.106", features = ["derive"] } serde_json = "1.0.48" jod-thread = "0.1.1" diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index e2a59497aa..4c75396f57 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -4,13 +4,14 @@ use std::{ fmt, - io::{self, BufReader}, + io::{self, BufRead, BufReader}, path::PathBuf, process::{self, Command, Stdio}, time::Duration, }; use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; +use serde::Deserialize; use stdx::JodChild; pub use cargo_metadata::diagnostic::{ @@ -128,7 +129,7 @@ struct FlycheckActor { enum Event { Restart(Restart), - CheckEvent(Option), + CheckEvent(Option), } impl FlycheckActor { @@ -180,21 +181,16 @@ impl FlycheckActor { self.progress(Progress::DidFinish(res)); } Event::CheckEvent(Some(message)) => match message { - cargo_metadata::Message::CompilerArtifact(msg) => { + CargoMessage::CompilerArtifact(msg) => { self.progress(Progress::DidCheckCrate(msg.target.name)); } - cargo_metadata::Message::CompilerMessage(msg) => { + CargoMessage::Diagnostic(msg) => { self.send(Message::AddDiagnostic { workspace_root: self.workspace_root.clone(), - diagnostic: msg.message, + diagnostic: msg, }); } - - cargo_metadata::Message::BuildScriptExecuted(_) - | cargo_metadata::Message::BuildFinished(_) - | cargo_metadata::Message::TextLine(_) - | _ => {} }, } } @@ -261,7 +257,7 @@ struct CargoHandle { child: JodChild, #[allow(unused)] thread: jod_thread::JoinHandle>, - receiver: Receiver, + receiver: Receiver, } impl CargoHandle { @@ -294,14 +290,11 @@ impl CargoHandle { struct CargoActor { child_stdout: process::ChildStdout, - sender: Sender, + sender: Sender, } impl CargoActor { - fn new( - child_stdout: process::ChildStdout, - sender: Sender, - ) -> CargoActor { + fn new(child_stdout: process::ChildStdout, sender: Sender) -> CargoActor { CargoActor { child_stdout, sender } } fn run(self) -> io::Result { @@ -315,7 +308,7 @@ impl CargoActor { // erroneus output. let stdout = BufReader::new(self.child_stdout); let mut read_at_least_one_message = false; - for message in cargo_metadata::Message::parse_stream(stdout) { + for message in stdout.lines() { let message = match message { Ok(message) => message, Err(err) => { @@ -326,13 +319,43 @@ impl CargoActor { read_at_least_one_message = true; - // Skip certain kinds of messages to only spend time on what's useful - match &message { - cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (), - cargo_metadata::Message::BuildScriptExecuted(_) => (), - _ => self.sender.send(message).unwrap(), + // Try to deserialize a message from Cargo. + { + let mut deserializer = serde_json::Deserializer::from_str(&message); + deserializer.disable_recursion_limit(); + if let Ok(message) = cargo_metadata::Message::deserialize(&mut deserializer) { + // Skip certain kinds of messages to only spend time on what's useful + match message { + cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => { + self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap() + } + cargo_metadata::Message::CompilerMessage(msg) => { + self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap() + } + + cargo_metadata::Message::CompilerArtifact(_) + | cargo_metadata::Message::BuildScriptExecuted(_) + | cargo_metadata::Message::BuildFinished(_) + | cargo_metadata::Message::TextLine(_) + | _ => (), + } + } + } + + // Try to deserialize a Diagnostic directly from Rustc. + { + let mut deserializer = serde_json::Deserializer::from_str(&message); + deserializer.disable_recursion_limit(); + if let Ok(message) = Diagnostic::deserialize(&mut deserializer) { + self.sender.send(CargoMessage::Diagnostic(message)).unwrap() + } } } Ok(read_at_least_one_message) } } + +enum CargoMessage { + CompilerArtifact(cargo_metadata::Artifact), + Diagnostic(Diagnostic), +}