rustc: Introduce and parse additional meta_item forms
Examples: #[test], #[link(name = "vers")] Issue #487
This commit is contained in:
parent
64513808ca
commit
adc18bb24a
8 changed files with 153 additions and 37 deletions
|
@ -291,7 +291,15 @@ fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
|
|||
str default, bool warn_default) -> str {
|
||||
let vec[@ast::meta_item] v = [];
|
||||
for each (@ast::meta_item mi in crate_export_metas(c)) {
|
||||
if (mi.node.key == k) { v += [mi]; }
|
||||
// FIXME (#487): Support all variants of meta_item
|
||||
alt (mi.node) {
|
||||
case (ast::meta_key_value(?key, ?value)) {
|
||||
if (key == k) { v += [mi]; }
|
||||
}
|
||||
case (_) {
|
||||
sess.unimpl("meta_item variant");
|
||||
}
|
||||
}
|
||||
}
|
||||
alt (vec::len(v)) {
|
||||
case (0u) {
|
||||
|
@ -301,7 +309,16 @@ fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
|
|||
}
|
||||
ret default;
|
||||
}
|
||||
case (1u) { ret v.(0).node.value; }
|
||||
case (1u) {
|
||||
alt (v.(0).node) {
|
||||
case (ast::meta_key_value(_, ?value)) {
|
||||
ret value;
|
||||
}
|
||||
case (_) {
|
||||
sess.unimpl("meta_item variant");
|
||||
}
|
||||
}
|
||||
}
|
||||
case (_) {
|
||||
sess.span_fatal(v.(1).span, #fmt("duplicate meta '%s'", k));
|
||||
}
|
||||
|
@ -312,21 +329,45 @@ fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
|
|||
// This calculates CMH as defined above
|
||||
fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
|
||||
fn lteq(&@ast::meta_item ma, &@ast::meta_item mb) -> bool {
|
||||
ret ma.node.key <= mb.node.key;
|
||||
fn key(&@ast::meta_item m) -> ast::ident {
|
||||
alt (m.node) {
|
||||
case (ast::meta_word(?name)) {
|
||||
name
|
||||
}
|
||||
case (ast::meta_key_value(?key, _)) {
|
||||
key
|
||||
}
|
||||
}
|
||||
}
|
||||
ret key(ma) <= key(mb);
|
||||
}
|
||||
fn len_and_str(&str s) -> str { ret #fmt("%u_%s", str::byte_len(s), s); }
|
||||
let vec[mutable @ast::meta_item] v = [mutable ];
|
||||
for each (@ast::meta_item mi in crate_export_metas(crate)) {
|
||||
if (mi.node.key != "name" && mi.node.key != "vers") {
|
||||
v += [mutable mi];
|
||||
alt (mi.node) {
|
||||
case (ast::meta_key_value(?key, _)) {
|
||||
if (key != "name" && key != "vers") {
|
||||
v += [mutable mi];
|
||||
}
|
||||
}
|
||||
case (_) {
|
||||
v += [mutable mi];
|
||||
}
|
||||
}
|
||||
}
|
||||
sort::quick_sort(lteq, v);
|
||||
sha.reset();
|
||||
for (@ast::meta_item m_ in v) {
|
||||
auto m = m_;
|
||||
sha.input_str(len_and_str(m.node.key));
|
||||
sha.input_str(len_and_str(m.node.value));
|
||||
alt (m.node) {
|
||||
case (ast::meta_key_value(?key, ?value)) {
|
||||
sha.input_str(len_and_str(key));
|
||||
sha.input_str(len_and_str(value));
|
||||
}
|
||||
case (ast::meta_word(?name)) {
|
||||
sha.input_str(len_and_str(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
ret truncated_sha1_result(sha);
|
||||
}
|
||||
|
|
|
@ -97,7 +97,11 @@ type crate_directive = spanned[crate_directive_];
|
|||
|
||||
type meta_item = spanned[meta_item_];
|
||||
|
||||
type meta_item_ = rec(ident key, str value);
|
||||
tag meta_item_ {
|
||||
meta_word(ident);
|
||||
meta_list(ident, vec[@meta_item]);
|
||||
meta_key_value(ident, str);
|
||||
}
|
||||
|
||||
type block = spanned[block_];
|
||||
|
||||
|
|
|
@ -548,19 +548,30 @@ fn metadata_matches(hashmap[str, str] mm, &vec[@ast::meta_item] metas) ->
|
|||
log #fmt("matching %u metadata requirements against %u metadata items",
|
||||
vec::len(metas), mm.size());
|
||||
for (@ast::meta_item mi in metas) {
|
||||
alt (mm.find(mi.node.key)) {
|
||||
case (some(?v)) {
|
||||
if (v == mi.node.value) {
|
||||
log #fmt("matched '%s': '%s'", mi.node.key,
|
||||
mi.node.value);
|
||||
} else {
|
||||
log #fmt("missing '%s': '%s' (got '%s')", mi.node.key,
|
||||
mi.node.value, v);
|
||||
ret false;
|
||||
alt (mi.node) {
|
||||
case (ast::meta_key_value(?key, ?value)) {
|
||||
alt (mm.find(key)) {
|
||||
case (some(?v)) {
|
||||
if (v == value) {
|
||||
log #fmt("matched '%s': '%s'", key,
|
||||
value);
|
||||
} else {
|
||||
log #fmt("missing '%s': '%s' (got '%s')",
|
||||
key,
|
||||
value, v);
|
||||
ret false;
|
||||
}
|
||||
}
|
||||
case (none) {
|
||||
log #fmt("missing '%s': '%s'",
|
||||
key, value);
|
||||
ret false;
|
||||
}
|
||||
}
|
||||
}
|
||||
case (none) {
|
||||
log #fmt("missing '%s': '%s'", mi.node.key, mi.node.value);
|
||||
case (_) {
|
||||
// FIXME (#487): Support all forms of meta_item
|
||||
log_err "unimplemented meta_item variant in metadata_matches";
|
||||
ret false;
|
||||
}
|
||||
}
|
||||
|
@ -574,7 +585,18 @@ fn find_library_crate(&session::session sess, &ast::ident ident,
|
|||
option::t[tup(str, vec[u8])] {
|
||||
let str crate_name = ident;
|
||||
for (@ast::meta_item mi in metas) {
|
||||
if (mi.node.key == "name") { crate_name = mi.node.value; break; }
|
||||
alt (mi.node) {
|
||||
case (ast::meta_key_value(?key, ?value)) {
|
||||
if (key == "name") {
|
||||
crate_name = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case (_) {
|
||||
// FIXME (#487)
|
||||
sess.unimpl("meta_item variant")
|
||||
}
|
||||
}
|
||||
}
|
||||
auto nn = parser::default_native_lib_naming(sess);
|
||||
let str prefix = nn.prefix + crate_name;
|
||||
|
|
|
@ -2113,26 +2113,41 @@ fn parse_inner_attrs(&parser p) -> vec[ast::attribute] {
|
|||
fn parse_meta_item(&parser p) -> @ast::meta_item {
|
||||
auto lo = p.get_lo_pos();
|
||||
auto ident = parse_ident(p);
|
||||
expect(p, token::EQ);
|
||||
alt (p.peek()) {
|
||||
case (token::LIT_STR(?s)) {
|
||||
auto hi = p.get_hi_pos();
|
||||
case (token::EQ) {
|
||||
p.bump();
|
||||
ret @spanned(lo, hi, rec(key=ident, value=p.get_str(s)));
|
||||
alt (p.peek()) {
|
||||
case (token::LIT_STR(?s)) {
|
||||
p.bump();
|
||||
auto value = p.get_str(s);
|
||||
auto hi = p.get_hi_pos();
|
||||
ret @spanned(lo, hi, ast::meta_key_value(ident, value));
|
||||
}
|
||||
case (_) {
|
||||
p.fatal("Metadata items must be string literals");
|
||||
}
|
||||
}
|
||||
}
|
||||
case (token::LPAREN) {
|
||||
auto inner_items = parse_meta_seq(p);
|
||||
auto hi = p.get_hi_pos();
|
||||
ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
|
||||
}
|
||||
case (_) {
|
||||
auto hi = p.get_hi_pos();
|
||||
ret @spanned(lo, hi, ast::meta_word(ident));
|
||||
}
|
||||
case (_) { p.fatal("Metadata items must be string literals"); }
|
||||
}
|
||||
fail;
|
||||
}
|
||||
|
||||
fn parse_meta(&parser p) -> vec[@ast::meta_item] {
|
||||
fn parse_meta_seq(&parser p) -> vec[@ast::meta_item] {
|
||||
ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
|
||||
parse_meta_item, p).node;
|
||||
}
|
||||
|
||||
fn parse_optional_meta(&parser p) -> vec[@ast::meta_item] {
|
||||
alt (p.peek()) {
|
||||
case (token::LPAREN) { ret parse_meta(p); }
|
||||
case (token::LPAREN) { ret parse_meta_seq(p); }
|
||||
case (_) { let vec[@ast::meta_item] v = []; ret v; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -669,13 +669,21 @@ fn write_int(&io::writer writer, &int n) {
|
|||
|
||||
fn encode_meta_items(&ebml::writer ebml_w, &crate crate) {
|
||||
fn encode_meta_item(&ebml::writer ebml_w, &meta_item mi) {
|
||||
// FIXME (#487): Support all forms of meta item
|
||||
ebml::start_tag(ebml_w, tag_meta_item);
|
||||
ebml::start_tag(ebml_w, tag_meta_item_key);
|
||||
ebml_w.writer.write(str::bytes(mi.node.key));
|
||||
ebml::end_tag(ebml_w);
|
||||
ebml::start_tag(ebml_w, tag_meta_item_value);
|
||||
ebml_w.writer.write(str::bytes(mi.node.value));
|
||||
ebml::end_tag(ebml_w);
|
||||
alt (mi.node) {
|
||||
case (meta_key_value(?key, ?value)) {
|
||||
ebml::start_tag(ebml_w, tag_meta_item_key);
|
||||
ebml_w.writer.write(str::bytes(key));
|
||||
ebml::end_tag(ebml_w);
|
||||
ebml::start_tag(ebml_w, tag_meta_item_value);
|
||||
ebml_w.writer.write(str::bytes(value));
|
||||
ebml::end_tag(ebml_w);
|
||||
}
|
||||
case (_) {
|
||||
log_err "unimplemented meta_item type";
|
||||
}
|
||||
}
|
||||
ebml::end_tag(ebml_w);
|
||||
}
|
||||
ebml::start_tag(ebml_w, tag_meta_export);
|
||||
|
|
|
@ -1018,9 +1018,18 @@ fn print_type_params(&ps s, &vec[ast::ty_param] params) {
|
|||
|
||||
fn print_meta_item(&ps s, &@ast::meta_item item) {
|
||||
ibox(s, indent_unit);
|
||||
word_space(s, item.node.key);
|
||||
word_space(s, "=");
|
||||
print_string(s, item.node.value);
|
||||
// FIXME (#487): Print other meta item variants
|
||||
alt (item.node) {
|
||||
case (ast::meta_key_value(?key, ?value)) {
|
||||
word_space(s, key);
|
||||
word_space(s, "=");
|
||||
print_string(s, value);
|
||||
}
|
||||
case (_) {
|
||||
log_err "unimplemented meta_item variant";
|
||||
fail;
|
||||
}
|
||||
}
|
||||
end(s);
|
||||
}
|
||||
|
||||
|
|
6
src/test/compile-fail/attr-bad-meta.rs
Normal file
6
src/test/compile-fail/attr-bad-meta.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
// xfail-stage0
|
||||
// error-pattern:expecting \]
|
||||
|
||||
// asterisk is bogus
|
||||
#[attr*]
|
||||
mod m { }
|
|
@ -173,6 +173,17 @@ mod test_distinguish_syntax_ext {
|
|||
}
|
||||
}
|
||||
|
||||
mod test_other_forms {
|
||||
#[attr]
|
||||
#[attr(word)]
|
||||
#[attr(attr(word))]
|
||||
#[attr(key1 = "val",
|
||||
key2 = "val",
|
||||
attr)]
|
||||
fn f() {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue