mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
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>
This commit is contained in:
commit
32491c0978
3 changed files with 48 additions and 22 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -396,6 +396,7 @@ dependencies = [
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"jod-thread",
|
"jod-thread",
|
||||||
"log",
|
"log",
|
||||||
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"stdx",
|
"stdx",
|
||||||
"toolchain",
|
"toolchain",
|
||||||
|
|
|
@ -13,6 +13,7 @@ doctest = false
|
||||||
crossbeam-channel = "0.5.0"
|
crossbeam-channel = "0.5.0"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
cargo_metadata = "0.13"
|
cargo_metadata = "0.13"
|
||||||
|
serde = { version = "1.0.106", features = ["derive"] }
|
||||||
serde_json = "1.0.48"
|
serde_json = "1.0.48"
|
||||||
jod-thread = "0.1.1"
|
jod-thread = "0.1.1"
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
io::{self, BufReader},
|
io::{self, BufRead, BufReader},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::{self, Command, Stdio},
|
process::{self, Command, Stdio},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
|
use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
|
||||||
|
use serde::Deserialize;
|
||||||
use stdx::JodChild;
|
use stdx::JodChild;
|
||||||
|
|
||||||
pub use cargo_metadata::diagnostic::{
|
pub use cargo_metadata::diagnostic::{
|
||||||
|
@ -128,7 +129,7 @@ struct FlycheckActor {
|
||||||
|
|
||||||
enum Event {
|
enum Event {
|
||||||
Restart(Restart),
|
Restart(Restart),
|
||||||
CheckEvent(Option<cargo_metadata::Message>),
|
CheckEvent(Option<CargoMessage>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlycheckActor {
|
impl FlycheckActor {
|
||||||
|
@ -180,21 +181,16 @@ impl FlycheckActor {
|
||||||
self.progress(Progress::DidFinish(res));
|
self.progress(Progress::DidFinish(res));
|
||||||
}
|
}
|
||||||
Event::CheckEvent(Some(message)) => match message {
|
Event::CheckEvent(Some(message)) => match message {
|
||||||
cargo_metadata::Message::CompilerArtifact(msg) => {
|
CargoMessage::CompilerArtifact(msg) => {
|
||||||
self.progress(Progress::DidCheckCrate(msg.target.name));
|
self.progress(Progress::DidCheckCrate(msg.target.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
cargo_metadata::Message::CompilerMessage(msg) => {
|
CargoMessage::Diagnostic(msg) => {
|
||||||
self.send(Message::AddDiagnostic {
|
self.send(Message::AddDiagnostic {
|
||||||
workspace_root: self.workspace_root.clone(),
|
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,
|
child: JodChild,
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
thread: jod_thread::JoinHandle<io::Result<bool>>,
|
thread: jod_thread::JoinHandle<io::Result<bool>>,
|
||||||
receiver: Receiver<cargo_metadata::Message>,
|
receiver: Receiver<CargoMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CargoHandle {
|
impl CargoHandle {
|
||||||
|
@ -294,14 +290,11 @@ impl CargoHandle {
|
||||||
|
|
||||||
struct CargoActor {
|
struct CargoActor {
|
||||||
child_stdout: process::ChildStdout,
|
child_stdout: process::ChildStdout,
|
||||||
sender: Sender<cargo_metadata::Message>,
|
sender: Sender<CargoMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CargoActor {
|
impl CargoActor {
|
||||||
fn new(
|
fn new(child_stdout: process::ChildStdout, sender: Sender<CargoMessage>) -> CargoActor {
|
||||||
child_stdout: process::ChildStdout,
|
|
||||||
sender: Sender<cargo_metadata::Message>,
|
|
||||||
) -> CargoActor {
|
|
||||||
CargoActor { child_stdout, sender }
|
CargoActor { child_stdout, sender }
|
||||||
}
|
}
|
||||||
fn run(self) -> io::Result<bool> {
|
fn run(self) -> io::Result<bool> {
|
||||||
|
@ -315,7 +308,7 @@ impl CargoActor {
|
||||||
// erroneus output.
|
// erroneus output.
|
||||||
let stdout = BufReader::new(self.child_stdout);
|
let stdout = BufReader::new(self.child_stdout);
|
||||||
let mut read_at_least_one_message = false;
|
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 {
|
let message = match message {
|
||||||
Ok(message) => message,
|
Ok(message) => message,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -326,13 +319,44 @@ impl CargoActor {
|
||||||
|
|
||||||
read_at_least_one_message = true;
|
read_at_least_one_message = true;
|
||||||
|
|
||||||
// Skip certain kinds of messages to only spend time on what's useful
|
// Try to deserialize a message from Cargo or Rustc.
|
||||||
match &message {
|
let mut deserializer = serde_json::Deserializer::from_str(&message);
|
||||||
cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (),
|
deserializer.disable_recursion_limit();
|
||||||
cargo_metadata::Message::BuildScriptExecuted(_) => (),
|
if let Ok(message) = JsonMessage::deserialize(&mut deserializer) {
|
||||||
_ => self.sender.send(message).unwrap(),
|
match message {
|
||||||
|
// Skip certain kinds of messages to only spend time on what's useful
|
||||||
|
JsonMessage::Cargo(message) => 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(_)
|
||||||
|
| _ => (),
|
||||||
|
},
|
||||||
|
JsonMessage::Rustc(message) => {
|
||||||
|
self.sender.send(CargoMessage::Diagnostic(message)).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(read_at_least_one_message)
|
Ok(read_at_least_one_message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CargoMessage {
|
||||||
|
CompilerArtifact(cargo_metadata::Artifact),
|
||||||
|
Diagnostic(Diagnostic),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum JsonMessage {
|
||||||
|
Cargo(cargo_metadata::Message),
|
||||||
|
Rustc(Diagnostic),
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue