Skip to content

Commit 32491c0

Browse files
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 <rickvanprim@gmail.com>
2 parents b21701c + b3a7953 commit 32491c0

File tree

3 files changed

+48
-22
lines changed

3 files changed

+48
-22
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/flycheck/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ doctest = false
1313
crossbeam-channel = "0.5.0"
1414
log = "0.4.8"
1515
cargo_metadata = "0.13"
16+
serde = { version = "1.0.106", features = ["derive"] }
1617
serde_json = "1.0.48"
1718
jod-thread = "0.1.1"
1819

crates/flycheck/src/lib.rs

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
55
use std::{
66
fmt,
7-
io::{self, BufReader},
7+
io::{self, BufRead, BufReader},
88
path::PathBuf,
99
process::{self, Command, Stdio},
1010
time::Duration,
1111
};
1212

1313
use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
14+
use serde::Deserialize;
1415
use stdx::JodChild;
1516

1617
pub use cargo_metadata::diagnostic::{
@@ -128,7 +129,7 @@ struct FlycheckActor {
128129

129130
enum Event {
130131
Restart(Restart),
131-
CheckEvent(Option<cargo_metadata::Message>),
132+
CheckEvent(Option<CargoMessage>),
132133
}
133134

134135
impl FlycheckActor {
@@ -180,21 +181,16 @@ impl FlycheckActor {
180181
self.progress(Progress::DidFinish(res));
181182
}
182183
Event::CheckEvent(Some(message)) => match message {
183-
cargo_metadata::Message::CompilerArtifact(msg) => {
184+
CargoMessage::CompilerArtifact(msg) => {
184185
self.progress(Progress::DidCheckCrate(msg.target.name));
185186
}
186187

187-
cargo_metadata::Message::CompilerMessage(msg) => {
188+
CargoMessage::Diagnostic(msg) => {
188189
self.send(Message::AddDiagnostic {
189190
workspace_root: self.workspace_root.clone(),
190-
diagnostic: msg.message,
191+
diagnostic: msg,
191192
});
192193
}
193-
194-
cargo_metadata::Message::BuildScriptExecuted(_)
195-
| cargo_metadata::Message::BuildFinished(_)
196-
| cargo_metadata::Message::TextLine(_)
197-
| _ => {}
198194
},
199195
}
200196
}
@@ -261,7 +257,7 @@ struct CargoHandle {
261257
child: JodChild,
262258
#[allow(unused)]
263259
thread: jod_thread::JoinHandle<io::Result<bool>>,
264-
receiver: Receiver<cargo_metadata::Message>,
260+
receiver: Receiver<CargoMessage>,
265261
}
266262

267263
impl CargoHandle {
@@ -294,14 +290,11 @@ impl CargoHandle {
294290

295291
struct CargoActor {
296292
child_stdout: process::ChildStdout,
297-
sender: Sender<cargo_metadata::Message>,
293+
sender: Sender<CargoMessage>,
298294
}
299295

300296
impl CargoActor {
301-
fn new(
302-
child_stdout: process::ChildStdout,
303-
sender: Sender<cargo_metadata::Message>,
304-
) -> CargoActor {
297+
fn new(child_stdout: process::ChildStdout, sender: Sender<CargoMessage>) -> CargoActor {
305298
CargoActor { child_stdout, sender }
306299
}
307300
fn run(self) -> io::Result<bool> {
@@ -315,7 +308,7 @@ impl CargoActor {
315308
// erroneus output.
316309
let stdout = BufReader::new(self.child_stdout);
317310
let mut read_at_least_one_message = false;
318-
for message in cargo_metadata::Message::parse_stream(stdout) {
311+
for message in stdout.lines() {
319312
let message = match message {
320313
Ok(message) => message,
321314
Err(err) => {
@@ -326,13 +319,44 @@ impl CargoActor {
326319

327320
read_at_least_one_message = true;
328321

329-
// Skip certain kinds of messages to only spend time on what's useful
330-
match &message {
331-
cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (),
332-
cargo_metadata::Message::BuildScriptExecuted(_) => (),
333-
_ => self.sender.send(message).unwrap(),
322+
// Try to deserialize a message from Cargo or Rustc.
323+
let mut deserializer = serde_json::Deserializer::from_str(&message);
324+
deserializer.disable_recursion_limit();
325+
if let Ok(message) = JsonMessage::deserialize(&mut deserializer) {
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+
}
334346
}
335347
}
336348
Ok(read_at_least_one_message)
337349
}
338350
}
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+
}

0 commit comments

Comments
 (0)