// Searching for information from the cstore
import syntax::ast;
+import syntax::ast_util;
import middle::ty;
import option::{some, none};
import driver::session;
export get_impls_for_mod;
export get_iface_methods;
export get_type;
-export get_item_name;
export get_impl_iface;
fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> str {
decoder::get_type(cdata, def.node, tcx)
}
-fn get_item_name(cstore: cstore::cstore, cnum: int, id: int) -> ast::ident {
- let cdata = cstore::get_crate_data(cstore, cnum).data;
- ret decoder::lookup_item_name(cdata, id);
-}
-
fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id)
-> option::t<ty::t> {
let cstore = tcx.sess.cstore;
import core::{vec, str};
import std::map;
import syntax::ast;
+import util::common::*;
export cstore;
export cnum_map;
export add_use_stmt_cnum;
export get_use_stmt_cnum;
export get_dep_hashes;
+export get_path;
// A map from external crate numbers (as decoded from some crate file) to
// own crate numbers.
type cnum_map = map::hashmap<ast::crate_num, ast::crate_num>;
+// Multiple items may have the same def_id in crate metadata. They may be
+// renamed imports or reexports. This map keeps the "real" module path
+// and def_id.
+type mod_path_map = map::hashmap<ast::def_id, str>;
+
type crate_metadata = @{name: str,
data: @[u8],
cnum_map: cnum_map,
type cstore_private =
@{metas: map::hashmap<ast::crate_num, crate_metadata>,
use_crate_map: use_crate_map,
+ mod_path_map: mod_path_map,
mutable used_crate_files: [str],
mutable used_libraries: [str],
mutable used_link_args: [str]};
fn mk_cstore() -> cstore {
let meta_cache = map::new_int_hash::<crate_metadata>();
let crate_map = map::new_int_hash::<ast::crate_num>();
+ let mod_path_map = new_def_hash();
ret private(@{metas: meta_cache,
use_crate_map: crate_map,
+ mod_path_map: mod_path_map,
mutable used_crate_files: [],
mutable used_libraries: [],
mutable used_link_args: []});
fn set_crate_data(cstore: cstore, cnum: ast::crate_num,
data: crate_metadata) {
p(cstore).metas.insert(cnum, data);
+ vec::iter(decoder::get_crate_module_paths(data.data)) {|dp|
+ let (did, path) = dp;
+ let d = {crate: cnum, node: did.node};
+ p(cstore).mod_path_map.insert(d, path);
+ }
}
fn have_crate_data(cstore: cstore, cnum: ast::crate_num) -> bool {
fn mapper(ch: crate_hash) -> str { ret ch.hash; }
ret vec::map(sorted, mapper);
}
+
+fn get_path(cstore: cstore, d: ast::def_id) -> [str] {
+ alt p(cstore).mod_path_map.find(d) {
+ option::some(ds) { str::split_str(ds, "::") }
+ option::none { [] }
+ }
+}
// Local Variables:
// mode: rust
// fill-column: 78;
// Decoding metadata from a single crate's metadata
-import std::{ebml, io};
+import std::{ebml, map, io};
import io::writer_util;
import syntax::{ast, ast_util};
import front::attr;
export get_crate_hash;
export get_impls_for_mod;
export get_iface_methods;
+export get_crate_module_paths;
+
// A function that takes a def_id relative to the crate being searched and
// returns a def_id relative to the compilation environment, i.e. if we hit a
// def_id for an item defined in another crate, somebody needs to figure out
fn list_crate_items(bytes: @[u8], md: ebml::doc, out: io::writer) {
out.write_str("=Items=\n");
- let paths = ebml::get_doc(md, tag_paths);
let items = ebml::get_doc(md, tag_items);
+ iter_crate_items(bytes) {|path, did|
+ out.write_str(#fmt["%s (%s)\n", path, describe_def(items, did)]);
+ }
+ out.write_str("\n");
+}
+
+fn iter_crate_items(bytes: @[u8], proc: block(str, ast::def_id)) {
+ let md = ebml::new_doc(bytes);
+ let paths = ebml::get_doc(md, tag_paths);
let index = ebml::get_doc(paths, tag_index);
let bs = ebml::get_doc(index, tag_index_buckets);
ebml::tagged_docs(bs, tag_index_buckets_bucket) {|bucket|
let def = ebml::doc_at(bytes, data.pos);
let did_doc = ebml::get_doc(def, tag_def_id);
let did = parse_def_id(ebml::doc_data(did_doc));
- out.write_str(#fmt["%s (%s)\n", data.path,
- describe_def(items, did)]);
+ proc(data.path, did);
};
};
- out.write_str("\n");
+}
+
+fn get_crate_module_paths(bytes: @[u8]) -> [(ast::def_id, str)] {
+ fn mod_of_path(p: str) -> str {
+ str::connect(vec::init(str::split_str(p, "::")), "::")
+ }
+
+ // find all module (path, def_ids), which are not
+ // fowarded path due to renamed import or reexport
+ let res = [];
+ let mods = map::new_str_hash();
+ iter_crate_items(bytes) {|path, did|
+ let m = mod_of_path(path);
+ if str::is_not_empty(m) {
+ // if m has a sub-item, it must be a module
+ mods.insert(m, true);
+ }
+ // Collect everything by now. There might be multiple
+ // paths pointing to the same did. Those will be
+ // unified later by using the mods map
+ res += [(did, path)];
+ }
+ ret vec::filter(res) {|x|
+ let (_, xp) = x;
+ mods.contains_key(xp)
+ }
}
fn list_crate_metadata(bytes: @[u8], out: io::writer) {
if !is_none(cached) { ret cached; }
let path = [name];
if defid.node != ast::crate_node_id {
- path = e.ext_map.get(defid) + path;
+ path = cstore::get_path(e.cstore, defid) + path;
}
let fnd = lookup_external(e, defid.crate, path, ns);
if !is_none(fnd) {
fn lookup_external(e: env, cnum: int, ids: [ident], ns: namespace) ->
option::t<def> {
for d: def in csearch::lookup_defs(e.sess.cstore, cnum, ids) {
- let did = def_id_of_def(d);
- alt d {
- def_mod(_) | def_native_mod(_) {
- // The [native] module name might have renamed when importing,
- // find the original name for further lookup of names inside the
- // [native] module
- if did.crate != ast::local_crate {
- let cname = cstore::get_crate_data(e.cstore, did.crate).name;
- let name =
- csearch::get_item_name(e.cstore, did.crate, did.node);
- #debug("lookup_external: %s %d, %d, %s, %s", cname,
- did.crate, did.node, str::connect(ids, "::"), name);
- e.ext_map.insert(did, vec::init(ids) + [name]);
- } else {
- e.ext_map.insert(did, ids);
- }
- }
- _ {
- e.ext_map.insert(did, ids);
- }
- }
+ e.ext_map.insert(def_id_of_def(d), ids);
if ns_ok(ns, ns_for_def(d)) { ret some(d); }
}
ret none::<def>;