Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(derive): Clean up in prep for parent attributes #4184

Merged
merged 17 commits into from Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
96 changes: 46 additions & 50 deletions clap_derive/src/derives/args.rs
Expand Up @@ -157,56 +157,40 @@ pub fn gen_augment(
parent_item: &Item,
override_required: bool,
) -> TokenStream {
let mut subcmds = fields.iter().filter_map(|(field, item)| {
let kind = item.kind();
if let Kind::Subcommand(ty) = &*kind {
let subcmd_type = match (**ty, sub_type(&field.ty)) {
(Ty::Option, Some(sub_type)) => sub_type,
_ => &field.ty,
};
let required = if **ty == Ty::Option {
quote!()
} else {
quote_spanned! { kind.span()=>
let #app_var = #app_var
.subcommand_required(true)
.arg_required_else_help(true);
}
};

let span = field.span();
let ts = if override_required {
quote! {
let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands_for_update( #app_var );
}
} else{
quote! {
let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands( #app_var );
#required
}
};
Some((span, ts))
} else {
None
}
});
let subcmd = subcmds.next().map(|(_, ts)| ts);
if let Some((span, _)) = subcmds.next() {
abort!(
span,
"multiple subcommand sets are not allowed, that's the second"
);
}

let mut subcommand_specified = false;
let args = fields.iter().filter_map(|(field, item)| {
let kind = item.kind();
match &*kind {
Kind::Command(_)
| Kind::Value(_)
| Kind::Subcommand(_)
| Kind::Value
| Kind::Skip(_, _)
| Kind::FromGlobal(_)
| Kind::ExternalSubcommand => None,
Kind::Subcommand(ty) => {
if subcommand_specified {
abort!(field.span(), "`#[command(subcommand)]` can only be used once per container");
}
subcommand_specified = true;

let subcmd_type = match (**ty, sub_type(&field.ty)) {
(Ty::Option, Some(sub_type)) => sub_type,
_ => &field.ty,
};
let implicit_methods = if **ty == Ty::Option || override_required {
quote!()
} else {
quote_spanned! { kind.span()=>
.subcommand_required(true)
.arg_required_else_help(true)
}
};

Some(quote! {
let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands( #app_var );
let #app_var = #app_var
#implicit_methods;
})
}
Kind::Flatten => {
let ty = &field.ty;
let old_heading_var = format_ident!("__clap_old_heading");
Expand All @@ -215,14 +199,18 @@ pub fn gen_augment(
if override_required {
Some(quote_spanned! { kind.span()=>
let #old_heading_var = #app_var.get_next_help_heading().map(|s| clap::builder::Str::from(s.to_owned()));
let #app_var = #app_var #next_help_heading #next_display_order;
let #app_var = #app_var
#next_help_heading
#next_display_order;
let #app_var = <#ty as clap::Args>::augment_args_for_update(#app_var);
let #app_var = #app_var.next_help_heading(clap::builder::Resettable::from(#old_heading_var));
})
} else {
Some(quote_spanned! { kind.span()=>
let #old_heading_var = #app_var.get_next_help_heading().map(|s| clap::builder::Str::from(s.to_owned()));
let #app_var = #app_var #next_help_heading #next_display_order;
let #app_var = #app_var
#next_help_heading
#next_display_order;
let #app_var = <#ty as clap::Args>::augment_args(#app_var);
let #app_var = #app_var.next_help_heading(clap::builder::Resettable::from(#old_heading_var));
})
Expand Down Expand Up @@ -299,7 +287,7 @@ pub fn gen_augment(
};

let id = item.id();
let explicit_methods = item.field_methods(true);
let explicit_methods = item.field_methods();
let deprecations = if !override_required {
item.deprecations()
} else {
Expand Down Expand Up @@ -334,7 +322,6 @@ pub fn gen_augment(
#deprecations
let #app_var = #app_var #initial_app_methods;
#( #args )*
#subcmd
#app_var #final_app_methods
}}
}
Expand All @@ -346,7 +333,7 @@ pub fn gen_constructor(fields: &[(&Field, Item)]) -> TokenStream {
let arg_matches = format_ident!("__clap_arg_matches");
match &*kind {
Kind::Command(_)
| Kind::Value(_)
| Kind::Value
| Kind::ExternalSubcommand => {
abort! { kind.span(),
"`{}` cannot be used with `arg`",
Expand All @@ -370,13 +357,22 @@ pub fn gen_constructor(fields: &[(&Field, Item)]) -> TokenStream {
}
}
},
_ => {
Ty::Vec |
Ty::Other => {
quote_spanned! { kind.span()=>
#field_name: {
<#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)?
}
}
},
Ty::OptionOption |
Ty::OptionVec => {
abort!(
ty.span(),
"{} types are not supported for subcommand",
ty.as_str()
);
}
}
}

Expand Down Expand Up @@ -417,7 +413,7 @@ pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> TokenStream {

match &*kind {
Kind::Command(_)
| Kind::Value(_)
| Kind::Value
| Kind::ExternalSubcommand => {
abort! { kind.span(),
"`{}` cannot be used with `arg`",
Expand Down
33 changes: 19 additions & 14 deletions clap_derive/src/derives/subcommand.rs
Expand Up @@ -137,7 +137,10 @@ fn gen_augment(
let kind = item.kind();

match &*kind {
Kind::Skip(_, _) => None,
Kind::Skip(_, _) |
Kind::Arg(_) |
Kind::FromGlobal(_) |
Kind::Value => None,

Kind::ExternalSubcommand => {
let ty = match variant.fields {
Expand All @@ -155,19 +158,17 @@ fn gen_augment(
} else {
quote!()
};
let subcommand = match subty_if_name(ty, "Vec") {
Some(subty) => {
quote_spanned! { kind.span()=>
#deprecations
let #app_var = #app_var.external_subcommand_value_parser(clap::value_parser!(#subty));
}
}

None => abort!(
let subty = subty_if_name(ty, "Vec").unwrap_or_else(|| {
abort!(
ty.span(),
"The type must be `Vec<_>` \
to be used with `external_subcommand`."
),
)
});
let subcommand = quote_spanned! { kind.span()=>
#deprecations
let #app_var = #app_var
.external_subcommand_value_parser(clap::value_parser!(#subty));
};
Some(subcommand)
}
Expand All @@ -187,15 +188,19 @@ fn gen_augment(
quote! {
#deprecations
let #old_heading_var = #app_var.get_next_help_heading().map(|s| clap::builder::Str::from(s.to_owned()));
let #app_var = #app_var #next_help_heading #next_display_order;
let #app_var = #app_var
#next_help_heading
#next_display_order;
let #app_var = <#ty as clap::Subcommand>::augment_subcommands_for_update(#app_var);
let #app_var = #app_var.next_help_heading(clap::builder::Resettable::from(#old_heading_var));
}
} else {
quote! {
#deprecations
let #old_heading_var = #app_var.get_next_help_heading().map(|s| clap::builder::Str::from(s.to_owned()));
let #app_var = #app_var #next_help_heading #next_display_order;
let #app_var = #app_var
#next_help_heading
#next_display_order;
let #app_var = <#ty as clap::Subcommand>::augment_subcommands(#app_var);
let #app_var = #app_var.next_help_heading(clap::builder::Resettable::from(#old_heading_var));
}
Expand Down Expand Up @@ -259,7 +264,7 @@ fn gen_augment(
Some(subcommand)
}

_ => {
Kind::Command(_) => {
let subcommand_var = Ident::new("__clap_subcommand", Span::call_site());
let sub_augment = match variant.fields {
Named(ref fields) => {
Expand Down
4 changes: 2 additions & 2 deletions clap_derive/src/derives/value_enum.rs
Expand Up @@ -42,7 +42,7 @@ 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(_)) {
if !matches!(&*item.kind(), Kind::Value) {
abort! { item.kind().span(),
"`{}` cannot be used with `value`",
item.kind().name(),
Expand Down Expand Up @@ -84,7 +84,7 @@ fn lits(variants: &[(&Variant, Item)]) -> Vec<(TokenStream, Ident)> {
if !matches!(variant.fields, Fields::Unit) {
abort!(variant.span(), "`#[derive(ValueEnum)]` only supports unit variants. Non-unit variants must be skipped");
}
let fields = item.field_methods(false);
let fields = item.field_methods();
let deprecations = item.deprecations();
let name = item.cased_name();
Some((
Expand Down