Skip to content

Commit 03f3de5

Browse files
committed
fix parsing of --extra-arg
also add test for this
1 parent 19d5517 commit 03f3de5

File tree

2 files changed

+94
-7
lines changed

2 files changed

+94
-7
lines changed

cpp-linter-lib/src/cli.rs

+91-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::fs;
44

55
// non-std crates
66
use clap::builder::FalseyValueParser;
7-
use clap::{Arg, ArgAction, Command};
7+
use clap::{Arg, ArgAction, ArgMatches, Command};
88

99
/// Builds and returns the Command Line Interface's argument parsing object.
1010
pub fn get_arg_parser() -> Command {
@@ -323,3 +323,93 @@ pub fn parse_ignore(ignore: &[&str]) -> (Vec<String>, Vec<String>) {
323323
}
324324
(ignored, not_ignored)
325325
}
326+
327+
/// Converts the parsed value of the `--extra-arg` option into an optional vector of strings.
328+
///
329+
/// This is for adapting to 2 scenarios where `--extra-arg` is either
330+
///
331+
/// - specified multiple times
332+
/// - each val is appended to a [`Vec`] (by clap crate)
333+
/// - specified once with multiple space-separated values
334+
/// - resulting [`Vec`] is made from splitting at the spaces between
335+
/// - not specified at all (returns [`None`])
336+
///
337+
/// It is preferred that the values specified in either situation do not contain spaces and are
338+
/// quoted:
339+
/// ```shell
340+
/// --extra-arg="-std=c++17" --extra-arg="-Wall"
341+
/// # or equivalently
342+
/// --extra-arg="-std=c++17 -Wall"
343+
/// ```
344+
/// The cpp-linter-action (for Github CI workflows) can only use 1 `extra-arg` input option, so
345+
/// the value will be split at spaces.
346+
pub fn convert_extra_arg_val(args: &ArgMatches) -> Option<Vec<&str>> {
347+
let raw_val = if let Ok(extra_args) = args.try_get_many::<String>("extra-arg") {
348+
extra_args.map(|extras| extras.map(|val| val.as_str()).collect::<Vec<_>>())
349+
} else {
350+
None
351+
};
352+
if let Some(val) = raw_val {
353+
if val.len() == 1 {
354+
// specified once; split and return result
355+
Some(
356+
val[0]
357+
.trim_matches('\'')
358+
.trim_matches('"')
359+
.split(' ')
360+
.collect(),
361+
)
362+
} else {
363+
// specified multiple times; just return
364+
Some(val)
365+
}
366+
} else {
367+
// no value specified; just return
368+
None
369+
}
370+
}
371+
372+
#[cfg(test)]
373+
mod test {
374+
use clap::ArgMatches;
375+
376+
use super::{convert_extra_arg_val, get_arg_parser};
377+
378+
fn parser_args(input: Vec<&str>) -> ArgMatches {
379+
let arg_parser = get_arg_parser();
380+
arg_parser.get_matches_from(input)
381+
}
382+
383+
#[test]
384+
fn extra_arg_0() {
385+
let args = parser_args(vec!["cpp-linter"]);
386+
let extras = convert_extra_arg_val(&args);
387+
assert!(extras.is_none());
388+
}
389+
390+
#[test]
391+
fn extra_arg_1() {
392+
let args = parser_args(vec!["cpp-linter", "--extra-arg='-std=c++17 -Wall'"]);
393+
let extras = convert_extra_arg_val(&args);
394+
assert!(extras.is_some());
395+
if let Some(extra_args) = extras {
396+
assert_eq!(extra_args.len(), 2);
397+
assert_eq!(extra_args, ["-std=c++17", "-Wall"])
398+
}
399+
}
400+
401+
#[test]
402+
fn extra_arg_2() {
403+
let args = parser_args(vec![
404+
"cpp-linter",
405+
"--extra-arg=-std=c++17",
406+
"--extra-arg=-Wall",
407+
]);
408+
let extras = convert_extra_arg_val(&args);
409+
assert!(extras.is_some());
410+
if let Some(extra_args) = extras {
411+
assert_eq!(extra_args.len(), 2);
412+
assert_eq!(extra_args, ["-std=c++17", "-Wall"])
413+
}
414+
}
415+
}

cpp-linter-lib/src/run.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use openssl_probe;
1313

1414
// project specific modules/crates
1515
use crate::clang_tools::capture_clang_tools_output;
16-
use crate::cli::{get_arg_parser, parse_ignore};
16+
use crate::cli::{convert_extra_arg_val, get_arg_parser, parse_ignore};
1717
use crate::common_fs::{list_source_files, FileObj};
1818
use crate::github_api::GithubApiClient;
1919
use crate::logger::{self, end_log_group, start_log_group};
@@ -112,18 +112,15 @@ pub fn run_main(args: Vec<String>) -> i32 {
112112
end_log_group();
113113

114114
let style = args.get_one::<String>("style").unwrap();
115+
let extra_args = convert_extra_arg_val(&args);
115116
let (format_advice, tidy_advice) = capture_clang_tools_output(
116117
&files,
117118
args.get_one::<String>("version").unwrap(),
118119
args.get_one::<String>("tidy-checks").unwrap(),
119120
style,
120121
lines_changed_only,
121122
database_path,
122-
if let Ok(extra_args) = args.try_get_many::<String>("extra-arg") {
123-
extra_args.map(|extras| extras.map(|val| val.as_str()).collect())
124-
} else {
125-
None
126-
},
123+
extra_args,
127124
);
128125
start_log_group(String::from("Posting feedback"));
129126
let no_lgtm = args.get_flag("no-lgtm");

0 commit comments

Comments
 (0)