2013-09-09 21:57:50 -04:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 16:48:01 -08:00
|
|
|
// 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.
|
|
|
|
|
2013-03-13 22:25:28 -04:00
|
|
|
use abi::AbiSet;
|
2012-09-04 11:37:29 -07:00
|
|
|
use ast::*;
|
2012-12-23 17:41:37 -05:00
|
|
|
use ast;
|
2013-03-26 16:38:07 -04:00
|
|
|
use ast_util::{inlined_item_utils, stmt_id};
|
2012-12-23 17:41:37 -05:00
|
|
|
use ast_util;
|
2013-08-31 18:13:04 +02:00
|
|
|
use codemap::Span;
|
2012-12-23 17:41:37 -05:00
|
|
|
use codemap;
|
2013-12-31 23:17:59 +09:00
|
|
|
use diagnostic::SpanHandler;
|
2013-09-02 22:34:37 -07:00
|
|
|
use parse::token::get_ident_interner;
|
2012-09-04 11:37:29 -07:00
|
|
|
use parse::token::ident_interner;
|
2013-07-19 18:42:11 -07:00
|
|
|
use parse::token::special_idents;
|
2012-12-23 17:41:37 -05:00
|
|
|
use print::pprust;
|
2013-07-19 18:42:11 -07:00
|
|
|
use visit::{Visitor, fn_kind};
|
2012-12-23 17:41:37 -05:00
|
|
|
use visit;
|
|
|
|
|
2013-06-24 20:40:33 -04:00
|
|
|
use std::hashmap::HashMap;
|
|
|
|
use std::vec;
|
2011-06-19 22:41:21 +02:00
|
|
|
|
2013-07-02 12:47:32 -07:00
|
|
|
#[deriving(Clone, Eq)]
|
2013-01-29 13:54:06 -08:00
|
|
|
pub enum path_elt {
|
2013-09-02 02:50:59 +02:00
|
|
|
path_mod(Ident),
|
2013-09-02 22:34:37 -07:00
|
|
|
path_name(Ident),
|
2013-08-30 00:47:10 -07:00
|
|
|
|
|
|
|
// A pretty name can come from an `impl` block. We attempt to select a
|
|
|
|
// reasonable name for debuggers to see, but to guarantee uniqueness with
|
|
|
|
// other paths the hash should also be taken into account during symbol
|
|
|
|
// generation.
|
|
|
|
path_pretty_name(Ident, u64),
|
2012-08-27 16:26:35 -07:00
|
|
|
}
|
|
|
|
|
2013-09-11 11:08:44 +02:00
|
|
|
impl path_elt {
|
|
|
|
pub fn ident(&self) -> Ident {
|
|
|
|
match *self {
|
|
|
|
path_mod(ident) |
|
|
|
|
path_name(ident) |
|
|
|
|
path_pretty_name(ident, _) => ident
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-29 13:54:06 -08:00
|
|
|
pub type path = ~[path_elt];
|
2012-02-03 09:53:37 +01:00
|
|
|
|
2013-06-05 21:57:24 +10:00
|
|
|
pub fn path_to_str_with_sep(p: &[path_elt], sep: &str, itr: @ident_interner)
|
2013-01-29 13:54:06 -08:00
|
|
|
-> ~str {
|
2013-11-20 16:23:04 -08:00
|
|
|
let strs = p.map(|e| {
|
2012-09-21 18:43:30 -07:00
|
|
|
match *e {
|
2013-08-30 00:47:10 -07:00
|
|
|
path_mod(s) | path_name(s) | path_pretty_name(s, _) => {
|
|
|
|
itr.get(s.name)
|
|
|
|
}
|
2012-02-10 06:01:32 -08:00
|
|
|
}
|
2013-11-20 16:23:04 -08:00
|
|
|
});
|
2013-06-10 23:25:25 +10:00
|
|
|
strs.connect(sep)
|
2012-02-10 06:01:32 -08:00
|
|
|
}
|
|
|
|
|
2013-09-02 02:50:59 +02:00
|
|
|
pub fn path_ident_to_str(p: &path, i: Ident, itr: @ident_interner) -> ~str {
|
2013-06-08 21:38:47 -04:00
|
|
|
if p.is_empty() {
|
2013-06-13 03:02:55 +10:00
|
|
|
itr.get(i.name).to_owned()
|
2012-03-28 12:54:06 -07:00
|
|
|
} else {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("{}::{}", path_to_str(*p, itr), itr.get(i.name))
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-29 13:54:06 -08:00
|
|
|
pub fn path_to_str(p: &[path_elt], itr: @ident_interner) -> ~str {
|
2013-06-05 21:57:24 +10:00
|
|
|
path_to_str_with_sep(p, "::", itr)
|
2012-02-10 06:01:32 -08:00
|
|
|
}
|
|
|
|
|
2013-01-29 13:54:06 -08:00
|
|
|
pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
|
2013-01-09 23:17:57 -08:00
|
|
|
match pe {
|
2013-08-30 00:47:10 -07:00
|
|
|
path_mod(s) | path_name(s) | path_pretty_name(s, _) => {
|
|
|
|
itr.get(s.name).to_owned()
|
|
|
|
}
|
2013-01-09 23:17:57 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-01 16:30:21 +11:00
|
|
|
/// write a "pretty" version of `ty` to `out`. This is designed so
|
|
|
|
/// that symbols of `impl`'d methods give some hint of where they came
|
|
|
|
/// from, even if it's hard to read (previously they would all just be
|
|
|
|
/// listed as `__extensions__::method_name::hash`, with no indication
|
|
|
|
/// of the type).
|
|
|
|
// XXX: these dollar signs and the names in general are actually a
|
|
|
|
// relic of $ being one of the very few valid symbol names on
|
|
|
|
// unix. These kinds of details shouldn't be exposed way up here
|
|
|
|
// in the ast.
|
|
|
|
fn pretty_ty(ty: &Ty, itr: @ident_interner, out: &mut ~str) {
|
|
|
|
let (prefix, subty) = match ty.node {
|
|
|
|
ty_uniq(ty) => ("$UP$", &*ty),
|
|
|
|
ty_box(mt { ty, .. }) => ("$SP$", &*ty),
|
|
|
|
ty_ptr(mt { ty, mutbl }) => (if mutbl == MutMutable {"$RPmut$"} else {"$RP$"},
|
|
|
|
&*ty),
|
|
|
|
ty_rptr(_, mt { ty, mutbl }) => (if mutbl == MutMutable {"$BPmut$"} else {"$BP$"},
|
|
|
|
&*ty),
|
|
|
|
|
|
|
|
ty_vec(ty) => ("$VEC$", &*ty),
|
|
|
|
ty_fixed_length_vec(ty, _) => ("$FIXEDVEC$", &*ty),
|
|
|
|
|
|
|
|
// these can't be represented as <prefix><contained ty>, so
|
|
|
|
// need custom handling.
|
|
|
|
ty_nil => { out.push_str("$NIL$"); return }
|
|
|
|
ty_path(ref path, _, _) => {
|
|
|
|
out.push_str(itr.get(path.segments.last().identifier.name));
|
|
|
|
return
|
|
|
|
}
|
|
|
|
ty_tup(ref tys) => {
|
|
|
|
out.push_str(format!("$TUP_{}$", tys.len()));
|
|
|
|
for subty in tys.iter() {
|
|
|
|
pretty_ty(*subty, itr, out);
|
|
|
|
out.push_char('$');
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// meh, better than nothing.
|
|
|
|
ty_bot => { out.push_str("$BOT$"); return }
|
|
|
|
ty_closure(..) => { out.push_str("$CLOSURE$"); return }
|
|
|
|
ty_bare_fn(..) => { out.push_str("$FN$"); return }
|
|
|
|
ty_typeof(..) => { out.push_str("$TYPEOF$"); return }
|
|
|
|
ty_infer(..) => { out.push_str("$INFER$"); return }
|
|
|
|
|
2013-09-06 23:56:17 -07:00
|
|
|
};
|
2014-01-01 16:30:21 +11:00
|
|
|
|
|
|
|
out.push_str(prefix);
|
|
|
|
pretty_ty(subty, itr, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn impl_pretty_name(trait_ref: &Option<trait_ref>, ty: &Ty) -> path_elt {
|
|
|
|
let itr = get_ident_interner();
|
|
|
|
|
2013-09-06 23:56:17 -07:00
|
|
|
let hash = (trait_ref, ty).hash();
|
2014-01-01 16:30:21 +11:00
|
|
|
let mut pretty;
|
2013-09-06 23:56:17 -07:00
|
|
|
match *trait_ref {
|
2014-01-01 16:30:21 +11:00
|
|
|
None => pretty = ~"",
|
2013-09-06 23:56:17 -07:00
|
|
|
Some(ref trait_ref) => {
|
2014-01-01 16:30:21 +11:00
|
|
|
pretty = itr.get(trait_ref.path.segments.last().identifier.name).to_owned();
|
|
|
|
pretty.push_char('$');
|
2013-09-06 23:56:17 -07:00
|
|
|
}
|
2014-01-01 16:30:21 +11:00
|
|
|
};
|
|
|
|
pretty_ty(ty, itr, &mut pretty);
|
|
|
|
|
|
|
|
path_pretty_name(Ident::new(itr.gensym(pretty)), hash)
|
2013-09-06 23:56:17 -07:00
|
|
|
}
|
|
|
|
|
2013-07-02 12:47:32 -07:00
|
|
|
#[deriving(Clone)]
|
2013-01-29 13:54:06 -08:00
|
|
|
pub enum ast_node {
|
2012-02-03 09:53:37 +01:00
|
|
|
node_item(@item, @path),
|
2013-03-13 22:25:28 -04:00
|
|
|
node_foreign_item(@foreign_item, AbiSet, visibility, @path),
|
2013-09-02 03:45:37 +02:00
|
|
|
node_trait_method(@trait_method, DefId /* trait did */,
|
2012-08-02 15:52:25 -07:00
|
|
|
@path /* path to the trait */),
|
2013-09-02 03:45:37 +02:00
|
|
|
node_method(@method, DefId /* impl did */, @path /* path to the impl */),
|
2013-11-24 18:38:41 -05:00
|
|
|
|
|
|
|
/// node_variant represents a variant of an enum, e.g., for
|
|
|
|
/// `enum A { B, C, D }`, there would be a node_item for `A`, and a
|
|
|
|
/// node_variant item for each of `B`, `C`, and `D`.
|
2013-12-01 00:00:39 +02:00
|
|
|
node_variant(P<variant>, @item, @path),
|
2013-09-02 03:45:37 +02:00
|
|
|
node_expr(@Expr),
|
|
|
|
node_stmt(@Stmt),
|
2013-09-04 19:31:13 +02:00
|
|
|
node_arg(@Pat),
|
2013-09-02 02:50:59 +02:00
|
|
|
node_local(Ident),
|
2013-12-01 00:00:39 +02:00
|
|
|
node_block(P<Block>),
|
2013-11-24 18:38:41 -05:00
|
|
|
|
|
|
|
/// node_struct_ctor represents a tuple struct.
|
2012-10-26 18:23:45 -07:00
|
|
|
node_struct_ctor(@struct_def, @item, @path),
|
2013-09-02 03:45:37 +02:00
|
|
|
node_callee_scope(@Expr)
|
2011-06-19 22:41:21 +02:00
|
|
|
}
|
|
|
|
|
2013-08-31 17:13:57 +10:00
|
|
|
impl ast_node {
|
2013-11-19 12:21:21 -08:00
|
|
|
pub fn with_attrs<T>(&self, f: |Option<&[Attribute]>| -> T) -> T {
|
2013-08-31 17:13:57 +10:00
|
|
|
let attrs = match *self {
|
|
|
|
node_item(i, _) => Some(i.attrs.as_slice()),
|
|
|
|
node_foreign_item(fi, _, _, _) => Some(fi.attrs.as_slice()),
|
|
|
|
node_trait_method(tm, _, _) => match *tm {
|
|
|
|
required(ref type_m) => Some(type_m.attrs.as_slice()),
|
|
|
|
provided(m) => Some(m.attrs.as_slice())
|
|
|
|
},
|
|
|
|
node_method(m, _, _) => Some(m.attrs.as_slice()),
|
|
|
|
node_variant(ref v, _, _) => Some(v.node.attrs.as_slice()),
|
|
|
|
// unit/tuple structs take the attributes straight from
|
|
|
|
// the struct definition.
|
|
|
|
node_struct_ctor(_, strct, _) => Some(strct.attrs.as_slice()),
|
|
|
|
_ => None
|
|
|
|
};
|
|
|
|
f(attrs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-27 10:25:59 +02:00
|
|
|
pub type map = @mut HashMap<NodeId, ast_node>;
|
2013-02-04 14:02:01 -08:00
|
|
|
|
|
|
|
pub struct Ctx {
|
2013-03-23 21:45:27 -04:00
|
|
|
map: map,
|
2013-02-04 14:02:01 -08:00
|
|
|
path: path,
|
2013-12-31 23:17:59 +09:00
|
|
|
diag: @mut SpanHandler,
|
2013-01-17 08:55:28 -08:00
|
|
|
}
|
2011-06-19 22:41:21 +02:00
|
|
|
|
2013-07-19 18:42:11 -07:00
|
|
|
impl Ctx {
|
2013-09-02 22:34:37 -07:00
|
|
|
fn extend(&self, elt: path_elt) -> @path {
|
|
|
|
@vec::append(self.path.clone(), [elt])
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
|
2013-08-08 14:23:25 +02:00
|
|
|
fn map_method(&mut self,
|
2013-09-02 03:45:37 +02:00
|
|
|
impl_did: DefId,
|
2013-07-19 18:42:11 -07:00
|
|
|
impl_path: @path,
|
|
|
|
m: @method,
|
|
|
|
is_provided: bool) {
|
|
|
|
let entry = if is_provided {
|
|
|
|
node_trait_method(@provided(m), impl_did, impl_path)
|
|
|
|
} else {
|
|
|
|
node_method(m, impl_did, impl_path)
|
|
|
|
};
|
|
|
|
self.map.insert(m.id, entry);
|
|
|
|
self.map.insert(m.self_id, node_local(special_idents::self_));
|
|
|
|
}
|
|
|
|
|
2013-08-08 14:23:25 +02:00
|
|
|
fn map_struct_def(&mut self,
|
2013-07-19 18:42:11 -07:00
|
|
|
struct_def: @ast::struct_def,
|
|
|
|
parent_node: ast_node,
|
2013-09-02 02:50:59 +02:00
|
|
|
ident: ast::Ident) {
|
2013-09-02 22:34:37 -07:00
|
|
|
let p = self.extend(path_name(ident));
|
2013-07-19 18:42:11 -07:00
|
|
|
|
|
|
|
// If this is a tuple-like struct, register the constructor.
|
|
|
|
match struct_def.ctor_id {
|
|
|
|
None => {}
|
|
|
|
Some(ctor_id) => {
|
|
|
|
match parent_node {
|
|
|
|
node_item(item, _) => {
|
|
|
|
self.map.insert(ctor_id,
|
|
|
|
node_struct_ctor(struct_def,
|
|
|
|
item,
|
|
|
|
p));
|
|
|
|
}
|
2013-10-21 13:08:31 -07:00
|
|
|
_ => fail!("struct def parent wasn't an item")
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
fn map_expr(&mut self, ex: @Expr) {
|
2013-07-19 18:42:11 -07:00
|
|
|
self.map.insert(ex.id, node_expr(ex));
|
|
|
|
|
|
|
|
// Expressions which are or might be calls:
|
|
|
|
{
|
|
|
|
let r = ex.get_callee_id();
|
2013-08-03 12:45:23 -04:00
|
|
|
for callee_id in r.iter() {
|
2013-07-19 18:42:11 -07:00
|
|
|
self.map.insert(*callee_id, node_callee_scope(ex));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-08 14:23:25 +02:00
|
|
|
visit::walk_expr(self, ex, ());
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
2013-02-04 14:02:01 -08:00
|
|
|
|
2013-08-08 14:23:25 +02:00
|
|
|
fn map_fn(&mut self,
|
2013-07-19 18:42:11 -07:00
|
|
|
fk: &visit::fn_kind,
|
|
|
|
decl: &fn_decl,
|
2013-12-01 00:00:39 +02:00
|
|
|
body: P<Block>,
|
2013-08-31 18:13:04 +02:00
|
|
|
sp: codemap::Span,
|
2013-07-19 18:42:11 -07:00
|
|
|
id: NodeId) {
|
2013-08-03 12:45:23 -04:00
|
|
|
for a in decl.inputs.iter() {
|
2013-08-23 18:45:02 +02:00
|
|
|
self.map.insert(a.id, node_arg(a.pat));
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
2013-08-29 22:29:26 -07:00
|
|
|
match *fk {
|
|
|
|
visit::fk_method(name, _, _) => { self.path.push(path_name(name)) }
|
|
|
|
_ => {}
|
|
|
|
}
|
2013-08-08 14:23:25 +02:00
|
|
|
visit::walk_fn(self, fk, decl, body, sp, id, ());
|
2013-08-29 22:29:26 -07:00
|
|
|
match *fk {
|
2013-11-28 12:22:53 -08:00
|
|
|
visit::fk_method(..) => { self.path.pop(); }
|
2013-08-29 22:29:26 -07:00
|
|
|
_ => {}
|
|
|
|
}
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
fn map_stmt(&mut self, stmt: @Stmt) {
|
2013-07-19 18:42:11 -07:00
|
|
|
self.map.insert(stmt_id(stmt), node_stmt(stmt));
|
2013-08-08 14:23:25 +02:00
|
|
|
visit::walk_stmt(self, stmt, ());
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
|
2013-12-01 00:00:39 +02:00
|
|
|
fn map_block(&mut self, b: P<Block>) {
|
|
|
|
self.map.insert(b.id, node_block(b));
|
2013-08-08 14:23:25 +02:00
|
|
|
visit::walk_block(self, b, ());
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
|
2013-11-26 03:22:21 +09:00
|
|
|
fn map_pat(&mut self, pat: &Pat) {
|
2013-07-19 18:42:11 -07:00
|
|
|
match pat.node {
|
2013-09-02 03:45:37 +02:00
|
|
|
PatIdent(_, ref path, _) => {
|
2013-07-19 18:42:11 -07:00
|
|
|
// Note: this is at least *potentially* a pattern...
|
|
|
|
self.map.insert(pat.id,
|
|
|
|
node_local(ast_util::path_to_ident(path)));
|
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
|
2013-08-08 14:23:25 +02:00
|
|
|
visit::walk_pat(self, pat, ());
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
2012-03-06 13:57:07 +01:00
|
|
|
}
|
|
|
|
|
2013-07-19 18:42:11 -07:00
|
|
|
impl Visitor<()> for Ctx {
|
2013-08-08 14:23:25 +02:00
|
|
|
fn visit_item(&mut self, i: @item, _: ()) {
|
2013-07-19 18:42:11 -07:00
|
|
|
// clone is FIXME #2543
|
|
|
|
let item_path = @self.path.clone();
|
|
|
|
self.map.insert(i.id, node_item(i, item_path));
|
|
|
|
match i.node {
|
2013-12-01 00:00:39 +02:00
|
|
|
item_impl(_, ref maybe_trait, ty, ref ms) => {
|
2013-09-02 22:34:37 -07:00
|
|
|
// Right now the ident on impls is __extensions__ which isn't
|
|
|
|
// very pretty when debugging, so attempt to select a better
|
|
|
|
// name to use.
|
2014-01-01 16:30:21 +11:00
|
|
|
let elt = impl_pretty_name(maybe_trait, ty);
|
2013-09-02 22:34:37 -07:00
|
|
|
|
2013-07-19 18:42:11 -07:00
|
|
|
let impl_did = ast_util::local_def(i.id);
|
2013-08-03 12:45:23 -04:00
|
|
|
for m in ms.iter() {
|
2013-09-02 22:34:37 -07:00
|
|
|
let extended = { self.extend(elt) };
|
2013-08-08 14:23:25 +02:00
|
|
|
self.map_method(impl_did, extended, *m, false)
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
2013-08-30 00:47:10 -07:00
|
|
|
|
2013-09-02 22:34:37 -07:00
|
|
|
self.path.push(elt);
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
item_enum(ref enum_definition, _) => {
|
2013-12-01 00:00:39 +02:00
|
|
|
for &v in enum_definition.variants.iter() {
|
2013-09-02 22:34:37 -07:00
|
|
|
let elt = path_name(i.ident);
|
2013-07-19 18:42:11 -07:00
|
|
|
self.map.insert(v.node.id,
|
2013-12-01 00:00:39 +02:00
|
|
|
node_variant(v, i, self.extend(elt)));
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
item_foreign_mod(ref nm) => {
|
2013-08-03 12:45:23 -04:00
|
|
|
for nitem in nm.items.iter() {
|
2013-07-19 18:42:11 -07:00
|
|
|
// Compute the visibility for this native item.
|
|
|
|
let visibility = match nitem.vis {
|
|
|
|
public => public,
|
|
|
|
private => private,
|
|
|
|
inherited => i.vis
|
|
|
|
};
|
|
|
|
|
|
|
|
self.map.insert(nitem.id,
|
|
|
|
node_foreign_item(*nitem,
|
|
|
|
nm.abis,
|
|
|
|
visibility,
|
|
|
|
// FIXME (#2543)
|
|
|
|
// Anonymous extern
|
|
|
|
// mods go in the
|
|
|
|
// parent scope.
|
|
|
|
@self.path.clone()
|
2013-10-10 12:57:34 -07:00
|
|
|
));
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
item_struct(struct_def, _) => {
|
|
|
|
self.map_struct_def(struct_def,
|
|
|
|
node_item(i, item_path),
|
|
|
|
i.ident)
|
|
|
|
}
|
|
|
|
item_trait(_, ref traits, ref methods) => {
|
2013-08-03 12:45:23 -04:00
|
|
|
for p in traits.iter() {
|
2013-07-19 18:42:11 -07:00
|
|
|
self.map.insert(p.ref_id, node_item(i, item_path));
|
|
|
|
}
|
2013-08-03 12:45:23 -04:00
|
|
|
for tm in methods.iter() {
|
2013-09-02 22:34:37 -07:00
|
|
|
let ext = { self.extend(path_name(i.ident)) };
|
2013-07-19 18:42:11 -07:00
|
|
|
let d_id = ast_util::local_def(i.id);
|
2013-08-20 10:15:36 -07:00
|
|
|
match *tm {
|
|
|
|
required(ref m) => {
|
|
|
|
let entry =
|
|
|
|
node_trait_method(@(*tm).clone(), d_id, ext);
|
|
|
|
self.map.insert(m.id, entry);
|
|
|
|
}
|
|
|
|
provided(m) => {
|
|
|
|
self.map_method(d_id, ext, m, true);
|
|
|
|
}
|
|
|
|
}
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
match i.node {
|
|
|
|
item_mod(_) | item_foreign_mod(_) => {
|
|
|
|
self.path.push(path_mod(i.ident));
|
|
|
|
}
|
2013-11-28 12:22:53 -08:00
|
|
|
item_impl(..) => {} // this was guessed above.
|
2013-07-19 18:42:11 -07:00
|
|
|
_ => self.path.push(path_name(i.ident))
|
|
|
|
}
|
2013-08-08 14:23:25 +02:00
|
|
|
visit::walk_item(self, i, ());
|
2013-07-19 18:42:11 -07:00
|
|
|
self.path.pop();
|
|
|
|
}
|
|
|
|
|
2013-11-26 03:22:21 +09:00
|
|
|
fn visit_pat(&mut self, pat: &Pat, _: ()) {
|
2013-07-19 18:42:11 -07:00
|
|
|
self.map_pat(pat);
|
2013-08-08 14:23:25 +02:00
|
|
|
visit::walk_pat(self, pat, ())
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
fn visit_expr(&mut self, expr: @Expr, _: ()) {
|
2013-07-19 18:42:11 -07:00
|
|
|
self.map_expr(expr)
|
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
fn visit_stmt(&mut self, stmt: @Stmt, _: ()) {
|
2013-07-19 18:42:11 -07:00
|
|
|
self.map_stmt(stmt)
|
|
|
|
}
|
|
|
|
|
2013-08-08 14:23:25 +02:00
|
|
|
fn visit_fn(&mut self,
|
2013-07-19 18:42:11 -07:00
|
|
|
function_kind: &fn_kind,
|
|
|
|
function_declaration: &fn_decl,
|
2013-12-01 00:00:39 +02:00
|
|
|
block: P<Block>,
|
2013-08-31 18:13:04 +02:00
|
|
|
span: Span,
|
2013-07-19 18:42:11 -07:00
|
|
|
node_id: NodeId,
|
|
|
|
_: ()) {
|
|
|
|
self.map_fn(function_kind, function_declaration, block, span, node_id)
|
|
|
|
}
|
|
|
|
|
2013-12-01 00:00:39 +02:00
|
|
|
fn visit_block(&mut self, block: P<Block>, _: ()) {
|
2013-07-19 18:42:11 -07:00
|
|
|
self.map_block(block)
|
|
|
|
}
|
|
|
|
|
2013-08-08 14:23:25 +02:00
|
|
|
fn visit_ty(&mut self, typ: &Ty, _: ()) {
|
|
|
|
visit::walk_ty(self, typ, ())
|
2013-07-19 18:42:11 -07:00
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
}
|
|
|
|
|
2013-12-31 23:17:59 +09:00
|
|
|
pub fn map_crate(diag: @mut SpanHandler, c: &Crate) -> map {
|
2013-02-04 14:02:01 -08:00
|
|
|
let cx = @mut Ctx {
|
2013-04-03 09:28:36 -04:00
|
|
|
map: @mut HashMap::new(),
|
2013-02-04 14:02:01 -08:00
|
|
|
path: ~[],
|
2013-01-17 08:55:28 -08:00
|
|
|
diag: diag,
|
|
|
|
};
|
2013-08-08 14:23:25 +02:00
|
|
|
visit::walk_crate(cx, c, ());
|
2013-03-23 21:45:27 -04:00
|
|
|
cx.map
|
2011-06-19 22:41:21 +02:00
|
|
|
}
|
|
|
|
|
2012-02-14 15:21:53 -08:00
|
|
|
// Used for items loaded from external crate that are being inlined into this
|
2012-03-02 13:14:10 -08:00
|
|
|
// crate. The `path` should be the path to the item but should not include
|
|
|
|
// the item itself.
|
2013-12-31 23:17:59 +09:00
|
|
|
pub fn map_decoded_item(diag: @mut SpanHandler,
|
2013-02-04 14:02:01 -08:00
|
|
|
map: map,
|
2013-04-17 12:15:08 -04:00
|
|
|
path: path,
|
|
|
|
ii: &inlined_item) {
|
2012-02-14 15:21:53 -08:00
|
|
|
// I believe it is ok for the local IDs of inlined items from other crates
|
|
|
|
// to overlap with the local ids from this crate, so just generate the ids
|
2013-07-19 18:42:11 -07:00
|
|
|
// starting from 0.
|
2013-02-04 14:02:01 -08:00
|
|
|
let cx = @mut Ctx {
|
2013-03-23 21:45:27 -04:00
|
|
|
map: map,
|
2013-07-02 12:47:32 -07:00
|
|
|
path: path.clone(),
|
2013-01-17 08:55:28 -08:00
|
|
|
diag: diag,
|
|
|
|
};
|
2012-03-02 13:14:10 -08:00
|
|
|
|
2013-09-26 21:53:40 -07:00
|
|
|
// Methods get added to the AST map when their impl is visited. Since we
|
2012-03-02 13:14:10 -08:00
|
|
|
// don't decode and instantiate the impl, but just the method, we have to
|
2013-09-26 21:53:40 -07:00
|
|
|
// add it to the table now. Likewise with foreign items.
|
2013-04-17 12:15:08 -04:00
|
|
|
match *ii {
|
2013-11-28 12:22:53 -08:00
|
|
|
ii_item(..) => {} // fallthrough
|
2013-07-19 18:42:11 -07:00
|
|
|
ii_foreign(i) => {
|
|
|
|
cx.map.insert(i.id, node_foreign_item(i,
|
|
|
|
AbiSet::Intrinsic(),
|
|
|
|
i.vis, // Wrong but OK
|
|
|
|
@path));
|
2012-02-22 16:57:23 +01:00
|
|
|
}
|
2013-07-19 18:42:11 -07:00
|
|
|
ii_method(impl_did, is_provided, m) => {
|
|
|
|
cx.map_method(impl_did, @path, m, is_provided);
|
2012-08-02 15:52:25 -07:00
|
|
|
}
|
2011-06-19 22:41:21 +02:00
|
|
|
}
|
2013-03-15 15:24:24 -04:00
|
|
|
|
2013-07-19 18:42:11 -07:00
|
|
|
// visit the item / method contents and add those to the map:
|
2013-08-08 14:23:25 +02:00
|
|
|
ii.accept((), cx);
|
2012-08-17 14:09:20 -07:00
|
|
|
}
|
|
|
|
|
2013-07-27 10:25:59 +02:00
|
|
|
pub fn node_id_to_str(map: map, id: NodeId, itr: @ident_interner) -> ~str {
|
2013-02-05 19:41:45 -08:00
|
|
|
match map.find(&id) {
|
2012-08-20 12:23:37 -07:00
|
|
|
None => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("unknown node (id={})", id)
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
2013-03-23 21:45:27 -04:00
|
|
|
Some(&node_item(item, path)) => {
|
2013-05-12 00:25:31 -04:00
|
|
|
let path_str = path_ident_to_str(path, item.ident, itr);
|
2012-08-09 09:59:50 -07:00
|
|
|
let item_str = match item.node {
|
2013-11-28 12:22:53 -08:00
|
|
|
item_static(..) => ~"static",
|
|
|
|
item_fn(..) => ~"fn",
|
|
|
|
item_mod(..) => ~"mod",
|
|
|
|
item_foreign_mod(..) => ~"foreign mod",
|
|
|
|
item_ty(..) => ~"ty",
|
|
|
|
item_enum(..) => ~"enum",
|
|
|
|
item_struct(..) => ~"struct",
|
|
|
|
item_trait(..) => ~"trait",
|
|
|
|
item_impl(..) => ~"impl",
|
|
|
|
item_mac(..) => ~"macro"
|
2012-08-09 09:59:50 -07:00
|
|
|
};
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("{} {} (id={})", item_str, path_str, id)
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
2013-03-23 21:45:27 -04:00
|
|
|
Some(&node_foreign_item(item, abi, _, path)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("foreign item {} with abi {:?} (id={})",
|
2013-05-12 00:25:31 -04:00
|
|
|
path_ident_to_str(path, item.ident, itr), abi, id)
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
2013-03-23 21:45:27 -04:00
|
|
|
Some(&node_method(m, _, path)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("method {} in {} (id={})",
|
2013-06-13 03:02:55 +10:00
|
|
|
itr.get(m.ident.name), path_to_str(*path, itr), id)
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
2013-03-23 21:45:27 -04:00
|
|
|
Some(&node_trait_method(ref tm, _, path)) => {
|
2013-02-17 22:20:36 -08:00
|
|
|
let m = ast_util::trait_method_to_ty_method(&**tm);
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("method {} in {} (id={})",
|
2013-06-13 03:02:55 +10:00
|
|
|
itr.get(m.ident.name), path_to_str(*path, itr), id)
|
2012-08-02 15:52:25 -07:00
|
|
|
}
|
2013-03-23 21:45:27 -04:00
|
|
|
Some(&node_variant(ref variant, _, path)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("variant {} in {} (id={})",
|
2013-06-13 03:02:55 +10:00
|
|
|
itr.get(variant.node.name.name), path_to_str(*path, itr), id)
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
2013-03-23 21:45:27 -04:00
|
|
|
Some(&node_expr(expr)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("expr {} (id={})", pprust::expr_to_str(expr, itr), id)
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
2013-03-15 15:24:24 -04:00
|
|
|
Some(&node_callee_scope(expr)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("callee_scope {} (id={})", pprust::expr_to_str(expr, itr), id)
|
2013-03-15 15:24:24 -04:00
|
|
|
}
|
2013-03-23 21:45:27 -04:00
|
|
|
Some(&node_stmt(stmt)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("stmt {} (id={})",
|
2013-04-17 12:15:08 -04:00
|
|
|
pprust::stmt_to_str(stmt, itr), id)
|
2012-08-17 14:09:20 -07:00
|
|
|
}
|
2013-08-23 18:45:02 +02:00
|
|
|
Some(&node_arg(pat)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("arg {} (id={})", pprust::pat_to_str(pat, itr), id)
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
2013-03-15 15:24:24 -04:00
|
|
|
Some(&node_local(ident)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("local (id={}, name={})", id, itr.get(ident.name))
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
2013-12-01 00:00:39 +02:00
|
|
|
Some(&node_block(block)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("block {} (id={})", pprust::block_to_str(block, itr), id)
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
2013-07-29 13:44:53 -07:00
|
|
|
Some(&node_struct_ctor(_, _, path)) => {
|
2013-09-27 21:01:58 -07:00
|
|
|
format!("struct_ctor {} (id={})", path_to_str(*path, itr), id)
|
2012-10-24 14:36:00 -07:00
|
|
|
}
|
2012-03-28 12:54:06 -07:00
|
|
|
}
|
|
|
|
}
|
2012-11-30 11:24:16 -08:00
|
|
|
|
2013-11-19 12:21:21 -08:00
|
|
|
pub fn node_item_query<Result>(items: map, id: NodeId, query: |@item| -> Result, error_msg: ~str)
|
|
|
|
-> Result {
|
2013-02-05 19:41:45 -08:00
|
|
|
match items.find(&id) {
|
2013-03-23 21:45:27 -04:00
|
|
|
Some(&node_item(it, _)) => query(it),
|
2013-10-21 13:08:31 -07:00
|
|
|
_ => fail!("{}", error_msg)
|
2012-11-30 11:24:16 -08:00
|
|
|
}
|
|
|
|
}
|
2013-10-29 06:03:32 -04:00
|
|
|
|
2013-12-19 14:41:59 +08:00
|
|
|
pub fn node_span(items: map,
|
2013-10-29 06:03:32 -04:00
|
|
|
id: ast::NodeId)
|
|
|
|
-> Span {
|
|
|
|
match items.find(&id) {
|
|
|
|
Some(&node_item(item, _)) => item.span,
|
2013-12-19 14:41:59 +08:00
|
|
|
Some(&node_foreign_item(foreign_item, _, _, _)) => foreign_item.span,
|
|
|
|
Some(&node_trait_method(@required(ref type_method), _, _)) => type_method.span,
|
|
|
|
Some(&node_trait_method(@provided(ref method), _, _)) => method.span,
|
|
|
|
Some(&node_method(method, _, _)) => method.span,
|
|
|
|
Some(&node_variant(variant, _, _)) => variant.span,
|
|
|
|
Some(&node_expr(expr)) => expr.span,
|
|
|
|
Some(&node_stmt(stmt)) => stmt.span,
|
|
|
|
Some(&node_arg(pat)) => pat.span,
|
|
|
|
Some(&node_local(_)) => fail!("node_span: cannot get span from node_local"),
|
|
|
|
Some(&node_block(block)) => block.span,
|
|
|
|
Some(&node_struct_ctor(_, item, _)) => item.span,
|
|
|
|
Some(&node_callee_scope(expr)) => expr.span,
|
|
|
|
None => fail!("node_span: could not find id {}", id),
|
2013-10-29 06:03:32 -04:00
|
|
|
}
|
|
|
|
}
|