From f58bca64878a944bda9c0c9aca94de7c1364d982 Mon Sep 17 00:00:00 2001 From: scturtle Date: Mon, 3 Jun 2019 00:11:18 +0800 Subject: [PATCH 1/3] filter before add --error-format --- rls/src/build/cargo.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rls/src/build/cargo.rs b/rls/src/build/cargo.rs index 39edd506233..3d5dd257bc3 100644 --- a/rls/src/build/cargo.rs +++ b/rls/src/build/cargo.rs @@ -392,6 +392,10 @@ impl Executor for RlsExecutor { _on_stderr_line: &mut dyn FnMut(&str) -> CargoResult<()>, ) -> CargoResult<()> { // Use JSON output so that we can parse the rustc output. + // Filter first to work around "--error-format" being passed with + // CARGO_PIPELINING(?) enabled in Cargo. + let filtered_args = filter_arg(cargo_cmd.get_args(), "--error-format"); + cargo_cmd.args_replace(&filtered_args); cargo_cmd.arg("--error-format=json"); // Delete any stale data. We try and remove any json files with // the same crate name as Cargo would emit. This includes files @@ -755,6 +759,18 @@ fn dedup_flags(flag_str: &str) -> String { result } +fn filter_arg(args: &[OsString], key: &str) -> Vec { + let key_as_prefix = key.to_owned() + "="; + args.iter() + .zip(vec!["".into()].iter().chain(args.iter())) + .filter_map(|(x, prev)| { + x.to_str() + .filter(|x| !x.starts_with(&key_as_prefix) && prev != key) + .map(|x| x.to_string()) + }) + .collect() +} + /// Error wrapper that tries to figure out which manifest the cause best relates to in the project #[derive(Debug)] pub struct ManifestAwareError { From 8f11693c737e92f20abb816577bfb70e9cd9ea5c Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 27 Jun 2019 00:28:34 +0200 Subject: [PATCH 2/3] Filter also --FLAG VALUE args in filter_arg --- rls/src/build/cargo.rs | 44 +++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/rls/src/build/cargo.rs b/rls/src/build/cargo.rs index 3d5dd257bc3..9f3a9e41139 100644 --- a/rls/src/build/cargo.rs +++ b/rls/src/build/cargo.rs @@ -759,16 +759,25 @@ fn dedup_flags(flag_str: &str) -> String { result } +/// Removes a selected flag of a `--flag=VALUE` or `--flag VALUE` shape from `args` (command line args for Rust). fn filter_arg(args: &[OsString], key: &str) -> Vec { let key_as_prefix = key.to_owned() + "="; - args.iter() - .zip(vec!["".into()].iter().chain(args.iter())) - .filter_map(|(x, prev)| { - x.to_str() - .filter(|x| !x.starts_with(&key_as_prefix) && prev != key) - .map(|x| x.to_string()) - }) - .collect() + let mut ret = vec![]; + + let mut iter = args.iter(); + while let Some(arg) = iter.next() { + let first = arg.to_str().unwrap(); + + if first == key { + iter.next(); + } else if first.starts_with(&key_as_prefix) { + // no-op + } else { + ret.push(first.to_owned()); + } + } + + ret } /// Error wrapper that tries to figure out which manifest the cause best relates to in the project @@ -853,7 +862,7 @@ impl failure::Fail for ManifestAwareError { #[cfg(test)] mod test { - use super::dedup_flags; + use super::{dedup_flags, filter_arg}; #[test] fn test_dedup_flags() { @@ -886,4 +895,21 @@ mod test { ) == " -Clink-args=-fuse-ld=gold -Ctarget-cpu=native" ); } + + #[test] + fn test_filter_arg() { + use std::ffi::OsString; + + fn args(input: &str) -> Vec { + input.split_whitespace().map(OsString::from).collect() + } + + assert!(filter_arg(&args("--error-format=json"), "--error-format").is_empty()); + assert!(filter_arg(&args("--error-format json"), "--error-format").is_empty()); + assert_eq!(filter_arg(&args("-a --error-format=json"), "--error-format"), ["-a"]); + assert_eq!(filter_arg(&args("-a --error-format json"), "--error-format"), ["-a"]); + assert_eq!(filter_arg(&args("-a --error-format=json -b"), "--error-format"), ["-a", "-b"]); + assert_eq!(filter_arg(&args("-a --error-format json -b"), "--error-format"), ["-a", "-b"]); + assert_eq!(filter_arg(&args("-a -b -x"), "--error-format"), ["-a", "-b", "-x"]); + } } From 202ce5dcd0938a975152d10cc3d81ada59bf22a4 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 27 Jun 2019 00:38:23 +0200 Subject: [PATCH 3/3] Adjust comment on why we strip --error-format --- rls/src/build/cargo.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rls/src/build/cargo.rs b/rls/src/build/cargo.rs index 9f3a9e41139..0d752b3377f 100644 --- a/rls/src/build/cargo.rs +++ b/rls/src/build/cargo.rs @@ -391,9 +391,9 @@ impl Executor for RlsExecutor { _on_stdout_line: &mut dyn FnMut(&str) -> CargoResult<()>, _on_stderr_line: &mut dyn FnMut(&str) -> CargoResult<()>, ) -> CargoResult<()> { - // Use JSON output so that we can parse the rustc output. - // Filter first to work around "--error-format" being passed with - // CARGO_PIPELINING(?) enabled in Cargo. + // Enforce JSON output so that we can parse the rustc output by + // stripping --error-format if it was specified (e.g. Cargo pipelined + // build) let filtered_args = filter_arg(cargo_cmd.get_args(), "--error-format"); cargo_cmd.args_replace(&filtered_args); cargo_cmd.arg("--error-format=json");