2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2011-06-28 17:25:20 -05:00
|
|
|
// Functions dealing with attributes and meta_items
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
use ast;
|
2013-01-30 11:56:33 -06:00
|
|
|
use codemap::{spanned, dummy_spanned};
|
2012-12-23 16:41:37 -06:00
|
|
|
use attr;
|
2012-11-15 21:37:29 -06:00
|
|
|
use codemap::BytePos;
|
2012-12-23 16:41:37 -06:00
|
|
|
use diagnostic::span_handler;
|
|
|
|
use parse::comments::{doc_comment_style, strip_doc_comment_decoration};
|
|
|
|
|
2013-06-08 00:12:39 -05:00
|
|
|
use core::iterator::IteratorUtil;
|
2013-04-03 08:28:36 -05:00
|
|
|
use core::hashmap::HashSet;
|
2013-05-24 21:35:29 -05:00
|
|
|
use core::vec;
|
2013-05-18 14:39:17 -05:00
|
|
|
use extra;
|
2011-06-28 13:24:24 -05:00
|
|
|
|
2012-04-15 03:07:47 -05:00
|
|
|
/* Constructors */
|
|
|
|
|
2013-06-12 12:02:55 -05:00
|
|
|
pub fn mk_name_value_item_str(name: @str, value: @str)
|
2013-01-29 15:54:06 -06:00
|
|
|
-> @ast::meta_item {
|
2013-02-14 22:19:27 -06:00
|
|
|
let value_lit = dummy_spanned(ast::lit_str(value));
|
|
|
|
mk_name_value_item(name, value_lit)
|
2012-04-06 00:10:51 -05:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:02:55 -05:00
|
|
|
pub fn mk_name_value_item(name: @str, value: ast::lit)
|
2012-09-20 20:15:39 -05:00
|
|
|
-> @ast::meta_item {
|
2013-02-14 09:34:21 -06:00
|
|
|
@dummy_spanned(ast::meta_name_value(name, value))
|
2011-06-28 13:24:24 -05:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:02:55 -05:00
|
|
|
pub fn mk_list_item(name: @str, items: ~[@ast::meta_item]) ->
|
2012-09-20 20:15:39 -05:00
|
|
|
@ast::meta_item {
|
2013-02-14 09:34:21 -06:00
|
|
|
@dummy_spanned(ast::meta_list(name, items))
|
2012-03-02 15:14:10 -06:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:02:55 -05:00
|
|
|
pub fn mk_word_item(name: @str) -> @ast::meta_item {
|
2013-02-14 09:34:21 -06:00
|
|
|
@dummy_spanned(ast::meta_word(name))
|
2012-03-02 12:05:30 -06:00
|
|
|
}
|
|
|
|
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn mk_attr(item: @ast::meta_item) -> ast::attribute {
|
2013-01-13 18:51:48 -06:00
|
|
|
dummy_spanned(ast::attribute_ { style: ast::attr_inner,
|
2013-02-25 08:19:44 -06:00
|
|
|
value: item,
|
2013-01-13 18:51:48 -06:00
|
|
|
is_sugared_doc: false })
|
2011-06-28 13:24:24 -05:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:02:55 -05:00
|
|
|
pub fn mk_sugared_doc_attr(text: @str,
|
2013-04-17 11:15:08 -05:00
|
|
|
lo: BytePos, hi: BytePos) -> ast::attribute {
|
2013-02-25 08:19:44 -06:00
|
|
|
let style = doc_comment_style(text);
|
2013-06-12 12:02:55 -05:00
|
|
|
let lit = spanned(lo, hi, ast::lit_str(text));
|
2013-01-13 18:51:48 -06:00
|
|
|
let attr = ast::attribute_ {
|
2013-02-25 08:19:44 -06:00
|
|
|
style: style,
|
2013-06-12 12:02:55 -05:00
|
|
|
value: @spanned(lo, hi, ast::meta_name_value(@"doc", lit)),
|
2012-06-30 05:54:54 -05:00
|
|
|
is_sugared_doc: true
|
|
|
|
};
|
2013-01-13 18:51:48 -06:00
|
|
|
spanned(lo, hi, attr)
|
2012-06-30 05:54:54 -05:00
|
|
|
}
|
2012-04-15 03:07:47 -05:00
|
|
|
|
|
|
|
/* Conversion */
|
|
|
|
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn attr_meta(attr: ast::attribute) -> @ast::meta_item {
|
2013-02-25 08:19:44 -06:00
|
|
|
attr.node.value
|
2013-01-29 15:54:06 -06:00
|
|
|
}
|
2012-04-15 03:07:47 -05:00
|
|
|
|
|
|
|
// Get the meta_items from inside a vector of attributes
|
2013-03-10 10:02:16 -05:00
|
|
|
pub fn attr_metas(attrs: &[ast::attribute]) -> ~[@ast::meta_item] {
|
2012-10-18 11:14:11 -05:00
|
|
|
do attrs.map |a| { attr_meta(*a) }
|
2012-01-26 18:23:34 -06:00
|
|
|
}
|
|
|
|
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn desugar_doc_attr(attr: &ast::attribute) -> ast::attribute {
|
2012-06-30 05:54:54 -05:00
|
|
|
if attr.node.is_sugared_doc {
|
2013-02-25 08:19:44 -06:00
|
|
|
let comment = get_meta_item_value_str(attr.node.value).get();
|
2013-06-12 12:02:55 -05:00
|
|
|
let meta = mk_name_value_item_str(@"doc",
|
|
|
|
strip_doc_comment_decoration(comment).to_managed());
|
2013-02-14 22:19:27 -06:00
|
|
|
mk_attr(meta)
|
2012-06-30 05:54:54 -05:00
|
|
|
} else {
|
2012-09-21 20:43:30 -05:00
|
|
|
*attr
|
2012-06-30 05:54:54 -05:00
|
|
|
}
|
|
|
|
}
|
2012-04-15 03:07:47 -05:00
|
|
|
|
|
|
|
/* Accessors */
|
|
|
|
|
2013-06-12 12:02:55 -05:00
|
|
|
pub fn get_attr_name(attr: &ast::attribute) -> @str {
|
2013-02-25 08:19:44 -06:00
|
|
|
get_meta_item_name(attr.node.value)
|
2011-06-28 13:24:24 -05:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:02:55 -05:00
|
|
|
pub fn get_meta_item_name(meta: @ast::meta_item) -> @str {
|
2012-08-06 14:34:08 -05:00
|
|
|
match meta.node {
|
2013-02-14 09:34:21 -06:00
|
|
|
ast::meta_word(n) => n,
|
|
|
|
ast::meta_name_value(n, _) => n,
|
|
|
|
ast::meta_list(n, _) => n,
|
2011-06-28 13:24:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Gets the string value if the meta_item is a meta_name_value variant
|
|
|
|
* containing a string, otherwise none
|
|
|
|
*/
|
2013-06-12 12:02:55 -05:00
|
|
|
pub fn get_meta_item_value_str(meta: @ast::meta_item) -> Option<@str> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match meta.node {
|
2013-02-14 22:19:27 -06:00
|
|
|
ast::meta_name_value(_, v) => {
|
|
|
|
match v.node {
|
|
|
|
ast::lit_str(s) => Some(s),
|
|
|
|
_ => None,
|
|
|
|
}
|
2012-07-18 18:18:02 -05:00
|
|
|
},
|
2013-02-14 22:19:27 -06:00
|
|
|
_ => None
|
2011-07-05 19:01:23 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Gets a list of inner meta items from a list meta_item type
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn get_meta_item_list(meta: @ast::meta_item)
|
|
|
|
-> Option<~[@ast::meta_item]> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match meta.node {
|
2013-02-18 23:25:44 -06:00
|
|
|
ast::meta_list(_, ref l) => Some(/* FIXME (#2543) */ copy *l),
|
|
|
|
_ => None
|
2011-10-29 19:35:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* If the meta item is a nam-value type with a string value then returns
|
|
|
|
* a tuple containing the name and string value, otherwise `none`
|
|
|
|
*/
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn get_name_value_str_pair(item: @ast::meta_item)
|
2013-06-12 12:02:55 -05:00
|
|
|
-> Option<(@str, @str)> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match attr::get_meta_item_value_str(item) {
|
2013-02-14 22:19:27 -06:00
|
|
|
Some(value) => {
|
2012-04-15 03:07:47 -05:00
|
|
|
let name = attr::get_meta_item_name(item);
|
2013-02-14 22:19:27 -06:00
|
|
|
Some((name, value))
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None => None
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
|
|
|
}
|
2011-06-28 14:53:59 -05:00
|
|
|
|
2012-04-15 03:07:47 -05:00
|
|
|
|
|
|
|
/* Searching */
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Search a list of attributes and return only those with a specific name
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn find_attrs_by_name(attrs: &[ast::attribute], name: &str) ->
|
2012-06-29 18:26:56 -05:00
|
|
|
~[ast::attribute] {
|
2013-02-11 10:34:00 -06:00
|
|
|
do vec::filter_mapped(attrs) |a| {
|
2013-06-12 12:02:55 -05:00
|
|
|
if name == get_attr_name(a) {
|
2013-02-11 10:34:00 -06:00
|
|
|
Some(*a)
|
2013-01-05 21:33:37 -06:00
|
|
|
} else {
|
2013-02-11 10:34:00 -06:00
|
|
|
None
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
2013-02-11 10:34:00 -06:00
|
|
|
}
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
|
|
|
|
2012-12-11 14:43:33 -06:00
|
|
|
/// Search a list of meta items and return only those with a specific name
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn find_meta_items_by_name(metas: &[@ast::meta_item], name: &str) ->
|
2012-09-20 20:15:39 -05:00
|
|
|
~[@ast::meta_item] {
|
2013-01-11 17:07:48 -06:00
|
|
|
let mut rs = ~[];
|
|
|
|
for metas.each |mi| {
|
2013-06-12 12:02:55 -05:00
|
|
|
if name == get_meta_item_name(*mi) {
|
2013-01-11 17:07:48 -06:00
|
|
|
rs.push(*mi)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rs
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Returns true if a list of meta items contains another meta item. The
|
|
|
|
* comparison is performed structurally.
|
|
|
|
*/
|
2013-01-10 12:59:58 -06:00
|
|
|
pub fn contains(haystack: &[@ast::meta_item],
|
|
|
|
needle: @ast::meta_item) -> bool {
|
2012-06-30 18:19:07 -05:00
|
|
|
for haystack.each |item| {
|
2012-09-20 20:15:39 -05:00
|
|
|
if eq(*item, needle) { return true; }
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return false;
|
2011-06-28 14:53:59 -05:00
|
|
|
}
|
|
|
|
|
2012-09-20 20:15:39 -05:00
|
|
|
fn eq(a: @ast::meta_item, b: @ast::meta_item) -> bool {
|
2013-02-18 00:20:36 -06:00
|
|
|
match a.node {
|
|
|
|
ast::meta_word(ref na) => match b.node {
|
2012-12-04 12:50:00 -06:00
|
|
|
ast::meta_word(ref nb) => (*na) == (*nb),
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => false
|
2013-02-18 00:20:36 -06:00
|
|
|
},
|
|
|
|
ast::meta_name_value(ref na, va) => match b.node {
|
2012-12-04 23:13:02 -06:00
|
|
|
ast::meta_name_value(ref nb, vb) => {
|
|
|
|
(*na) == (*nb) && va.node == vb.node
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => false
|
2013-02-18 00:20:36 -06:00
|
|
|
},
|
|
|
|
ast::meta_list(ref na, ref misa) => match b.node {
|
|
|
|
ast::meta_list(ref nb, ref misb) => {
|
2013-02-16 08:31:57 -06:00
|
|
|
if na != nb { return false; }
|
2013-02-18 00:20:36 -06:00
|
|
|
for misa.each |mi| {
|
|
|
|
if !misb.contains(mi) { return false; }
|
2013-02-16 08:31:57 -06:00
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
_ => false
|
2011-06-28 14:53:59 -05:00
|
|
|
}
|
2013-02-18 00:20:36 -06:00
|
|
|
}
|
2011-06-28 14:53:59 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn contains_name(metas: &[@ast::meta_item], name: &str) -> bool {
|
2011-07-27 07:19:39 -05:00
|
|
|
let matches = find_meta_items_by_name(metas, name);
|
2013-02-17 10:28:11 -06:00
|
|
|
matches.len() > 0u
|
2011-07-13 20:13:19 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn attrs_contains_name(attrs: &[ast::attribute], name: &str) -> bool {
|
2013-01-24 22:24:57 -06:00
|
|
|
!find_attrs_by_name(attrs, name).is_empty()
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
|
|
|
|
2013-03-10 10:02:16 -05:00
|
|
|
pub fn first_attr_value_str_by_name(attrs: &[ast::attribute], name: &str)
|
2013-06-12 12:02:55 -05:00
|
|
|
-> Option<@str> {
|
2012-07-18 18:18:02 -05:00
|
|
|
|
2012-04-15 03:07:47 -05:00
|
|
|
let mattrs = find_attrs_by_name(attrs, name);
|
2013-02-14 22:19:27 -06:00
|
|
|
if mattrs.len() > 0 {
|
|
|
|
get_meta_item_value_str(attr_meta(mattrs[0]))
|
|
|
|
} else {
|
|
|
|
None
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-17 10:28:11 -06:00
|
|
|
fn last_meta_item_by_name(items: &[@ast::meta_item], name: &str)
|
2012-09-20 20:15:39 -05:00
|
|
|
-> Option<@ast::meta_item> {
|
2012-07-18 18:18:02 -05:00
|
|
|
|
2012-04-15 03:07:47 -05:00
|
|
|
let items = attr::find_meta_items_by_name(items, name);
|
2013-03-05 21:39:18 -06:00
|
|
|
items.last_opt().map(|item| **item)
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
|
|
|
|
2013-02-17 10:28:11 -06:00
|
|
|
pub fn last_meta_item_value_str_by_name(items: &[@ast::meta_item], name: &str)
|
2013-06-12 12:02:55 -05:00
|
|
|
-> Option<@str> {
|
2012-07-18 18:18:02 -05:00
|
|
|
|
2012-08-06 14:34:08 -05:00
|
|
|
match last_meta_item_by_name(items, name) {
|
2013-02-14 22:19:27 -06:00
|
|
|
Some(item) => {
|
|
|
|
match attr::get_meta_item_value_str(item) {
|
|
|
|
Some(value) => Some(value),
|
|
|
|
None => None
|
|
|
|
}
|
|
|
|
},
|
2012-08-20 14:23:37 -05:00
|
|
|
None => None
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 22:19:27 -06:00
|
|
|
pub fn last_meta_item_list_by_name(items: ~[@ast::meta_item], name: &str)
|
2012-09-20 20:15:39 -05:00
|
|
|
-> Option<~[@ast::meta_item]> {
|
2012-07-18 18:18:02 -05:00
|
|
|
|
2012-08-06 14:34:08 -05:00
|
|
|
match last_meta_item_by_name(items, name) {
|
2012-09-20 20:15:39 -05:00
|
|
|
Some(item) => attr::get_meta_item_list(item),
|
2012-08-20 14:23:37 -05:00
|
|
|
None => None
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Higher-level applications */
|
|
|
|
|
2013-02-18 00:20:36 -06:00
|
|
|
pub fn sort_meta_items(items: &[@ast::meta_item]) -> ~[@ast::meta_item] {
|
2011-06-28 17:46:09 -05:00
|
|
|
// This is sort of stupid here, converting to a vec of mutables and back
|
2013-06-10 20:49:51 -05:00
|
|
|
let mut v = items.to_owned();
|
2013-05-18 14:39:17 -05:00
|
|
|
do extra::sort::quick_sort(v) |ma, mb| {
|
2013-02-14 22:19:27 -06:00
|
|
|
get_meta_item_name(*ma) <= get_meta_item_name(*mb)
|
|
|
|
}
|
2013-02-16 08:31:57 -06:00
|
|
|
|
|
|
|
// There doesn't seem to be a more optimal way to do this
|
2013-02-18 00:20:36 -06:00
|
|
|
do v.map |m| {
|
2013-02-16 08:31:57 -06:00
|
|
|
match m.node {
|
2013-02-18 00:20:36 -06:00
|
|
|
ast::meta_list(n, ref mis) => {
|
|
|
|
@spanned {
|
|
|
|
node: ast::meta_list(n, sort_meta_items(*mis)),
|
|
|
|
.. /*bad*/ copy **m
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => /*bad*/ copy *m
|
2013-02-16 08:31:57 -06:00
|
|
|
}
|
|
|
|
}
|
2011-06-28 17:46:09 -05:00
|
|
|
}
|
|
|
|
|
2013-02-14 22:19:27 -06:00
|
|
|
pub fn remove_meta_items_by_name(items: ~[@ast::meta_item], name: &str) ->
|
2012-09-20 20:15:39 -05:00
|
|
|
~[@ast::meta_item] {
|
2011-06-29 16:17:23 -05:00
|
|
|
|
2013-01-31 19:12:29 -06:00
|
|
|
return vec::filter_mapped(items, |item| {
|
2013-06-12 12:02:55 -05:00
|
|
|
if name != get_meta_item_name(*item) {
|
2013-02-14 22:19:27 -06:00
|
|
|
Some(*item)
|
2012-06-07 22:12:05 -05:00
|
|
|
} else {
|
2013-02-14 22:19:27 -06:00
|
|
|
None
|
2012-06-07 22:12:05 -05:00
|
|
|
}
|
|
|
|
});
|
2011-06-29 16:17:23 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
2012-08-22 18:43:23 -05:00
|
|
|
* From a list of crate attributes get only the meta_items that affect crate
|
2012-07-04 16:53:12 -05:00
|
|
|
* linkage
|
|
|
|
*/
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn find_linkage_metas(attrs: &[ast::attribute]) -> ~[@ast::meta_item] {
|
2013-05-19 00:07:44 -05:00
|
|
|
do find_attrs_by_name(attrs, "link").flat_map |attr| {
|
2012-08-22 18:43:23 -05:00
|
|
|
match attr.node.value.node {
|
2013-02-24 18:56:49 -06:00
|
|
|
ast::meta_list(_, ref items) => /* FIXME (#2543) */ copy *items,
|
2012-08-22 18:43:23 -05:00
|
|
|
_ => ~[]
|
2011-07-05 13:46:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-26 07:04:54 -05:00
|
|
|
#[deriving(Eq)]
|
2013-01-29 15:54:06 -06:00
|
|
|
pub enum inline_attr {
|
2012-04-15 03:07:47 -05:00
|
|
|
ia_none,
|
|
|
|
ia_hint,
|
2012-07-25 19:29:34 -05:00
|
|
|
ia_always,
|
|
|
|
ia_never,
|
2012-01-16 23:12:08 -06:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// True if something like #[inline] is found in the list of attrs.
|
2013-01-29 15:54:06 -06:00
|
|
|
pub fn find_inline_attr(attrs: &[ast::attribute]) -> inline_attr {
|
2012-07-05 17:58:25 -05:00
|
|
|
// FIXME (#2809)---validate the usage of #[inline] and #[inline(always)]
|
2013-06-08 00:12:39 -05:00
|
|
|
do attrs.iter().fold(ia_none) |ia,attr| {
|
2012-08-06 14:34:08 -05:00
|
|
|
match attr.node.value.node {
|
2013-06-12 12:02:55 -05:00
|
|
|
ast::meta_word(s) if "inline" == s => ia_hint,
|
|
|
|
ast::meta_list(s, ref items) if "inline" == s => {
|
2013-05-19 00:07:44 -05:00
|
|
|
if !find_meta_items_by_name(*items, "always").is_empty() {
|
2012-04-15 03:07:47 -05:00
|
|
|
ia_always
|
2013-05-19 00:07:44 -05:00
|
|
|
} else if !find_meta_items_by_name(*items, "never").is_empty() {
|
2012-07-25 19:29:34 -05:00
|
|
|
ia_never
|
2012-04-15 03:07:47 -05:00
|
|
|
} else {
|
|
|
|
ia_hint
|
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => ia
|
2012-01-16 23:12:08 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-12 15:00:50 -05:00
|
|
|
pub fn require_unique_names(diagnostic: @span_handler,
|
2013-01-29 15:54:06 -06:00
|
|
|
metas: &[@ast::meta_item]) {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut set = HashSet::new();
|
2012-06-30 18:19:07 -05:00
|
|
|
for metas.each |meta| {
|
2012-09-20 20:15:39 -05:00
|
|
|
let name = get_meta_item_name(*meta);
|
2012-06-07 22:12:05 -05:00
|
|
|
|
2012-06-14 20:46:33 -05:00
|
|
|
// FIXME: How do I silence the warnings? --pcw (#2619)
|
2013-02-14 22:19:27 -06:00
|
|
|
if !set.insert(name) {
|
2012-04-15 03:07:47 -05:00
|
|
|
diagnostic.span_fatal(meta.span,
|
2013-06-12 12:02:55 -05:00
|
|
|
fmt!("duplicate meta item `%s`", name));
|
2012-04-15 03:07:47 -05:00
|
|
|
}
|
2012-01-16 23:12:08 -06:00
|
|
|
}
|
|
|
|
}
|