decoder.rs 38.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// 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.

11
// Decoding metadata from a single crate's metadata
B
Brian Anderson 已提交
12

13 14 15 16 17 18 19 20 21 22 23 24
use cmd = metadata::cstore::crate_metadata;
use dvec::DVec;
use hash::{Hash, HashUtil};
use io::WriterUtil;
use metadata::common::*;
use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo};
use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data};
use metadata::tydecode::{parse_ident};
use middle::ty;
use util::ppaux::ty_to_str;

use reader = std::ebml::reader;
25
use std::ebml;
26
use std::map::HashMap;
27
use std::map;
28
#[cfg(stage0)]
29
use std::serialize::traits::Decodable;
30 31 32
#[cfg(stage1)]
#[cfg(stage2)]
use std::serialize::Decodable;
P
Patrick Walton 已提交
33
use syntax::ast_map;
34
use syntax::attr;
P
Patrick Walton 已提交
35 36
use syntax::diagnostic::span_handler;
use syntax::parse::token::ident_interner;
37 38
use syntax::print::pprust;
use syntax::{ast, ast_util};
39

40 41
export struct_dtor;
export get_struct_fields;
42
export get_symbol;
43
export get_enum_variants;
44
export get_type;
45
export get_region_param;
46
export get_type_param_count;
47
export get_impl_traits;
48
export get_impl_method;
49
export get_static_methods_if_impl;
50 51
export lookup_def;
export resolve_path;
52
export get_crate_attributes;
53
export list_crate_metadata;
54 55
export crate_dep;
export get_crate_deps;
H
Haitao Li 已提交
56
export get_crate_hash;
57
export get_crate_vers;
58
export get_impls_for_mod;
59
export get_trait_methods;
60
export get_provided_trait_methods;
61
export get_supertraits;
62
export get_method_names_if_trait;
63
export get_type_name_if_impl;
64
export get_item_attrs;
65
export get_crate_module_paths;
66 67 68 69 70 71
export def_like;
export dl_def;
export dl_impl;
export dl_field;
export path_entry;
export each_path;
72
export get_item_path;
T
Tim Chevalier 已提交
73 74
export maybe_find_item; // sketchy
export item_type; // sketchy
75
export maybe_get_item_ast;
76
export decode_inlined_item;
77
export method_info, _impl;
78
export GetCrateDataCb;
79 80 81

// Used internally by astencode:
export translate_def_id;
82

83 84 85 86 87
// 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
// what crate that's in and give us a def_id that makes sense for the current
// build.
M
Marijn Haverbeke 已提交
88

89 90
fn lookup_hash(d: ebml::Doc, eq_fn: fn(x:&[u8]) -> bool, hash: uint) ->
   Option<ebml::Doc> {
91 92
    let index = reader::get_doc(d, tag_index);
    let table = reader::get_doc(index, tag_index_table);
M
Marijn Haverbeke 已提交
93
    let hash_pos = table.start + hash % 256u * 4u;
94
    let pos = io::u64_from_be_bytes(*d.data, hash_pos, 4u) as uint;
95
    let tagged_doc = reader::doc_at(d.data, pos);
96

M
Marijn Haverbeke 已提交
97
    let belt = tag_index_buckets_bucket_elt;
98
    for reader::tagged_docs(tagged_doc.doc, belt) |elt| {
99
        let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4u) as uint;
100
        if eq_fn(vec::view(*elt.data, elt.start + 4u, elt.end)) {
101
            return Some(reader::doc_at(d.data, pos).doc);
102
        }
103
    };
B
Brian Anderson 已提交
104
    None
105 106
}

107 108
pub type GetCrateDataCb = &fn(ast::crate_num) -> cmd;

109
fn maybe_find_item(item_id: int, items: ebml::Doc) -> Option<ebml::Doc> {
110
    fn eq_item(bytes: &[u8], item_id: int) -> bool {
111
        return io::u64_from_be_bytes(vec::view(bytes, 0u, 4u), 0u, 4u) as int
112
            == item_id;
113
    }
114 115
    lookup_hash(items,
                |a| eq_item(a, item_id),
116
                item_id.hash() as uint)
117 118
}

119
fn find_item(item_id: int, items: ebml::Doc) -> ebml::Doc {
B
Brian Anderson 已提交
120
    return maybe_find_item(item_id, items).get();
121 122
}

123
// Looks up an item in the given metadata and returns an ebml doc pointing
124
// to the item data.
125
fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc {
126
    let items = reader::get_doc(reader::Doc(data), tag_items);
127
    match maybe_find_item(item_id, items) {
B
Brian Anderson 已提交
128 129
       None => fail(fmt!("lookup_item: id not found: %d", item_id)),
       Some(d) => d
T
Tim Chevalier 已提交
130
    }
131 132
}

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
enum Family {
    Const,                 // c
    Fn,                    // f
    UnsafeFn,              // u
    PureFn,                // p
    StaticMethod,          // F
    UnsafeStaticMethod,    // U
    PureStaticMethod,      // P
    ForeignFn,             // e
    Type,                  // y
    ForeignType,           // T
    Mod,                   // m
    ForeignMod,            // n
    Enum,                  // t
    Variant,               // v
    Impl,                  // i
    Trait,                 // I
    Struct,                // S
    PublicField,           // g
    PrivateField,          // j
    InheritedField         // N
}

156
impl Family : cmp::Eq {
157 158 159 160
    pure fn eq(&self, other: &Family) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &Family) -> bool { !(*self).eq(other) }
161
}
162

163
fn item_family(item: ebml::Doc) -> Family {
164 165
    let fam = reader::get_doc(item, tag_items_data_item_family);
    match reader::doc_as_u8(fam) as char {
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
      'c' => Const,
      'f' => Fn,
      'u' => UnsafeFn,
      'p' => PureFn,
      'F' => StaticMethod,
      'U' => UnsafeStaticMethod,
      'P' => PureStaticMethod,
      'e' => ForeignFn,
      'y' => Type,
      'T' => ForeignType,
      'm' => Mod,
      'n' => ForeignMod,
      't' => Enum,
      'v' => Variant,
      'i' => Impl,
      'I' => Trait,
      'S' => Struct,
      'g' => PublicField,
      'j' => PrivateField,
      'N' => InheritedField,
186
       c => fail (fmt!("unexpected family char: %c", c))
187
    }
188 189
}

