Skip to content

Commit c3e2e6c

Browse files
committed
remove panic via helper trait
1 parent eef236e commit c3e2e6c

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

macro/src/lib.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,21 @@ pub fn attribute_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStre
5252
}
5353
}
5454
}
55-
let attribute_ident = attribute_ident
56-
.map(|attribute_ident| quote!(Some(#attribute_ident)))
57-
.unwrap_or_else(|| quote!(None));
5855

5956
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
6057

58+
let attribute_ident = attribute_ident
59+
.map(|attribute_ident| {
60+
quote! {
61+
# use attribute_derive::AttributeIdent;
62+
63+
impl #impl_generics AttributeIdent for #ident #ty_generics #where_clause {
64+
const ATTRIBUTE_IDENT: &'static str = #attribute_ident;
65+
}
66+
}
67+
})
68+
.unwrap_or_default();
69+
6170
let mut options_ty: Punctuated<TokenStream, Token!(,)> = Punctuated::new();
6271
let mut parsing: Punctuated<TokenStream, Token!(,)> = Punctuated::new();
6372
let mut option_assignments: Punctuated<TokenStream, Token!(;)> = Punctuated::new();
@@ -246,9 +255,10 @@ pub fn attribute_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStre
246255
}
247256
}
248257

258+
#attribute_ident
259+
249260
#[allow(unreachable_code)]
250261
impl #impl_generics ::attribute_derive::Attribute for #ident #ty_generics #where_clause {
251-
const IDENT: Option<&'static str> = #attribute_ident;
252262
type Parser = #parser_ident;
253263

254264
fn from_parser($parser: Self::Parser) -> Result<Self> {

src/lib.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ pub mod __private {
104104
pub use syn;
105105
}
106106

107+
/// Helper trait providing the path for an attribute.
108+
///
109+
/// Automatically derived with [`Attribute`], if `#[attribute(ident =
110+
/// "some_ident")]` is provided.
111+
/// ```
112+
pub trait AttributeIdent: Sized {
113+
const ATTRIBUTE_IDENT: &'static str;
114+
fn get_attribute_ident() -> &'static str {
115+
Self::ATTRIBUTE_IDENT
116+
}
117+
}
118+
107119
/// The trait you actually derive on your attribute struct.
108120
///
109121
/// Basic gist is a struct like this:
@@ -132,7 +144,6 @@ pub mod __private {
132144
/// #[collection(authority="Some String", name = r#"Another string"#, views = [Option, ()], some_flag)]
133145
/// ```
134146
pub trait Attribute: Sized {
135-
const IDENT: Option<&'static str>;
136147
type Parser: TryExtendOne + Parse + Default;
137148

138149
#[doc(hidden)]
@@ -162,12 +173,15 @@ pub trait Attribute: Sized {
162173
/// - Invalid input is given for a parameter
163174
/// - A non aggregating parameter is specified multiple times
164175
/// - An attribute called [`IDENT`](Self::IDENT) has invalid syntax (e.g. `#attr(a: "a")`)
165-
fn from_attributes<'a>(attrs: impl IntoIterator<Item = &'a syn::Attribute>) -> Result<Self> {
176+
fn from_attributes<'a>(attrs: impl IntoIterator<Item = &'a syn::Attribute>) -> Result<Self>
177+
where
178+
Self: AttributeIdent,
179+
{
166180
attrs
167181
.into_iter()
168182
.filter_map(|attr| {
169183
attr.path
170-
.is_ident(Self::IDENT.expect(r#"To use `from_attributes` you need to pass the attribute name while deriving with `#[attribute(ident="some_ident")]"#))
184+
.is_ident(Self::ATTRIBUTE_IDENT)
171185
.then(|| attr.parse_args::<Self::Parser>())
172186
})
173187
.try_fold(Self::Parser::default(), |mut acc, item| {
@@ -201,11 +215,14 @@ pub trait Attribute: Sized {
201215
/// - Invalid input is given for a parameter
202216
/// - A non aggregating parameter is specified multiple times
203217
/// - An attribute called [`IDENT`](Self::IDENT) has invalid syntax (e.g. `#attr(a: "a")`)
204-
fn remove_attributes(attrs: &mut Vec<syn::Attribute>) -> Result<Self> {
218+
fn remove_attributes(attrs: &mut Vec<syn::Attribute>) -> Result<Self>
219+
where
220+
Self: AttributeIdent,
221+
{
205222
let mut parser: Self::Parser = Default::default();
206223
let mut i = 0;
207224
while i < attrs.len() {
208-
if attrs[i].path.is_ident(Self::IDENT.expect(r#"To use `remove_attributes` you need to pass the attribute name while deriving with `#[attribute(ident="some_ident")]"#)) {
225+
if attrs[i].path.is_ident(Self::ATTRIBUTE_IDENT) {
209226
parser.try_extend_one(attrs.remove(i).parse_args()?)?;
210227
} else {
211228
i += 1;

0 commit comments

Comments
 (0)