Skip to content

Commit

Permalink
Merge pull request #4777 from epage/error
Browse files Browse the repository at this point in the history
perf(derive): Improve build times
  • Loading branch information
epage committed Mar 23, 2023
2 parents cc1474f + 062622f commit dbf1b9a
Show file tree
Hide file tree
Showing 17 changed files with 710 additions and 628 deletions.
68 changes: 27 additions & 41 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions clap_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ proc-macro = true
bench = false

[dependencies]
syn = { version = "1.0.74", features = ["full"] }
syn = { version = "2.0.8", features = ["full"] }
quote = "1.0.9"
proc-macro2 = "1.0.42"
heck = "0.4.0"
proc-macro-error = "1.0.4"

[features]
default = []
Expand Down
71 changes: 32 additions & 39 deletions clap_derive/src/attr.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::iter::FromIterator;

use proc_macro2::TokenStream;
use proc_macro_error::abort;
use proc_macro_error::ResultExt;
use quote::quote;
use quote::ToTokens;
use syn::spanned::Spanned;
Expand All @@ -24,49 +22,44 @@ pub struct ClapAttr {
}

impl ClapAttr {
pub fn parse_all(all_attrs: &[Attribute]) -> Vec<Self> {
all_attrs
.iter()
.filter_map(|attr| {
let kind = if attr.path.is_ident("clap") {
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("group") {
Some(Sp::new(AttrKind::Group, 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
};
kind.map(|k| (k, attr))
})
.flat_map(|(k, attr)| {
attr.parse_args_with(Punctuated::<ClapAttr, Token![,]>::parse_terminated)
.unwrap_or_abort()
.into_iter()
.map(move |mut a| {
a.kind = k;
a
})
})
.collect()
pub fn parse_all(all_attrs: &[Attribute]) -> Result<Vec<Self>, syn::Error> {
let mut parsed = Vec::new();
for attr in all_attrs {
let kind = if attr.path().is_ident("clap") {
Sp::new(AttrKind::Clap, attr.path().span())
} else if attr.path().is_ident("structopt") {
Sp::new(AttrKind::StructOpt, attr.path().span())
} else if attr.path().is_ident("command") {
Sp::new(AttrKind::Command, attr.path().span())
} else if attr.path().is_ident("group") {
Sp::new(AttrKind::Group, attr.path().span())
} else if attr.path().is_ident("arg") {
Sp::new(AttrKind::Arg, attr.path().span())
} else if attr.path().is_ident("value") {
Sp::new(AttrKind::Value, attr.path().span())
} else {
continue;
};
for mut attr in
attr.parse_args_with(Punctuated::<ClapAttr, Token![,]>::parse_terminated)?
{
attr.kind = kind;
parsed.push(attr);
}
}
Ok(parsed)
}

pub fn value_or_abort(&self) -> &AttrValue {
pub fn value_or_abort(&self) -> Result<&AttrValue, syn::Error> {
self.value
.as_ref()
.unwrap_or_else(|| abort!(self.name, "attribute `{}` requires a value", self.name))
.ok_or_else(|| format_err!(self.name, "attribute `{}` requires a value", self.name))
}

pub fn lit_str_or_abort(&self) -> &LitStr {
let value = self.value_or_abort();
pub fn lit_str_or_abort(&self) -> Result<&LitStr, syn::Error> {
let value = self.value_or_abort()?;
match value {
AttrValue::LitStr(tokens) => tokens,
AttrValue::LitStr(tokens) => Ok(tokens),
AttrValue::Expr(_) | AttrValue::Call(_) => {
abort!(
self.name,
Expand Down Expand Up @@ -133,7 +126,7 @@ impl Parse for ClapAttr {
let nested;
parenthesized!(nested in input);

let method_args: Punctuated<_, Token![,]> = nested.parse_terminated(Expr::parse)?;
let method_args: Punctuated<_, _> = nested.parse_terminated(Expr::parse, Token![,])?;
Some(AttrValue::Call(Vec::from_iter(method_args)))
} else {
None
Expand Down

0 comments on commit dbf1b9a

Please sign in to comment.