190
fn item_method_sort(item: ebml::Doc) -> char {
191 192
    for reader::tagged_docs(item, tag_item_trait_method_sort) |doc| {
        return str::from_bytes(reader::doc_data(doc))[0] as char;
193 194 195 196
    }
    return 'r';
}

197
fn item_symbol(item: ebml::Doc) -> ~str {
198 199
    let sym = reader::get_doc(item, tag_items_data_item_symbol);
    return str::from_bytes(reader::doc_data(sym));
200 201
}

202
fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> {
203 204
    for reader::tagged_docs(d, tag_items_data_parent_item) |did| {
        return Some(reader::with_doc_data(did, |d| parse_def_id(d)));
205
    }
B
Brian Anderson 已提交
206
    None
207 208
}

209 210 211 212 213 214
fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) ->
        Option<ast::def_id> {
    let trait_did_opt = item_parent_item(d);
    trait_did_opt.map(|trait_did| {crate: cnum, node: trait_did.node})
}

215 216 217 218 219 220
fn item_reqd_and_translated_parent_item(cnum: ast::crate_num,
                                        d: ebml::Doc) -> ast::def_id {
    let trait_did = item_parent_item(d).expect(~"item without parent");
    {crate: cnum, node: trait_did.node}
}

221
fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id {
222 223
    let tagdoc = reader::get_doc(d, tag_def_id);
    return translate_def_id(cdata, reader::with_doc_data(tagdoc,
224
                                                    |d| parse_def_id(d)));
T
Tim Chevalier 已提交
225 226
}

227
fn each_reexport(d: ebml::Doc, f: fn(ebml::Doc) -> bool) {
228
    for reader::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| {
229 230 231 232 233 234
        if !f(reexport_doc) {
            return;
        }
    }
}

235
fn field_mutability(d: ebml::Doc) -> ast::struct_mutability {
236
    // Use maybe_get_doc in case it's a method
B
Brian Anderson 已提交
237
    option::map_default(
238 239
        &reader::maybe_get_doc(d, tag_struct_mut),
        ast::struct_immutable,
B
Brian Anderson 已提交
240
        |d| {
241
            match reader::doc_as_u8(*d) as char {
242 243
              'm' => ast::struct_mutable,
              _   => ast::struct_immutable
B
Brian Anderson 已提交
244 245
            }
        })
246 247
}

248
fn variant_disr_val(d: ebml::Doc) -> Option<int> {
249 250
    do option::chain(reader::maybe_get_doc(d, tag_disr_val)) |val_doc| {
        int::parse_bytes(reader::doc_data(val_doc), 10u)
251 252 253
    }
}

254
fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
255
    let tp = reader::get_doc(doc, tag_items_data_item_type);
B
Brian Anderson 已提交
256
    parse_ty_data(tp.data, cdata.cnum, tp.start, tcx, |did| {
257 258
        translate_def_id(cdata, did)
    })
259 260
}

261
fn item_type(item_id: ast::def_id, item: ebml::Doc,
262
             tcx: ty::ctxt, cdata: cmd) -> ty::t {
263
    let t = doc_type(item, tcx, cdata);
264
    if family_names_type(item_family(item)) {
265
        ty::mk_with_id(tcx, t, item_id)
266
    } else { t }
267 268
}

269
fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] {
270
    let mut results = ~[];
271
    for reader::tagged_docs(item, tag_impl_trait) |ity| {
272
        results.push(doc_type(ity, tcx, cdata));
273
    };
274
    results
275 276
}

277
fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd)
278 279
    -> @~[ty::param_bounds] {
    let mut bounds = ~[];
280
    for reader::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| {
B
Brian Anderson 已提交
281
        let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx, |did| {
282 283
            translate_def_id(cdata, did)
        });
284
        bounds.push(bd);
285
    }
286
    @bounds
287 288
}

289
fn item_ty_region_param(item: ebml::Doc) -> Option<ty::region_variance> {
290
    reader::maybe_get_doc(item, tag_region_param).map(|doc| {
291
        Decodable::decode(&reader::Decoder(*doc))
292
    })
293 294
}

295
fn item_ty_param_count(item: ebml::Doc) -> uint {
296
    let mut n = 0u;
297
    reader::tagged_docs(item, tag_items_data_item_ty_param_bounds,
298
                      |_p| { n += 1u; true } );
299 300 301
    n
}

302
fn enum_variant_ids(item: ebml::Doc, cdata: cmd) -> ~[ast::def_id] {
303
    let mut ids: ~[ast::def_id] = ~[];
M
Marijn Haverbeke 已提交
304
    let v = tag_items_data_item_variant;
305 306
    for reader::tagged_docs(item, v) |p| {
        let ext = reader::with_doc_data(p, |d| parse_def_id(d));
307
        ids.push({crate: cdata.cnum, node: ext.node});
308
    };
B
Brian Anderson 已提交
309
    return ids;
310 311
}

312
fn item_path(intr: @ident_interner, item_doc: ebml::Doc) -> ast_map::path {
313
    let path_doc = reader::get_doc(item_doc, tag_path);
314

315 316
    let len_doc = reader::get_doc(path_doc, tag_path_len);
    let len = reader::doc_as_u32(len_doc) as uint;
317

318
    let mut result = vec::with_capacity(len);
319
    for reader::docs(path_doc) |tag, elt_doc| {
320
        if tag == tag_path_elt_mod {
321
            let str = reader::doc_as_str(elt_doc);
322
            result.push(ast_map::path_mod(intr.intern(@str)));
323
        } else if tag == tag_path_elt_name {
324
            let str = reader::doc_as_str(elt_doc);
325
            result.push(ast_map::path_name(intr.intern(@str)));
326 327 328 329 330
        } else {
            // ignore tag_path_len element
        }
    }

B
Brian Anderson 已提交
331
    return result;
332 333
}

334
fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident {
335 336
    let name = reader::get_doc(item, tag_paths_data_name);
    intr.intern(@str::from_bytes(reader::doc_data(name)))
337 338
}

339
fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
340 341
    -> def_like
{
342 343
    let fam = item_family(item);
    match fam {
344
        Const     => dl_def(ast::def_const(did)),
345
        Struct    => dl_def(ast::def_struct(did)),
346 347 348 349 350
        UnsafeFn  => dl_def(ast::def_fn(did, ast::unsafe_fn)),
        Fn        => dl_def(ast::def_fn(did, ast::impure_fn)),
        PureFn    => dl_def(ast::def_fn(did, ast::pure_fn)),
        ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)),
        UnsafeStaticMethod => {
351 352
            let trait_did_opt = translated_parent_item_opt(cnum, item);
            dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn))
353 354
        }
        StaticMethod => {
355 356
            let trait_did_opt = translated_parent_item_opt(cnum, item);
            dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn))
357 358
        }
        PureStaticMethod => {
359 360
            let trait_did_opt = translated_parent_item_opt(cnum, item);
            dl_def(ast::def_static_method(did, trait_did_opt, ast::pure_fn))
361 362 363 364 365 366 367 368 369 370 371
        }
        Type | ForeignType => dl_def(ast::def_ty(did)),
        Mod => dl_def(ast::def_mod(did)),
        ForeignMod => dl_def(ast::def_foreign_mod(did)),
        Variant => {
            let enum_did = item_reqd_and_translated_parent_item(cnum, item);
            dl_def(ast::def_variant(enum_did, did))
        }
        Trait | Enum => dl_def(ast::def_ty(did)),
        Impl => dl_impl(did),
        PublicField | PrivateField | InheritedField => dl_field,
372
    }
373 374
}

375 376 377 378 379
fn lookup_def(cnum: ast::crate_num, data: @~[u8], did_: ast::def_id) ->
   ast::def {
    let item = lookup_item(did_.node, data);
    let did = {crate: cnum, node: did_.node};
    // We treat references to enums as references to types.
B
Brian Anderson 已提交
380
    return def_like_to_def(item_to_def_like(item, did, cnum));
381 382
}

383 384
fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
    -> ty::ty_param_bounds_and_ty {
385

386
    let item = lookup_item(id, cdata.data);
387
    let t = item_type({crate: cdata.cnum, node: id}, item, tcx, cdata);
M
Marijn Haverbeke 已提交
388 389
    let tp_bounds = if family_has_type_params(item_family(item)) {
        item_ty_param_bounds(item, tcx, cdata)
390
    } else { @~[] };
391
    let rp = item_ty_region_param(item);
392 393 394
    return {bounds: tp_bounds,
            region_param: rp,
            ty: t};
395 396
}

397
fn get_region_param(cdata: cmd, id: ast::node_id)
B
Brian Anderson 已提交
398
    -> Option<ty::region_variance> {
399

400
    let item = lookup_item(id, cdata.data);
B
Brian Anderson 已提交
401
    return item_ty_region_param(item);
402 403
}

404
fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
405
    item_ty_param_count(lookup_item(id, data))
406 407
}

408 409
fn get_impl_traits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ~[ty::t] {
    item_impl_traits(lookup_item(id, cdata.data), tcx, cdata)
410 411
}

E
Erick Tryzelaar 已提交
412
fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
B
Brian Anderson 已提交
413
                   name: ast::ident) -> ast::def_id {
414
    let items = reader::get_doc(reader::Doc(cdata.data), tag_items);
B
Brian Anderson 已提交
415
    let mut found = None;
416
    for reader::tagged_docs(find_item(id, items), tag_item_impl_method)
417
        |mid| {
418
            let m_did = reader::with_doc_data(mid, |d| parse_def_id(d));
419 420 421
            if item_name(intr, find_item(m_did.node, items)) == name {
                found = Some(translate_def_id(cdata, m_did));
            }
422
        }
B
Brian Anderson 已提交
423
    found.get()
424 425
}

426
fn struct_dtor(cdata: cmd, id: ast::node_id) -> Option<ast::def_id> {
427
    let items = reader::get_doc(reader::Doc(cdata.data), tag_items);
B
Brian Anderson 已提交
428
    let mut found = None;
429
    let cls_items = match maybe_find_item(id, items) {
B
Brian Anderson 已提交
430
            Some(it) => it,
431
            None     => fail (fmt!("struct_dtor: class id not found \
P
Paul Stansifer 已提交
432
              when looking up dtor for %d", id))
433
    };
434 435 436
    for reader::tagged_docs(cls_items, tag_item_dtor) |doc| {
         let doc1 = reader::get_doc(doc, tag_def_id);
         let did = reader::with_doc_data(doc1, |d| parse_def_id(d));
B
Brian Anderson 已提交
437
         found = Some(translate_def_id(cdata, did));
438 439
    };
    found
440 441
}

442
fn get_symbol(data: @~[u8], id: ast::node_id) -> ~str {
B
Brian Anderson 已提交
443
    return item_symbol(lookup_item(id, data));
444 445
}

446 447 448 449 450 451 452 453
// Something that a name can resolve to.
enum def_like {
    dl_def(ast::def),
    dl_impl(ast::def_id),
    dl_field
}

fn def_like_to_def(def_like: def_like) -> ast::def {
454
    match def_like {
B
Brian Anderson 已提交
455 456 457
        dl_def(def) => return def,
        dl_impl(*) => fail ~"found impl in def_like_to_def",
        dl_field => fail ~"found field in def_like_to_def"
458 459 460 461
    }
}

// A path.
B
Brian Anderson 已提交
462
struct path_entry {
463
    // The full path, separated by '::'.
464
    path_string: ~str,
465
    // The definition, implementation, or field that this path corresponds to.
466
    def_like: def_like,
B
Brian Anderson 已提交
467
}
468

B
Brian Anderson 已提交
469 470 471 472
fn path_entry(path_string: ~str, def_like: def_like) -> path_entry {
    path_entry {
        path_string: path_string,
        def_like: def_like
473 474 475
    }
}

476
/// Iterates over all the paths in the given crate.
477 478 479
fn each_path(intr: @ident_interner, cdata: cmd,
             get_crate_data: GetCrateDataCb,
             f: fn(path_entry) -> bool) {
480 481 482
    let root = reader::Doc(cdata.data);
    let items = reader::get_doc(root, tag_items);
    let items_data = reader::get_doc(items, tag_items_data);
483 484 485 486

    let mut broken = false;

    // First, go through all the explicit items.
487
    for reader::tagged_docs(items_data, tag_items_data_item) |item_doc| {
488
        if !broken {
P
Paul Stansifer 已提交
489 490
            let path = ast_map::path_to_str_with_sep(
                item_path(intr, item_doc), ~"::", intr);
491
            if path != ~"" {
492
                // Extract the def ID.
493
                let def_id = item_def_id(item_doc, cdata);
494 495

                // Construct the def for this item.
P
Paul Stansifer 已提交
496
                debug!("(each_path) yielding explicit item: %s", path);
497 498 499
                let def_like = item_to_def_like(item_doc, def_id, cdata.cnum);

                // Hand the information off to the iteratee.
500
                let this_path_entry = path_entry(path, def_like);
501 502 503 504
                if !f(this_path_entry) {
                    broken = true;      // XXX: This is awful.
                }
            }
505

506 507 508 509
            // If this is a module, find the reexports.
            for each_reexport(item_doc) |reexport_doc| {
                if !broken {
                    let def_id_doc =
510
                        reader::get_doc(reexport_doc,
511 512
                            tag_items_data_item_reexport_def_id);
                    let def_id =
513
                        reader::with_doc_data(def_id_doc,
514
                                              |d| parse_def_id(d));
515 516 517
                    let def_id = translate_def_id(cdata, def_id);

                    let reexport_name_doc =
518
                        reader::get_doc(reexport_doc,
519
                                      tag_items_data_item_reexport_name);
520
                    let reexport_name = reader::doc_as_str(reexport_name_doc);
521 522 523 524 525 526 527

                    let reexport_path;
                    if path == ~"" {
                        reexport_path = reexport_name;
                    } else {
                        reexport_path = path + ~"::" + reexport_name;
                    }
528

529 530 531 532 533
                    // This reexport may be in yet another crate
                    let other_crates_items = if def_id.crate == cdata.cnum {
                        items
                    } else {
                        let crate_data = get_crate_data(def_id.crate);
534 535
                        let root = reader::Doc(crate_data.data);
                        reader::get_doc(root, tag_items)
536 537
                    };

538
                    // Get the item.
539
                    match maybe_find_item(def_id.node, other_crates_items) {
B
Brian Anderson 已提交
540 541
                        None => {}
                        Some(item_doc) => {
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
                            // Construct the def for this item.
                            let def_like = item_to_def_like(item_doc,
                                                            def_id,
                                                            cdata.cnum);

                            // Hand the information off to the iteratee.
                            debug!("(each_path) yielding reexported \
                                    item: %s", reexport_path);

                            let this_path_entry =
                                path_entry(reexport_path, def_like);
                            if (!f(this_path_entry)) {
                                broken = true;  // XXX: This is awful.
                            }
                        }
557 558 559 560 561
                    }
                }
            }
        }
    }
562

563 564 565
    // If broken, stop here.
    if broken {
        return;
566
    }
567 568
}

E
Erick Tryzelaar 已提交
569
fn get_item_path(intr: @ident_interner, cdata: cmd, id: ast::node_id)
P
Paul Stansifer 已提交
570 571
    -> ast_map::path {
    item_path(intr, lookup_item(id, cdata.data))
572 573
}

574 575 576 577
type decode_inlined_item = fn(
    cdata: cstore::crate_metadata,
    tcx: ty::ctxt,
    path: ast_map::path,
578
    par_doc: ebml::Doc) -> Option<ast::inlined_item>;
579

E
Erick Tryzelaar 已提交
580
fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt,
581 582 583
                      id: ast::node_id,
                      decode_inlined_item: decode_inlined_item
                     ) -> csearch::found_ast {
P
Paul Stansifer 已提交
584
    debug!("Looking up item: %d", id);
585
    let item_doc = lookup_item(id, cdata.data);
P
Paul Stansifer 已提交
586
    let path = vec::init(item_path(intr, item_doc));
587
    match decode_inlined_item(cdata, tcx, path, item_doc) {
588
      Some(ref ii) => csearch::found((*ii)),
B
Brian Anderson 已提交
589
      None => {
590
        match item_parent_item(item_doc) {
B
Brian Anderson 已提交
591
          Some(did) => {
592 593
            let did = translate_def_id(cdata, did);
            let parent_item = lookup_item(did.node, cdata.data);
594
            match decode_inlined_item(cdata, tcx, path,
595
                                               parent_item) {
596
              Some(ref ii) => csearch::found_parent(did, (*ii)),
B
Brian Anderson 已提交
597
              None => csearch::not_found
598 599
            }
          }
B
Brian Anderson 已提交
600
          None => csearch::not_found
601 602 603
        }
      }
    }
604 605
}

E
Erick Tryzelaar 已提交
606
fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
607
                     tcx: ty::ctxt) -> ~[ty::VariantInfo] {
608
    let data = cdata.data;
609
    let items = reader::get_doc(reader::Doc(data), tag_items);
610
    let item = find_item(id, items);
611
    let mut infos: ~[ty::VariantInfo] = ~[];
612
    let variant_ids = enum_variant_ids(item, cdata);
613
    let mut disr_val = 0;
B
Brian Anderson 已提交
614
    for variant_ids.each |did| {
M
Marijn Haverbeke 已提交
615
        let item = find_item(did.node, items);
616 617
        let ctor_ty = item_type({crate: cdata.cnum, node: id}, item,
                                tcx, cdata);
P
Paul Stansifer 已提交
618
        let name = item_name(intr, item);
E
Erick Tryzelaar 已提交
619
        let arg_tys = match ty::get(ctor_ty).sty {
620
          ty::ty_fn(ref f) => (*f).sig.inputs.map(|a| a.ty),
E
Erick Tryzelaar 已提交
621 622 623 624

          // Nullary enum variant.
          _ => ~[],
        };
625
        match variant_disr_val(item) {
B
Brian Anderson 已提交
626
          Some(val) => { disr_val = val; }
B
Brian Anderson 已提交
627
          _         => { /* empty */ }
628
        }
629 630 631 632 633
        infos.push(@ty::VariantInfo_{args: arg_tys,
                       ctor_ty: ctor_ty, name: name,
                  // I'm not even sure if we encode visibility
                  // for variants -- TEST -- tjc
                  id: *did, disr_val: disr_val, vis: ast::inherited});
634
        disr_val += 1;
635
    }
B
Brian Anderson 已提交
636
    return infos;
637 638
}

639
// NB: These types are duplicated in resolve.rs
640 641 642 643 644 645 646
type method_info = {
    did: ast::def_id,
    n_tps: uint,
    ident: ast::ident,
    self_type: ast::self_ty_
};

647
type _impl = {did: ast::def_id, ident: ast::ident, methods: ~[@method_info]};
648

649
fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ {
650
    fn get_mutability(ch: u8) -> ast::mutability {
651
        match ch as char {
652 653 654 655
            'i' => { ast::m_imm }
            'm' => { ast::m_mutbl }
            'c' => { ast::m_const }
            _ => {
P
Paul Stansifer 已提交
656
                fail fmt!("unknown mutability character: `%c`", ch as char)
657 658 659 660
            }
        }
    }

661 662
    let self_type_doc = reader::get_doc(item, tag_item_trait_method_self_ty);
    let string = reader::doc_as_str(self_type_doc);
663 664

    let self_ty_kind = string[0];
665
    match self_ty_kind as char {
666
        's' => { return ast::sty_static; }
B
Brian Anderson 已提交
667 668 669 670
        'r' => { return ast::sty_by_ref; }
        'v' => { return ast::sty_value; }
        '@' => { return ast::sty_box(get_mutability(string[1])); }
        '~' => { return ast::sty_uniq(get_mutability(string[1])); }
671
        '&' => { return ast::sty_region(get_mutability(string[1])); }
672
        _ => {
P
Paul Stansifer 已提交
673
            fail fmt!("unknown self type code: `%c`", self_ty_kind as char);
674 675 676 677
        }
    }
}

678
fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc,
P
Paul Stansifer 已提交
679
                     base_tps: uint) -> ~[@method_info] {
680
    let mut rslt = ~[];
681 682
    for reader::tagged_docs(item, tag_item_impl_method) |doc| {
        let m_did = reader::with_doc_data(doc, |d| parse_def_id(d));
683
        let mth_item = lookup_item(m_did.node, cdata.data);
684
        let self_ty = get_self_ty(mth_item);
685
        rslt.push(@{did: translate_def_id(cdata, m_did),
686
                   n_tps: item_ty_param_count(mth_item) - base_tps,
P
Paul Stansifer 已提交
687
                   ident: item_name(intr, mth_item),
688
                   self_type: self_ty});
689 690 691 692
    }
    rslt
}

E
Erick Tryzelaar 已提交
693
fn get_impls_for_mod(intr: @ident_interner, cdata: cmd,
B
Brian Anderson 已提交
694
                     m_id: ast::node_id, name: Option<ast::ident>,
695
                     get_cdata: fn(ast::crate_num) -> cmd)
696 697
                  -> @~[@_impl] {

698
    let data = cdata.data;
699
    let mod_item = lookup_item(m_id, data);
700
    let mut result = ~[];
701 702
    for reader::tagged_docs(mod_item, tag_mod_impl) |doc| {
        let did = reader::with_doc_data(doc, |d| parse_def_id(d));
703
        let local_did = translate_def_id(cdata, did);
P
Paul Stansifer 已提交
704 705
        debug!("(get impls for mod) getting did %? for '%?'",
               local_did, name);
706 707
          // The impl may be defined in a different crate. Ask the caller
          // to give us the metadata
708 709 710
        let impl_cdata = get_cdata(local_did.crate);
        let impl_data = impl_cdata.data;
        let item = lookup_item(local_did.node, impl_data);
P
Paul Stansifer 已提交
711
        let nm = item_name(intr, item);
B
Brian Anderson 已提交
712
        if match name { Some(n) => { n == nm } None => { true } } {
713
           let base_tps = item_ty_param_count(item);
714
           result.push(@{
715
                did: local_did, ident: nm,
P
Paul Stansifer 已提交
716
                methods: item_impl_methods(intr, impl_cdata, item, base_tps)
717
            });
718
        };
719 720 721 722
    }
    @result
}

723
/* Works for both classes and traits */
E
Erick Tryzelaar 已提交
724
fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
P
Paul Stansifer 已提交
725
                     tcx: ty::ctxt) -> @~[ty::method] {
726
    let data = cdata.data;
727
    let item = lookup_item(id, data);
728
    let mut result = ~[];
729
    for reader::tagged_docs(item, tag_item_trait_method) |mth| {
M
Marijn Haverbeke 已提交
730
        let bounds = item_ty_param_bounds(mth, tcx, cdata);
P
Paul Stansifer 已提交
731
        let name = item_name(intr, mth);
732
        let ty = doc_type(mth, tcx, cdata);
733
        let def_id = item_def_id(mth, cdata);
734
        let fty = match ty::get(ty).sty {
735
          ty::ty_fn(ref f) => (*f),
B
Brian Anderson 已提交
736
          _ => {
737
            tcx.diag.handler().bug(
738
                ~"get_trait_methods: id has non-function type");
T
Tim Chevalier 已提交
739
        } };
740
        let self_ty = get_self_ty(mth);
741 742
        result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty,
                     vis: ast::public, def_id: def_id});
743
    }
744
    debug!("get_trait_methods: }");
745 746 747
    @result
}

748 749 750 751 752 753 754
fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
                              id: ast::node_id, tcx: ty::ctxt) ->
        ~[ProvidedTraitMethodInfo] {
    let data = cdata.data;
    let item = lookup_item(id, data);
    let mut result = ~[];

755
    for reader::tagged_docs(item, tag_item_trait_method) |mth| {
756 757 758 759 760 761 762 763 764 765
        if item_method_sort(mth) != 'p' { loop; }

        let did = item_def_id(mth, cdata);

        let bounds = item_ty_param_bounds(mth, tcx, cdata);
        let name = item_name(intr, mth);
        let ty = doc_type(mth, tcx, cdata);

        let fty;
        match ty::get(ty).sty {
766
            ty::ty_fn(ref f) => fty = (*f),
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
            _ => {
                tcx.diag.handler().bug(~"get_provided_trait_methods(): id \
                                         has non-function type");
            }
        }

        let self_ty = get_self_ty(mth);
        let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty,
                         vis: ast::public, def_id: did};
        let provided_trait_method_info = ProvidedTraitMethodInfo {
            ty: ty_method,
            def_id: did
        };

        vec::push(&mut result, move provided_trait_method_info);
    }

    return move result;
}

787 788 789 790
/// Returns the supertraits of the given trait.
fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ~[ty::t] {
    let results = dvec::DVec();
    let item_doc = lookup_item(id, cdata.data);
791
    for reader::tagged_docs(item_doc, tag_impl_trait) |trait_doc| {
792 793 794 795 796
        results.push(doc_type(trait_doc, tcx, cdata));
    }
    return dvec::unwrap(move results);
}

797 798 799
// If the item in question is a trait, returns its set of methods and
// their self types. Otherwise, returns none. This overlaps in an
// annoying way with get_trait_methods.
E
Erick Tryzelaar 已提交
800
fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd,
P
Paul Stansifer 已提交
801
                             node_id: ast::node_id)
B
Brian Anderson 已提交
802
                          -> Option<@DVec<(ast::ident, ast::self_ty_)>> {
803 804

    let item = lookup_item(node_id, cdata.data);
805
    if item_family(item) != Trait {
B
Brian Anderson 已提交
806
        return None;
807 808
    }

809
    let resulting_methods = @DVec();
810
    for reader::tagged_docs(item, tag_item_trait_method) |method| {
811
        resulting_methods.push(
P
Paul Stansifer 已提交
812
            (item_name(intr, method), get_self_ty(method)));
813
    }
B
Brian Anderson 已提交
814
    return Some(resulting_methods);
815 816
}

817 818 819 820 821 822 823 824
fn get_type_name_if_impl(intr: @ident_interner,
                         cdata: cmd,
                         node_id: ast::node_id) -> Option<ast::ident> {
    let item = lookup_item(node_id, cdata.data);
    if item_family(item) != Impl {
        return None;
    }

825 826
    for reader::tagged_docs(item, tag_item_impl_type_basename) |doc| {
        return Some(intr.intern(@str::from_bytes(reader::doc_data(doc))));
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
    }

    return None;
}

fn get_static_methods_if_impl(intr: @ident_interner,
                               cdata: cmd,
                               node_id: ast::node_id) ->
                               Option<~[StaticMethodInfo]> {
    let item = lookup_item(node_id, cdata.data);
    if item_family(item) != Impl {
        return None;
    }

    // If this impl has a trait ref, don't consider it.
842
    for reader::tagged_docs(item, tag_impl_trait) |_doc| {
843 844 845 846
        return None;
    }

    let impl_method_ids = DVec();
847 848
    for reader::tagged_docs(item, tag_item_impl_method) |impl_method_doc| {
        impl_method_ids.push(parse_def_id(reader::doc_data(impl_method_doc)));
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
    }

    let static_impl_methods = DVec();
    for impl_method_ids.each |impl_method_id| {
        let impl_method_doc = lookup_item(impl_method_id.node, cdata.data);
        let family = item_family(impl_method_doc);
        match family {
            StaticMethod | UnsafeStaticMethod | PureStaticMethod => {
                let purity;
                match item_family(impl_method_doc) {
                    StaticMethod => purity = ast::impure_fn,
                    UnsafeStaticMethod => purity = ast::unsafe_fn,
                    PureStaticMethod => purity = ast::pure_fn,
                    _ => fail
                }

                static_impl_methods.push(StaticMethodInfo {
                    ident: item_name(intr, impl_method_doc),
                    def_id: item_def_id(impl_method_doc, cdata),
                    purity: purity
                });
            }
            _ => {}
        }
    }

    return Some(dvec::unwrap(move static_impl_methods));
}

878 879
fn get_item_attrs(cdata: cmd,
                  node_id: ast::node_id,
880
                  f: fn(~[@ast::meta_item])) {
881 882

    let item = lookup_item(node_id, cdata.data);
883 884
    for reader::tagged_docs(item, tag_attributes) |attributes| {
        for reader::tagged_docs(attributes, tag_attribute) |attribute| {
885 886 887 888 889
            f(get_meta_items(attribute));
        }
    }
}

890 891 892 893 894 895 896 897 898 899 900
pure fn family_to_visibility(family: Family) -> ast::visibility {
    match family {
      PublicField => ast::public,
      PrivateField => ast::private,
      InheritedField => ast::inherited,
      _ => fail
    }
}

fn get_struct_fields(intr: @ident_interner, cdata: cmd, id: ast::node_id)
    -> ~[ty::field_ty] {
T
Tim Chevalier 已提交
901
    let data = cdata.data;
902
    let item = lookup_item(id, data);
903
    let mut result = ~[];
904
    for reader::tagged_docs(item, tag_item_field) |an_item| {
905
       let f = item_family(an_item);
906
       if f == PublicField || f == PrivateField || f == InheritedField {
P
Paul Stansifer 已提交
907
          let name = item_name(intr, an_item);
908
          let did = item_def_id(an_item, cdata);
909
          let mt = field_mutability(an_item);
910
          result.push({ident: name, id: did, vis:
911
                  family_to_visibility(f), mutability: mt});
T
Tim Chevalier 已提交
912
       }
T
Tim Chevalier 已提交
913 914 915 916
    }
    result
}

917 918 919 920 921
fn family_has_type_params(fam: Family) -> bool {
    match fam {
      Const | ForeignType | Mod | ForeignMod | PublicField | PrivateField
      | ForeignFn => false,
      _           => true
922
    }
923 924
}

925 926
fn family_names_type(fam: Family) -> bool {
    match fam { Type | Mod | Trait => true, _ => false }
927 928
}

929
fn read_path(d: ebml::Doc) -> {path: ~str, pos: uint} {
930
    let desc = reader::doc_data(d);
931
    let pos = io::u64_from_be_bytes(desc, 0u, 4u) as uint;
932
    let pathbytes = vec::slice::<u8>(desc, 4u, vec::len::<u8>(desc));
933
    let path = str::from_bytes(pathbytes);
B
Brian Anderson 已提交
934
    return {path: path, pos: pos};
935 936
}

937
fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str {
B
Brian Anderson 已提交
938
    if id.crate != ast::local_crate { return ~"external"; }
939
    let it = match maybe_find_item(id.node, items) {
B
Brian Anderson 已提交
940 941
        Some(it) => it,
        None => fail (fmt!("describe_def: item not found %?", id))
942
    };
B
Brian Anderson 已提交
943
    return item_family_to_str(item_family(it));
944 945
}

946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
fn item_family_to_str(fam: Family) -> ~str {
    match fam {
      Const => ~"const",
      Fn => ~"fn",
      UnsafeFn => ~"unsafe fn",
      PureFn => ~"pure fn",
      StaticMethod => ~"static method",
      UnsafeStaticMethod => ~"unsafe static method",
      PureStaticMethod => ~"pure static method",
      ForeignFn => ~"foreign fn",
      Type => ~"type",
      ForeignType => ~"foreign type",
      Mod => ~"mod",
      ForeignMod => ~"foreign mod",
      Enum => ~"enum",
      Variant => ~"variant",
      Impl => ~"impl",
      Trait => ~"trait",
      Struct => ~"struct",
      PublicField => ~"public field",
      PrivateField => ~"private field",
      InheritedField => ~"inherited field",
968 969 970
    }
}

971
fn get_meta_items(md: ebml::Doc) -> ~[@ast::meta_item] {
972
    let mut items: ~[@ast::meta_item] = ~[];
973 974 975
    for reader::tagged_docs(md, tag_meta_item_word) |meta_item_doc| {
        let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
        let n = str::from_bytes(reader::doc_data(nd));
976
        items.push(attr::mk_word_item(n));
977
    };
978 979 980 981 982
    for reader::tagged_docs(md, tag_meta_item_name_value) |meta_item_doc| {
        let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
        let vd = reader::get_doc(meta_item_doc, tag_meta_item_value);
        let n = str::from_bytes(reader::doc_data(nd));
        let v = str::from_bytes(reader::doc_data(vd));
983 984
        // FIXME (#623): Should be able to decode meta_name_value variants,
        // but currently the encoder just drops them
985
        items.push(attr::mk_name_value_item_str(n, v));
986
    };
987 988 989
    for reader::tagged_docs(md, tag_meta_item_list) |meta_item_doc| {
        let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
        let n = str::from_bytes(reader::doc_data(nd));
M
Marijn Haverbeke 已提交
990
        let subitems = get_meta_items(meta_item_doc);
991
        items.push(attr::mk_list_item(n, subitems));
992
    };
B
Brian Anderson 已提交
993
    return items;
994 995
}

996
fn get_attributes(md: ebml::Doc) -> ~[ast::attribute] {
997
    let mut attrs: ~[ast::attribute] = ~[];
998
    match reader::maybe_get_doc(md, tag_attributes) {
B
Brian Anderson 已提交
999
      option::Some(attrs_d) => {
1000
        for reader::tagged_docs(attrs_d, tag_attribute) |attr_doc| {
M
Marijn Haverbeke 已提交
1001 1002 1003
            let meta_items = get_meta_items(attr_doc);
            // Currently it's only possible to have a single meta item on
            // an attribute
B
Brian Anderson 已提交
1004
            assert (vec::len(meta_items) == 1u);
B
Brian Anderson 已提交
1005
            let meta_item = meta_items[0];
1006 1007 1008 1009
            attrs.push(
                {node: {style: ast::attr_outer, value: *meta_item,
                        is_sugared_doc: false},
                 span: ast_util::dummy_sp()});
1010
        };
M
Marijn Haverbeke 已提交
1011
      }
B
Brian Anderson 已提交
1012
      option::None => ()
1013
    }
B
Brian Anderson 已提交
1014
    return attrs;
1015 1016
}

E
Erick Tryzelaar 已提交
1017
fn list_meta_items(intr: @ident_interner,
1018
                   meta_items: ebml::Doc, out: io::Writer) {
B
Brian Anderson 已提交
1019
    for get_meta_items(meta_items).each |mi| {
1020
        out.write_str(fmt!("%s\n", pprust::meta_item_to_str(*mi, intr)));
1021 1022 1023
    }
}

1024
fn list_crate_attributes(intr: @ident_interner, md: ebml::Doc, hash: ~str,
P
Paul Stansifer 已提交
1025
                         out: io::Writer) {
P
Paul Stansifer 已提交
1026
    out.write_str(fmt!("=Crate Attributes (%s)=\n", hash));
1027

B
Brian Anderson 已提交
1028
    for get_attributes(md).each |attr| {
1029
        out.write_str(fmt!("%s\n", pprust::attribute_to_str(*attr, intr)));
1030 1031
    }

1032
    out.write_str(~"\n\n");
1033 1034
}

