about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-06-29 14:17:23 -0700
committerBrian Anderson <banderson@mozilla.com>2011-06-29 14:21:39 -0700
commit29afe1a518dac8bcaae3f2e9e9b246193fb6868d (patch)
treeedd342c44c9111459e086507db773d52502ecd2d
parent308bc31f242d2c1e0e41f5d13a980315b5ce1afb (diff)
downloadrust-29afe1a518dac8bcaae3f2e9e9b246193fb6868d.tar.gz
rust-29afe1a518dac8bcaae3f2e9e9b246193fb6868d.zip
Write metadata for sythesized name/vers items to the crate's link attr
If the crate doesn't specify it's name or version, the defaults need to be
exported in the crate metadata
-rw-r--r--src/comp/metadata/encoder.rs67
-rw-r--r--src/comp/middle/attr.rs17
2 files changed, 83 insertions, 1 deletions
diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs
index 0aefb60a597..2927e77d4b1 100644
--- a/src/comp/metadata/encoder.rs
+++ b/src/comp/metadata/encoder.rs
@@ -13,6 +13,7 @@ import tags::*;
 import middle::trans::crate_ctxt;
 import middle::trans::node_id_type;
 import middle::ty;
+import middle::attr;
 
 export def_to_str;
 export hash_path;
@@ -457,12 +458,76 @@ fn encode_attributes(&ebml::writer ebml_w, &vec[attribute] attrs) {
     ebml::end_tag(ebml_w);
 }
 
+// So there's a special crate attribute called 'link' which defines the metadata
+// that Rust cares about for linking crates. This attribute requires name and
+// value attributes, so if the user didn't provide them we will throw them in
+// anyway with default values.
+fn synthesize_crate_attrs(&@crate_ctxt cx,
+                          &@crate crate) -> vec[attribute] {
+
+    fn synthesize_link_attr(&@crate_ctxt cx,
+                            &vec[@meta_item] items)
+        -> attribute {
+
+        auto bogus_span = rec(lo = 0u, hi = 0u);
+
+        auto name_item_ = meta_name_value("name", cx.link_meta.name);
+        auto name_item = rec(node=name_item_,
+                             span=bogus_span);
+
+        auto vers_item_ = meta_name_value("vers", cx.link_meta.vers);
+        auto vers_item = rec(node=vers_item_,
+                             span=bogus_span);
+
+        auto other_items = {
+            auto tmp = attr::remove_meta_items_by_name(items, "name");
+            attr::remove_meta_items_by_name(tmp, "vers")
+        };
+
+        auto meta_items = [@name_item] + [@vers_item] + other_items;
+
+        auto link_item_ = meta_list("link", meta_items);
+        auto link_item = rec(node=link_item_,
+                             span=bogus_span);
+
+        auto attr_ = rec(style = attr_inner,
+                         value = link_item);
+        auto attr = rec(node=attr_,
+                        span=bogus_span);
+
+        ret attr;
+    }
+
+    let vec[attribute] attrs = [];
+    auto found_link_attr = false;
+    for (attribute attr in crate.node.attrs) {
+        attrs += if (attr::get_attr_name(attr) != "link") {
+            [attr]
+        } else {
+            alt (attr.node.value.node) {
+                case (meta_list(?n, ?l)) {
+                    found_link_attr = true;
+                    [synthesize_link_attr(cx, l)]
+                }
+                case (_) { [attr] }
+            }
+        }
+    }
+
+    if (!found_link_attr) {
+        attrs += [synthesize_link_attr(cx, [])];
+    }
+
+    ret attrs;
+}
+
 fn encode_metadata(&@crate_ctxt cx, &@crate crate) -> str {
     auto string_w = io::string_writer();
     auto buf_w = string_w.get_writer().get_buf_writer();
     auto ebml_w = ebml::create_writer(buf_w);
 
-    encode_attributes(ebml_w, crate.node.attrs);
+    auto crate_attrs = synthesize_crate_attrs(cx, crate);
+    encode_attributes(ebml_w, crate_attrs);
     // Encode and index the paths.
 
     ebml::start_tag(ebml_w, tag_paths);
diff --git a/src/comp/middle/attr.rs b/src/comp/middle/attr.rs
index 1c15e9d8d25..152f81c5b7a 100644
--- a/src/comp/middle/attr.rs
+++ b/src/comp/middle/attr.rs
@@ -10,6 +10,8 @@ export find_attrs_by_name;
 export find_meta_items_by_name;
 export contains;
 export sort_meta_items;
+export remove_meta_items_by_name;
+export get_attr_name;
 
 // From a list of crate attributes get only the meta_items that impact crate
 // linkage
@@ -138,6 +140,21 @@ fn sort_meta_items(&vec[@ast::meta_item] items) -> vec[@ast::meta_item] {
     ret v2;
 }
 
+fn remove_meta_items_by_name(&vec[@ast::meta_item] items,
+                             str name) -> vec[@ast::meta_item] {
+
+    auto filter = bind fn(&@ast::meta_item item,
+                          str name) -> option::t[@ast::meta_item] {
+        if (get_meta_item_name(item) != name) {
+            option::some(item)
+        } else {
+            option::none
+        }
+    } (_, name);
+
+    ret vec::filter_map(filter, items);
+}
+
 //
 // Local Variables:
 // mode: rust