pub struct Attribute {
pub pound_token: Pound,
pub style: AttrStyle,
pub bracket_token: Bracket,
pub meta: Meta,
}
Expand description
An attribute, like #[repr(transparent)]
.
Syntax
Rust has six types of attributes.
-
Outer attributes like
#[repr(transparent)]
. These appear outside or in front of the item they describe. -
Inner attributes like
#![feature(proc_macro)]
. These appear inside of the item they describe, usually a module. -
Outer one-line doc comments like
/// Example
. -
Inner one-line doc comments like
//! Please file an issue
. -
Outer documentation blocks
/** Example */
. -
Inner documentation blocks
/*! Please file an issue */
.
The style
field of type AttrStyle
distinguishes whether an attribute
is outer or inner.
Every attribute has a path
that indicates the intended interpretation
of the rest of the attribute’s contents. The path and the optional
additional contents are represented together in the meta
field of the
attribute in three possible varieties:
-
Meta::Path — attributes whose information content conveys just a path, for example the
#[test]
attribute. -
Meta::List — attributes that carry arbitrary tokens after the path, surrounded by a delimiter (parenthesis, bracket, or brace). For example
#[derive(Copy)]
or#[precondition(x < 5)]
. -
Meta::NameValue — attributes with an
=
sign after the path, followed by a Rust expression. For example#[path = "sys/windows.rs"]
.
All doc comments are represented in the NameValue style with a path of
“doc”, as this is how they are processed by the compiler and by
macro_rules!
macros.
#[derive(Copy, Clone)]
~~~~~~Path
^^^^^^^^^^^^^^^^^^^Meta::List
#[path = "sys/windows.rs"]
~~~~Path
^^^^^^^^^^^^^^^^^^^^^^^Meta::NameValue
#[test]
^^^^Meta::Path
Parsing from tokens to Attribute
This type does not implement the Parse
trait and thus cannot be
parsed directly by ParseStream::parse
. Instead use
ParseStream::call
with one of the two parser functions
[Attribute::parse_outer
] or [Attribute::parse_inner
] depending on
which you intend to parse.
use syn::{Attribute, Ident, Result, Token};
use syn::parse::{Parse, ParseStream};
// Parses a unit struct with attributes.
//
// #[path = "s.tmpl"]
// struct S;
struct UnitStruct {
attrs: Vec<Attribute>,
struct_token: Token![struct],
name: Ident,
semi_token: Token![;],
}
impl Parse for UnitStruct {
fn parse(input: ParseStream) -> Result<Self> {
Ok(UnitStruct {
attrs: input.call(Attribute::parse_outer)?,
struct_token: input.parse()?,
name: input.parse()?,
semi_token: input.parse()?,
})
}
}
Parsing from Attribute to structured arguments
The grammar of attributes in Rust is very flexible, which makes the
syntax tree not that useful on its own. In particular, arguments of the
Meta::List
variety of attribute are held in an arbitrary tokens: TokenStream
. Macros are expected to check the path
of the attribute,
decide whether they recognize it, and then parse the remaining tokens
according to whatever grammar they wish to require for that kind of
attribute. Use parse_args()
to parse those tokens into the expected
data structure.
Doc comments
The compiler transforms doc comments, such as /// comment
and /*! comment */
, into attributes before macros are expanded. Each comment is
expanded into an attribute of the form #[doc = r"comment"]
.
As an example, the following mod
items are expanded identically:
let doc: ItemMod = parse_quote! {
/// Single line doc comments
/// We write so many!
/**
* Multi-line comments...
* May span many lines
*/
mod example {
//! Of course, they can be inner too
/*! And fit in a single line */
}
};
let attr: ItemMod = parse_quote! {
#[doc = r" Single line doc comments"]
#[doc = r" We write so many!"]
#[doc = r"
* Multi-line comments...
* May span many lines
"]
mod example {
#![doc = r" Of course, they can be inner too"]
#![doc = r" And fit in a single line "]
}
};
assert_eq!(doc, attr);
Fields§
§pound_token: Pound
§style: AttrStyle
§bracket_token: Bracket
§meta: Meta