diff options
author | Leo Kettmeir <crowlkats@toaxl.com> | 2024-09-23 16:01:05 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-23 16:01:05 -0700 |
commit | 1eebd207250afbefaeeff1e889bc6962474a15fa (patch) | |
tree | 752f974cf878de58304de76d86f88daca5ba26e6 /cli/args | |
parent | 33f169beb90814b7f2f62a8c0e3990722ae3db4c (diff) |
fix: error out if a valid flag is passed before a subcommand (#25830)
Closes #25808
Diffstat (limited to 'cli/args')
-rw-r--r-- | cli/args/flags.rs | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 8490fdab6..d325ce7bc 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -1233,6 +1233,51 @@ pub fn flags_from_vec(args: Vec<OsString>) -> clap::error::Result<Flags> { } 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::CommandLine) + }) + .map(|arg| { + format!( + "--{}", + arg.get_long().unwrap_or_else(|| arg.get_id().as_str()) + ) + }); + + 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), @@ -4695,16 +4740,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(()) @@ -10799,4 +10838,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" + ) + } } |