commit
4f3c19f547
3 changed files with 331 additions and 207 deletions
|
|
@ -54,6 +54,15 @@ use super::recorder::{Recorder, FmtStrs};
|
|||
|
||||
use util::ppaux;
|
||||
|
||||
macro_rules! down_cast_data {
|
||||
($id:ident, $kind:ident, $this:ident, $sp:expr) => {
|
||||
let $id = if let super::Data::$kind(data) = $id {
|
||||
data
|
||||
} else {
|
||||
$this.sess.span_bug($sp, &format!("unexpected data kind: {:?}", $id));
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
|
||||
save_ctxt: SaveContext<'l, 'tcx>,
|
||||
|
|
@ -249,7 +258,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
match def {
|
||||
def::DefMod(_) |
|
||||
def::DefForeignMod(_) => Some(recorder::ModRef),
|
||||
def::DefStruct(_) => Some(recorder::StructRef),
|
||||
def::DefStruct(_) => Some(recorder::TypeRef),
|
||||
def::DefTy(..) |
|
||||
def::DefAssociatedTy(..) |
|
||||
def::DefTrait(_) => Some(recorder::TypeRef),
|
||||
|
|
@ -419,48 +428,31 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
id);
|
||||
}
|
||||
|
||||
fn process_trait_ref(&mut self,
|
||||
trait_ref: &ast::TraitRef) {
|
||||
match self.lookup_type_ref(trait_ref.ref_id) {
|
||||
Some(id) => {
|
||||
let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
|
||||
self.fmt.ref_str(recorder::TypeRef,
|
||||
trait_ref.path.span,
|
||||
sub_span,
|
||||
id,
|
||||
self.cur_scope);
|
||||
visit::walk_path(self, &trait_ref.path);
|
||||
},
|
||||
None => ()
|
||||
fn process_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
|
||||
let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref, self.cur_scope);
|
||||
if let Some(trait_ref_data) = trait_ref_data {
|
||||
self.fmt.ref_str(recorder::TypeRef,
|
||||
trait_ref.path.span,
|
||||
Some(trait_ref_data.span),
|
||||
trait_ref_data.ref_id,
|
||||
trait_ref_data.scope);
|
||||
visit::walk_path(self, &trait_ref.path);
|
||||
}
|
||||
}
|
||||
|
||||
fn process_struct_field_def(&mut self,
|
||||
field: &ast::StructField,
|
||||
qualname: &str,
|
||||
scope_id: NodeId) {
|
||||
match field.node.kind {
|
||||
ast::NamedField(ident, _) => {
|
||||
let name = get_ident(ident);
|
||||
let qualname = format!("{}::{}", qualname, name);
|
||||
let typ =
|
||||
ppaux::ty_to_string(
|
||||
&self.analysis.ty_cx,
|
||||
*self.analysis.ty_cx.node_types().get(&field.node.id).unwrap());
|
||||
match self.span.sub_span_before_token(field.span, token::Colon) {
|
||||
Some(sub_span) => self.fmt.field_str(field.span,
|
||||
Some(sub_span),
|
||||
field.node.id,
|
||||
&name,
|
||||
&qualname,
|
||||
&typ,
|
||||
scope_id),
|
||||
None => self.sess.span_bug(field.span,
|
||||
&format!("Could not find sub-span for field {}",
|
||||
qualname)),
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
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,
|
||||
&field_data.name,
|
||||
&field_data.qualname,
|
||||
&field_data.type_value,
|
||||
field_data.scope);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -497,19 +489,16 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
ty_params: &ast::Generics,
|
||||
body: &ast::Block) {
|
||||
let fn_data = self.save_ctxt.get_item_data(item);
|
||||
if let super::Data::FunctionData(fn_data) = fn_data {
|
||||
self.fmt.fn_str(item.span,
|
||||
Some(fn_data.span),
|
||||
fn_data.id,
|
||||
&fn_data.qualname,
|
||||
fn_data.scope);
|
||||
down_cast_data!(fn_data, FunctionData, self, item.span);
|
||||
self.fmt.fn_str(item.span,
|
||||
Some(fn_data.span),
|
||||
fn_data.id,
|
||||
&fn_data.qualname,
|
||||
fn_data.scope);
|
||||
|
||||
|
||||
self.process_formals(&decl.inputs, &fn_data.qualname);
|
||||
self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
|
||||
} else {
|
||||
self.sess.span_bug(item.span, "expected FunctionData");
|
||||
}
|
||||
self.process_formals(&decl.inputs, &fn_data.qualname);
|
||||
self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
|
||||
|
||||
for arg in &decl.inputs {
|
||||
self.visit_ty(&arg.ty);
|
||||
|
|
@ -528,18 +517,15 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
expr: &ast::Expr)
|
||||
{
|
||||
let var_data = self.save_ctxt.get_item_data(item);
|
||||
if let super::Data::VariableData(var_data) = var_data {
|
||||
self.fmt.static_str(item.span,
|
||||
Some(var_data.span),
|
||||
var_data.id,
|
||||
&var_data.name,
|
||||
&var_data.qualname,
|
||||
&var_data.value,
|
||||
&var_data.type_value,
|
||||
var_data.scope);
|
||||
} else {
|
||||
self.sess.span_bug(item.span, "expected VariableData");
|
||||
}
|
||||
down_cast_data!(var_data, VariableData, self, item.span);
|
||||
self.fmt.static_str(item.span,
|
||||
Some(var_data.span),
|
||||
var_data.id,
|
||||
&var_data.name,
|
||||
&var_data.qualname,
|
||||
&var_data.value,
|
||||
&var_data.type_value,
|
||||
var_data.scope);
|
||||
|
||||
self.visit_ty(&typ);
|
||||
self.visit_expr(expr);
|
||||
|
|
@ -593,8 +579,8 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
|
||||
// fields
|
||||
for field in &def.fields {
|
||||
self.process_struct_field_def(field, &qualname, item.id);
|
||||
self.visit_ty(&*field.node.ty);
|
||||
self.process_struct_field_def(field, item.id);
|
||||
self.visit_ty(&field.node.ty);
|
||||
}
|
||||
|
||||
self.process_generic_params(ty_params, item.span, &qualname, item.id);
|
||||
|
|
@ -605,59 +591,57 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
enum_definition: &ast::EnumDef,
|
||||
ty_params: &ast::Generics) {
|
||||
let enum_data = self.save_ctxt.get_item_data(item);
|
||||
if let super::Data::EnumData(enum_data) = enum_data {
|
||||
self.fmt.enum_str(item.span,
|
||||
Some(enum_data.span),
|
||||
enum_data.id,
|
||||
&enum_data.qualname,
|
||||
self.cur_scope,
|
||||
&enum_data.value);
|
||||
for variant in &enum_definition.variants {
|
||||
let name = &get_ident(variant.node.name);
|
||||
let mut qualname = enum_data.qualname.clone();
|
||||
qualname.push_str("::");
|
||||
qualname.push_str(name);
|
||||
let val = self.span.snippet(variant.span);
|
||||
match variant.node.kind {
|
||||
ast::TupleVariantKind(ref args) => {
|
||||
// first ident in span is the variant's name
|
||||
self.fmt.tuple_variant_str(variant.span,
|
||||
self.span.span_for_first_ident(variant.span),
|
||||
variant.node.id,
|
||||
name,
|
||||
&qualname,
|
||||
&enum_data.qualname,
|
||||
&val,
|
||||
item.id);
|
||||
for arg in args {
|
||||
self.visit_ty(&*arg.ty);
|
||||
}
|
||||
}
|
||||
ast::StructVariantKind(ref struct_def) => {
|
||||
let ctor_id = match struct_def.ctor_id {
|
||||
Some(node_id) => node_id,
|
||||
None => -1,
|
||||
};
|
||||
self.fmt.struct_variant_str(variant.span,
|
||||
self.span.span_for_first_ident(variant.span),
|
||||
variant.node.id,
|
||||
ctor_id,
|
||||
&qualname,
|
||||
&enum_data.qualname,
|
||||
&val,
|
||||
item.id);
|
||||
down_cast_data!(enum_data, EnumData, self, item.span);
|
||||
self.fmt.enum_str(item.span,
|
||||
Some(enum_data.span),
|
||||
enum_data.id,
|
||||
&enum_data.qualname,
|
||||
enum_data.scope,
|
||||
&enum_data.value);
|
||||
|
||||
for field in &struct_def.fields {
|
||||
self.process_struct_field_def(field, &qualname, variant.node.id);
|
||||
self.visit_ty(&*field.node.ty);
|
||||
}
|
||||
for variant in &enum_definition.variants {
|
||||
let name = &get_ident(variant.node.name);
|
||||
let mut qualname = enum_data.qualname.clone();
|
||||
qualname.push_str("::");
|
||||
qualname.push_str(name);
|
||||
let val = self.span.snippet(variant.span);
|
||||
match variant.node.kind {
|
||||
ast::TupleVariantKind(ref args) => {
|
||||
// first ident in span is the variant's name
|
||||
self.fmt.tuple_variant_str(variant.span,
|
||||
self.span.span_for_first_ident(variant.span),
|
||||
variant.node.id,
|
||||
name,
|
||||
&qualname,
|
||||
&enum_data.qualname,
|
||||
&val,
|
||||
enum_data.id);
|
||||
for arg in args {
|
||||
self.visit_ty(&*arg.ty);
|
||||
}
|
||||
}
|
||||
ast::StructVariantKind(ref struct_def) => {
|
||||
let ctor_id = match struct_def.ctor_id {
|
||||
Some(node_id) => node_id,
|
||||
None => -1,
|
||||
};
|
||||
self.fmt.struct_variant_str(variant.span,
|
||||
self.span.span_for_first_ident(variant.span),
|
||||
variant.node.id,
|
||||
ctor_id,
|
||||
&qualname,
|
||||
&enum_data.qualname,
|
||||
&val,
|
||||
enum_data.id);
|
||||
|
||||
for field in &struct_def.fields {
|
||||
self.process_struct_field_def(field, variant.node.id);
|
||||
self.visit_ty(&*field.node.ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id);
|
||||
} else {
|
||||
self.sess.span_bug(item.span, "expected EnumData");
|
||||
}
|
||||
self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id);
|
||||
}
|
||||
|
||||
fn process_impl(&mut self,
|
||||
|
|
@ -666,45 +650,36 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
trait_ref: &Option<ast::TraitRef>,
|
||||
typ: &ast::Ty,
|
||||
impl_items: &[P<ast::ImplItem>]) {
|
||||
let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id));
|
||||
match typ.node {
|
||||
// Common case impl for a struct or something basic.
|
||||
ast::TyPath(None, ref path) => {
|
||||
let sub_span = self.span.sub_span_for_type_name(path.span);
|
||||
let self_id = self.lookup_type_ref(typ.id).map(|id| {
|
||||
self.fmt.ref_str(recorder::TypeRef,
|
||||
path.span,
|
||||
sub_span,
|
||||
id,
|
||||
self.cur_scope);
|
||||
id
|
||||
});
|
||||
self.fmt.impl_str(path.span,
|
||||
sub_span,
|
||||
item.id,
|
||||
self_id,
|
||||
trait_id,
|
||||
self.cur_scope);
|
||||
},
|
||||
_ => {
|
||||
// Less useful case, impl for a compound type.
|
||||
self.visit_ty(&*typ);
|
||||
|
||||
let sub_span = self.span.sub_span_for_type_name(typ.span);
|
||||
self.fmt.impl_str(typ.span,
|
||||
sub_span,
|
||||
item.id,
|
||||
None,
|
||||
trait_id,
|
||||
self.cur_scope);
|
||||
let impl_data = self.save_ctxt.get_item_data(item);
|
||||
down_cast_data!(impl_data, ImplData, self, item.span);
|
||||
match impl_data.self_ref {
|
||||
Some(ref self_ref) => {
|
||||
self.fmt.ref_str(recorder::TypeRef,
|
||||
item.span,
|
||||
Some(self_ref.span),
|
||||
self_ref.ref_id,
|
||||
self_ref.scope);
|
||||
}
|
||||
None => {
|
||||
self.visit_ty(&typ);
|
||||
}
|
||||
}
|
||||
|
||||
match *trait_ref {
|
||||
Some(ref trait_ref) => self.process_trait_ref(trait_ref),
|
||||
None => (),
|
||||
if let Some(ref trait_ref_data) = impl_data.trait_ref {
|
||||
self.fmt.ref_str(recorder::TypeRef,
|
||||
item.span,
|
||||
Some(trait_ref_data.span),
|
||||
trait_ref_data.ref_id,
|
||||
trait_ref_data.scope);
|
||||
visit::walk_path(self, &trait_ref.as_ref().unwrap().path);
|
||||
}
|
||||
|
||||
self.fmt.impl_str(item.span,
|
||||
Some(impl_data.span),
|
||||
impl_data.id,
|
||||
impl_data.self_ref.map(|data| data.ref_id),
|
||||
impl_data.trait_ref.map(|data| data.ref_id),
|
||||
impl_data.scope);
|
||||
|
||||
self.process_generic_params(type_parameters, item.span, "", item.id);
|
||||
for impl_item in impl_items {
|
||||
self.visit_impl_item(impl_item);
|
||||
|
|
@ -765,16 +740,13 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
fn process_mod(&mut self,
|
||||
item: &ast::Item) { // The module in question, represented as an item.
|
||||
let mod_data = self.save_ctxt.get_item_data(item);
|
||||
if let super::Data::ModData(mod_data) = mod_data {
|
||||
self.fmt.mod_str(item.span,
|
||||
Some(mod_data.span),
|
||||
mod_data.id,
|
||||
&mod_data.qualname,
|
||||
mod_data.scope,
|
||||
&mod_data.filename);
|
||||
} else {
|
||||
self.sess.span_bug(item.span, "expected ModData");
|
||||
}
|
||||
down_cast_data!(mod_data, ModData, self, item.span);
|
||||
self.fmt.mod_str(item.span,
|
||||
Some(mod_data.span),
|
||||
mod_data.id,
|
||||
&mod_data.qualname,
|
||||
mod_data.scope,
|
||||
&mod_data.filename);
|
||||
}
|
||||
|
||||
fn process_path(&mut self,
|
||||
|
|
@ -804,7 +776,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
sub_span,
|
||||
def.def_id(),
|
||||
self.cur_scope),
|
||||
def::DefStruct(def_id) => self.fmt.ref_str(recorder::StructRef,
|
||||
def::DefStruct(def_id) => self.fmt.ref_str(recorder::TypeRef,
|
||||
span,
|
||||
sub_span,
|
||||
def_id,
|
||||
|
|
@ -901,44 +873,33 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
|
||||
self.write_sub_paths_truncated(path, false);
|
||||
|
||||
let ty = &ty::expr_ty_adjusted(&self.analysis.ty_cx, ex).sty;
|
||||
let struct_def = match *ty {
|
||||
ty::TyStruct(def_id, _) => {
|
||||
let sub_span = self.span.span_for_last_ident(path.span);
|
||||
self.fmt.ref_str(recorder::StructRef,
|
||||
path.span,
|
||||
sub_span,
|
||||
def_id,
|
||||
self.cur_scope);
|
||||
Some(def_id)
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
|
||||
down_cast_data!(struct_lit_data, TypeRefData, self, ex.span);
|
||||
self.fmt.ref_str(recorder::TypeRef,
|
||||
ex.span,
|
||||
Some(struct_lit_data.span),
|
||||
struct_lit_data.ref_id,
|
||||
struct_lit_data.scope);
|
||||
let struct_def = struct_lit_data.ref_id;
|
||||
|
||||
for field in fields {
|
||||
match struct_def {
|
||||
Some(struct_def) => {
|
||||
let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def);
|
||||
for f in &fields {
|
||||
if generated_code(field.ident.span) {
|
||||
continue;
|
||||
}
|
||||
if f.name == field.ident.node.name {
|
||||
// We don't really need a sub-span here, but no harm done
|
||||
let sub_span = self.span.span_for_last_ident(field.ident.span);
|
||||
self.fmt.ref_str(recorder::VarRef,
|
||||
field.ident.span,
|
||||
sub_span,
|
||||
f.id,
|
||||
self.cur_scope);
|
||||
}
|
||||
}
|
||||
for field in fields {
|
||||
if generated_code(field.ident.span) {
|
||||
continue;
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
self.visit_expr(&*field.expr)
|
||||
let field_data = self.save_ctxt.get_field_ref_data(field,
|
||||
struct_def,
|
||||
self.cur_scope);
|
||||
self.fmt.ref_str(recorder::VarRef,
|
||||
field.ident.span,
|
||||
Some(field_data.span),
|
||||
field_data.ref_id,
|
||||
field_data.scope);
|
||||
|
||||
self.visit_expr(&field.expr)
|
||||
}
|
||||
}
|
||||
|
||||
visit::walk_expr_opt(self, base)
|
||||
}
|
||||
|
||||
|
|
@ -1174,7 +1135,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
|||
self.process_impl(item,
|
||||
ty_params,
|
||||
trait_ref,
|
||||
&**typ,
|
||||
&typ,
|
||||
impl_items)
|
||||
}
|
||||
ast::ItemTrait(_, ref generics, ref trait_refs, ref methods) =>
|
||||
|
|
@ -1296,15 +1257,13 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
|||
|
||||
self.visit_expr(&sub_ex);
|
||||
|
||||
let field_data = self.save_ctxt.get_expr_data(ex);
|
||||
if let super::Data::VariableRefData(field_data) = field_data {
|
||||
if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
|
||||
down_cast_data!(field_data, VariableRefData, self, ex.span);
|
||||
self.fmt.ref_str(recorder::VarRef,
|
||||
ex.span,
|
||||
Some(field_data.span),
|
||||
field_data.ref_id,
|
||||
field_data.scope);
|
||||
} else {
|
||||
self.sess.span_bug(ex.span, "expected VariableRefData");
|
||||
}
|
||||
},
|
||||
ast::ExprTupField(ref sub_ex, idx) => {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
use session::Session;
|
||||
use middle::ty;
|
||||
use middle::def;
|
||||
|
||||
use std::env;
|
||||
use std::fs::{self, File};
|
||||
|
|
@ -23,9 +24,11 @@ use syntax::parse::token::{self, get_ident, keywords};
|
|||
use syntax::visit::{self, Visitor};
|
||||
use syntax::print::pprust::ty_to_string;
|
||||
|
||||
use util::ppaux;
|
||||
|
||||
use self::span_utils::SpanUtils;
|
||||
|
||||
|
||||
mod span_utils;
|
||||
mod recorder;
|
||||
|
||||
|
|
@ -44,22 +47,28 @@ pub struct CrateData {
|
|||
|
||||
/// Data for any entity in the Rust language. The actual data contained varied
|
||||
/// with the kind of entity being queried. See the nested structs for details.
|
||||
#[derive(Debug)]
|
||||
pub enum Data {
|
||||
/// Data for all kinds of functions and methods.
|
||||
FunctionData(FunctionData),
|
||||
/// Data for local and global variables (consts and statics).
|
||||
/// Data for local and global variables (consts and statics), and fields.
|
||||
VariableData(VariableData),
|
||||
/// Data for modules.
|
||||
ModData(ModData),
|
||||
/// Data for Enums.
|
||||
EnumData(EnumData),
|
||||
/// Data for impls.
|
||||
ImplData(ImplData),
|
||||
|
||||
/// Data for the use of some variable (e.g., the use of a local variable, which
|
||||
/// will refere to that variables declaration).
|
||||
VariableRefData(VariableRefData),
|
||||
/// Data for a reference to a type or trait.
|
||||
TypeRefData(TypeRefData),
|
||||
}
|
||||
|
||||
/// Data for all kinds of functions and methods.
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
|
|
@ -70,6 +79,7 @@ pub struct FunctionData {
|
|||
}
|
||||
|
||||
/// Data for local and global variables (consts and statics).
|
||||
#[derive(Debug)]
|
||||
pub struct VariableData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
|
|
@ -81,6 +91,7 @@ pub struct VariableData {
|
|||
}
|
||||
|
||||
/// Data for modules.
|
||||
#[derive(Debug)]
|
||||
pub struct ModData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
|
|
@ -91,15 +102,30 @@ pub struct ModData {
|
|||
}
|
||||
|
||||
/// Data for enum declarations.
|
||||
#[derive(Debug)]
|
||||
pub struct EnumData {
|
||||
pub id: NodeId,
|
||||
pub value: String,
|
||||
pub qualname: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImplData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
// FIXME: I'm not really sure inline data is the best way to do this. Seems
|
||||
// OK in this case, but generalising leads to returning chunks of AST, which
|
||||
// feels wrong.
|
||||
pub trait_ref: Option<TypeRefData>,
|
||||
pub self_ref: Option<TypeRefData>,
|
||||
}
|
||||
|
||||
/// 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)).
|
||||
#[derive(Debug)]
|
||||
pub struct VariableRefData {
|
||||
pub name: String,
|
||||
pub span: Span,
|
||||
|
|
@ -107,6 +133,14 @@ pub struct VariableRefData {
|
|||
pub ref_id: DefId,
|
||||
}
|
||||
|
||||
/// Data for a reference to a type or trait.
|
||||
#[derive(Debug)]
|
||||
pub struct TypeRefData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub ref_id: DefId,
|
||||
}
|
||||
|
||||
|
||||
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
pub fn new(sess: &'l Session,
|
||||
|
|
@ -209,8 +243,42 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||
value: val,
|
||||
span: sub_span.unwrap(),
|
||||
qualname: enum_name,
|
||||
scope: self.analysis.ty_cx.map.get_parent(item.id),
|
||||
})
|
||||
},
|
||||
ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
|
||||
let mut type_data = None;
|
||||
let sub_span;
|
||||
|
||||
let parent = self.analysis.ty_cx.map.get_parent(item.id);
|
||||
|
||||
match typ.node {
|
||||
// Common case impl for a struct or something basic.
|
||||
ast::TyPath(None, ref path) => {
|
||||
sub_span = self.span_utils.sub_span_for_type_name(path.span);
|
||||
type_data = self.lookup_ref_id(typ.id).map(|id| TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
ref_id: id,
|
||||
});
|
||||
},
|
||||
_ => {
|
||||
// Less useful case, impl for a compound type.
|
||||
sub_span = self.span_utils.sub_span_for_type_name(typ.span);
|
||||
}
|
||||
}
|
||||
|
||||
let trait_data =
|
||||
trait_ref.as_ref().and_then(|tr| self.get_trait_ref_data(tr, parent));
|
||||
|
||||
Data::ImplData(ImplData {
|
||||
id: item.id,
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
trait_ref: trait_data,
|
||||
self_ref: type_data,
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
// FIXME
|
||||
unimplemented!();
|
||||
|
|
@ -218,7 +286,50 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_expr_data(&self, expr: &ast::Expr) -> Data {
|
||||
// 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> {
|
||||
match field.node.kind {
|
||||
ast::NamedField(ident, _) => {
|
||||
let name = get_ident(ident);
|
||||
let qualname = format!("::{}::{}",
|
||||
self.analysis.ty_cx.map.path_to_string(parent),
|
||||
name);
|
||||
let typ = ppaux::ty_to_string(&self.analysis.ty_cx,
|
||||
*self.analysis.ty_cx.node_types()
|
||||
.get(&field.node.id).unwrap());
|
||||
let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon);
|
||||
Some(Data::VariableData(VariableData {
|
||||
id: field.node.id,
|
||||
name: get_ident(ident).to_string(),
|
||||
qualname: qualname,
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
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.
|
||||
pub fn get_trait_ref_data(&self,
|
||||
trait_ref: &ast::TraitRef,
|
||||
parent: NodeId)
|
||||
-> Option<TypeRefData> {
|
||||
self.lookup_ref_id(trait_ref.ref_id).map(|def_id| {
|
||||
let sub_span = self.span_utils.sub_span_for_type_name(trait_ref.path.span);
|
||||
TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
ref_id: def_id,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
|
||||
match expr.node {
|
||||
ast::ExprField(ref sub_ex, ident) => {
|
||||
let ty = &ty::expr_ty_adjusted(&self.analysis.ty_cx, &sub_ex).sty;
|
||||
|
|
@ -228,12 +339,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||
for f in &fields {
|
||||
if f.name == ident.node.name {
|
||||
let sub_span = self.span_utils.span_for_last_ident(expr.span);
|
||||
return Data::VariableRefData(VariableRefData {
|
||||
return Some(Data::VariableRefData(VariableRefData {
|
||||
name: get_ident(ident.node).to_string(),
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.analysis.ty_cx.map.get_parent(expr.id),
|
||||
ref_id: f.id,
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -242,8 +353,29 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||
&get_ident(ident.node),
|
||||
ty))
|
||||
}
|
||||
_ => self.sess.span_bug(expr.span,
|
||||
&format!("Expected struct type, found {:?}", ty)),
|
||||
_ => {
|
||||
debug!("Expected struct type, found {:?}", ty);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprStruct(ref path, _, _) => {
|
||||
let ty = &ty::expr_ty_adjusted(&self.analysis.ty_cx, expr).sty;
|
||||
match *ty {
|
||||
ty::TyStruct(def_id, _) => {
|
||||
let sub_span = self.span_utils.span_for_last_ident(path.span);
|
||||
Some(Data::TypeRefData(TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.analysis.ty_cx.map.get_parent(expr.id),
|
||||
ref_id: def_id,
|
||||
}))
|
||||
}
|
||||
_ => {
|
||||
// FIXME ty could legitimately be a TyEnum, but then we will fail
|
||||
// later if we try to look up the fields.
|
||||
debug!("expected TyStruct, found {:?}", ty);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
|
@ -253,10 +385,47 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_field_ref_data(&self,
|
||||
field_ref: &ast::Field,
|
||||
struct_id: DefId,
|
||||
parent: NodeId)
|
||||
-> VariableRefData {
|
||||
let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_id);
|
||||
let field_name = get_ident(field_ref.ident.node).to_string();
|
||||
for f in &fields {
|
||||
if f.name == field_ref.ident.node.name {
|
||||
// We don't really need a sub-span here, but no harm done
|
||||
let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
|
||||
return VariableRefData {
|
||||
name: field_name,
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
ref_id: f.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
self.sess.span_bug(field_ref.span,
|
||||
&format!("Couldn't find field {}", field_name));
|
||||
}
|
||||
|
||||
pub fn get_data_for_id(&self, _id: &NodeId) -> Data {
|
||||
// FIXME
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
|
||||
if !self.analysis.ty_cx.def_map.borrow().contains_key(&ref_id) {
|
||||
self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
|
||||
ref_id));
|
||||
}
|
||||
let def = self.analysis.ty_cx.def_map.borrow().get(&ref_id).unwrap().full_def();
|
||||
match def {
|
||||
def::DefPrimTy(_) => None,
|
||||
_ => Some(def.def_id()),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// An AST visitor for collecting paths from patterns.
|
||||
|
|
@ -284,7 +453,7 @@ impl<'v> Visitor<'v> for PathCollector {
|
|||
self.collected_paths.push((p.id,
|
||||
path.clone(),
|
||||
ast::MutMutable,
|
||||
recorder::StructRef));
|
||||
recorder::TypeRef));
|
||||
}
|
||||
ast::PatEnum(ref path, _) |
|
||||
ast::PatQPath(_, ref path) => {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ pub enum Row {
|
|||
ModRef,
|
||||
VarRef,
|
||||
TypeRef,
|
||||
StructRef,
|
||||
FnRef,
|
||||
}
|
||||
|
||||
|
|
@ -150,9 +149,6 @@ impl<'a> FmtStrs<'a> {
|
|||
TypeRef => ("type_ref",
|
||||
vec!("refid","refidcrate","qualname","scopeid"),
|
||||
true, true),
|
||||
StructRef => ("struct_ref",
|
||||
vec!("refid","refidcrate","qualname","scopeid"),
|
||||
true, true),
|
||||
FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue