decoder.rs 39.1 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

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

14 15
use core::prelude::*;

16 17 18 19 20 21
use cmd = metadata::cstore::crate_metadata;
use dvec::DVec;
use hash::{Hash, HashUtil};
use io::WriterUtil;
use metadata::common::*;
use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo};
22 23 24
use metadata::csearch;
use metadata::cstore;
use metadata::decoder;
25 26 27 28 29
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;

30 31 32 33 34 35 36 37
use core::cmp;
use core::dvec;
use core::int;
use core::io;
use core::option;
use core::str;
use core::vec;
use std::ebml::reader;
38
use std::ebml;
39
use std::map::HashMap;
40
use std::map;
41
use std::serialize::Decodable;
P
Patrick Walton 已提交
42
use syntax::ast_map;
43
use syntax::attr;
P
Patrick Walton 已提交
44 45
use syntax::diagnostic::span_handler;
use syntax::parse::token::ident_interner;
46 47
use syntax::print::pprust;
use syntax::{ast, ast_util};
48

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

// Used internally by astencode:
export translate_def_id;
91

92 93 94 95 96
// 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 已提交
97

98 99
fn lookup_hash(d: ebml::Doc, eq_fn: fn(x:&[u8]) -> bool, hash: uint) ->
   Option<ebml::Doc> {
100 101
    let index = reader::get_doc(d, tag_index);
    let table = reader::get_doc(index, tag_index_table);
M
Marijn Haverbeke 已提交
102
    let hash_pos = table.start + hash % 256u * 4u;
103
    let pos = io::u64_from_be_bytes(*d.data, hash_pos, 4u) as uint;
104
    let tagged_doc = reader::doc_at(d.data, pos);
105

M
Marijn Haverbeke 已提交
106
    let belt = tag_index_buckets_bucket_elt;
107
    for reader::tagged_docs(tagged_doc.doc, belt) |elt| {
108
        let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4u) as uint;
109
        if eq_fn(vec::view(*elt.data, elt.start + 4u, elt.end)) {
110
            return Some(reader::doc_at(d.data, pos).doc);
111
        }
112
    };
B
Brian Anderson 已提交
113
    None
114 115
}

116 117
pub type GetCrateDataCb = &fn(ast::crate_num) -> cmd;

118
fn maybe_find_item(item_id: int, items: ebml::Doc) -> Option<ebml::Doc> {
119
    fn eq_item(bytes: &[u8], item_id: int) -> bool {
120
        return io::u64_from_be_bytes(vec::view(bytes, 0u, 4u), 0u, 4u) as int
121
            == item_id;
122
    }
123 124
    lookup_hash(items,
                |a| eq_item(a, item_id),
125
                item_id.hash() as uint)
126 127
}

128
fn find_item(item_id: int, items: ebml::Doc) -> ebml::Doc {
B
Brian Anderson 已提交
129
    return maybe_find_item(item_id, items).get();
130 131
}

132
// Looks up an item in the given metadata and returns an ebml doc pointing
133
// to the item data.
134
fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc {
135
    let items = reader::get_doc(reader::Doc(data), tag_items);
136
    match maybe_find_item(item_id, items) {
B
Brian Anderson 已提交
137 138
       None => fail(fmt!("lookup_item: id not found: %d", item_id)),
       Some(d) => d
T
Tim Chevalier 已提交
139
    }
140 141
}

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
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
}

165
impl Family : cmp::Eq {
166 167 168 169
    pure fn eq(&self, other: &Family) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &Family) -> bool { !(*self).eq(other) }
170
}
171

172
fn item_family(item: ebml::Doc) -> Family {
173 174
    let fam = reader::get_doc(item, tag_items_data_item_family);
    match reader::doc_as_u8(fam) as char {
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
      '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,
195
       c => fail (fmt!("unexpected family char: %c", c))
196
    }
197 198
}

199
fn item_method_sort(item: ebml::Doc) -> char {
200 201
    for reader::tagged_docs(item, tag_item_trait_method_sort) |doc| {
        return str::from_bytes(reader::doc_data(doc))[0] as char;
202 203 204 205
    }
    return 'r';
}

206
fn item_symbol(item: ebml::Doc) -> ~str {
207 208
    let sym = reader::get_doc(item, tag_items_data_item_symbol);
    return str::from_bytes(reader::doc_data(sym));
209 210
}

211
fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> {
212 213
    for reader::tagged_docs(d, tag_items_data_parent_item) |did| {
        return Some(reader::with_doc_data(did, |d| parse_def_id(d)));
214
    }
B
Brian Anderson 已提交
215
    None
216 217
}

218 219 220
fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) ->
        Option<ast::def_id> {
    let trait_did_opt = item_parent_item(d);
221 222 223
    do trait_did_opt.map |trait_did| {
        ast::def_id { crate: cnum, node: trait_did.node }
    }
224 225
}

226 227 228
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");
229
    ast::def_id { crate: cnum, node: trait_did.node }
230 231
}

232
fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id {
233 234
    let tagdoc = reader::get_doc(d, tag_def_id);
    return translate_def_id(cdata, reader::with_doc_data(tagdoc,
235
                                                    |d| parse_def_id(d)));
T
Tim Chevalier 已提交
236 237
}

238
fn each_reexport(d: ebml::Doc, f: fn(ebml::Doc) -> bool) {
239
    for reader::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| {
240 241 242 243 244 245
        if !f(reexport_doc) {
            return;
        }
    }
}

246
fn field_mutability(d: ebml::Doc) -> ast::struct_mutability {
247
    // Use maybe_get_doc in case it's a method
B
Brian Anderson 已提交
248
    option::map_default(
249 250
        &reader::maybe_get_doc(d, tag_struct_mut),
        ast::struct_immutable,
B
Brian Anderson 已提交
251
        |d| {
252
            match reader::doc_as_u8(*d) as char {
253 254
              'm' => ast::struct_mutable,
              _   => ast::struct_immutable
B
Brian Anderson 已提交
255 256
            }
        })
257 258
}

259
fn variant_disr_val(d: ebml::Doc) -> Option<int> {
260 261
    do option::chain(reader::maybe_get_doc(d, tag_disr_val)) |val_doc| {
        int::parse_bytes(reader::doc_data(val_doc), 10u)
262 263 264
    }
}

265
fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
266
    let tp = reader::get_doc(doc, tag_items_data_item_type);
267 268
    parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
                  |_, did| translate_def_id(cdata, did))
269 270
}

271
fn item_type(item_id: ast::def_id, item: ebml::Doc,
272
             tcx: ty::ctxt, cdata: cmd) -> ty::t {
273
    let t = doc_type(item, tcx, cdata);
274
    if family_names_type(item_family(item)) {
275
        ty::mk_with_id(tcx, t, item_id)
276
    } else { t }
277 278
}

279
fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] {
280
    let mut results = ~[];
281
    for reader::tagged_docs(item, tag_impl_trait) |ity| {
282
        results.push(doc_type(ity, tcx, cdata));
283
    };
284
    results
285 286
}

287
fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd)
288 289
    -> @~[ty::param_bounds] {
    let mut bounds = ~[];
290
    for reader::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| {
291 292
        let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx,
                                   |_, did| translate_def_id(cdata, did));
293
        bounds.push(bd);
294
    }
295
    @bounds
296 297
}

298
fn item_ty_region_param(item: ebml::Doc) -> Option<ty::region_variance> {
299
    reader::maybe_get_doc(item, tag_region_param).map(|doc| {
300
        Decodable::decode(&reader::Decoder(*doc))
301
    })
302 303
}

304
fn item_ty_param_count(item: ebml::Doc) -> uint {
305
    let mut n = 0u;
306
    reader::tagged_docs(item, tag_items_data_item_ty_param_bounds,
307
                      |_p| { n += 1u; true } );
308 309 310
    n
}

311
fn enum_variant_ids(item: ebml::Doc, cdata: cmd) -> ~[ast::def_id] {
312
    let mut ids: ~[ast::def_id] = ~[];
M
Marijn Haverbeke 已提交
313
    let v = tag_items_data_item_variant;
314 315
    for reader::tagged_docs(item, v) |p| {
        let ext = reader::with_doc_data(p, |d| parse_def_id(d));
316
        ids.push(ast::def_id { crate: cdata.cnum, node: ext.node });
317
    };
B
Brian Anderson 已提交
318
    return ids;
319 320
}

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

324 325
    let len_doc = reader::get_doc(path_doc, tag_path_len);
    let len = reader::doc_as_u32(len_doc) as uint;
326

327
    let mut result = vec::with_capacity(len);
328
    for reader::docs(path_doc) |tag, elt_doc| {
329
        if tag == tag_path_elt_mod {
330
            let str = reader::doc_as_str(elt_doc);
331
            result.push(ast_map::path_mod(intr.intern(@str)));
332
        } else if tag == tag_path_elt_name {
333
            let str = reader::doc_as_str(elt_doc);
334
            result.push(ast_map::path_name(intr.intern(@str)));
335 336 337 338 339
        } else {
            // ignore tag_path_len element
        }
    }

B
Brian Anderson 已提交
340
    return result;
341 342
}

343
fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident {
344 345
    let name = reader::get_doc(item, tag_paths_data_name);
    intr.intern(@str::from_bytes(reader::doc_data(name)))
346 347
}

348
fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
349 350
    -> def_like
{
351 352
    let fam = item_family(item);
    match fam {
353
        Const     => dl_def(ast::def_const(did)),
354
        Struct    => dl_def(ast::def_struct(did)),
355 356 357 358 359
        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 => {
360 361
            let trait_did_opt = translated_parent_item_opt(cnum, item);
            dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn))
362 363
        }
        StaticMethod => {
364 365
            let trait_did_opt = translated_parent_item_opt(cnum, item);
            dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn))
366 367
        }
        PureStaticMethod => {
368 369
            let trait_did_opt = translated_parent_item_opt(cnum, item);
            dl_def(ast::def_static_method(did, trait_did_opt, ast::pure_fn))
370 371 372 373 374 375 376 377 378 379 380
        }
        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,
381
    }
382 383
}

384 385 386
fn lookup_def(cnum: ast::crate_num, data: @~[u8], did_: ast::def_id) ->
   ast::def {
    let item = lookup_item(did_.node, data);
387
    let did = ast::def_id { crate: cnum, node: did_.node };
388
    // We treat references to enums as references to types.
B
Brian Anderson 已提交
389
    return def_like_to_def(item_to_def_like(item, did, cnum));
390 391
}

392 393
fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
    -> ty::ty_param_bounds_and_ty {
394

395
    let item = lookup_item(id, cdata.data);
396 397
    let t = item_type(ast::def_id { crate: cdata.cnum, node: id }, item, tcx,
                      cdata);
M
Marijn Haverbeke 已提交
398 399
    let tp_bounds = if family_has_type_params(item_family(item)) {
        item_ty_param_bounds(item, tcx, cdata)
400
    } else { @~[] };
401
    let rp = item_ty_region_param(item);
402 403 404
    return {bounds: tp_bounds,
            region_param: rp,
            ty: t};
405 406
}

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

410
    let item = lookup_item(id, cdata.data);
B
Brian Anderson 已提交
411
    return item_ty_region_param(item);
412 413
}

414
fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
415
    item_ty_param_count(lookup_item(id, data))
416 417
}

418 419
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)
420 421
}

E
Erick Tryzelaar 已提交
422
fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
B
Brian Anderson 已提交
423
                   name: ast::ident) -> ast::def_id {
424
    let items = reader::get_doc(reader::Doc(cdata.data), tag_items);
B
Brian Anderson 已提交
425
    let mut found = None;
426
    for reader::tagged_docs(find_item(id, items), tag_item_impl_method)
427
        |mid| {
428
            let m_did = reader::with_doc_data(mid, |d| parse_def_id(d));
429 430 431
            if item_name(intr, find_item(m_did.node, items)) == name {
                found = Some(translate_def_id(cdata, m_did));
            }
432
        }
B
Brian Anderson 已提交
433
    found.get()
434 435
}

436
fn struct_dtor(cdata: cmd, id: ast::node_id) -> Option<ast::def_id> {
437
    let items = reader::get_doc(reader::Doc(cdata.data), tag_items);
B
Brian Anderson 已提交
438
    let mut found = None;
439
    let cls_items = match maybe_find_item(id, items) {
B
Brian Anderson 已提交
440
            Some(it) => it,
441
            None     => fail (fmt!("struct_dtor: class id not found \
P
Paul Stansifer 已提交
442
              when looking up dtor for %d", id))
443
    };
444 445 446
    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 已提交
447
         found = Some(translate_def_id(cdata, did));
448 449
    };
    found
450 451
}

452
fn get_symbol(data: @~[u8], id: ast::node_id) -> ~str {
B
Brian Anderson 已提交
453
    return item_symbol(lookup_item(id, data));
454 455
}

456 457 458 459 460 461 462 463
// 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 {
464
    match def_like {
B
Brian Anderson 已提交
465 466 467
        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"
468 469 470 471
    }
}

