mirror of
https://github.com/clap-rs/clap
synced 2025-03-04 23:37:32 +00:00
fix(derive): Builder-specialized attributes
This commit is contained in:
parent
20ba828f21
commit
e0f2f6fbae
6 changed files with 63 additions and 22 deletions
|
@ -32,6 +32,12 @@ impl ClapAttr {
|
|||
Some(Sp::new(AttrKind::Clap, attr.path.span()))
|
||||
} else if attr.path.is_ident("structopt") {
|
||||
Some(Sp::new(AttrKind::StructOpt, attr.path.span()))
|
||||
} else if attr.path.is_ident("command") {
|
||||
Some(Sp::new(AttrKind::Command, attr.path.span()))
|
||||
} else if attr.path.is_ident("arg") {
|
||||
Some(Sp::new(AttrKind::Arg, attr.path.span()))
|
||||
} else if attr.path.is_ident("value") {
|
||||
Some(Sp::new(AttrKind::Value, attr.path.span()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -194,6 +200,9 @@ impl ToTokens for AttrValue {
|
|||
pub enum AttrKind {
|
||||
Clap,
|
||||
StructOpt,
|
||||
Command,
|
||||
Arg,
|
||||
Value,
|
||||
}
|
||||
|
||||
impl AttrKind {
|
||||
|
@ -201,6 +210,9 @@ impl AttrKind {
|
|||
match self {
|
||||
Self::Clap => "clap",
|
||||
Self::StructOpt => "structopt",
|
||||
Self::Command => "command",
|
||||
Self::Arg => "arg",
|
||||
Self::Value => "value",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@ pub fn gen_augment(
|
|||
Kind::Command(_)
|
||||
| Kind::Value(_)
|
||||
| Kind::Subcommand(_)
|
||||
| Kind::Skip(_)
|
||||
| Kind::Skip(_, _)
|
||||
| Kind::FromGlobal(_)
|
||||
| Kind::ExternalSubcommand => None,
|
||||
Kind::Flatten => {
|
||||
|
@ -384,7 +384,7 @@ pub fn gen_constructor(fields: &[(&Field, Item)]) -> TokenStream {
|
|||
#field_name: clap::FromArgMatches::from_arg_matches_mut(#arg_matches)?
|
||||
},
|
||||
|
||||
Kind::Skip(val) => match val {
|
||||
Kind::Skip(val, _) => match val {
|
||||
None => quote_spanned!(kind.span()=> #field_name: Default::default()),
|
||||
Some(val) => quote_spanned!(kind.span()=> #field_name: (#val).into()),
|
||||
},
|
||||
|
@ -463,7 +463,7 @@ pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> TokenStream {
|
|||
}
|
||||
},
|
||||
|
||||
Kind::Skip(_) => quote!(),
|
||||
Kind::Skip(_, _) => quote!(),
|
||||
|
||||
Kind::Arg(ty) | Kind::FromGlobal(ty) => gen_parsers(item, ty, field_name, field, Some(&access)),
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ fn gen_augment(
|
|||
let kind = item.kind();
|
||||
|
||||
match &*kind {
|
||||
Kind::Skip(_) => None,
|
||||
Kind::Skip(_, _) => None,
|
||||
|
||||
Kind::ExternalSubcommand => {
|
||||
let ty = match variant.fields {
|
||||
|
|
|
@ -78,7 +78,7 @@ fn lits(variants: &[(&Variant, Item)]) -> Vec<(TokenStream, Ident)> {
|
|||
variants
|
||||
.iter()
|
||||
.filter_map(|(variant, item)| {
|
||||
if let Kind::Skip(_) = &*item.kind() {
|
||||
if let Kind::Skip(_, _) = &*item.kind() {
|
||||
None
|
||||
} else {
|
||||
if !matches!(variant.fields, Fields::Unit) {
|
||||
|
|
|
@ -197,7 +197,7 @@ impl Item {
|
|||
|
||||
Kind::ExternalSubcommand
|
||||
| Kind::FromGlobal(_)
|
||||
| Kind::Skip(_)
|
||||
| Kind::Skip(_, _)
|
||||
| Kind::Command(_)
|
||||
| Kind::Value(_)
|
||||
| Kind::Arg(_) => (),
|
||||
|
@ -321,7 +321,7 @@ impl Item {
|
|||
|
||||
res.kind = Sp::new(Kind::Subcommand(ty), res.kind.span());
|
||||
}
|
||||
Kind::Skip(_) => {
|
||||
Kind::Skip(_, _) => {
|
||||
if res.has_explicit_methods() {
|
||||
abort!(
|
||||
res.kind.span(),
|
||||
|
@ -463,7 +463,10 @@ impl Item {
|
|||
}
|
||||
Some(MagicAttrName::Skip) => {
|
||||
let expr = attr.value.clone();
|
||||
let kind = Sp::new(Kind::Skip(expr), attr.name.clone().span());
|
||||
let kind = Sp::new(
|
||||
Kind::Skip(expr, self.kind.attr_kind()),
|
||||
attr.name.clone().span(),
|
||||
);
|
||||
Some(kind)
|
||||
}
|
||||
_ => None,
|
||||
|
@ -475,16 +478,29 @@ impl Item {
|
|||
}
|
||||
|
||||
for attr in &parsed {
|
||||
match attr.kind.get() {
|
||||
AttrKind::Clap => {}
|
||||
AttrKind::StructOpt => {
|
||||
let actual_attr_kind = *attr.kind.get();
|
||||
let expected_attr_kind = self.kind.attr_kind();
|
||||
match (actual_attr_kind, expected_attr_kind) {
|
||||
(AttrKind::Clap, _) => {}
|
||||
(AttrKind::StructOpt, _) => {
|
||||
self.deprecations.push(Deprecation::attribute(
|
||||
"4.0.0",
|
||||
*attr.kind.get(),
|
||||
AttrKind::Clap,
|
||||
actual_attr_kind,
|
||||
expected_attr_kind,
|
||||
attr.kind.span(),
|
||||
));
|
||||
}
|
||||
|
||||
_ if attr.kind != expected_attr_kind => {
|
||||
abort!(
|
||||
attr.kind.span(),
|
||||
"Expected `{}` attribute instead of `{}`",
|
||||
expected_attr_kind.as_str(),
|
||||
actual_attr_kind.as_str()
|
||||
);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Some(AttrValue::Call(tokens)) = &attr.value {
|
||||
|
@ -868,12 +884,12 @@ impl Item {
|
|||
(Kind::Arg(_), Kind::FromGlobal(_))
|
||||
| (Kind::Arg(_), Kind::Subcommand(_))
|
||||
| (Kind::Arg(_), Kind::Flatten)
|
||||
| (Kind::Arg(_), Kind::Skip(_))
|
||||
| (Kind::Arg(_), Kind::Skip(_, _))
|
||||
| (Kind::Command(_), Kind::Subcommand(_))
|
||||
| (Kind::Command(_), Kind::Flatten)
|
||||
| (Kind::Command(_), Kind::Skip(_))
|
||||
| (Kind::Command(_), Kind::Skip(_, _))
|
||||
| (Kind::Command(_), Kind::ExternalSubcommand)
|
||||
| (Kind::Value(_), Kind::Skip(_)) => {
|
||||
| (Kind::Value(_), Kind::Skip(_, _)) => {
|
||||
self.kind = kind;
|
||||
}
|
||||
|
||||
|
@ -1117,7 +1133,7 @@ pub enum Kind {
|
|||
FromGlobal(Sp<Ty>),
|
||||
Subcommand(Sp<Ty>),
|
||||
Flatten,
|
||||
Skip(Option<AttrValue>),
|
||||
Skip(Option<AttrValue>, AttrKind),
|
||||
ExternalSubcommand,
|
||||
}
|
||||
|
||||
|
@ -1130,10 +1146,23 @@ impl Kind {
|
|||
Self::FromGlobal(_) => "from_global",
|
||||
Self::Subcommand(_) => "subcommand",
|
||||
Self::Flatten => "flatten",
|
||||
Self::Skip(_) => "skip",
|
||||
Self::Skip(_, _) => "skip",
|
||||
Self::ExternalSubcommand => "external_subcommand",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attr_kind(&self) -> AttrKind {
|
||||
match self {
|
||||
Self::Arg(_) => AttrKind::Arg,
|
||||
Self::Command(_) => AttrKind::Command,
|
||||
Self::Value(_) => AttrKind::Value,
|
||||
Self::FromGlobal(_) => AttrKind::Arg,
|
||||
Self::Subcommand(_) => AttrKind::Command,
|
||||
Self::Flatten => AttrKind::Command,
|
||||
Self::Skip(_, kind) => *kind,
|
||||
Self::ExternalSubcommand => AttrKind::Command,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -29,7 +29,7 @@ mod item;
|
|||
mod utils;
|
||||
|
||||
/// Generates the `ValueEnum` impl.
|
||||
#[proc_macro_derive(ValueEnum, attributes(clap))]
|
||||
#[proc_macro_derive(ValueEnum, attributes(clap, value))]
|
||||
#[proc_macro_error]
|
||||
pub fn value_enum(input: TokenStream) -> TokenStream {
|
||||
let input: DeriveInput = parse_macro_input!(input);
|
||||
|
@ -42,7 +42,7 @@ pub fn value_enum(input: TokenStream) -> TokenStream {
|
|||
/// receiving an instance of `clap::ArgMatches` from conducting parsing, and then
|
||||
/// implementing a conversion code to instantiate an instance of the user
|
||||
/// context struct.
|
||||
#[proc_macro_derive(Parser, attributes(clap, structopt))]
|
||||
#[proc_macro_derive(Parser, attributes(clap, structopt, command, arg))]
|
||||
#[proc_macro_error]
|
||||
pub fn parser(input: TokenStream) -> TokenStream {
|
||||
let input: DeriveInput = parse_macro_input!(input);
|
||||
|
@ -50,7 +50,7 @@ pub fn parser(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
/// Generates the `Subcommand` impl.
|
||||
#[proc_macro_derive(Subcommand, attributes(clap))]
|
||||
#[proc_macro_derive(Subcommand, attributes(clap, command, arg))]
|
||||
#[proc_macro_error]
|
||||
pub fn subcommand(input: TokenStream) -> TokenStream {
|
||||
let input: DeriveInput = parse_macro_input!(input);
|
||||
|
@ -58,7 +58,7 @@ pub fn subcommand(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
/// Generates the `Args` impl.
|
||||
#[proc_macro_derive(Args, attributes(clap))]
|
||||
#[proc_macro_derive(Args, attributes(clap, command, arg))]
|
||||
#[proc_macro_error]
|
||||
pub fn args(input: TokenStream) -> TokenStream {
|
||||
let input: DeriveInput = parse_macro_input!(input);
|
||||
|
|
Loading…
Add table
Reference in a new issue