blob: 2862baefcb3317014e611b7593c0d9d654f38f80 [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
David Tolnayb79ee962016-09-04 09:39:20 -07003#[derive(Debug, Clone, Eq, PartialEq)]
4pub struct Attribute {
5 pub value: MetaItem,
6 pub is_sugared_doc: bool,
7}
8
9/// A compile-time attribute item.
10///
11/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
12#[derive(Debug, Clone, Eq, PartialEq)]
13pub enum MetaItem {
14 /// Word meta item.
15 ///
16 /// E.g. `test` as in `#[test]`
17 Word(Ident),
18 /// List meta item.
19 ///
20 /// E.g. `derive(..)` as in `#[derive(..)]`
21 List(Ident, Vec<MetaItem>),
22 /// Name value meta item.
23 ///
24 /// E.g. `feature = "foo"` as in `#[feature = "foo"]`
25 NameValue(Ident, String),
26}
27
David Tolnay86eca752016-09-04 11:26:41 -070028#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -070029pub mod parsing {
30 use super::*;
31 use common::parsing::word;
32 use helper::escaped_string;
33 use nom::multispace;
David Tolnayb79ee962016-09-04 09:39:20 -070034
David Tolnay9d8f1972016-09-04 11:58:48 -070035 named!(pub attribute<&str, Attribute>, alt!(
36 do_parse!(
37 punct!("#") >>
38 punct!("[") >>
39 meta_item: meta_item >>
40 punct!("]") >>
41 (Attribute {
42 value: meta_item,
43 is_sugared_doc: false,
44 })
45 )
46 |
47 do_parse!(
48 punct!("///") >>
49 space: multispace >>
50 content: take_until_s!("\n") >>
51 (Attribute {
52 value: MetaItem::NameValue(
David Tolnay42f50292016-09-04 13:54:21 -070053 "doc".into(),
David Tolnay9d8f1972016-09-04 11:58:48 -070054 format!("///{}{}", space, content),
55 ),
56 is_sugared_doc: true,
57 })
58 )
59 ));
David Tolnayb79ee962016-09-04 09:39:20 -070060
David Tolnay9d8f1972016-09-04 11:58:48 -070061 named!(quoted<&str, String>, delimited!(
62 punct!("\""),
63 escaped_string,
64 tag_s!("\"")
65 ));
66
67 named!(meta_item<&str, MetaItem>, alt!(
68 do_parse!(
69 ident: word >>
70 punct!("(") >>
71 inner: separated_list!(punct!(","), meta_item) >>
72 punct!(")") >>
73 (MetaItem::List(ident, inner))
74 )
75 |
76 do_parse!(
77 ident: word >>
78 punct!("=") >>
79 string: quoted >>
80 (MetaItem::NameValue(ident, string))
81 )
82 |
83 map!(word, MetaItem::Word)
84 ));
85}
David Tolnay87d0b442016-09-04 11:52:12 -070086
87#[cfg(feature = "printing")]
88mod printing {
89 use super::*;
90 use quote::{Tokens, ToTokens};
91
92 impl ToTokens for Attribute {
93 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnayfbef2342016-09-04 14:42:34 -070094 tokens.append("#");
95 tokens.append("[");
David Tolnay87d0b442016-09-04 11:52:12 -070096 self.value.to_tokens(tokens);
97 tokens.append("]");
98 }
99 }
100
101 impl ToTokens for MetaItem {
102 fn to_tokens(&self, tokens: &mut Tokens) {
103 match *self {
David Tolnay26469072016-09-04 13:59:48 -0700104 MetaItem::Word(ref ident) => {
105 ident.to_tokens(tokens);
106 }
David Tolnay87d0b442016-09-04 11:52:12 -0700107 MetaItem::List(ref ident, ref inner) => {
David Tolnay26469072016-09-04 13:59:48 -0700108 ident.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700109 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700110 tokens.append_separated(inner, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700111 tokens.append(")");
112 }
113 MetaItem::NameValue(ref name, ref value) => {
David Tolnay26469072016-09-04 13:59:48 -0700114 name.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700115 tokens.append("=");
116 value.to_tokens(tokens);
117 }
118 }
119 }
120 }
121}