mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 21:47:04 +00:00
commit
736886c84b
@ -28,19 +28,17 @@
|
||||
//! DumpCsvVisitor walks the AST and processes it.
|
||||
|
||||
|
||||
use super::{escape, generated_code, recorder, SaveContext, PathCollector};
|
||||
use super::{escape, generated_code, recorder, SaveContext, PathCollector, Data};
|
||||
|
||||
use session::Session;
|
||||
|
||||
use middle::def;
|
||||
use middle::ty::{self, Ty};
|
||||
use rustc::ast_map::NodeItem;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use syntax::ast_util;
|
||||
use syntax::ast::{self, NodeId, DefId};
|
||||
use syntax::codemap::*;
|
||||
use syntax::parse::token::{self, get_ident, keywords};
|
||||
@ -298,9 +296,11 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn process_method(&mut self, sig: &ast::MethodSig,
|
||||
fn process_method(&mut self,
|
||||
sig: &ast::MethodSig,
|
||||
body: Option<&ast::Block>,
|
||||
id: ast::NodeId, name: ast::Name,
|
||||
id: ast::NodeId,
|
||||
name: ast::Name,
|
||||
span: Span) {
|
||||
if generated_code(span) {
|
||||
return;
|
||||
@ -308,91 +308,22 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
|
||||
debug!("process_method: {}:{}", id, token::get_name(name));
|
||||
|
||||
let scope_id;
|
||||
// The qualname for a method is the trait name or name of the struct in an impl in
|
||||
// which the method is declared in, followed by the method's name.
|
||||
let qualname = match self.tcx.impl_of_method(ast_util::local_def(id)) {
|
||||
Some(impl_id) => match self.tcx.map.get(impl_id.node) {
|
||||
NodeItem(item) => {
|
||||
scope_id = item.id;
|
||||
match item.node {
|
||||
ast::ItemImpl(_, _, _, _, ref ty, _) => {
|
||||
let mut result = String::from("<");
|
||||
result.push_str(&ty_to_string(&**ty));
|
||||
let method_data = self.save_ctxt.get_method_data(id, name, span);
|
||||
|
||||
match self.tcx.trait_of_item(ast_util::local_def(id)) {
|
||||
Some(def_id) => {
|
||||
result.push_str(" as ");
|
||||
result.push_str(
|
||||
&self.tcx.item_path_str(def_id));
|
||||
},
|
||||
None => {}
|
||||
}
|
||||
result.push_str(">");
|
||||
result
|
||||
}
|
||||
_ => {
|
||||
self.sess.span_bug(span,
|
||||
&format!("Container {} for method {} not an impl?",
|
||||
impl_id.node, id));
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
self.sess.span_bug(span,
|
||||
&format!("Container {} for method {} is not a node item {:?}",
|
||||
impl_id.node, id, self.tcx.map.get(impl_id.node)));
|
||||
},
|
||||
},
|
||||
None => match self.tcx.trait_of_item(ast_util::local_def(id)) {
|
||||
Some(def_id) => {
|
||||
scope_id = def_id.node;
|
||||
match self.tcx.map.get(def_id.node) {
|
||||
NodeItem(_) => {
|
||||
format!("::{}", self.tcx.item_path_str(def_id))
|
||||
}
|
||||
_ => {
|
||||
self.sess.span_bug(span,
|
||||
&format!("Could not find container {} for method {}",
|
||||
def_id.node, id));
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
self.sess.span_bug(span,
|
||||
&format!("Could not find container for method {}", id));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let qualname = &format!("{}::{}", qualname, &token::get_name(name));
|
||||
|
||||
// record the decl for this def (if it has one)
|
||||
let decl_id = self.tcx.trait_item_of_item(ast_util::local_def(id))
|
||||
.and_then(|new_id| {
|
||||
let def_id = new_id.def_id();
|
||||
if def_id.node != 0 && def_id != ast_util::local_def(id) {
|
||||
Some(def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let sub_span = self.span.sub_span_after_keyword(span, keywords::Fn);
|
||||
if body.is_some() {
|
||||
self.fmt.method_str(span,
|
||||
sub_span,
|
||||
id,
|
||||
qualname,
|
||||
decl_id,
|
||||
scope_id);
|
||||
self.process_formals(&sig.decl.inputs, qualname);
|
||||
Some(method_data.span),
|
||||
method_data.id,
|
||||
&method_data.qualname,
|
||||
method_data.declaration,
|
||||
method_data.scope);
|
||||
self.process_formals(&sig.decl.inputs, &method_data.qualname);
|
||||
} else {
|
||||
self.fmt.method_decl_str(span,
|
||||
sub_span,
|
||||
id,
|
||||
qualname,
|
||||
scope_id);
|
||||
Some(method_data.span),
|
||||
method_data.id,
|
||||
&method_data.qualname,
|
||||
method_data.scope);
|
||||
}
|
||||
|
||||
// walk arg and return types
|
||||
@ -411,7 +342,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
|
||||
self.process_generic_params(&sig.generics,
|
||||
span,
|
||||
qualname,
|
||||
&method_data.qualname,
|
||||
id);
|
||||
}
|
||||
|
||||
@ -432,7 +363,6 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
parent_id: NodeId) {
|
||||
let field_data = self.save_ctxt.get_field_data(field, parent_id);
|
||||
if let Some(field_data) = field_data {
|
||||
down_cast_data!(field_data, VariableData, self, field.span);
|
||||
self.fmt.field_str(field.span,
|
||||
Some(field_data.span),
|
||||
field_data.id,
|
||||
@ -738,90 +668,51 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
|
||||
fn process_path(&mut self,
|
||||
id: NodeId,
|
||||
span: Span,
|
||||
path: &ast::Path,
|
||||
ref_kind: Option<recorder::Row>) {
|
||||
if generated_code(span) {
|
||||
return
|
||||
if generated_code(path.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
let def_map = self.tcx.def_map.borrow();
|
||||
if !def_map.contains_key(&id) {
|
||||
self.sess.span_bug(span,
|
||||
&format!("def_map has no key for {} in visit_expr", id));
|
||||
}
|
||||
let def = def_map.get(&id).unwrap().full_def();
|
||||
let sub_span = self.span.span_for_last_ident(span);
|
||||
match def {
|
||||
def::DefUpvar(..) |
|
||||
def::DefLocal(..) |
|
||||
def::DefStatic(..) |
|
||||
def::DefConst(..) |
|
||||
def::DefAssociatedConst(..) |
|
||||
def::DefVariant(..) => self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef),
|
||||
span,
|
||||
sub_span,
|
||||
def.def_id(),
|
||||
self.cur_scope),
|
||||
def::DefStruct(def_id) => self.fmt.ref_str(recorder::TypeRef,
|
||||
span,
|
||||
sub_span,
|
||||
def_id,
|
||||
self.cur_scope),
|
||||
def::DefTy(def_id, _) => self.fmt.ref_str(recorder::TypeRef,
|
||||
span,
|
||||
sub_span,
|
||||
def_id,
|
||||
self.cur_scope),
|
||||
def::DefMethod(declid, provenence) => {
|
||||
let sub_span = self.span.sub_span_for_meth_name(span);
|
||||
let defid = if declid.krate == ast::LOCAL_CRATE {
|
||||
let ti = self.tcx.impl_or_trait_item(declid);
|
||||
match provenence {
|
||||
def::FromTrait(def_id) => {
|
||||
Some(self.tcx.trait_items(def_id)
|
||||
.iter()
|
||||
.find(|mr| {
|
||||
mr.name() == ti.name()
|
||||
})
|
||||
.unwrap()
|
||||
.def_id())
|
||||
}
|
||||
def::FromImpl(def_id) => {
|
||||
let impl_items = self.tcx.impl_items.borrow();
|
||||
Some(impl_items.get(&def_id)
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|mr| {
|
||||
self.tcx.impl_or_trait_item(mr.def_id()).name()
|
||||
== ti.name()
|
||||
})
|
||||
.unwrap()
|
||||
.def_id())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.fmt.meth_call_str(span,
|
||||
sub_span,
|
||||
defid,
|
||||
Some(declid),
|
||||
self.cur_scope);
|
||||
},
|
||||
def::DefFn(def_id, _) => {
|
||||
self.fmt.fn_call_str(span,
|
||||
sub_span,
|
||||
def_id,
|
||||
self.cur_scope)
|
||||
let path_data = self.save_ctxt.get_path_data(id, path);
|
||||
match path_data {
|
||||
Data::VariableRefData(ref vrd) => {
|
||||
self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef),
|
||||
path.span,
|
||||
Some(vrd.span),
|
||||
vrd.ref_id,
|
||||
vrd.scope);
|
||||
|
||||
}
|
||||
Data::TypeRefData(ref trd) => {
|
||||
self.fmt.ref_str(recorder::TypeRef,
|
||||
path.span,
|
||||
Some(trd.span),
|
||||
trd.ref_id,
|
||||
trd.scope);
|
||||
}
|
||||
Data::MethodCallData(ref mcd) => {
|
||||
self.fmt.meth_call_str(path.span,
|
||||
Some(mcd.span),
|
||||
mcd.ref_id,
|
||||
mcd.decl_id,
|
||||
mcd.scope);
|
||||
}
|
||||
Data::FunctionCallData(fcd) => {
|
||||
self.fmt.fn_call_str(path.span,
|
||||
Some(fcd.span),
|
||||
fcd.ref_id,
|
||||
fcd.scope);
|
||||
}
|
||||
_ => {
|
||||
self.sess.span_bug(path.span,
|
||||
&format!("Unexpected data: {:?}", path_data));
|
||||
}
|
||||
_ => self.sess.span_bug(span,
|
||||
&format!("Unexpected def kind while looking \
|
||||
up path in `{}`: `{:?}`",
|
||||
self.span.snippet(span),
|
||||
def)),
|
||||
}
|
||||
// modules or types in the path prefix
|
||||
|
||||
// Modules or types in the path prefix.
|
||||
let def_map = self.tcx.def_map.borrow();
|
||||
let def = def_map.get(&id).unwrap().full_def();
|
||||
match def {
|
||||
def::DefMethod(did, _) => {
|
||||
let ti = self.tcx.impl_or_trait_item(did);
|
||||
@ -861,6 +752,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
struct_lit_data.ref_id,
|
||||
struct_lit_data.scope);
|
||||
let struct_def = struct_lit_data.ref_id;
|
||||
let scope = self.save_ctxt.enclosing_scope(ex.id);
|
||||
|
||||
for field in fields {
|
||||
if generated_code(field.ident.span) {
|
||||
@ -869,7 +761,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
|
||||
let field_data = self.save_ctxt.get_field_ref_data(field,
|
||||
struct_def,
|
||||
self.cur_scope);
|
||||
scope);
|
||||
self.fmt.ref_str(recorder::VarRef,
|
||||
field.ident.span,
|
||||
Some(field_data.span),
|
||||
@ -886,18 +778,14 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
fn process_method_call(&mut self,
|
||||
ex: &ast::Expr,
|
||||
args: &Vec<P<ast::Expr>>) {
|
||||
let method_call = ty::MethodCall::expr(ex.id);
|
||||
let method_id = self.tcx.tables.borrow().method_map[&method_call].def_id;
|
||||
let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() {
|
||||
ty::ImplContainer(_) => (Some(method_id), None),
|
||||
ty::TraitContainer(_) => (None, Some(method_id))
|
||||
};
|
||||
let sub_span = self.span.sub_span_for_meth_name(ex.span);
|
||||
self.fmt.meth_call_str(ex.span,
|
||||
sub_span,
|
||||
def_id,
|
||||
decl_id,
|
||||
self.cur_scope);
|
||||
if let Some(call_data) = self.save_ctxt.get_expr_data(ex) {
|
||||
down_cast_data!(call_data, MethodCallData, self, ex.span);
|
||||
self.fmt.meth_call_str(ex.span,
|
||||
Some(call_data.span),
|
||||
call_data.ref_id,
|
||||
call_data.decl_id,
|
||||
call_data.scope);
|
||||
}
|
||||
|
||||
// walk receiver and args
|
||||
visit::walk_exprs(self, &args);
|
||||
@ -1129,8 +1017,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||
trait_item.span, &*ty, &*expr);
|
||||
}
|
||||
ast::MethodTraitItem(ref sig, ref body) => {
|
||||
self.process_method(sig, body.as_ref().map(|x| &**x),
|
||||
trait_item.id, trait_item.ident.name, trait_item.span);
|
||||
self.process_method(sig,
|
||||
body.as_ref().map(|x| &**x),
|
||||
trait_item.id,
|
||||
trait_item.ident.name,
|
||||
trait_item.span);
|
||||
}
|
||||
ast::ConstTraitItem(_, None) |
|
||||
ast::TypeTraitItem(..) => {}
|
||||
@ -1144,8 +1035,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||
impl_item.span, &ty, &expr);
|
||||
}
|
||||
ast::MethodImplItem(ref sig, ref body) => {
|
||||
self.process_method(sig, Some(body), impl_item.id,
|
||||
impl_item.ident.name, impl_item.span);
|
||||
self.process_method(sig,
|
||||
Some(body),
|
||||
impl_item.id,
|
||||
impl_item.ident.name,
|
||||
impl_item.span);
|
||||
}
|
||||
ast::TypeImplItem(_) |
|
||||
ast::MacImplItem(_) => {}
|
||||
@ -1191,7 +1085,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||
visit::walk_expr(self, ex);
|
||||
}
|
||||
ast::ExprPath(_, ref path) => {
|
||||
self.process_path(ex.id, path.span, path, None);
|
||||
self.process_path(ex.id, path, None);
|
||||
visit::walk_expr(self, ex);
|
||||
}
|
||||
ast::ExprStruct(ref path, ref fields, ref base) =>
|
||||
@ -1287,6 +1181,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||
|
||||
// This is to get around borrow checking, because we need mut self to call process_path.
|
||||
let mut paths_to_process = vec![];
|
||||
|
||||
// process collected paths
|
||||
for &(id, ref p, immut, ref_kind) in &collector.collected_paths {
|
||||
let def_map = self.tcx.def_map.borrow();
|
||||
@ -1323,11 +1218,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||
def)
|
||||
}
|
||||
}
|
||||
|
||||
for &(id, ref path, ref_kind) in &paths_to_process {
|
||||
self.process_path(id, path.span, path, ref_kind);
|
||||
self.process_path(id, path, ref_kind);
|
||||
}
|
||||
visit::walk_expr_opt(self, &arm.guard);
|
||||
self.visit_expr(&*arm.body);
|
||||
self.visit_expr(&arm.body);
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, s: &ast::Stmt) {
|
||||
|
@ -15,6 +15,8 @@ use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc::ast_map::NodeItem;
|
||||
|
||||
use syntax::{attr};
|
||||
use syntax::ast::{self, NodeId, DefId};
|
||||
use syntax::ast_util;
|
||||
@ -61,6 +63,10 @@ pub enum Data {
|
||||
VariableRefData(VariableRefData),
|
||||
/// Data for a reference to a type or trait.
|
||||
TypeRefData(TypeRefData),
|
||||
/// Data about a function call.
|
||||
FunctionCallData(FunctionCallData),
|
||||
/// Data about a method call.
|
||||
MethodCallData(MethodCallData),
|
||||
}
|
||||
|
||||
/// Data for all kinds of functions and methods.
|
||||
@ -120,7 +126,7 @@ pub struct ImplData {
|
||||
}
|
||||
|
||||
/// Data for the use of some item (e.g., the use of a local variable, which
|
||||
/// will refere to that variables declaration (by ref_id)).
|
||||
/// will refer to that variables declaration (by ref_id)).
|
||||
#[derive(Debug)]
|
||||
pub struct VariableRefData {
|
||||
pub name: String,
|
||||
@ -137,6 +143,24 @@ pub struct TypeRefData {
|
||||
pub ref_id: DefId,
|
||||
}
|
||||
|
||||
/// Data about a function call.
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionCallData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub ref_id: DefId,
|
||||
}
|
||||
|
||||
/// Data about a method call.
|
||||
#[derive(Debug)]
|
||||
pub struct MethodCallData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub ref_id: Option<DefId>,
|
||||
pub decl_id: Option<DefId>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
pub fn new(tcx: &'l ty::ctxt<'tcx>,
|
||||
@ -172,7 +196,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
qualname: qualname,
|
||||
declaration: None,
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
|
||||
scope: self.enclosing_scope(item.id),
|
||||
})
|
||||
}
|
||||
ast::ItemStatic(ref typ, mt, ref expr) => {
|
||||
@ -191,7 +215,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
name: get_ident(item.ident).to_string(),
|
||||
qualname: qualname,
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
|
||||
scope: self.enclosing_scope(item.id),
|
||||
value: value,
|
||||
type_value: ty_to_string(&typ),
|
||||
})
|
||||
@ -205,7 +229,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
name: get_ident(item.ident).to_string(),
|
||||
qualname: qualname,
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
|
||||
scope: self.enclosing_scope(item.id),
|
||||
value: self.span_utils.snippet(expr.span),
|
||||
type_value: ty_to_string(&typ),
|
||||
})
|
||||
@ -223,7 +247,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
name: get_ident(item.ident).to_string(),
|
||||
qualname: qualname,
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
|
||||
scope: self.enclosing_scope(item.id),
|
||||
filename: filename,
|
||||
})
|
||||
},
|
||||
@ -237,14 +261,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
value: val,
|
||||
span: sub_span.unwrap(),
|
||||
qualname: enum_name,
|
||||
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
|
||||
scope: self.enclosing_scope(item.id),
|
||||
})
|
||||
},
|
||||
ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
|
||||
let mut type_data = None;
|
||||
let sub_span;
|
||||
|
||||
let parent = self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0);
|
||||
let parent = self.enclosing_scope(item.id);
|
||||
|
||||
match typ.node {
|
||||
// Common case impl for a struct or something basic.
|
||||
@ -281,34 +305,114 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: we ought to be able to get the parent id ourselves, but we can't
|
||||
// for now.
|
||||
pub fn get_field_data(&self, field: &ast::StructField, parent: NodeId) -> Option<Data> {
|
||||
pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<VariableData> {
|
||||
match field.node.kind {
|
||||
ast::NamedField(ident, _) => {
|
||||
let name = get_ident(ident);
|
||||
let qualname = format!("::{}::{}",
|
||||
self.tcx.map.path_to_string(parent),
|
||||
self.tcx.map.path_to_string(scope),
|
||||
name);
|
||||
let typ = self.tcx.node_types().get(&field.node.id).unwrap()
|
||||
.to_string();
|
||||
let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon);
|
||||
Some(Data::VariableData(VariableData {
|
||||
Some(VariableData {
|
||||
id: field.node.id,
|
||||
name: get_ident(ident).to_string(),
|
||||
qualname: qualname,
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
scope: scope,
|
||||
value: "".to_owned(),
|
||||
type_value: typ,
|
||||
}))
|
||||
})
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: we ought to be able to get the parent id ourselves, but we can't
|
||||
// for now.
|
||||
// FIXME would be nice to take a MethodItem here, but the ast provides both
|
||||
// trait and impl flavours, so the caller must do the disassembly.
|
||||
pub fn get_method_data(&self,
|
||||
id: ast::NodeId,
|
||||
name: ast::Name,
|
||||
span: Span) -> FunctionData {
|
||||
// The qualname for a method is the trait name or name of the struct in an impl in
|
||||
// which the method is declared in, followed by the method's name.
|
||||
let qualname = match self.tcx.impl_of_method(ast_util::local_def(id)) {
|
||||
Some(impl_id) => match self.tcx.map.get(impl_id.node) {
|
||||
NodeItem(item) => {
|
||||
match item.node {
|
||||
ast::ItemImpl(_, _, _, _, ref ty, _) => {
|
||||
let mut result = String::from("<");
|
||||
result.push_str(&ty_to_string(&**ty));
|
||||
|
||||
match self.tcx.trait_of_item(ast_util::local_def(id)) {
|
||||
Some(def_id) => {
|
||||
result.push_str(" as ");
|
||||
result.push_str(
|
||||
&self.tcx.item_path_str(def_id));
|
||||
},
|
||||
None => {}
|
||||
}
|
||||
result.push_str(">");
|
||||
result
|
||||
}
|
||||
_ => {
|
||||
self.tcx.sess.span_bug(span,
|
||||
&format!("Container {} for method {} not an impl?",
|
||||
impl_id.node, id));
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
self.tcx.sess.span_bug(span,
|
||||
&format!("Container {} for method {} is not a node item {:?}",
|
||||
impl_id.node, id, self.tcx.map.get(impl_id.node)));
|
||||
},
|
||||
},
|
||||
None => match self.tcx.trait_of_item(ast_util::local_def(id)) {
|
||||
Some(def_id) => {
|
||||
match self.tcx.map.get(def_id.node) {
|
||||
NodeItem(_) => {
|
||||
format!("::{}", self.tcx.item_path_str(def_id))
|
||||
}
|
||||
_ => {
|
||||
self.tcx.sess.span_bug(span,
|
||||
&format!("Could not find container {} for method {}",
|
||||
def_id.node, id));
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
self.tcx.sess.span_bug(span,
|
||||
&format!("Could not find container for method {}", id));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let qualname = format!("{}::{}", qualname, &token::get_name(name));
|
||||
|
||||
let decl_id = self.tcx.trait_item_of_item(ast_util::local_def(id))
|
||||
.and_then(|new_id| {
|
||||
let def_id = new_id.def_id();
|
||||
if def_id.node != 0 && def_id != ast_util::local_def(id) {
|
||||
Some(def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
|
||||
|
||||
FunctionData {
|
||||
id: id,
|
||||
name: token::get_name(name).to_string(),
|
||||
qualname: qualname,
|
||||
declaration: decl_id,
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.enclosing_scope(id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_trait_ref_data(&self,
|
||||
trait_ref: &ast::TraitRef,
|
||||
parent: NodeId)
|
||||
@ -337,7 +441,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
return Some(Data::VariableRefData(VariableRefData {
|
||||
name: get_ident(ident.node).to_string(),
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
|
||||
scope: self.enclosing_scope(expr.id),
|
||||
ref_id: f.id,
|
||||
}));
|
||||
}
|
||||
@ -360,7 +464,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
let sub_span = self.span_utils.span_for_last_ident(path.span);
|
||||
Some(Data::TypeRefData(TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
|
||||
scope: self.enclosing_scope(expr.id),
|
||||
ref_id: def_id,
|
||||
}))
|
||||
}
|
||||
@ -372,6 +476,25 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprMethodCall(..) => {
|
||||
let method_call = ty::MethodCall::expr(expr.id);
|
||||
let method_id = self.tcx.tables.borrow().method_map[&method_call].def_id;
|
||||
let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() {
|
||||
ty::ImplContainer(_) => (Some(method_id), None),
|
||||
ty::TraitContainer(_) => (None, Some(method_id))
|
||||
};
|
||||
let sub_span = self.span_utils.sub_span_for_meth_name(expr.span);
|
||||
let parent = self.enclosing_scope(expr.id);
|
||||
Some(Data::MethodCallData(MethodCallData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
ref_id: def_id,
|
||||
decl_id: decl_id,
|
||||
}))
|
||||
}
|
||||
ast::ExprPath(_, ref path) => {
|
||||
Some(self.get_path_data(expr.id, path))
|
||||
}
|
||||
_ => {
|
||||
// FIXME
|
||||
unimplemented!();
|
||||
@ -379,6 +502,90 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_path_data(&self,
|
||||
id: NodeId,
|
||||
path: &ast::Path)
|
||||
-> Data {
|
||||
let def_map = self.tcx.def_map.borrow();
|
||||
if !def_map.contains_key(&id) {
|
||||
self.tcx.sess.span_bug(path.span,
|
||||
&format!("def_map has no key for {} in visit_expr", id));
|
||||
}
|
||||
let def = def_map.get(&id).unwrap().full_def();
|
||||
let sub_span = self.span_utils.span_for_last_ident(path.span);
|
||||
match def {
|
||||
def::DefUpvar(..) |
|
||||
def::DefLocal(..) |
|
||||
def::DefStatic(..) |
|
||||
def::DefConst(..) |
|
||||
def::DefAssociatedConst(..) |
|
||||
def::DefVariant(..) => {
|
||||
Data::VariableRefData(VariableRefData {
|
||||
name: self.span_utils.snippet(sub_span.unwrap()),
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.enclosing_scope(id),
|
||||
ref_id: def.def_id(),
|
||||
})
|
||||
}
|
||||
def::DefStruct(def_id) | def::DefTy(def_id, _) => {
|
||||
Data::TypeRefData(TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
ref_id: def_id,
|
||||
scope: self.enclosing_scope(id),
|
||||
})
|
||||
}
|
||||
def::DefMethod(decl_id, provenence) => {
|
||||
let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
|
||||
let def_id = if decl_id.krate == ast::LOCAL_CRATE {
|
||||
let ti = self.tcx.impl_or_trait_item(decl_id);
|
||||
match provenence {
|
||||
def::FromTrait(def_id) => {
|
||||
Some(self.tcx.trait_items(def_id)
|
||||
.iter()
|
||||
.find(|mr| {
|
||||
mr.name() == ti.name()
|
||||
})
|
||||
.unwrap()
|
||||
.def_id())
|
||||
}
|
||||
def::FromImpl(def_id) => {
|
||||
let impl_items = self.tcx.impl_items.borrow();
|
||||
Some(impl_items.get(&def_id)
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|mr| {
|
||||
self.tcx.impl_or_trait_item(mr.def_id()).name()
|
||||
== ti.name()
|
||||
})
|
||||
.unwrap()
|
||||
.def_id())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Data::MethodCallData(MethodCallData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.enclosing_scope(id),
|
||||
ref_id: def_id,
|
||||
decl_id: Some(decl_id),
|
||||
})
|
||||
},
|
||||
def::DefFn(def_id, _) => {
|
||||
Data::FunctionCallData(FunctionCallData {
|
||||
ref_id: def_id,
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.enclosing_scope(id),
|
||||
})
|
||||
}
|
||||
_ => self.tcx.sess.span_bug(path.span,
|
||||
&format!("Unexpected def kind while looking \
|
||||
up path in `{}`: `{:?}`",
|
||||
self.span_utils.snippet(path.span),
|
||||
def)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_field_ref_data(&self,
|
||||
field_ref: &ast::Field,
|
||||
struct_id: DefId,
|
||||
@ -420,6 +627,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn enclosing_scope(&self, id: NodeId) -> NodeId {
|
||||
self.tcx.map.get_enclosing_scope(id).unwrap_or(0)
|
||||
}
|
||||
}
|
||||
|
||||
// An AST visitor for collecting paths from patterns.
|
||||
|
@ -60,14 +60,14 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
|
||||
};
|
||||
|
||||
// Keep going, outside-in.
|
||||
//
|
||||
let fully_expanded = fld.fold_expr(expanded_expr);
|
||||
let span = fld.new_span(span);
|
||||
fld.cx.bt_pop();
|
||||
|
||||
fully_expanded.map(|e| ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
node: e.node,
|
||||
span: fld.new_span(span),
|
||||
span: span,
|
||||
})
|
||||
}
|
||||
|
||||
@ -367,7 +367,8 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
|
||||
/// of expansion and the mark which must be applied to the result.
|
||||
/// Our current interface doesn't allow us to apply the mark to the
|
||||
/// result until after calling make_expr, make_items, etc.
|
||||
fn expand_mac_invoc<T, F, G>(mac: ast::Mac, span: codemap::Span,
|
||||
fn expand_mac_invoc<T, F, G>(mac: ast::Mac,
|
||||
span: codemap::Span,
|
||||
parse_thunk: F,
|
||||
mark_thunk: G,
|
||||
fld: &mut MacroExpander)
|
||||
|
@ -1566,12 +1566,13 @@ impl<'a> Parser<'a> {
|
||||
// Assumes that the leading `<` has been parsed already.
|
||||
pub fn parse_qualified_path(&mut self, mode: PathParsingMode)
|
||||
-> PResult<(QSelf, ast::Path)> {
|
||||
let span = self.last_span;
|
||||
let self_type = try!(self.parse_ty_sum());
|
||||
let mut path = if try!(self.eat_keyword(keywords::As)) {
|
||||
try!(self.parse_path(LifetimeAndTypesWithoutColons))
|
||||
} else {
|
||||
ast::Path {
|
||||
span: self.span,
|
||||
span: span,
|
||||
global: false,
|
||||
segments: vec![]
|
||||
}
|
||||
@ -1598,9 +1599,6 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
path.segments.extend(segments);
|
||||
|
||||
if path.segments.len() == 1 {
|
||||
path.span.lo = self.last_span.lo;
|
||||
}
|
||||
path.span.hi = self.last_span.hi;
|
||||
|
||||
Ok((qself, path))
|
||||
|
@ -364,3 +364,18 @@ impl<'a> Pattern<'a> for CharEqPattern {
|
||||
}
|
||||
|
||||
struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
|
||||
|
||||
pub trait Error {
|
||||
}
|
||||
|
||||
impl Error + 'static {
|
||||
pub fn is<T: Error + 'static>(&self) -> bool {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Error + 'static + Send {
|
||||
pub fn is<T: Error + 'static>(&self) -> bool {
|
||||
<Error + 'static>::is::<T>(self)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user