Skip to content

Commit

Permalink
Merge pull request #5425 from epage/lit
Browse files Browse the repository at this point in the history
fix(derive): Re-allow expressions for id's
  • Loading branch information
epage authored Mar 25, 2024
2 parents 024089b + df915fe commit 132b5dd
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 27 deletions.
18 changes: 15 additions & 3 deletions clap_derive/src/derives/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -717,9 +717,21 @@ fn gen_parsers(
},

Ty::Other => {
quote_spanned! { ty.span()=>
#arg_matches.#get_one(#id)
.ok_or_else(|| clap::Error::raw(clap::error::ErrorKind::MissingRequiredArgument, concat!("The following required argument was not provided: ", #id)))?
// Prefer `concat` where possible for reduced code size but fallback to `format!` to
// allow non-literal `id`s
match id {
Name::Assigned(_) => {
quote_spanned! { ty.span()=>
#arg_matches.#get_one(#id)
.ok_or_else(|| clap::Error::raw(clap::error::ErrorKind::MissingRequiredArgument, format!("The following required argument was not provided: {}", #id)))?
}
}
Name::Derived(_) => {
quote_spanned! { ty.span()=>
#arg_matches.#get_one(#id)
.ok_or_else(|| clap::Error::raw(clap::error::ErrorKind::MissingRequiredArgument, concat!("The following required argument was not provided: ", #id)))?
}
}
}
}
};
Expand Down
30 changes: 16 additions & 14 deletions clap_derive/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -974,8 +974,8 @@ impl Item {
quote!( #(#doc_comment)* #(#methods)* )
}

pub fn group_id(&self) -> TokenStream {
self.group_id.clone().raw()
pub fn group_id(&self) -> &Name {
&self.group_id
}

pub fn group_methods(&self) -> TokenStream {
Expand All @@ -998,8 +998,8 @@ impl Item {
quote!( #(#next_help_heading)* )
}

pub fn id(&self) -> TokenStream {
self.name.clone().raw()
pub fn id(&self) -> &Name {
&self.name
}

pub fn cased_name(&self) -> TokenStream {
Expand Down Expand Up @@ -1410,16 +1410,6 @@ pub enum Name {
}

impl Name {
pub fn raw(self) -> TokenStream {
match self {
Name::Assigned(tokens) => tokens,
Name::Derived(ident) => {
let s = ident.unraw().to_string();
quote_spanned!(ident.span()=> #s)
}
}
}

pub fn translate(self, style: CasingStyle) -> TokenStream {
use CasingStyle::*;

Expand Down Expand Up @@ -1466,3 +1456,15 @@ impl Name {
}
}
}

impl ToTokens for Name {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Name::Assigned(t) => t.to_tokens(tokens),
Name::Derived(ident) => {
let s = ident.unraw().to_string();
quote_spanned!(ident.span()=> #s).to_tokens(tokens)
}
}
}
}
37 changes: 27 additions & 10 deletions tests/derive/non_literal_attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,19 @@ fn test_bool() {
assert_eq!(result.unwrap_err().kind(), ErrorKind::NoEquals);
}

fn parse_hex(input: &str) -> Result<u64, ParseIntError> {
u64::from_str_radix(input, 16)
}

#[derive(Parser, PartialEq, Debug)]
struct HexOpt {
#[arg(short, value_parser = parse_hex)]
number: u64,
}

#[test]
#[cfg(feature = "error-context")]
fn test_parse_hex_function_path() {
#[derive(Parser, PartialEq, Debug)]
struct HexOpt {
#[arg(short, value_parser = parse_hex)]
number: u64,
}

fn parse_hex(input: &str) -> Result<u64, ParseIntError> {
u64::from_str_radix(input, 16)
}

assert_eq!(
HexOpt { number: 5 },
HexOpt::try_parse_from(["test", "-n", "5"]).unwrap()
Expand All @@ -156,3 +156,20 @@ fn test_parse_hex_function_path() {
err
);
}

#[test]
#[cfg(feature = "error-context")]
fn test_const_name() {
#[derive(Parser, PartialEq, Debug)]
struct Opt {
#[arg(id = NAME, short, long)]
number: u64,
}

const NAME: &str = "fun";

assert_eq!(
Opt { number: 5 },
Opt::try_parse_from(["test", "-f", "5"]).unwrap()
);
}

0 comments on commit 132b5dd

Please sign in to comment.