Expand description
Basically clap for attribute macros:
use attribute_derive::FromAttr;
#[derive(FromAttr)]
#[attribute(ident = attr_name)]
// overriding the builtin error messages
#[attribute(error(missing_field = "`{field}` was not specified"))]
struct MyAttribute {
// Positional values need to be specified before any named ones
#[attribute(positional)]
positional: u8,
// Options are optional by default (will be set to None if not specified)
optional: Option<String>,
required: String,
// Any type implementing default can be flagged as default
// This will be set to Vec::default() when not specified
#[attribute(optional)]
list: Vec<syn::Type>,
// Booleans can be used without assigning a value, i.e., as a flag.
// If omitted they are set to false
some_flag: bool,
}
Will be able to parse an attribute like this:
#[attr_name(5, optional="some", required = r#"string"#, some_flag, list = [Option, ()])]
// or
#[attr_name(5, required = "string", list(Option, ()))]
Any type that for AttributeNamed
or AttributePositional
are
implemented respectively are supported. These should be the general types
that syn
supports like LitStr
or Type
or that
have a direct equivalent in those like String
, char
or f32
. A
special treatment have Vecs
which are parsed as either name = [a, b, c]
or name(a, b, c)
and Options
that will be None
if
not specified and Some
when the value is specified via the attribute. It
is not specified via Some(value)
but as just value
. Bools
are
used for flags, i.e., without a value. Most should just behave as expected,
see parsing
for details.
Tuple structs can derive FromAttr
as well, but all fields will be
positional. Tuples with a single field
(new types)
will copy the behavior of the contained field, e.g. for bool
:
use syn::{Attribute, parse_quote};
use attribute_derive::FromAttr;
#[derive(FromAttr, PartialEq, Debug)]
#[attribute(ident = flag)]
struct Flag(bool);
let attr: Attribute = parse_quote!(#[flag]);
assert_eq!(Flag::from_attribute(attr).unwrap(), Flag(true));
let attr: Attribute = parse_quote!(#[flag = true]);
assert_eq!(Flag::from_attribute(attr).unwrap(), Flag(true));
let attr: Attribute = parse_quote!(#[flag(false)]);
assert_eq!(Flag::from_attribute(attr).unwrap(), Flag(false));
§Attributes
The parsing of attributes can be modified with the following parameters via
the #[attribute(<params>)]
attribute. All of them are optional. Error
messages are formatted using interpolator, and only support display and
lists i
formatting. See interpolator docs for details.
§Struct
-
ident = <ident>
The attribute ident. Improves error messages and enables thefrom_attributes
andremove_attributes
functions. -
aliases = [<alias>, ...]
Aliases for the attribute ident. -
error = "<error message>"
Overrides default error message. -
error(
unknown_field = "supported fields are {expected_fields:i..-1(`{}`)(, )} and `{expected_fields:i-1}`",
Custom error message printed if an unknown property is specified and attribute has more than one field. Placeholders:{expected_fields:i}
.unknown_field_single = "expected supported field `{expected_field}`",
Custom error message printed if an unknown property is specified, and attribute only has a single field. Placeholders:{expected_field}
.unknown_field_empty = "expected empty attribute",
Custom error message printed if a property is specified, and attribute has no fields.duplicate_field = "`{field}` is specified multiple times",
Custom error message printed if a property is specified multiple times. Placeholders:{field}
.missing_field = "required `{field}` is not specified",
Custom error message printed if a required property is not specified. Placeholders:{field}
.field_help = "try `#[{attribute}({field}={example})]`",
Additional help message printed if a required property is not specified or has an error. Placeholders:{attribute}
,{field}
and{example}
.conflict = "`{first}` conflicts with mutually exclusive `{second}`"
Custom error message printed when conflicting properties are specified. Placeholders:{first}
and{second}
.
)
§Fields
optional
If field is not specified, the default value is used instead.default = <default expr>
provides a default to be used instead ofDefault::default()
. Enablesoptional
.conflicts(<field>, ...)
Conflicting fieldsexample = "<example>"
§Parse methods
There are multiple ways of parsing a struct deriving FromAttr
.
For helper attributes there is:
FromAttr::from_attributes
which takes in anIntoIterator<Item = &'a syn::Attribute
(e.g. a&Vec<syn::Attribute>
). Most useful for derive macros.FromAttr::remove_attributes
which takes a&mut Vec<syn::Attribute>
and does not only parse the attributes, but also removes those matching. Useful for helper attributes for attribute macros, where the helper attributes need to be removed.
For parsing a single TokenStream
e.g. for parsing the proc macro input
there are two ways:
FromAttr::from_args
taking in aTokenStream
- As
derive(FromAttr)
also derivesParse
so you can use the parse API, e.g. withparse_macro_input!(tokens as Attribute)
.
Re-exports§
pub use utils::FlagOrValue;
pub use from_partial::FromPartial;
Modules§
- Contains utilities for implementing
FromPartial
. - This module defines the traits defining how parsing works.
- Utilities implementing useful patterns for fields inside an attribute.
Macros§
Traits§
- Helper trait providing the path for an attribute.
- The trait you actually derive on your attribute struct.