attr.rs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. #[cfg(feature = "parsing")]
  3. use crate::error::Error;
  4. #[cfg(feature = "parsing")]
  5. use crate::error::Result;
  6. use crate::expr::Expr;
  7. use crate::mac::MacroDelimiter;
  8. #[cfg(feature = "parsing")]
  9. use crate::meta::{self, ParseNestedMeta};
  10. #[cfg(feature = "parsing")]
  11. use crate::parse::{Parse, ParseStream, Parser};
  12. use crate::path::Path;
  13. use crate::token;
  14. use proc_macro2::TokenStream;
  15. #[cfg(feature = "printing")]
  16. use std::iter;
  17. #[cfg(feature = "printing")]
  18. use std::slice;
  19. ast_struct! {
  20. /// An attribute, like `#[repr(transparent)]`.
  21. ///
  22. /// <br>
  23. ///
  24. /// # Syntax
  25. ///
  26. /// Rust has six types of attributes.
  27. ///
  28. /// - Outer attributes like `#[repr(transparent)]`. These appear outside or
  29. /// in front of the item they describe.
  30. ///
  31. /// - Inner attributes like `#![feature(proc_macro)]`. These appear inside
  32. /// of the item they describe, usually a module.
  33. ///
  34. /// - Outer one-line doc comments like `/// Example`.
  35. ///
  36. /// - Inner one-line doc comments like `//! Please file an issue`.
  37. ///
  38. /// - Outer documentation blocks `/** Example */`.
  39. ///
  40. /// - Inner documentation blocks `/*! Please file an issue */`.
  41. ///
  42. /// The `style` field of type `AttrStyle` distinguishes whether an attribute
  43. /// is outer or inner.
  44. ///
  45. /// Every attribute has a `path` that indicates the intended interpretation
  46. /// of the rest of the attribute's contents. The path and the optional
  47. /// additional contents are represented together in the `meta` field of the
  48. /// attribute in three possible varieties:
  49. ///
  50. /// - Meta::Path &mdash; attributes whose information content conveys just a
  51. /// path, for example the `#[test]` attribute.
  52. ///
  53. /// - Meta::List &mdash; attributes that carry arbitrary tokens after the
  54. /// path, surrounded by a delimiter (parenthesis, bracket, or brace). For
  55. /// example `#[derive(Copy)]` or `#[precondition(x < 5)]`.
  56. ///
  57. /// - Meta::NameValue &mdash; attributes with an `=` sign after the path,
  58. /// followed by a Rust expression. For example `#[path =
  59. /// "sys/windows.rs"]`.
  60. ///
  61. /// All doc comments are represented in the NameValue style with a path of
  62. /// "doc", as this is how they are processed by the compiler and by
  63. /// `macro_rules!` macros.
  64. ///
  65. /// ```text
  66. /// #[derive(Copy, Clone)]
  67. /// ~~~~~~Path
  68. /// ^^^^^^^^^^^^^^^^^^^Meta::List
  69. ///
  70. /// #[path = "sys/windows.rs"]
  71. /// ~~~~Path
  72. /// ^^^^^^^^^^^^^^^^^^^^^^^Meta::NameValue
  73. ///
  74. /// #[test]
  75. /// ^^^^Meta::Path
  76. /// ```
  77. ///
  78. /// <br>
  79. ///
  80. /// # Parsing from tokens to Attribute
  81. ///
  82. /// This type does not implement the [`Parse`] trait and thus cannot be
  83. /// parsed directly by [`ParseStream::parse`]. Instead use
  84. /// [`ParseStream::call`] with one of the two parser functions
  85. /// [`Attribute::parse_outer`] or [`Attribute::parse_inner`] depending on
  86. /// which you intend to parse.
  87. ///
  88. /// [`Parse`]: crate::parse::Parse
  89. /// [`ParseStream::parse`]: crate::parse::ParseBuffer::parse
  90. /// [`ParseStream::call`]: crate::parse::ParseBuffer::call
  91. ///
  92. /// ```
  93. /// use syn::{Attribute, Ident, Result, Token};
  94. /// use syn::parse::{Parse, ParseStream};
  95. ///
  96. /// // Parses a unit struct with attributes.
  97. /// //
  98. /// // #[path = "s.tmpl"]
  99. /// // struct S;
  100. /// struct UnitStruct {
  101. /// attrs: Vec<Attribute>,
  102. /// struct_token: Token![struct],
  103. /// name: Ident,
  104. /// semi_token: Token![;],
  105. /// }
  106. ///
  107. /// impl Parse for UnitStruct {
  108. /// fn parse(input: ParseStream) -> Result<Self> {
  109. /// Ok(UnitStruct {
  110. /// attrs: input.call(Attribute::parse_outer)?,
  111. /// struct_token: input.parse()?,
  112. /// name: input.parse()?,
  113. /// semi_token: input.parse()?,
  114. /// })
  115. /// }
  116. /// }
  117. /// ```
  118. ///
  119. /// <p><br></p>
  120. ///
  121. /// # Parsing from Attribute to structured arguments
  122. ///
  123. /// The grammar of attributes in Rust is very flexible, which makes the
  124. /// syntax tree not that useful on its own. In particular, arguments of the
  125. /// `Meta::List` variety of attribute are held in an arbitrary `tokens:
  126. /// TokenStream`. Macros are expected to check the `path` of the attribute,
  127. /// decide whether they recognize it, and then parse the remaining tokens
  128. /// according to whatever grammar they wish to require for that kind of
  129. /// attribute. Use [`parse_args()`] to parse those tokens into the expected
  130. /// data structure.
  131. ///
  132. /// [`parse_args()`]: Attribute::parse_args
  133. ///
  134. /// <p><br></p>
  135. ///
  136. /// # Doc comments
  137. ///
  138. /// The compiler transforms doc comments, such as `/// comment` and `/*!
  139. /// comment */`, into attributes before macros are expanded. Each comment is
  140. /// expanded into an attribute of the form `#[doc = r"comment"]`.
  141. ///
  142. /// As an example, the following `mod` items are expanded identically:
  143. ///
  144. /// ```
  145. /// # use syn::{ItemMod, parse_quote};
  146. /// let doc: ItemMod = parse_quote! {
  147. /// /// Single line doc comments
  148. /// /// We write so many!
  149. /// /**
  150. /// * Multi-line comments...
  151. /// * May span many lines
  152. /// */
  153. /// mod example {
  154. /// //! Of course, they can be inner too
  155. /// /*! And fit in a single line */
  156. /// }
  157. /// };
  158. /// let attr: ItemMod = parse_quote! {
  159. /// #[doc = r" Single line doc comments"]
  160. /// #[doc = r" We write so many!"]
  161. /// #[doc = r"
  162. /// * Multi-line comments...
  163. /// * May span many lines
  164. /// "]
  165. /// mod example {
  166. /// #![doc = r" Of course, they can be inner too"]
  167. /// #![doc = r" And fit in a single line "]
  168. /// }
  169. /// };
  170. /// assert_eq!(doc, attr);
  171. /// ```
  172. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  173. pub struct Attribute {
  174. pub pound_token: Token![#],
  175. pub style: AttrStyle,
  176. pub bracket_token: token::Bracket,
  177. pub meta: Meta,
  178. }
  179. }
  180. impl Attribute {
  181. /// Returns the path that identifies the interpretation of this attribute.
  182. ///
  183. /// For example this would return the `test` in `#[test]`, the `derive` in
  184. /// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`.
  185. pub fn path(&self) -> &Path {
  186. self.meta.path()
  187. }
  188. /// Parse the arguments to the attribute as a syntax tree.
  189. ///
  190. /// This is similar to pulling out the `TokenStream` from `Meta::List` and
  191. /// doing `syn::parse2::<T>(meta_list.tokens)`, except that using
  192. /// `parse_args` the error message has a more useful span when `tokens` is
  193. /// empty.
  194. ///
  195. /// The surrounding delimiters are *not* included in the input to the
  196. /// parser.
  197. ///
  198. /// ```text
  199. /// #[my_attr(value < 5)]
  200. /// ^^^^^^^^^ what gets parsed
  201. /// ```
  202. ///
  203. /// # Example
  204. ///
  205. /// ```
  206. /// use syn::{parse_quote, Attribute, Expr};
  207. ///
  208. /// let attr: Attribute = parse_quote! {
  209. /// #[precondition(value < 5)]
  210. /// };
  211. ///
  212. /// if attr.path().is_ident("precondition") {
  213. /// let precondition: Expr = attr.parse_args()?;
  214. /// // ...
  215. /// }
  216. /// # anyhow::Ok(())
  217. /// ```
  218. #[cfg(feature = "parsing")]
  219. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  220. pub fn parse_args<T: Parse>(&self) -> Result<T> {
  221. self.parse_args_with(T::parse)
  222. }
  223. /// Parse the arguments to the attribute using the given parser.
  224. ///
  225. /// # Example
  226. ///
  227. /// ```
  228. /// use syn::{parse_quote, Attribute};
  229. ///
  230. /// let attr: Attribute = parse_quote! {
  231. /// #[inception { #[brrrrrrraaaaawwwwrwrrrmrmrmmrmrmmmmm] }]
  232. /// };
  233. ///
  234. /// let bwom = attr.parse_args_with(Attribute::parse_outer)?;
  235. ///
  236. /// // Attribute does not have a Parse impl, so we couldn't directly do:
  237. /// // let bwom: Attribute = attr.parse_args()?;
  238. /// # anyhow::Ok(())
  239. /// ```
  240. #[cfg(feature = "parsing")]
  241. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  242. pub fn parse_args_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
  243. match &self.meta {
  244. Meta::Path(path) => Err(crate::error::new2(
  245. path.segments.first().unwrap().ident.span(),
  246. path.segments.last().unwrap().ident.span(),
  247. format!(
  248. "expected attribute arguments in parentheses: {}[{}(...)]",
  249. parsing::DisplayAttrStyle(&self.style),
  250. parsing::DisplayPath(path),
  251. ),
  252. )),
  253. Meta::NameValue(meta) => Err(Error::new(
  254. meta.eq_token.span,
  255. format_args!(
  256. "expected parentheses: {}[{}(...)]",
  257. parsing::DisplayAttrStyle(&self.style),
  258. parsing::DisplayPath(&meta.path),
  259. ),
  260. )),
  261. Meta::List(meta) => meta.parse_args_with(parser),
  262. }
  263. }
  264. /// Parse the arguments to the attribute, expecting it to follow the
  265. /// conventional structure used by most of Rust's built-in attributes.
  266. ///
  267. /// The [*Meta Item Attribute Syntax*][syntax] section in the Rust reference
  268. /// explains the convention in more detail. Not all attributes follow this
  269. /// convention, so [`parse_args()`][Self::parse_args] is available if you
  270. /// need to parse arbitrarily goofy attribute syntax.
  271. ///
  272. /// [syntax]: https://doc.rust-lang.org/reference/attributes.html#meta-item-attribute-syntax
  273. ///
  274. /// # Example
  275. ///
  276. /// We'll parse a struct, and then parse some of Rust's `#[repr]` attribute
  277. /// syntax.
  278. ///
  279. /// ```
  280. /// use syn::{parenthesized, parse_quote, token, ItemStruct, LitInt};
  281. ///
  282. /// let input: ItemStruct = parse_quote! {
  283. /// #[repr(C, align(4))]
  284. /// pub struct MyStruct(u16, u32);
  285. /// };
  286. ///
  287. /// let mut repr_c = false;
  288. /// let mut repr_transparent = false;
  289. /// let mut repr_align = None::<usize>;
  290. /// let mut repr_packed = None::<usize>;
  291. /// for attr in &input.attrs {
  292. /// if attr.path().is_ident("repr") {
  293. /// attr.parse_nested_meta(|meta| {
  294. /// // #[repr(C)]
  295. /// if meta.path.is_ident("C") {
  296. /// repr_c = true;
  297. /// return Ok(());
  298. /// }
  299. ///
  300. /// // #[repr(transparent)]
  301. /// if meta.path.is_ident("transparent") {
  302. /// repr_transparent = true;
  303. /// return Ok(());
  304. /// }
  305. ///
  306. /// // #[repr(align(N))]
  307. /// if meta.path.is_ident("align") {
  308. /// let content;
  309. /// parenthesized!(content in meta.input);
  310. /// let lit: LitInt = content.parse()?;
  311. /// let n: usize = lit.base10_parse()?;
  312. /// repr_align = Some(n);
  313. /// return Ok(());
  314. /// }
  315. ///
  316. /// // #[repr(packed)] or #[repr(packed(N))], omitted N means 1
  317. /// if meta.path.is_ident("packed") {
  318. /// if meta.input.peek(token::Paren) {
  319. /// let content;
  320. /// parenthesized!(content in meta.input);
  321. /// let lit: LitInt = content.parse()?;
  322. /// let n: usize = lit.base10_parse()?;
  323. /// repr_packed = Some(n);
  324. /// } else {
  325. /// repr_packed = Some(1);
  326. /// }
  327. /// return Ok(());
  328. /// }
  329. ///
  330. /// Err(meta.error("unrecognized repr"))
  331. /// })?;
  332. /// }
  333. /// }
  334. /// # anyhow::Ok(())
  335. /// ```
  336. ///
  337. /// # Alternatives
  338. ///
  339. /// In some cases, for attributes which have nested layers of structured
  340. /// content, the following less flexible approach might be more convenient:
  341. ///
  342. /// ```
  343. /// # use syn::{parse_quote, ItemStruct};
  344. /// #
  345. /// # let input: ItemStruct = parse_quote! {
  346. /// # #[repr(C, align(4))]
  347. /// # pub struct MyStruct(u16, u32);
  348. /// # };
  349. /// #
  350. /// use syn::punctuated::Punctuated;
  351. /// use syn::{parenthesized, token, Error, LitInt, Meta, Token};
  352. ///
  353. /// let mut repr_c = false;
  354. /// let mut repr_transparent = false;
  355. /// let mut repr_align = None::<usize>;
  356. /// let mut repr_packed = None::<usize>;
  357. /// for attr in &input.attrs {
  358. /// if attr.path().is_ident("repr") {
  359. /// let nested = attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
  360. /// for meta in nested {
  361. /// match meta {
  362. /// // #[repr(C)]
  363. /// Meta::Path(path) if path.is_ident("C") => {
  364. /// repr_c = true;
  365. /// }
  366. ///
  367. /// // #[repr(align(N))]
  368. /// Meta::List(meta) if meta.path.is_ident("align") => {
  369. /// let lit: LitInt = meta.parse_args()?;
  370. /// let n: usize = lit.base10_parse()?;
  371. /// repr_align = Some(n);
  372. /// }
  373. ///
  374. /// /* ... */
  375. ///
  376. /// _ => {
  377. /// return Err(Error::new_spanned(meta, "unrecognized repr"));
  378. /// }
  379. /// }
  380. /// }
  381. /// }
  382. /// }
  383. /// # Ok(())
  384. /// ```
  385. #[cfg(feature = "parsing")]
  386. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  387. pub fn parse_nested_meta(
  388. &self,
  389. logic: impl FnMut(ParseNestedMeta) -> Result<()>,
  390. ) -> Result<()> {
  391. self.parse_args_with(meta::parser(logic))
  392. }
  393. /// Parses zero or more outer attributes from the stream.
  394. ///
  395. /// # Example
  396. ///
  397. /// See
  398. /// [*Parsing from tokens to Attribute*](#parsing-from-tokens-to-attribute).
  399. #[cfg(feature = "parsing")]
  400. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  401. pub fn parse_outer(input: ParseStream) -> Result<Vec<Self>> {
  402. let mut attrs = Vec::new();
  403. while input.peek(Token![#]) {
  404. attrs.push(input.call(parsing::single_parse_outer)?);
  405. }
  406. Ok(attrs)
  407. }
  408. /// Parses zero or more inner attributes from the stream.
  409. ///
  410. /// # Example
  411. ///
  412. /// See
  413. /// [*Parsing from tokens to Attribute*](#parsing-from-tokens-to-attribute).
  414. #[cfg(feature = "parsing")]
  415. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  416. pub fn parse_inner(input: ParseStream) -> Result<Vec<Self>> {
  417. let mut attrs = Vec::new();
  418. parsing::parse_inner(input, &mut attrs)?;
  419. Ok(attrs)
  420. }
  421. }
  422. ast_enum! {
  423. /// Distinguishes between attributes that decorate an item and attributes
  424. /// that are contained within an item.
  425. ///
  426. /// # Outer attributes
  427. ///
  428. /// - `#[repr(transparent)]`
  429. /// - `/// # Example`
  430. /// - `/** Please file an issue */`
  431. ///
  432. /// # Inner attributes
  433. ///
  434. /// - `#![feature(proc_macro)]`
  435. /// - `//! # Example`
  436. /// - `/*! Please file an issue */`
  437. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  438. pub enum AttrStyle {
  439. Outer,
  440. Inner(Token![!]),
  441. }
  442. }
  443. ast_enum! {
  444. /// Content of a compile-time structured attribute.
  445. ///
  446. /// ## Path
  447. ///
  448. /// A meta path is like the `test` in `#[test]`.
  449. ///
  450. /// ## List
  451. ///
  452. /// A meta list is like the `derive(Copy)` in `#[derive(Copy)]`.
  453. ///
  454. /// ## NameValue
  455. ///
  456. /// A name-value meta is like the `path = "..."` in `#[path =
  457. /// "sys/windows.rs"]`.
  458. ///
  459. /// # Syntax tree enum
  460. ///
  461. /// This type is a [syntax tree enum].
  462. ///
  463. /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
  464. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  465. pub enum Meta {
  466. Path(Path),
  467. /// A structured list within an attribute, like `derive(Copy, Clone)`.
  468. List(MetaList),
  469. /// A name-value pair within an attribute, like `feature = "nightly"`.
  470. NameValue(MetaNameValue),
  471. }
  472. }
  473. ast_struct! {
  474. /// A structured list within an attribute, like `derive(Copy, Clone)`.
  475. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  476. pub struct MetaList {
  477. pub path: Path,
  478. pub delimiter: MacroDelimiter,
  479. pub tokens: TokenStream,
  480. }
  481. }
  482. ast_struct! {
  483. /// A name-value pair within an attribute, like `feature = "nightly"`.
  484. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  485. pub struct MetaNameValue {
  486. pub path: Path,
  487. pub eq_token: Token![=],
  488. pub value: Expr,
  489. }
  490. }
  491. impl Meta {
  492. /// Returns the path that begins this structured meta item.
  493. ///
  494. /// For example this would return the `test` in `#[test]`, the `derive` in
  495. /// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`.
  496. pub fn path(&self) -> &Path {
  497. match self {
  498. Meta::Path(path) => path,
  499. Meta::List(meta) => &meta.path,
  500. Meta::NameValue(meta) => &meta.path,
  501. }
  502. }
  503. /// Error if this is a `Meta::List` or `Meta::NameValue`.
  504. #[cfg(feature = "parsing")]
  505. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  506. pub fn require_path_only(&self) -> Result<&Path> {
  507. let error_span = match self {
  508. Meta::Path(path) => return Ok(path),
  509. Meta::List(meta) => meta.delimiter.span().open(),
  510. Meta::NameValue(meta) => meta.eq_token.span,
  511. };
  512. Err(Error::new(error_span, "unexpected token in attribute"))
  513. }
  514. /// Error if this is a `Meta::Path` or `Meta::NameValue`.
  515. #[cfg(feature = "parsing")]
  516. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  517. pub fn require_list(&self) -> Result<&MetaList> {
  518. match self {
  519. Meta::List(meta) => Ok(meta),
  520. Meta::Path(path) => Err(crate::error::new2(
  521. path.segments.first().unwrap().ident.span(),
  522. path.segments.last().unwrap().ident.span(),
  523. format!(
  524. "expected attribute arguments in parentheses: `{}(...)`",
  525. parsing::DisplayPath(path),
  526. ),
  527. )),
  528. Meta::NameValue(meta) => Err(Error::new(meta.eq_token.span, "expected `(`")),
  529. }
  530. }
  531. /// Error if this is a `Meta::Path` or `Meta::List`.
  532. #[cfg(feature = "parsing")]
  533. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  534. pub fn require_name_value(&self) -> Result<&MetaNameValue> {
  535. match self {
  536. Meta::NameValue(meta) => Ok(meta),
  537. Meta::Path(path) => Err(crate::error::new2(
  538. path.segments.first().unwrap().ident.span(),
  539. path.segments.last().unwrap().ident.span(),
  540. format!(
  541. "expected a value for this attribute: `{} = ...`",
  542. parsing::DisplayPath(path),
  543. ),
  544. )),
  545. Meta::List(meta) => Err(Error::new(meta.delimiter.span().open(), "expected `=`")),
  546. }
  547. }
  548. }
  549. impl MetaList {
  550. /// See [`Attribute::parse_args`].
  551. #[cfg(feature = "parsing")]
  552. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  553. pub fn parse_args<T: Parse>(&self) -> Result<T> {
  554. self.parse_args_with(T::parse)
  555. }
  556. /// See [`Attribute::parse_args_with`].
  557. #[cfg(feature = "parsing")]
  558. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  559. pub fn parse_args_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
  560. let scope = self.delimiter.span().close();
  561. crate::parse::parse_scoped(parser, scope, self.tokens.clone())
  562. }
  563. /// See [`Attribute::parse_nested_meta`].
  564. #[cfg(feature = "parsing")]
  565. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  566. pub fn parse_nested_meta(
  567. &self,
  568. logic: impl FnMut(ParseNestedMeta) -> Result<()>,
  569. ) -> Result<()> {
  570. self.parse_args_with(meta::parser(logic))
  571. }
  572. }
  573. #[cfg(feature = "printing")]
  574. pub(crate) trait FilterAttrs<'a> {
  575. type Ret: Iterator<Item = &'a Attribute>;
  576. fn outer(self) -> Self::Ret;
  577. #[cfg(feature = "full")]
  578. fn inner(self) -> Self::Ret;
  579. }
  580. #[cfg(feature = "printing")]
  581. impl<'a> FilterAttrs<'a> for &'a [Attribute] {
  582. type Ret = iter::Filter<slice::Iter<'a, Attribute>, fn(&&Attribute) -> bool>;
  583. fn outer(self) -> Self::Ret {
  584. fn is_outer(attr: &&Attribute) -> bool {
  585. match attr.style {
  586. AttrStyle::Outer => true,
  587. AttrStyle::Inner(_) => false,
  588. }
  589. }
  590. self.iter().filter(is_outer)
  591. }
  592. #[cfg(feature = "full")]
  593. fn inner(self) -> Self::Ret {
  594. fn is_inner(attr: &&Attribute) -> bool {
  595. match attr.style {
  596. AttrStyle::Inner(_) => true,
  597. AttrStyle::Outer => false,
  598. }
  599. }
  600. self.iter().filter(is_inner)
  601. }
  602. }
  603. impl From<Path> for Meta {
  604. fn from(meta: Path) -> Meta {
  605. Meta::Path(meta)
  606. }
  607. }
  608. impl From<MetaList> for Meta {
  609. fn from(meta: MetaList) -> Meta {
  610. Meta::List(meta)
  611. }
  612. }
  613. impl From<MetaNameValue> for Meta {
  614. fn from(meta: MetaNameValue) -> Meta {
  615. Meta::NameValue(meta)
  616. }
  617. }
  618. #[cfg(feature = "parsing")]
  619. pub(crate) mod parsing {
  620. use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue};
  621. use crate::error::Result;
  622. use crate::expr::{Expr, ExprLit};
  623. use crate::lit::Lit;
  624. use crate::parse::discouraged::Speculative as _;
  625. use crate::parse::{Parse, ParseStream};
  626. use crate::path::Path;
  627. use crate::{mac, token};
  628. use proc_macro2::Ident;
  629. use std::fmt::{self, Display};
  630. pub(crate) fn parse_inner(input: ParseStream, attrs: &mut Vec<Attribute>) -> Result<()> {
  631. while input.peek(Token![#]) && input.peek2(Token![!]) {
  632. attrs.push(input.call(single_parse_inner)?);
  633. }
  634. Ok(())
  635. }
  636. pub(crate) fn single_parse_inner(input: ParseStream) -> Result<Attribute> {
  637. let content;
  638. Ok(Attribute {
  639. pound_token: input.parse()?,
  640. style: AttrStyle::Inner(input.parse()?),
  641. bracket_token: bracketed!(content in input),
  642. meta: content.parse()?,
  643. })
  644. }
  645. pub(crate) fn single_parse_outer(input: ParseStream) -> Result<Attribute> {
  646. let content;
  647. Ok(Attribute {
  648. pound_token: input.parse()?,
  649. style: AttrStyle::Outer,
  650. bracket_token: bracketed!(content in input),
  651. meta: content.parse()?,
  652. })
  653. }
  654. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  655. impl Parse for Meta {
  656. fn parse(input: ParseStream) -> Result<Self> {
  657. let path = parse_outermost_meta_path(input)?;
  658. parse_meta_after_path(path, input)
  659. }
  660. }
  661. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  662. impl Parse for MetaList {
  663. fn parse(input: ParseStream) -> Result<Self> {
  664. let path = parse_outermost_meta_path(input)?;
  665. parse_meta_list_after_path(path, input)
  666. }
  667. }
  668. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  669. impl Parse for MetaNameValue {
  670. fn parse(input: ParseStream) -> Result<Self> {
  671. let path = parse_outermost_meta_path(input)?;
  672. parse_meta_name_value_after_path(path, input)
  673. }
  674. }
  675. // Unlike meta::parse_meta_path which accepts arbitrary keywords in the path,
  676. // only the `unsafe` keyword is accepted as an attribute's outermost path.
  677. fn parse_outermost_meta_path(input: ParseStream) -> Result<Path> {
  678. if input.peek(Token![unsafe]) {
  679. let unsafe_token: Token![unsafe] = input.parse()?;
  680. Ok(Path::from(Ident::new("unsafe", unsafe_token.span)))
  681. } else {
  682. Path::parse_mod_style(input)
  683. }
  684. }
  685. pub(crate) fn parse_meta_after_path(path: Path, input: ParseStream) -> Result<Meta> {
  686. if input.peek(token::Paren) || input.peek(token::Bracket) || input.peek(token::Brace) {
  687. parse_meta_list_after_path(path, input).map(Meta::List)
  688. } else if input.peek(Token![=]) {
  689. parse_meta_name_value_after_path(path, input).map(Meta::NameValue)
  690. } else {
  691. Ok(Meta::Path(path))
  692. }
  693. }
  694. fn parse_meta_list_after_path(path: Path, input: ParseStream) -> Result<MetaList> {
  695. let (delimiter, tokens) = mac::parse_delimiter(input)?;
  696. Ok(MetaList {
  697. path,
  698. delimiter,
  699. tokens,
  700. })
  701. }
  702. fn parse_meta_name_value_after_path(path: Path, input: ParseStream) -> Result<MetaNameValue> {
  703. let eq_token: Token![=] = input.parse()?;
  704. let ahead = input.fork();
  705. let lit: Option<Lit> = ahead.parse()?;
  706. let value = if let (Some(lit), true) = (lit, ahead.is_empty()) {
  707. input.advance_to(&ahead);
  708. Expr::Lit(ExprLit {
  709. attrs: Vec::new(),
  710. lit,
  711. })
  712. } else if input.peek(Token![#]) && input.peek2(token::Bracket) {
  713. return Err(input.error("unexpected attribute inside of attribute"));
  714. } else {
  715. input.parse()?
  716. };
  717. Ok(MetaNameValue {
  718. path,
  719. eq_token,
  720. value,
  721. })
  722. }
  723. pub(super) struct DisplayAttrStyle<'a>(pub &'a AttrStyle);
  724. impl<'a> Display for DisplayAttrStyle<'a> {
  725. fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
  726. formatter.write_str(match self.0 {
  727. AttrStyle::Outer => "#",
  728. AttrStyle::Inner(_) => "#!",
  729. })
  730. }
  731. }
  732. pub(super) struct DisplayPath<'a>(pub &'a Path);
  733. impl<'a> Display for DisplayPath<'a> {
  734. fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
  735. for (i, segment) in self.0.segments.iter().enumerate() {
  736. if i > 0 || self.0.leading_colon.is_some() {
  737. formatter.write_str("::")?;
  738. }
  739. write!(formatter, "{}", segment.ident)?;
  740. }
  741. Ok(())
  742. }
  743. }
  744. }
  745. #[cfg(feature = "printing")]
  746. mod printing {
  747. use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue};
  748. use crate::path;
  749. use crate::path::printing::PathStyle;
  750. use proc_macro2::TokenStream;
  751. use quote::ToTokens;
  752. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  753. impl ToTokens for Attribute {
  754. fn to_tokens(&self, tokens: &mut TokenStream) {
  755. self.pound_token.to_tokens(tokens);
  756. if let AttrStyle::Inner(b) = &self.style {
  757. b.to_tokens(tokens);
  758. }
  759. self.bracket_token.surround(tokens, |tokens| {
  760. self.meta.to_tokens(tokens);
  761. });
  762. }
  763. }
  764. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  765. impl ToTokens for Meta {
  766. fn to_tokens(&self, tokens: &mut TokenStream) {
  767. match self {
  768. Meta::Path(path) => path::printing::print_path(tokens, path, PathStyle::Mod),
  769. Meta::List(meta_list) => meta_list.to_tokens(tokens),
  770. Meta::NameValue(meta_name_value) => meta_name_value.to_tokens(tokens),
  771. }
  772. }
  773. }
  774. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  775. impl ToTokens for MetaList {
  776. fn to_tokens(&self, tokens: &mut TokenStream) {
  777. path::printing::print_path(tokens, &self.path, PathStyle::Mod);
  778. self.delimiter.surround(tokens, self.tokens.clone());
  779. }
  780. }
  781. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  782. impl ToTokens for MetaNameValue {
  783. fn to_tokens(&self, tokens: &mut TokenStream) {
  784. path::printing::print_path(tokens, &self.path, PathStyle::Mod);
  785. self.eq_token.to_tokens(tokens);
  786. self.value.to_tokens(tokens);
  787. }
  788. }
  789. }