From 4e9610284fee41b961f606e05a29cf55927e00a7 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 2 Sep 2022 13:04:49 -0500 Subject: [PATCH] refactor(derive): Further generalize kind errors --- clap_derive/src/derives/args.rs | 40 ++++++++-------- clap_derive/src/derives/subcommand.rs | 7 +++ clap_derive/src/derives/value_enum.rs | 7 +++ clap_derive/src/item.rs | 61 ++++++------------------ tests/derive_ui/struct_subcommand.stderr | 2 +- 5 files changed, 50 insertions(+), 67 deletions(-) diff --git a/clap_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs index ae5172ec440c..f057abe1032d 100644 --- a/clap_derive/src/derives/args.rs +++ b/clap_derive/src/derives/args.rs @@ -72,6 +72,13 @@ pub fn gen_for_struct( generics: &Generics, fields: &[(&Field, Item)], ) -> TokenStream { + if !matches!(&*item.kind(), Kind::Command(_)) { + abort! { item.kind().span(), + "`{}` cannot be used with `command`", + item.kind().name(), + } + } + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let constructor = gen_constructor(fields); @@ -194,12 +201,9 @@ pub fn gen_augment( let args = fields.iter().filter_map(|(field, item)| { let kind = item.kind(); match &*kind { - Kind::Command(ty) - | Kind::Value(ty) => { - abort!(ty.span(), "Invalid attribute are for arguments") - } - - Kind::Subcommand(_) + Kind::Command(_) + | Kind::Value(_) + | Kind::Subcommand(_) | Kind::Skip(_) | Kind::FromGlobal(_) | Kind::ExternalSubcommand => None, @@ -341,14 +345,12 @@ pub fn gen_constructor(fields: &[(&Field, Item)]) -> TokenStream { let kind = item.kind(); let arg_matches = format_ident!("__clap_arg_matches"); match &*kind { - Kind::Command(ty) - | Kind::Value(ty) => { - abort!(ty.span(), "Invalid attribute are for arguments") - } - - Kind::ExternalSubcommand => { + Kind::Command(_) + | Kind::Value(_) + | Kind::ExternalSubcommand => { abort! { kind.span(), - "`external_subcommand` can be used only on enum variants" + "`{}` cannot be used with `arg`", + kind.name(), } } Kind::Subcommand(ty) => { @@ -414,14 +416,12 @@ pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> TokenStream { let arg_matches = format_ident!("__clap_arg_matches"); match &*kind { - Kind::Command(ty) - | Kind::Value(ty) => { - abort!(ty.span(), "Invalid attribute are for arguments") - } - - Kind::ExternalSubcommand => { + Kind::Command(_) + | Kind::Value(_) + | Kind::ExternalSubcommand => { abort! { kind.span(), - "`external_subcommand` can be used only on enum variants" + "`{}` cannot be used with `arg`", + kind.name(), } } Kind::Subcommand(ty) => { diff --git a/clap_derive/src/derives/subcommand.rs b/clap_derive/src/derives/subcommand.rs index 772b63a06984..c6a13c21bc06 100644 --- a/clap_derive/src/derives/subcommand.rs +++ b/clap_derive/src/derives/subcommand.rs @@ -52,6 +52,13 @@ pub fn gen_for_enum( generics: &Generics, variants: &[(&Variant, Item)], ) -> TokenStream { + if !matches!(&*item.kind(), Kind::Command(_)) { + abort! { item.kind().span(), + "`{}` cannot be used with `command`", + item.kind().name(), + } + } + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let from_arg_matches = gen_from_arg_matches(variants); diff --git a/clap_derive/src/derives/value_enum.rs b/clap_derive/src/derives/value_enum.rs index 6a13156d0e4a..f53b09dfcabe 100644 --- a/clap_derive/src/derives/value_enum.rs +++ b/clap_derive/src/derives/value_enum.rs @@ -42,6 +42,13 @@ pub fn derive_value_enum(input: &DeriveInput) -> TokenStream { } pub fn gen_for_enum(item: &Item, item_name: &Ident, variants: &[(&Variant, Item)]) -> TokenStream { + if !matches!(&*item.kind(), Kind::Value(_)) { + abort! { item.kind().span(), + "`{}` cannot be used with `value`", + item.kind().name(), + } + } + let lits = lits(variants); let value_variants = gen_value_variants(&lits); let to_possible_value = gen_to_possible_value(item, &lits); diff --git a/clap_derive/src/item.rs b/clap_derive/src/item.rs index acb05e7b3f95..61d2a706338b 100644 --- a/clap_derive/src/item.rs +++ b/clap_derive/src/item.rs @@ -103,19 +103,8 @@ impl Item { "`action` attribute is only allowed on fields" ); } - match &*res.kind { - Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => res, - Kind::Subcommand(_) | Kind::Skip(_) | Kind::FromGlobal(_) | Kind::Flatten => abort!( - res.kind.span(), - "`{}` is only allowed on fields", - res.kind.name(), - ), - Kind::ExternalSubcommand => abort!( - res.kind.span(), - "`{}` is only allowed on variants", - res.kind.name(), - ), - } + + res } pub fn from_subcommand_variant( @@ -155,8 +144,6 @@ impl Item { res.doc_comment = vec![]; } - Kind::ExternalSubcommand => (), - Kind::Subcommand(_) => { if let Some(value_parser) = res.value_parser.as_ref() { abort!( @@ -207,15 +194,13 @@ impl Item { res.kind = Sp::new(Kind::Subcommand(ty), res.kind.span()); } - Kind::Skip(_) => (), - Kind::FromGlobal(_) => { - abort!( - res.kind.span(), - "`{}` is only allowed on fields", - res.kind.name(), - ) - } - Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => (), + + Kind::ExternalSubcommand + | Kind::FromGlobal(_) + | Kind::Skip(_) + | Kind::Command(_) + | Kind::Value(_) + | Kind::Arg(_) => (), } res @@ -250,20 +235,8 @@ impl Item { "`action` attribute is only allowed on fields" ); } - match &*res.kind { - Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => res, - Kind::Skip(_) => res, - Kind::Subcommand(_) | Kind::FromGlobal(_) | Kind::Flatten => abort!( - res.kind.span(), - "`{}` is only allowed on fields", - res.kind.name(), - ), - Kind::ExternalSubcommand => abort!( - res.kind.span(), - "`{}` is only allowed on variants", - res.kind.name(), - ), - } + + res } pub fn from_args_field( @@ -309,12 +282,6 @@ impl Item { res.doc_comment = vec![]; } - Kind::ExternalSubcommand => abort!( - res.kind.span(), - "`{}` is only allowed on variants", - res.kind.name(), - ), - Kind::Subcommand(_) => { if let Some(value_parser) = res.value_parser.as_ref() { abort!( @@ -366,7 +333,7 @@ impl Item { let ty = Ty::from_syn_ty(&field.ty); res.kind = Sp::new(Kind::FromGlobal(ty), orig_ty.span()); } - Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => { + Kind::Arg(_) => { let ty = Ty::from_syn_ty(&field.ty); match *ty { @@ -403,6 +370,8 @@ impl Item { .unwrap_or_else(|| field.ty.span()), ); } + + Kind::Command(_) | Kind::Value(_) | Kind::ExternalSubcommand => {} } res @@ -1153,7 +1122,7 @@ pub enum Kind { } impl Kind { - fn name(&self) -> &'static str { + pub fn name(&self) -> &'static str { match self { Self::Arg(_) => "arg", Self::Command(_) => "command", diff --git a/tests/derive_ui/struct_subcommand.stderr b/tests/derive_ui/struct_subcommand.stderr index 5c3f9e15f1bf..29290808f9b3 100644 --- a/tests/derive_ui/struct_subcommand.stderr +++ b/tests/derive_ui/struct_subcommand.stderr @@ -1,4 +1,4 @@ -error: `subcommand` is only allowed on fields +error: `subcommand` cannot be used with `command` --> tests/derive_ui/struct_subcommand.rs:12:24 | 12 | #[clap(name = "basic", subcommand)]