fix(derive): Add "id" attribute

Previously the Arg id was set with the "name" attribute. This allows use
of an "id" attribute to match the underlying struct.

A side effect of this is that the "id" attribute may also be used on
Commands. This isn't desired, but given the current architecture of the
attribute parser, it's hard to avoid.

Fixes: #3785
This commit is contained in:
Daniel Parks 2022-07-30 17:07:15 -07:00
parent 6aa4f90609
commit 1a2ae76738
No known key found for this signature in database
GPG key ID: 3C85EBB0234DE864
3 changed files with 58 additions and 2 deletions

View file

@ -400,7 +400,7 @@ impl Attrs {
}
fn push_method(&mut self, name: Ident, arg: impl ToTokens) {
if name == "name" {
if name == "name" || name == "id" {
self.name = Name::Assigned(quote!(#arg));
} else if name == "value_parser" {
self.value_parser = Some(ValueParser::Explicit(Method::new(name, quote!(#arg))));

View file

@ -181,7 +181,7 @@
//! - e.g. `#[clap(max_values(3))]` would translate to `arg.max_values(3)`
//!
//! **Magic attributes**:
//! - `name = <expr>`: [`Arg::id`][crate::Arg::id]
//! - `id = <expr>`: [`Arg::id`][crate::Arg::id]
//! - When not present: case-converted field name is used
//! - `value_parser [= <expr>]`: [`Arg::value_parser`][crate::Arg::value_parser]
//! - When not present: will auto-select an implementation based on the field type using

View file

@ -57,6 +57,34 @@ fn test_standalone_long_ignores_afterwards_defined_custom_name() {
);
}
#[test]
fn test_standalone_long_uses_previous_defined_custom_id() {
#[derive(Parser, Debug, PartialEq)]
struct Opt {
#[clap(id = "foo", long)]
foo_option: bool,
}
assert_eq!(
Opt { foo_option: true },
Opt::try_parse_from(&["test", "--foo"]).unwrap()
);
}
#[test]
fn test_standalone_long_ignores_afterwards_defined_custom_id() {
#[derive(Parser, Debug, PartialEq)]
struct Opt {
#[clap(long, id = "foo")]
foo_option: bool,
}
assert_eq!(
Opt { foo_option: true },
Opt::try_parse_from(&["test", "--foo-option"]).unwrap()
);
}
#[test]
fn test_standalone_short_generates_kebab_case() {
#[derive(Parser, Debug, PartialEq)]
@ -114,6 +142,34 @@ fn test_standalone_short_ignores_afterwards_defined_custom_name() {
);
}
#[test]
fn test_standalone_short_uses_previous_defined_custom_id() {
#[derive(Parser, Debug, PartialEq)]
struct Opt {
#[clap(id = "option", short)]
foo_option: bool,
}
assert_eq!(
Opt { foo_option: true },
Opt::try_parse_from(&["test", "-o"]).unwrap()
);
}
#[test]
fn test_standalone_short_ignores_afterwards_defined_custom_id() {
#[derive(Parser, Debug, PartialEq)]
struct Opt {
#[clap(short, id = "option")]
foo_option: bool,
}
assert_eq!(
Opt { foo_option: true },
Opt::try_parse_from(&["test", "-f"]).unwrap()
);
}
#[test]
fn test_standalone_long_uses_previous_defined_casing() {
#[derive(Parser, Debug, PartialEq)]