// A path.
B
Brian Anderson 已提交
472
struct path_entry {
473
    // The full path, separated by '::'.
474
    path_string: ~str,
475
    // The definition, implementation, or field that this path corresponds to.
476
    def_like: def_like,
B
Brian Anderson 已提交
477
}
478

479
fn path_entry(+path_string: ~str, def_like: def_like) -> path_entry {
B
Brian Anderson 已提交
480 481 482
    path_entry {
        path_string: path_string,
        def_like: def_like
483 484 485
    }
}

486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
/// Iterates over the language items in the given crate.
fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) {
    let root = reader::Doc(cdata.data);
    let lang_items = reader::get_doc(root, tag_lang_items);
    for reader::tagged_docs(lang_items, tag_lang_items_item) |item_doc| {
        let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id);
        let id = reader::doc_as_u32(id_doc) as uint;
        let node_id_doc = reader::get_doc(item_doc,
                                          tag_lang_items_item_node_id);
        let node_id = reader::doc_as_u32(node_id_doc) as ast::node_id;

        if !f(node_id, id) {
            break;
        }
    }
}

503
/// Iterates over all the paths in the given crate.
504 505 506
fn each_path(intr: @ident_interner, cdata: cmd,
             get_crate_data: GetCrateDataCb,
             f: fn(path_entry) -> bool) {
507 508 509
    let root = reader::Doc(cdata.data);
    let items = reader::get_doc(root, tag_items);
    let items_data = reader::get_doc(items, tag_items_data);
510 511 512 513

    let mut broken = false;

    // First, go through all the explicit items.
514
    for reader::tagged_docs(items_data, tag_items_data_item) |item_doc| {
515
        if !broken {
P
Paul Stansifer 已提交
516 517
            let path = ast_map::path_to_str_with_sep(
                item_path(intr, item_doc), ~"::", intr);
518
            if path != ~"" {
519
                // Extract the def ID.
520
                let def_id = item_def_id(item_doc, cdata);
521 522

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

                // Hand the information off to the iteratee.
527 528
                // XXX: Bad copy.
                let this_path_entry = path_entry(copy path, def_like);
529 530 531 532
                if !f(this_path_entry) {
                    broken = true;      // XXX: This is awful.
                }
            }
533

534 535 536 537
            // If this is a module, find the reexports.
            for each_reexport(item_doc) |reexport_doc| {
                if !broken {
                    let def_id_doc =
538
                        reader::get_doc(reexport_doc,
539 540
                            tag_items_data_item_reexport_def_id);
                    let def_id =
541
                        reader::with_doc_data(def_id_doc,
542
                                              |d| parse_def_id(d));
543 544 545
                    let def_id = translate_def_id(cdata, def_id);

                    let reexport_name_doc =
546
                        reader::get_doc(reexport_doc,
547
                                      tag_items_data_item_reexport_name);
548
                    let reexport_name = reader::doc_as_str(reexport_name_doc);
549 550 551 552 553 554 555

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

557 558 559 560 561
                    // 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);
562 563
                        let root = reader::Doc(crate_data.data);
                        reader::get_doc(root, tag_items)
564 565
                    };

566
                    // Get the item.
567
                    match maybe_find_item(def_id.node, other_crates_items) {
B
Brian Anderson 已提交
568 569
                        None => {}
                        Some(item_doc) => {
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
                            // 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.
                            }
                        }
585 586 587 588 589
                    }
                }
            }
        }
    }
590

591 592 593
    // If broken, stop here.
    if broken {
        return;
594
    }
595 596
}

E
Erick Tryzelaar 已提交
597
fn get_item_path(intr: @ident_interner, cdata: cmd, id: ast::node_id)
P
Paul Stansifer 已提交
598 599
    -> ast_map::path {
    item_path(intr, lookup_item(id, cdata.data))
600 601
}

602 603 604 605
type decode_inlined_item = fn(
    cdata: cstore::crate_metadata,
    tcx: ty::ctxt,
    path: ast_map::path,
606
    par_doc: ebml::Doc) -> Option<ast::inlined_item>;
607

E
Erick Tryzelaar 已提交
608
fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt,
609 610 611
                      id: ast::node_id,
                      decode_inlined_item: decode_inlined_item
                     ) -> csearch::found_ast {
P
Paul Stansifer 已提交
612
    debug!("Looking up item: %d", id);
613
    let item_doc = lookup_item(id, cdata.data);
P
Paul Stansifer 已提交
614
    let path = vec::init(item_path(intr, item_doc));
615
    match decode_inlined_item(cdata, tcx, path, item_doc) {
616
      Some(ref ii) => csearch::found((/*bad*/copy *ii)),
B
Brian Anderson 已提交
617
      None => {
618
        match item_parent_item(item_doc) {
B
Brian Anderson 已提交
619
          Some(did) => {
620 621
            let did = translate_def_id(cdata, did);
            let parent_item = lookup_item(did.node, cdata.data);
622
            match decode_inlined_item(cdata, tcx, path,
623
                                               parent_item) {
624
              Some(ref ii) => csearch::found_parent(did, (/*bad*/copy *ii)),
B
Brian Anderson 已提交
625
              None => csearch::not_found
626 627
            }
          }
B
Brian Anderson 已提交
628
          None => csearch::not_found
629 630 631
        }
      }
    }
632 633
}

E
Erick Tryzelaar 已提交
634
fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
635
                     tcx: ty::ctxt) -> ~[ty::VariantInfo] {
636
    let data = cdata.data;
637
    let items = reader::get_doc(reader::Doc(data), tag_items);
638
    let item = find_item(id, items);
639
    let mut infos: ~[ty::VariantInfo] = ~[];
640
    let variant_ids = enum_variant_ids(item, cdata);
641
    let mut disr_val = 0;
B
Brian Anderson 已提交
642
    for variant_ids.each |did| {
M
Marijn Haverbeke 已提交
643
        let item = find_item(did.node, items);
644 645
        let ctor_ty = item_type(ast::def_id { crate: cdata.cnum, node: id},
                                item, tcx, cdata);
P
Paul Stansifer 已提交
646
        let name = item_name(intr, item);
E
Erick Tryzelaar 已提交
647
        let arg_tys = match ty::get(ctor_ty).sty {
648
          ty::ty_fn(ref f) => (*f).sig.inputs.map(|a| a.ty),
E
Erick Tryzelaar 已提交
649 650 651 652

          // Nullary enum variant.
          _ => ~[],
        };
653
        match variant_disr_val(item) {
B
Brian Anderson 已提交
654
          Some(val) => { disr_val = val; }
B
Brian Anderson 已提交
655
          _         => { /* empty */ }
656
        }
657 658 659 660 661
        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});
662
        disr_val += 1;
663
    }
B
Brian Anderson 已提交
664
    return infos;
665 666
}

667
// NB: These types are duplicated in resolve.rs
668 669 670 671 672 673 674
type method_info = {
    did: ast::def_id,
    n_tps: uint,
    ident: ast::ident,
    self_type: ast::self_ty_
};

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

677
fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ {
678
    fn get_mutability(ch: u8) -> ast::mutability {
679
        match ch as char {
680 681 682 683
            'i' => { ast::m_imm }
            'm' => { ast::m_mutbl }
            'c' => { ast::m_const }
            _ => {
P
Paul Stansifer 已提交
684
                fail fmt!("unknown mutability character: `%c`", ch as char)
685 686 687 688
            }
        }
    }

689 690
    let self_type_doc = reader::get_doc(item, tag_item_trait_method_self_ty);
    let string = reader::doc_as_str(self_type_doc);
691 692

    let self_ty_kind = string[0];
693
    match self_ty_kind as char {
694
        's' => { return ast::sty_static; }
B
Brian Anderson 已提交
695 696 697 698
        '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])); }
699
        '&' => { return ast::sty_region(get_mutability(string[1])); }
700
        _ => {
P
Paul Stansifer 已提交
701
            fail fmt!("unknown self type code: `%c`", self_ty_kind as char);
702 703 704 705
        }
    }
}

706
fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc,
P
Paul Stansifer 已提交
707
                     base_tps: uint) -> ~[@method_info] {
708
    let mut rslt = ~[];
709 710
    for reader::tagged_docs(item, tag_item_impl_method) |doc| {
        let m_did = reader::with_doc_data(doc, |d| parse_def_id(d));
711
        let mth_item = lookup_item(m_did.node, cdata.data);
712
        let self_ty = get_self_ty(mth_item);
713
        rslt.push(@{did: translate_def_id(cdata, m_did),
714
                   n_tps: item_ty_param_count(mth_item) - base_tps,
P
Paul Stansifer 已提交
715
                   ident: item_name(intr, mth_item),
716
                   self_type: self_ty});
717 718 719 720
    }
    rslt
}

E
Erick Tryzelaar 已提交
721
fn get_impls_for_mod(intr: @ident_interner, cdata: cmd,
B
Brian Anderson 已提交
722
                     m_id: ast::node_id, name: Option<ast::ident>,
723
                     get_cdata: fn(ast::crate_num) -> cmd)
724 725
                  -> @~[@_impl] {

726
    let data = cdata.data;
727
    let mod_item = lookup_item(m_id, data);
728
    let mut result = ~[];
729 730
    for reader::tagged_docs(mod_item, tag_mod_impl) |doc| {
        let did = reader::with_doc_data(doc, |d| parse_def_id(d));
731
        let local_did = translate_def_id(cdata, did);
P
Paul Stansifer 已提交
732 733
        debug!("(get impls for mod) getting did %? for '%?'",
               local_did, name);
734 735
          // The impl may be defined in a different crate. Ask the caller
          // to give us the metadata
736 737 738
        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 已提交
739
        let nm = item_name(intr, item);
B
Brian Anderson 已提交
740
        if match name { Some(n) => { n == nm } None => { true } } {
741
           let base_tps = item_ty_param_count(item);
742
           result.push(@{
743
                did: local_did, ident: nm,
P
Paul Stansifer 已提交
744
                methods: item_impl_methods(intr, impl_cdata, item, base_tps)
745
            });
746
        };
747 748 749 750
    }
    @result
}

751
/* Works for both classes and traits */
E
Erick Tryzelaar 已提交
752
fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
P
Paul Stansifer 已提交
753
                     tcx: ty::ctxt) -> @~[ty::method] {
754
    let data = cdata.data;
755
    let item = lookup_item(id, data);
756
    let mut result = ~[];
757
    for reader::tagged_docs(item, tag_item_trait_method) |mth| {
M
Marijn Haverbeke 已提交
758
        let bounds = item_ty_param_bounds(mth, tcx, cdata);
P
Paul Stansifer 已提交
759
        let name = item_name(intr, mth);
760
        let ty = doc_type(mth, tcx, cdata);
761
        let def_id = item_def_id(mth, cdata);
762
        let fty = match ty::get(ty).sty {
763
          ty::ty_fn(ref f) => (/*bad*/copy *f),
B
Brian Anderson 已提交
764
          _ => {
765
            tcx.diag.handler().bug(
766
                ~"get_trait_methods: id has non-function type");
T
Tim Chevalier 已提交
767
        } };
768
        let self_ty = get_self_ty(mth);
769 770
        result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty,
                     vis: ast::public, def_id: def_id});
771
    }
772
    debug!("get_trait_methods: }");
773 774 775
    @result
}

776 777 778 779 780 781 782
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 = ~[];

783
    for reader::tagged_docs(item, tag_item_trait_method) |mth| {
784 785 786 787 788 789 790 791 792 793
        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 {
794
            ty::ty_fn(ref f) => fty = (/*bad*/copy *f),
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
            _ => {
                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;
}

815 816 817 818
/// 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);
819
    for reader::tagged_docs(item_doc, tag_impl_trait) |trait_doc| {
820 821 822 823 824
        results.push(doc_type(trait_doc, tcx, cdata));
    }
    return dvec::unwrap(move results);
}

825 826 827
// 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 已提交
828
fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd,
P
Paul Stansifer 已提交
829
                             node_id: ast::node_id)
B
Brian Anderson 已提交
830
                          -> Option<@DVec<(ast::ident, ast::self_ty_)>> {
831 832

    let item = lookup_item(node_id, cdata.data);
833
    if item_family(item) != Trait {
B
Brian Anderson 已提交
834
        return None;
835 836
    }

837
    let resulting_methods = @DVec();
838
    for reader::tagged_docs(item, tag_item_trait_method) |method| {
839
        resulting_methods.push(
P
Paul Stansifer 已提交
840
            (item_name(intr, method), get_self_ty(method)));
841
    }
B
Brian Anderson 已提交
842
    return Some(resulting_methods);
843 844
}

845 846 847 848 849 850 851 852
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;
    }

853 854
    for reader::tagged_docs(item, tag_item_impl_type_basename) |doc| {
        return Some(intr.intern(@str::from_bytes(reader::doc_data(doc))));
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
    }

    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.
870
    for reader::tagged_docs(item, tag_impl_trait) |_doc| {
871 872 873 874
        return None;
    }

    let impl_method_ids = DVec();
875 876
    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)));
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
    }

    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));
}

906 907
fn get_item_attrs(cdata: cmd,
                  node_id: ast::node_id,
908
                  f: fn(~[@ast::meta_item])) {
909 910

    let item = lookup_item(node_id, cdata.data);
911 912
    for reader::tagged_docs(item, tag_attributes) |attributes| {
        for reader::tagged_docs(attributes, tag_attribute) |attribute| {
913 914 915 916 917
            f(get_meta_items(attribute));
        }
    }
}

918 919 920 921 922 923 924 925 926 927 928
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 已提交
929
    let data = cdata.data;
930
    let item = lookup_item(id, data);
931
    let mut result = ~[];
932
    for reader::tagged_docs(item, tag_item_field) |an_item| {
933
       let f = item_family(an_item);
934
       if f == PublicField || f == PrivateField || f == InheritedField {
P
Paul Stansifer 已提交
935
          let name = item_name(intr, an_item);
936
          let did = item_def_id(an_item, cdata);
937
          let mt = field_mutability(an_item);
938
          result.push({ident: name, id: did, vis:
939
                  family_to_visibility(f), mutability: mt});
T
Tim Chevalier 已提交
940
       }
T
Tim Chevalier 已提交
941 942 943 944
    }
    result
}

945 946 947 948 949
fn family_has_type_params(fam: Family) -> bool {
    match fam {
      Const | ForeignType | Mod | ForeignMod | PublicField | PrivateField
      | ForeignFn => false,
      _           => true
950
    }
951 952
}

953 954
fn family_names_type(fam: Family) -> bool {
    match fam { Type | Mod | Trait => true, _ => false }
955 956
}

957
fn read_path(d: ebml::Doc) -> {path: ~str, pos: uint} {
958
    let desc = reader::doc_data(d);
959
    let pos = io::u64_from_be_bytes(desc, 0u, 4u) as uint;
960
    let pathbytes = vec::slice::<u8>(desc, 4u, vec::len::<u8>(desc));
961
    let path = str::from_bytes(pathbytes);
B
Brian Anderson 已提交
962
    return {path: path, pos: pos};
963 964
}

965
fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str {
B
Brian Anderson 已提交
966
    if id.crate != ast::local_crate { return ~"external"; }
967
    let it = match maybe_find_item(id.node, items) {
B
Brian Anderson 已提交
968 969
        Some(it) => it,
        None => fail (fmt!("describe_def: item not found %?", id))
970
    };
B
Brian Anderson 已提交
971
    return item_family_to_str(item_family(it));
972 973
}

974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995
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",
996 997 998
    }
}

999
fn get_meta_items(md: ebml::Doc) -> ~[@ast::meta_item] {
1000
    let mut items: ~[@ast::meta_item] = ~[];
1001 1002 1003
    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));
1004
        items.push(attr::mk_word_item(n));
1005
    };
1006 1007 1008 1009 1010
    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));
1011 1012
        // FIXME (#623): Should be able to decode meta_name_value variants,
        // but currently the encoder just drops them
1013
        items.push(attr::mk_name_value_item_str(n, v));
1014
    };
1015 1016 1017
    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 已提交
1018
        let subitems = get_meta_items(meta_item_doc);
1019
        items.push(attr::mk_list_item(n, subitems));
1020
    };
B
Brian Anderson 已提交
1021
    return items;
1022 1023
}

1024
fn get_attributes(md: ebml::Doc) -> ~[ast::attribute] {
1025
    let mut attrs: ~[ast::attribute] = ~[];
1026
    match reader::maybe_get_doc(md, tag_attributes) {
B
Brian Anderson 已提交
1027
      option::Some(attrs_d) => {
1028
        for reader::tagged_docs(attrs_d, tag_attribute) |attr_doc| {
M
Marijn Haverbeke 已提交
1029 1030 1031
            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 已提交
1032
            assert (vec::len(meta_items) == 1u);
B
Brian Anderson 已提交
1033
            let meta_item = meta_items[0];
1034
            attrs.push(
1035 1036 1037 1038 1039 1040 1041 1042
                ast::spanned {
                    node: ast::attribute_ {
                        style: ast::attr_outer,
                        value: /*bad*/copy *meta_item,
                        is_sugared_doc: false,
                    },
                    span: ast_util::dummy_sp()
                });
1043
        };
M
Marijn Haverbeke 已提交
1044
      }
B
Brian Anderson 已提交
1045
      option::None => ()
1046
    }
B
Brian Anderson 已提交
1047
    return attrs;
1048 1049
}

E
Erick Tryzelaar 已提交
1050
fn list_meta_items(intr: @ident_interner,
1051
                   meta_items: ebml::Doc, out: io::Writer) {
B
Brian Anderson 已提交
1052
    for get_meta_items(meta_items).each |mi| {
1053
        out.write_str(fmt!("%s\n", pprust::meta_item_to_str(*mi, intr)));
1054 1055 1056
    }
}

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

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

1065
    out.write_str(~"\n\n");
1066 1067
}

1068
fn get_crate_attributes(data: @~[u8]) -> ~[ast::attribute] {
1069
    return get_attributes(reader::Doc(data));
1070 1071
}

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

E
Erick Tryzelaar 已提交
1075
fn get_crate_deps(intr: @ident_interner, data: @~[u8]) -> ~[crate_dep] {
1076
    let mut deps: ~[crate_dep] = ~[];
1077 1078
    let cratedoc = reader::Doc(data);
    let depsdoc = reader::get_doc(cratedoc, tag_crate_deps);
1079
    let mut crate_num = 1;
1080
    fn docstr(doc: ebml::Doc, tag_: uint) -> ~str {
1081
        str::from_bytes(reader::doc_data(reader::get_doc(doc, tag_)))
1082
    }
1083
    for reader::tagged_docs(depsdoc, tag_crate_dep) |depdoc| {
1084
        deps.push({cnum: crate_num,
P
Paul Stansifer 已提交
1085 1086 1087
                  name: intr.intern(@docstr(depdoc, tag_crate_dep_name)),
                  vers: docstr(depdoc, tag_crate_dep_vers),
                  hash: docstr(depdoc, tag_crate_dep_hash)});
1088
        crate_num += 1;
1089
    };
B
Brian Anderson 已提交
1090
    return deps;
1091 1092
}

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

P
Paul Stansifer 已提交
1096 1097
    for get_crate_deps(intr, data).each |dep| {
        out.write_str(
P
Paul Stansifer 已提交
1098 1099
            fmt!("%d %s-%s-%s\n",
                 dep.cnum, *intr.get(dep.name), dep.hash, dep.vers));
1100 1101
    }

1102
    out.write_str(~"\n");
1103 1104
}

P
Paul Stansifer 已提交
1105
fn get_crate_hash(data: @~[u8]) -> ~str {
1106 1107 1108
    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 已提交
1109 1110
}

P
Paul Stansifer 已提交
1111
fn get_crate_vers(data: @~[u8]) -> ~str {
1112
    let attrs = decoder::get_crate_attributes(data);
1113
    return match attr::last_meta_item_value_str_by_name(
1114
        attr::find_linkage_metas(attrs), ~"vers") {
1115
      Some(ref ver) => (/*bad*/copy *ver),
B
Brian Anderson 已提交
1116
      None => ~"0.0"
1117 1118 1119
    };
}

1120 1121
fn iter_crate_items(intr: @ident_interner, cdata: cmd,
                    get_crate_data: GetCrateDataCb,
1122
                    proc: fn(+path: ~str, ast::def_id)) {
1123
    for each_path(intr, cdata, get_crate_data) |path_entry| {
1124 1125 1126
        match path_entry.def_like {
            dl_impl(*) | dl_field => {}
            dl_def(def) => {
1127 1128
                proc(/*bad*/copy path_entry.path_string,
                     ast_util::def_id_of_def(def))
1129 1130
            }
        }
1131 1132 1133
    }
}

E
Erick Tryzelaar 已提交
1134
fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8],
P
Paul Stansifer 已提交
1135
                       out: io::Writer) {
H
Haitao Li 已提交
1136
    let hash = get_crate_hash(bytes);
1137
    let md = reader::Doc(bytes);
P
Paul Stansifer 已提交
1138 1139
    list_crate_attributes(intr, md, hash, out);
    list_crate_deps(intr, bytes, out);
1140 1141
}

1142 1143 1144 1145 1146 1147 1148
// 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 {
1149
        return ast::def_id { crate: cdata.cnum, node: did.node };
1150 1151
    }

1152
    match cdata.cnum_map.find(did.crate) {
1153
      option::Some(n) => ast::def_id { crate: n, node: did.node },
B
Brian Anderson 已提交
1154
      option::None => fail ~"didn't find a crate in the cnum_map"
1155 1156 1157
    }
}

1158 1159 1160 1161 1162 1163 1164
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: