fixup! Reinstated name in MetaItem since it's no longer trivial to get it from its parent.
diff --git a/src/attr.rs b/src/attr.rs
index 0edace9..82bc02a 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -25,8 +25,14 @@
impl Attribute {
/// Parses the tokens after the path as a [`MetaItem`](enum.MetaItem.html) if possible.
pub fn meta_item(&self) -> Option<MetaItem> {
+ let name = if self.path.segments.len() == 1 {
+ &self.path.segments[0].ident
+ } else {
+ return None;
+ };
+
if self.tts.is_empty() {
- return Some(MetaItem::Word);
+ return Some(MetaItem::Word(name.clone()));
}
if self.tts.len() == 1 {
@@ -43,7 +49,7 @@
if tts.len() >= 3 {
match (&tts[1], &tts[2]) {
(&TokenTree::Token(Token::Eq), &TokenTree::Token(Token::Literal(ref lit))) => {
- return Some((NestedMetaItem::MetaItem(ident.clone(), MetaItem::NameValue(lit.clone())), &tts[3..]));
+ return Some((NestedMetaItem::MetaItem(MetaItem::NameValue(ident.clone(), lit.clone())), &tts[3..]));
}
_ => {}
@@ -54,7 +60,7 @@
if let TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: ref inner_tts }) = tts[1] {
return match list_of_nested_meta_items_from_tokens(vec![], inner_tts) {
Some(nested_meta_items) => {
- Some((NestedMetaItem::MetaItem(ident.clone(), MetaItem::List(nested_meta_items)), &tts[2..]))
+ Some((NestedMetaItem::MetaItem(MetaItem::List(ident.clone(), nested_meta_items)), &tts[2..]))
}
None => None
@@ -62,7 +68,7 @@
}
}
- Some((NestedMetaItem::MetaItem(ident.clone(), MetaItem::Word), &tts[1..]))
+ Some((NestedMetaItem::MetaItem(MetaItem::Word(ident.clone())), &tts[1..]))
}
_ => None
@@ -93,7 +99,7 @@
}
if let Some(nested_meta_items) = list_of_nested_meta_items_from_tokens(vec![], tts) {
- return Some(MetaItem::List(nested_meta_items));
+ return Some(MetaItem::List(name.clone(), nested_meta_items));
}
}
}
@@ -101,7 +107,7 @@
if self.tts.len() == 2 {
match (&self.tts[0], &self.tts[1]) {
(&TokenTree::Token(Token::Eq), &TokenTree::Token(Token::Literal(ref lit))) => {
- return Some(MetaItem::NameValue(lit.clone()));
+ return Some(MetaItem::NameValue(name.clone(), lit.clone()));
}
_ => {}
@@ -132,17 +138,31 @@
/// Word meta item.
///
/// E.g. `test` as in `#[test]`
- Word,
+ Word(Ident),
/// List meta item.
///
/// E.g. `derive(..)` as in `#[derive(..)]`
- List(Vec<NestedMetaItem>),
+ List(Ident, Vec<NestedMetaItem>),
/// Name-value meta item.
///
/// E.g. `feature = "foo"` as in `#[feature = "foo"]`
- NameValue(Lit),
+ NameValue(Ident, Lit),
+}
+
+impl MetaItem {
+ /// Name of the item.
+ ///
+ /// E.g. `test` as in `#[test]`, `derive` as in `#[derive(..)]`, and
+ /// `feature` as in `#[feature = "foo"]`.
+ pub fn name(&self) -> &str {
+ match *self {
+ MetaItem::Word(ref name) |
+ MetaItem::List(ref name, _) |
+ MetaItem::NameValue(ref name, _) => name.as_ref(),
+ }
+ }
}
/// Possible values inside of compile-time attribute lists.
@@ -152,8 +172,8 @@
pub enum NestedMetaItem {
/// A full `MetaItem`.
///
- /// E.g. `Copy` in `#[derive(Copy)]` would be a `(Ident::from("Copy"), MetaItem::Word)`.
- MetaItem(Ident, MetaItem),
+ /// E.g. `Copy` in `#[derive(Copy)]` would be a `MetaItem::Word(Ident::from("Copy"))`.
+ MetaItem(MetaItem),
/// A Rust literal.
///
@@ -369,13 +389,17 @@
impl ToTokens for MetaItem {
fn to_tokens(&self, tokens: &mut Tokens) {
match *self {
- MetaItem::Word => {}
- MetaItem::List(ref inner) => {
+ MetaItem::Word(ref ident) => {
+ ident.to_tokens(tokens);
+ }
+ MetaItem::List(ref ident, ref inner) => {
+ ident.to_tokens(tokens);
tokens.append("(");
tokens.append_separated(inner, ",");
tokens.append(")");
}
- MetaItem::NameValue(ref value) => {
+ MetaItem::NameValue(ref name, ref value) => {
+ name.to_tokens(tokens);
tokens.append("=");
value.to_tokens(tokens);
}
@@ -386,8 +410,7 @@
impl ToTokens for NestedMetaItem {
fn to_tokens(&self, tokens: &mut Tokens) {
match *self {
- NestedMetaItem::MetaItem(ref ident, ref nested) => {
- ident.to_tokens(tokens);
+ NestedMetaItem::MetaItem(ref nested) => {
nested.to_tokens(tokens);
}
NestedMetaItem::Literal(ref lit) => {
diff --git a/tests/test_macro_input.rs b/tests/test_macro_input.rs
index eca7b33..353562a 100644
--- a/tests/test_macro_input.rs
+++ b/tests/test_macro_input.rs
@@ -34,9 +34,9 @@
path: "derive".into(),
tts: vec![
TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![
- TokenTree::Token(Token::Ident(Ident::from("Debug"))),
+ TokenTree::Token(Token::Ident("Debug".into())),
TokenTree::Token(Token::Comma),
- TokenTree::Token(Token::Ident(Ident::from("Clone"))),
+ TokenTree::Token(Token::Ident("Clone".into())),
]})
],
is_sugared_doc: false,
@@ -75,9 +75,9 @@
assert_eq!(expected, actual);
- let expected_meta_item = MetaItem::List(vec![
- NestedMetaItem::MetaItem(Ident::from("Debug"), MetaItem::Word),
- NestedMetaItem::MetaItem(Ident::from("Clone"), MetaItem::Word),
+ let expected_meta_item = MetaItem::List("derive".into(), vec![
+ NestedMetaItem::MetaItem(MetaItem::Word("Debug".into())),
+ NestedMetaItem::MetaItem(MetaItem::Word("Clone".into())),
]);
assert_eq!(expected_meta_item, actual.attrs[0].meta_item().unwrap());
@@ -204,11 +204,11 @@
assert_eq!(expected, actual);
let expected_meta_items = vec![
- MetaItem::NameValue(Lit::Str(
+ MetaItem::NameValue("doc".into(), Lit::Str(
"/// See the std::result module documentation for details.".into(),
StrStyle::Cooked,
)),
- MetaItem::Word,
+ MetaItem::Word("must_use".into()),
];
let actual_meta_items: Vec<_> = actual.attrs.into_iter().map(|attr| attr.meta_item().unwrap()).collect();
@@ -231,14 +231,14 @@
style: AttrStyle::Outer,
path: Path { global: true, segments: vec!["attr_args".into(), "identity".into()] },
tts: vec![
- TokenTree::Token(Token::Ident(Ident::from("fn"))),
- TokenTree::Token(Token::Ident(Ident::from("main"))),
+ TokenTree::Token(Token::Ident("fn".into())),
+ TokenTree::Token(Token::Ident("main".into())),
TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![] }),
TokenTree::Delimited(Delimited { delim: DelimToken::Brace, tts: vec![
- TokenTree::Token(Token::Ident(Ident::from("assert_eq"))),
+ TokenTree::Token(Token::Ident("assert_eq".into())),
TokenTree::Token(Token::Not),
TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![
- TokenTree::Token(Token::Ident(Ident::from("foo"))),
+ TokenTree::Token(Token::Ident("foo".into())),
TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: vec![] }),
TokenTree::Token(Token::Comma),
TokenTree::Token(Token::Literal(Lit::Str("Hello, world!".into(), StrStyle::Cooked))),
diff --git a/tests/test_meta_item.rs b/tests/test_meta_item.rs
index ceb178c..95efaf3 100644
--- a/tests/test_meta_item.rs
+++ b/tests/test_meta_item.rs
@@ -3,38 +3,48 @@
#[test]
fn test_meta_item_word() {
- run_test("#[foo]", MetaItem::Word)
+ run_test("#[foo]", MetaItem::Word("foo".into()))
}
#[test]
fn test_meta_item_name_value() {
- run_test("#[foo = 5]", MetaItem::NameValue(Lit::Int(5, IntTy::Unsuffixed)))
+ run_test("#[foo = 5]", MetaItem::NameValue("foo".into(),
+ Lit::Int(5, IntTy::Unsuffixed)))
}
#[test]
fn test_meta_item_list_lit() {
- run_test("#[foo(5)]", MetaItem::List(vec![NestedMetaItem::Literal(Lit::Int(5, IntTy::Unsuffixed))]))
+ run_test("#[foo(5)]", MetaItem::List("foo".into(), vec![
+ NestedMetaItem::Literal(Lit::Int(5, IntTy::Unsuffixed)),
+ ]))
}
#[test]
fn test_meta_item_list_word() {
- run_test("#[foo(bar)]", MetaItem::List(vec![NestedMetaItem::MetaItem(Ident::from("bar"), MetaItem::Word)]))
+ run_test("#[foo(bar)]", MetaItem::List("foo".into(), vec![
+ NestedMetaItem::MetaItem(MetaItem::Word("bar".into())),
+ ]))
}
#[test]
fn test_meta_item_list_name_value() {
- run_test("#[foo(bar = 5)]", MetaItem::List(vec![NestedMetaItem::MetaItem(Ident::from("bar"), MetaItem::NameValue(Lit::Int(5, IntTy::Unsuffixed)))]))
+ run_test("#[foo(bar = 5)]", MetaItem::List("foo".into(), vec![
+ NestedMetaItem::MetaItem(MetaItem::NameValue("bar".into(),
+ Lit::Int(5, IntTy::Unsuffixed))),
+ ]))
}
#[test]
fn test_meta_item_multiple() {
- run_test("#[foo(word, name = 5, list(name2 = 6), word2)]", MetaItem::List(vec![
- NestedMetaItem::MetaItem(Ident::from("word"), MetaItem::Word),
- NestedMetaItem::MetaItem(Ident::from("name"), MetaItem::NameValue(Lit::Int(5, IntTy::Unsuffixed))),
- NestedMetaItem::MetaItem(Ident::from("list"), MetaItem::List(vec![
- NestedMetaItem::MetaItem(Ident::from("name2"), MetaItem::NameValue(Lit::Int(6, IntTy::Unsuffixed)))
+ run_test("#[foo(word, name = 5, list(name2 = 6), word2)]", MetaItem::List("foo".into(), vec![
+ NestedMetaItem::MetaItem(MetaItem::Word("word".into())),
+ NestedMetaItem::MetaItem(MetaItem::NameValue("name".into(),
+ Lit::Int(5, IntTy::Unsuffixed))),
+ NestedMetaItem::MetaItem(MetaItem::List("list".into(), vec![
+ NestedMetaItem::MetaItem(MetaItem::NameValue("name2".into(),
+ Lit::Int(6, IntTy::Unsuffixed)))
])),
- NestedMetaItem::MetaItem(Ident::from("word2"), MetaItem::Word),
+ NestedMetaItem::MetaItem(MetaItem::Word("word2".into())),
]))
}