From 0908734efa16fbc0d92f087870fcda98f5ca9af0 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Mon, 23 Sep 2024 16:49:45 +0200 Subject: [PATCH 1/4] fix: error out if a valid flag is passed before a subcommand --- cli/args/flags.rs | 75 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/cli/args/flags.rs b/cli/args/flags.rs index a5ca78accc20dd..7cc3f72fc6f505 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -1236,6 +1236,54 @@ pub fn flags_from_vec(args: Vec) -> clap::error::Result { } if let Some((subcommand, mut m)) = matches.remove_subcommand() { + let pre_subcommand_arg = app + .get_arguments() + .filter(|arg| !arg.is_global_set()) + .find(|arg| { + matches + .value_source(arg.get_id().as_str()) + .is_some_and(|value| value != clap::parser::ValueSource::DefaultValue) + }) + .map(|arg| { + format!( + "--{}", + arg + .get_long() + .unwrap_or_else(|| arg.get_id().as_str()) + .to_string() + ) + }); + + if let Some(arg) = pre_subcommand_arg { + let usage = app.find_subcommand_mut(&subcommand).unwrap().render_usage(); + + let mut err = + clap::error::Error::new(ErrorKind::UnknownArgument).with_cmd(&app); + err.insert( + clap::error::ContextKind::InvalidArg, + clap::error::ContextValue::String(arg.clone()), + ); + + let valid = app.get_styles().get_valid(); + + let styled_suggestion = clap::builder::StyledStr::from(format!( + "'{}{subcommand} {arg}{}' exists", + valid.render(), + valid.render_reset() + )); + + err.insert( + clap::error::ContextKind::Suggested, + clap::error::ContextValue::StyledStrs(vec![styled_suggestion]), + ); + err.insert( + clap::error::ContextKind::Usage, + clap::error::ContextValue::StyledStr(usage), + ); + + return Err(err); + } + match subcommand.as_str() { "add" => add_parse(&mut flags, &mut m), "remove" => remove_parse(&mut flags, &mut m), @@ -4701,16 +4749,10 @@ fn run_parse( "[SCRIPT_ARG] may only be omitted with --v8-flags=--help, else to use the repl with arguments, please use the `deno repl` subcommand", )); } else { - return Err( - app - .get_subcommands_mut() - .find(|subcommand| subcommand.get_name() == "run") - .unwrap() - .error( - clap::error::ErrorKind::MissingRequiredArgument, - "[SCRIPT_ARG] may only be omitted with --v8-flags=--help", - ), - ); + return Err(app.find_subcommand_mut("run").unwrap().error( + clap::error::ErrorKind::MissingRequiredArgument, + "[SCRIPT_ARG] may only be omitted with --v8-flags=--help", + )); } Ok(()) @@ -10835,4 +10877,17 @@ mod tests { } ) } + + #[test] + fn flag_before_subcommand() { + let r = flags_from_vec(svec!["deno", "--allow-net", "repl"]); + assert_eq!( + r.unwrap_err().to_string(), + "error: unexpected argument '--allow-net' found + + tip: 'repl --allow-net' exists + +Usage: deno repl [OPTIONS] [-- [ARGS]...]\n" + ) + } } From 09250a739d79ddbc6c3a346bea02e7fecadb57ad Mon Sep 17 00:00:00 2001 From: crowlkats Date: Mon, 23 Sep 2024 17:20:08 +0200 Subject: [PATCH 2/4] lint --- cli/args/flags.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 7cc3f72fc6f505..698d97523c5be5 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -1250,7 +1250,6 @@ pub fn flags_from_vec(args: Vec) -> clap::error::Result { arg .get_long() .unwrap_or_else(|| arg.get_id().as_str()) - .to_string() ) }); From 67f33bf0583922c0e9f0f8c006eacef2d0f47240 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Mon, 23 Sep 2024 17:26:18 +0200 Subject: [PATCH 3/4] fmt --- cli/args/flags.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 698d97523c5be5..3b4211e51f8c6f 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -1247,9 +1247,7 @@ pub fn flags_from_vec(args: Vec) -> clap::error::Result { .map(|arg| { format!( "--{}", - arg - .get_long() - .unwrap_or_else(|| arg.get_id().as_str()) + arg.get_long().unwrap_or_else(|| arg.get_id().as_str()) ) }); From ac26d978f4f56e1f97e86230fbab7abccbe2fe70 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Mon, 23 Sep 2024 23:49:17 +0200 Subject: [PATCH 4/4] fix --- cli/args/flags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 3b4211e51f8c6f..7101918110ba2c 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -1242,7 +1242,7 @@ pub fn flags_from_vec(args: Vec) -> clap::error::Result { .find(|arg| { matches .value_source(arg.get_id().as_str()) - .is_some_and(|value| value != clap::parser::ValueSource::DefaultValue) + .is_some_and(|value| value == clap::parser::ValueSource::CommandLine) }) .map(|arg| { format!(