Skip to content

Commit d03d638

Browse files
bors[bot]matklad
andauthored
Merge #3804
3804: Generalize flycheck to arbitrary commands r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents aad0e63 + cc8113d commit d03d638

File tree

2 files changed

+38
-53
lines changed

2 files changed

+38
-53
lines changed

crates/ra_flycheck/src/lib.rs

Lines changed: 37 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
mod conv;
55

66
use std::{
7-
env, error, fmt,
8-
io::{BufRead, BufReader},
7+
env,
8+
io::{self, BufRead, BufReader},
99
path::PathBuf,
1010
process::{Command, Stdio},
1111
time::Instant,
@@ -23,10 +23,9 @@ use crate::conv::{map_rust_diagnostic_to_lsp, MappedRustDiagnostic};
2323
pub use crate::conv::url_from_path_with_drive_lowercasing;
2424

2525
#[derive(Clone, Debug)]
26-
pub struct FlycheckConfig {
27-
pub command: String,
28-
pub all_targets: bool,
29-
pub extra_args: Vec<String>,
26+
pub enum FlycheckConfig {
27+
CargoCommand { command: String, all_targets: bool, extra_args: Vec<String> },
28+
CustomCommand { command: String, args: Vec<String> },
3029
}
3130

3231
/// Flycheck wraps the shared state and communication machinery used for
@@ -215,18 +214,25 @@ impl FlycheckThread {
215214
self.message_recv = never();
216215
self.check_process = None;
217216

218-
let cmd = {
219-
let mut cmd = Command::new(cargo_binary());
220-
cmd.arg(&self.config.command);
221-
cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]);
222-
cmd.arg(self.workspace_root.join("Cargo.toml"));
223-
if self.config.all_targets {
224-
cmd.arg("--all-targets");
217+
let mut cmd = match &self.config {
218+
FlycheckConfig::CargoCommand { command, all_targets, extra_args } => {
219+
let mut cmd = Command::new(cargo_binary());
220+
cmd.arg(command);
221+
cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]);
222+
cmd.arg(self.workspace_root.join("Cargo.toml"));
223+
if *all_targets {
224+
cmd.arg("--all-targets");
225+
}
226+
cmd.args(extra_args);
227+
cmd
228+
}
229+
FlycheckConfig::CustomCommand { command, args } => {
230+
let mut cmd = Command::new(command);
231+
cmd.args(args);
232+
cmd
225233
}
226-
cmd.args(self.config.extra_args.iter());
227-
cmd.current_dir(&self.workspace_root);
228-
cmd
229234
};
235+
cmd.current_dir(&self.workspace_root);
230236

231237
let (message_send, message_recv) = unbounded();
232238
self.message_recv = message_recv;
@@ -273,27 +279,12 @@ enum CheckEvent {
273279
End,
274280
}
275281

276-
#[derive(Debug)]
277-
pub struct CargoError(String);
278-
279-
impl fmt::Display for CargoError {
280-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
281-
write!(f, "Cargo failed: {}", self.0)
282-
}
283-
}
284-
impl error::Error for CargoError {}
285-
286282
fn run_cargo(
287283
mut command: Command,
288284
on_message: &mut dyn FnMut(cargo_metadata::Message) -> bool,
289-
) -> Result<(), CargoError> {
290-
dbg!(&command);
291-
let mut child = command
292-
.stdout(Stdio::piped())
293-
.stderr(Stdio::null())
294-
.stdin(Stdio::null())
295-
.spawn()
296-
.expect("couldn't launch cargo");
285+
) -> io::Result<()> {
286+
let mut child =
287+
command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()).spawn()?;
297288

298289
// We manually read a line at a time, instead of using serde's
299290
// stream deserializers, because the deserializer cannot recover
@@ -307,13 +298,7 @@ fn run_cargo(
307298
let mut read_at_least_one_message = false;
308299

309300
for line in stdout.lines() {
310-
let line = match line {
311-
Ok(line) => line,
312-
Err(err) => {
313-
log::error!("Couldn't read line from cargo: {}", err);
314-
continue;
315-
}
316-
};
301+
let line = line?;
317302

318303
let message = serde_json::from_str::<cargo_metadata::Message>(&line);
319304
let message = match message {
@@ -334,20 +319,20 @@ fn run_cargo(
334319
// It is okay to ignore the result, as it only errors if the process is already dead
335320
let _ = child.kill();
336321

337-
let err_msg = match child.wait() {
338-
Ok(exit_code) if !exit_code.success() && !read_at_least_one_message => {
339-
// FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment:
340-
// https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298
322+
let exit_status = child.wait()?;
323+
if !exit_status.success() && !read_at_least_one_message {
324+
// FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment:
325+
// https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298
326+
return Err(io::Error::new(
327+
io::ErrorKind::Other,
341328
format!(
342329
"the command produced no valid metadata (exit code: {:?}): {:?}",
343-
exit_code, command
344-
)
345-
}
346-
Err(err) => format!("io error: {:?}", err),
347-
Ok(_) => return Ok(()),
348-
};
330+
exit_status, command
331+
),
332+
));
333+
}
349334

350-
Err(CargoError(err_msg))
335+
Ok(())
351336
}
352337

353338
fn cargo_binary() -> String {

crates/rust-analyzer/src/main_loop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ fn get_config(
102102
max_length: config.inlay_hints_max_length,
103103
},
104104
check: if config.cargo_watch_enable {
105-
Some(FlycheckConfig {
105+
Some(FlycheckConfig::CargoCommand {
106106
command: config.cargo_watch_command.clone(),
107107
all_targets: config.cargo_watch_all_targets,
108108
extra_args: config.cargo_watch_args.clone(),

0 commit comments

Comments
 (0)