mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 14:22:34 +00:00
Merge pull request #3591 from Shir0kamii/fix-ArgEnum-non-unit
Fix ArgEnum non-unit variant
This commit is contained in:
commit
71ef8878c5
5 changed files with 53 additions and 7 deletions
|
@ -15,11 +15,11 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use proc_macro_error::abort_call_site;
|
use proc_macro_error::{abort, abort_call_site};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{
|
use syn::{
|
||||||
punctuated::Punctuated, token::Comma, Attribute, Data, DataEnum, DeriveInput, Fields, Ident,
|
punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Data, DataEnum, DeriveInput,
|
||||||
Variant,
|
Fields, Ident, Variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn derive_arg_enum(input: &DeriveInput) -> TokenStream {
|
pub fn derive_arg_enum(input: &DeriveInput) -> TokenStream {
|
||||||
|
@ -34,10 +34,6 @@ pub fn derive_arg_enum(input: &DeriveInput) -> TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStream {
|
pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStream {
|
||||||
if !e.variants.iter().all(|v| matches!(v.fields, Fields::Unit)) {
|
|
||||||
return quote!();
|
|
||||||
};
|
|
||||||
|
|
||||||
let attrs = Attrs::from_struct(
|
let attrs = Attrs::from_struct(
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
attrs,
|
attrs,
|
||||||
|
@ -86,6 +82,9 @@ fn lits(
|
||||||
if let Kind::Skip(_) = &*attrs.kind() {
|
if let Kind::Skip(_) = &*attrs.kind() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
if !matches!(variant.fields, Fields::Unit) {
|
||||||
|
abort!(variant.span(), "`#[derive(ArgEnum)]` only supports non-unit variants, unless they are skipped");
|
||||||
|
}
|
||||||
let fields = attrs.field_methods(false);
|
let fields = attrs.field_methods(false);
|
||||||
let name = attrs.cased_name();
|
let name = attrs.cased_name();
|
||||||
Some((
|
Some((
|
||||||
|
|
|
@ -82,6 +82,7 @@ fn main() {
|
||||||
- `Subcommand` defines available subcommands.
|
- `Subcommand` defines available subcommands.
|
||||||
- Subcommand arguments can be defined in a struct-variant or automatically flattened with a tuple-variant.
|
- Subcommand arguments can be defined in a struct-variant or automatically flattened with a tuple-variant.
|
||||||
- `ArgEnum` allows parsing a value directly into an `enum`, erroring on unsupported values.
|
- `ArgEnum` allows parsing a value directly into an `enum`, erroring on unsupported values.
|
||||||
|
- The derive doesn't work on enums that contain non-unit variants, unless they are skipped
|
||||||
|
|
||||||
See also the [tutorial](../tutorial_derive/README.md) and [examples](../README.md).
|
See also the [tutorial](../tutorial_derive/README.md) and [examples](../README.md).
|
||||||
|
|
||||||
|
|
|
@ -321,6 +321,37 @@ fn skip_variant() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn skip_non_unit_variant() {
|
||||||
|
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
|
||||||
|
#[allow(dead_code)] // silence warning about `Baz` being unused
|
||||||
|
enum ArgChoice {
|
||||||
|
Foo,
|
||||||
|
Bar,
|
||||||
|
#[clap(skip)]
|
||||||
|
Baz(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
<ArgChoice as clap::ArgEnum>::value_variants()
|
||||||
|
.iter()
|
||||||
|
.map(clap::ArgEnum::to_possible_value)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
vec![
|
||||||
|
clap::PossibleValue::new("foo"),
|
||||||
|
clap::PossibleValue::new("bar")
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
use clap::ArgEnum;
|
||||||
|
assert!(ArgChoice::from_str("foo", true).is_ok());
|
||||||
|
assert!(ArgChoice::from_str("bar", true).is_ok());
|
||||||
|
assert!(ArgChoice::from_str("baz", true).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_str_invalid() {
|
fn from_str_invalid() {
|
||||||
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
|
#[derive(clap::ArgEnum, PartialEq, Debug, Clone)]
|
||||||
|
|
10
tests/derive_ui/arg_enum_non_unit.rs
Normal file
10
tests/derive_ui/arg_enum_non_unit.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
use clap::ArgEnum;
|
||||||
|
|
||||||
|
#[derive(ArgEnum, Clone, Debug)]
|
||||||
|
enum Opt {
|
||||||
|
Foo(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("{:?}", Opt::Foo(42));
|
||||||
|
}
|
5
tests/derive_ui/arg_enum_non_unit.stderr
Normal file
5
tests/derive_ui/arg_enum_non_unit.stderr
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
error: `#[derive(ArgEnum)]` only supports non-unit variants, unless they are skipped
|
||||||
|
--> tests/derive_ui/arg_enum_non_unit.rs:5:5
|
||||||
|
|
|
||||||
|
5 | Foo(usize),
|
||||||
|
| ^^^
|
Loading…
Reference in a new issue