1035
fn get_crate_attributes(data: @~[u8]) -> ~[ast::attribute] {
1036
    return get_attributes(reader::Doc(data));
1037 1038
}

1039
type crate_dep = {cnum: ast::crate_num, name: ast::ident,
P
Paul Stansifer 已提交
1040
                  vers: ~str, hash: ~str};
M
Marijn Haverbeke 已提交
1041

E
Erick Tryzelaar 已提交
1042
fn get_crate_deps(intr: @ident_interner, data: @~[u8]) -> ~[crate_dep] {
1043
    let mut deps: ~[crate_dep] = ~[];
1044 1045
    let cratedoc = reader::Doc(data);
    let depsdoc = reader::get_doc(cratedoc, tag_crate_deps);
1046
    let mut crate_num = 1;
1047
    fn docstr(doc: ebml::Doc, tag_: uint) -> ~str {
1048
        str::from_bytes(reader::doc_data(reader::get_doc(doc, tag_)))
1049
    }
1050
    for reader::tagged_docs(depsdoc, tag_crate_dep) |depdoc| {
1051
        deps.push({cnum: crate_num,
P
Paul Stansifer 已提交
1052 1053 1054
                  name: intr.intern(@docstr(depdoc, tag_crate_dep_name)),
                  vers: docstr(depdoc, tag_crate_dep_vers),
                  hash: docstr(depdoc, tag_crate_dep_hash)});
1055
        crate_num += 1;
1056
    };
B
Brian Anderson 已提交
1057
    return deps;
1058 1059
}

E
Erick Tryzelaar 已提交
1060
fn list_crate_deps(intr: @ident_interner, data: @~[u8], out: io::Writer) {
1061
    out.write_str(~"=External Dependencies=\n");
1062

P
Paul Stansifer 已提交
1063 1064
    for get_crate_deps(intr, data).each |dep| {
        out.write_str(
P
Paul Stansifer 已提交
1065 1066
            fmt!("%d %s-%s-%s\n",
                 dep.cnum, *intr.get(dep.name), dep.hash, dep.vers));
1067 1068
    }

1069
    out.write_str(~"\n");
1070 1071
}

P
Paul Stansifer 已提交
1072
fn get_crate_hash(data: @~[u8]) -> ~str {
1073 1074 1075
    let cratedoc = reader::Doc(data);
    let hashdoc = reader::get_doc(cratedoc, tag_crate_hash);
    return str::from_bytes(reader::doc_data(hashdoc));
H
Haitao Li 已提交
1076 1077
}

P
Paul Stansifer 已提交
1078
fn get_crate_vers(data: @~[u8]) -> ~str {
1079
    let attrs = decoder::get_crate_attributes(data);
1080
    return match attr::last_meta_item_value_str_by_name(
1081
        attr::find_linkage_metas(attrs), ~"vers") {
1082
      Some(ref ver) => (*ver),
B
Brian Anderson 已提交
1083
      None => ~"0.0"
1084 1085 1086
    };
}

1087 1088 1089 1090
fn iter_crate_items(intr: @ident_interner, cdata: cmd,
                    get_crate_data: GetCrateDataCb,
                    proc: fn(~str, ast::def_id)) {
    for each_path(intr, cdata, get_crate_data) |path_entry| {
1091 1092 1093 1094 1095 1096
        match path_entry.def_like {
            dl_impl(*) | dl_field => {}
            dl_def(def) => {
                proc(path_entry.path_string, ast_util::def_id_of_def(def))
            }
        }
1097 1098 1099
    }
}

1100 1101
fn get_crate_module_paths(intr: @ident_interner, cdata: cmd,
                          get_crate_data: GetCrateDataCb)
P
Paul Stansifer 已提交
1102
                                    -> ~[(ast::def_id, ~str)] {
1103 1104
    fn mod_of_path(p: ~str) -> ~str {
        str::connect(vec::init(str::split_str(p, ~"::")), ~"::")
1105 1106 1107 1108
    }

    // find all module (path, def_ids), which are not
    // fowarded path due to renamed import or reexport
1109
    let mut res = ~[];
1110
    let mods = map::HashMap();
1111
    do iter_crate_items(intr, cdata, get_crate_data) |path, did| {
1112 1113 1114 1115 1116 1117 1118 1119
        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
1120
        res.push((did, path));
1121
    }
B
Brian Anderson 已提交
1122
    return do vec::filter(res) |x| {
N
Niko Matsakis 已提交
1123
        let (_, xp) = *x;
1124 1125
        mods.contains_key(xp)
    }
1126 1127
}

E
Erick Tryzelaar 已提交
1128
fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8],
P
Paul Stansifer 已提交
1129
                       out: io::Writer) {
H
Haitao Li 已提交
1130
    let hash = get_crate_hash(bytes);
1131
    let md = reader::Doc(bytes);
P
Paul Stansifer 已提交
1132 1133
    list_crate_attributes(intr, md, hash, out);
    list_crate_deps(intr, bytes, out);
1134 1135
}

1136 1137 1138 1139 1140 1141 1142
// Translates a def_id from an external crate to a def_id for the current
// compilation environment. We use this when trying to load types from
// external crates - if those types further refer to types in other crates
// then we must translate the crate number from that encoded in the external
// crate to the correct local crate number.
fn translate_def_id(cdata: cmd, did: ast::def_id) -> ast::def_id {
    if did.crate == ast::local_crate {
B
Brian Anderson 已提交
1143
        return {crate: cdata.cnum, node: did.node};
1144 1145
    }

1146
    match cdata.cnum_map.find(did.crate) {
B
Brian Anderson 已提交
1147 1148
      option::Some(n) => return {crate: n, node: did.node},
      option::None => fail ~"didn't find a crate in the cnum_map"
1149 1150 1151
    }
}

1152 1153 1154 1155 1156 1157 1158
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: