blob: 0c5b24bde5ae93df2c9cda8409462cda9b61cb7f [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
David Tolnayaed77b02016-09-23 20:50:31 -07003/// Doc-comments are promoted to attributes that have `is_sugared_doc` = true
David Tolnayb79ee962016-09-04 09:39:20 -07004#[derive(Debug, Clone, Eq, PartialEq)]
5pub struct Attribute {
6 pub value: MetaItem,
7 pub is_sugared_doc: bool,
8}
9
10/// A compile-time attribute item.
11///
12/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
13#[derive(Debug, Clone, Eq, PartialEq)]
14pub enum MetaItem {
15 /// Word meta item.
16 ///
17 /// E.g. `test` as in `#[test]`
18 Word(Ident),
19 /// List meta item.
20 ///
21 /// E.g. `derive(..)` as in `#[derive(..)]`
22 List(Ident, Vec<MetaItem>),
23 /// Name value meta item.
24 ///
25 /// E.g. `feature = "foo"` as in `#[feature = "foo"]`
David Tolnayf4bbbd92016-09-23 14:41:55 -070026 NameValue(Ident, Lit),
David Tolnayb79ee962016-09-04 09:39:20 -070027}
28
David Tolnay8e661e22016-09-27 00:00:04 -070029impl MetaItem {
30 pub fn name(&self) -> &str {
31 match *self {
32 MetaItem::Word(ref name) => name.as_ref(),
33 MetaItem::List(ref name, _) => name.as_ref(),
34 MetaItem::NameValue(ref name, _) => name.as_ref(),
35 }
36 }
37}
38
David Tolnay86eca752016-09-04 11:26:41 -070039#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -070040pub mod parsing {
41 use super::*;
David Tolnay55337722016-09-11 12:58:56 -070042 use ident::parsing::ident;
David Tolnayf4bbbd92016-09-23 14:41:55 -070043 use lit::{Lit, StrStyle};
44 use lit::parsing::lit;
David Tolnay9d8f1972016-09-04 11:58:48 -070045 use nom::multispace;
David Tolnayb79ee962016-09-04 09:39:20 -070046
David Tolnayb5a7b142016-09-13 22:46:39 -070047 named!(pub attribute -> Attribute, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -070048 do_parse!(
49 punct!("#") >>
50 punct!("[") >>
51 meta_item: meta_item >>
52 punct!("]") >>
53 (Attribute {
54 value: meta_item,
55 is_sugared_doc: false,
56 })
57 )
58 |
59 do_parse!(
60 punct!("///") >>
61 space: multispace >>
David Tolnayb5a7b142016-09-13 22:46:39 -070062 content: take_until!("\n") >>
David Tolnay9d8f1972016-09-04 11:58:48 -070063 (Attribute {
64 value: MetaItem::NameValue(
David Tolnay42f50292016-09-04 13:54:21 -070065 "doc".into(),
David Tolnayf4bbbd92016-09-23 14:41:55 -070066 Lit::Str(
67 format!("///{}{}", space, content),
68 StrStyle::Cooked,
69 ),
David Tolnay9d8f1972016-09-04 11:58:48 -070070 ),
71 is_sugared_doc: true,
72 })
73 )
74 ));
David Tolnayb79ee962016-09-04 09:39:20 -070075
David Tolnayb5a7b142016-09-13 22:46:39 -070076 named!(meta_item -> MetaItem, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -070077 do_parse!(
David Tolnay55337722016-09-11 12:58:56 -070078 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -070079 punct!("(") >>
80 inner: separated_list!(punct!(","), meta_item) >>
81 punct!(")") >>
David Tolnay55337722016-09-11 12:58:56 -070082 (MetaItem::List(id, inner))
David Tolnay9d8f1972016-09-04 11:58:48 -070083 )
84 |
85 do_parse!(
David Tolnayf4bbbd92016-09-23 14:41:55 -070086 name: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -070087 punct!("=") >>
David Tolnayf4bbbd92016-09-23 14:41:55 -070088 value: lit >>
89 (MetaItem::NameValue(name, value))
David Tolnay9d8f1972016-09-04 11:58:48 -070090 )
91 |
David Tolnay55337722016-09-11 12:58:56 -070092 map!(ident, MetaItem::Word)
David Tolnay9d8f1972016-09-04 11:58:48 -070093 ));
94}
David Tolnay87d0b442016-09-04 11:52:12 -070095
96#[cfg(feature = "printing")]
97mod printing {
98 use super::*;
99 use quote::{Tokens, ToTokens};
100
101 impl ToTokens for Attribute {
102 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnayfbef2342016-09-04 14:42:34 -0700103 tokens.append("#");
104 tokens.append("[");
David Tolnay87d0b442016-09-04 11:52:12 -0700105 self.value.to_tokens(tokens);
106 tokens.append("]");
107 }
108 }
109
110 impl ToTokens for MetaItem {
111 fn to_tokens(&self, tokens: &mut Tokens) {
112 match *self {
David Tolnay26469072016-09-04 13:59:48 -0700113 MetaItem::Word(ref ident) => {
114 ident.to_tokens(tokens);
115 }
David Tolnay87d0b442016-09-04 11:52:12 -0700116 MetaItem::List(ref ident, ref inner) => {
David Tolnay26469072016-09-04 13:59:48 -0700117 ident.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700118 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700119 tokens.append_separated(inner, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700120 tokens.append(")");
121 }
122 MetaItem::NameValue(ref name, ref value) => {
David Tolnay26469072016-09-04 13:59:48 -0700123 name.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700124 tokens.append("=");
125 value.to_tokens(tokens);
126 }
127 }
128 }
129 }
130}