save-analysis: API-ify methods
This commit is contained in:
parent
df5a1ca880
commit
0c766cb8bc
2 changed files with 116 additions and 94 deletions
|
@ -34,13 +34,11 @@ use session::Session;
|
||||||
|
|
||||||
use middle::def;
|
use middle::def;
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, Ty};
|
||||||
use rustc::ast_map::NodeItem;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use syntax::ast_util;
|
|
||||||
use syntax::ast::{self, NodeId, DefId};
|
use syntax::ast::{self, NodeId, DefId};
|
||||||
use syntax::codemap::*;
|
use syntax::codemap::*;
|
||||||
use syntax::parse::token::{self, get_ident, keywords};
|
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>,
|
body: Option<&ast::Block>,
|
||||||
id: ast::NodeId, name: ast::Name,
|
id: ast::NodeId,
|
||||||
|
name: ast::Name,
|
||||||
span: Span) {
|
span: Span) {
|
||||||
if generated_code(span) {
|
if generated_code(span) {
|
||||||
return;
|
return;
|
||||||
|
@ -308,91 +308,22 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||||
|
|
||||||
debug!("process_method: {}:{}", id, token::get_name(name));
|
debug!("process_method: {}:{}", id, token::get_name(name));
|
||||||
|
|
||||||
let scope_id;
|
let method_data = self.save_ctxt.get_method_data(id, name, span);
|
||||||
// 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));
|
|
||||||
|
|
||||||
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() {
|
if body.is_some() {
|
||||||
self.fmt.method_str(span,
|
self.fmt.method_str(span,
|
||||||
sub_span,
|
Some(method_data.span),
|
||||||
id,
|
method_data.id,
|
||||||
qualname,
|
&method_data.qualname,
|
||||||
decl_id,
|
method_data.declaration,
|
||||||
scope_id);
|
method_data.scope);
|
||||||
self.process_formals(&sig.decl.inputs, qualname);
|
self.process_formals(&sig.decl.inputs, &method_data.qualname);
|
||||||
} else {
|
} else {
|
||||||
self.fmt.method_decl_str(span,
|
self.fmt.method_decl_str(span,
|
||||||
sub_span,
|
Some(method_data.span),
|
||||||
id,
|
method_data.id,
|
||||||
qualname,
|
&method_data.qualname,
|
||||||
scope_id);
|
method_data.scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk arg and return types
|
// walk arg and return types
|
||||||
|
@ -411,7 +342,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||||
|
|
||||||
self.process_generic_params(&sig.generics,
|
self.process_generic_params(&sig.generics,
|
||||||
span,
|
span,
|
||||||
qualname,
|
&method_data.qualname,
|
||||||
id);
|
id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,7 +363,6 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||||
parent_id: NodeId) {
|
parent_id: NodeId) {
|
||||||
let field_data = self.save_ctxt.get_field_data(field, parent_id);
|
let field_data = self.save_ctxt.get_field_data(field, parent_id);
|
||||||
if let Some(field_data) = field_data {
|
if let Some(field_data) = field_data {
|
||||||
down_cast_data!(field_data, VariableData, self, field.span);
|
|
||||||
self.fmt.field_str(field.span,
|
self.fmt.field_str(field.span,
|
||||||
Some(field_data.span),
|
Some(field_data.span),
|
||||||
field_data.id,
|
field_data.id,
|
||||||
|
@ -1087,8 +1017,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||||
trait_item.span, &*ty, &*expr);
|
trait_item.span, &*ty, &*expr);
|
||||||
}
|
}
|
||||||
ast::MethodTraitItem(ref sig, ref body) => {
|
ast::MethodTraitItem(ref sig, ref body) => {
|
||||||
self.process_method(sig, body.as_ref().map(|x| &**x),
|
self.process_method(sig,
|
||||||
trait_item.id, trait_item.ident.name, trait_item.span);
|
body.as_ref().map(|x| &**x),
|
||||||
|
trait_item.id,
|
||||||
|
trait_item.ident.name,
|
||||||
|
trait_item.span);
|
||||||
}
|
}
|
||||||
ast::ConstTraitItem(_, None) |
|
ast::ConstTraitItem(_, None) |
|
||||||
ast::TypeTraitItem(..) => {}
|
ast::TypeTraitItem(..) => {}
|
||||||
|
@ -1102,8 +1035,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
||||||
impl_item.span, &ty, &expr);
|
impl_item.span, &ty, &expr);
|
||||||
}
|
}
|
||||||
ast::MethodImplItem(ref sig, ref body) => {
|
ast::MethodImplItem(ref sig, ref body) => {
|
||||||
self.process_method(sig, Some(body), impl_item.id,
|
self.process_method(sig,
|
||||||
impl_item.ident.name, impl_item.span);
|
Some(body),
|
||||||
|
impl_item.id,
|
||||||
|
impl_item.ident.name,
|
||||||
|
impl_item.span);
|
||||||
}
|
}
|
||||||
ast::TypeImplItem(_) |
|
ast::TypeImplItem(_) |
|
||||||
ast::MacImplItem(_) => {}
|
ast::MacImplItem(_) => {}
|
||||||
|
|
|
@ -15,6 +15,8 @@ use std::env;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use rustc::ast_map::NodeItem;
|
||||||
|
|
||||||
use syntax::{attr};
|
use syntax::{attr};
|
||||||
use syntax::ast::{self, NodeId, DefId};
|
use syntax::ast::{self, NodeId, DefId};
|
||||||
use syntax::ast_util;
|
use syntax::ast_util;
|
||||||
|
@ -227,7 +229,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||||
name: get_ident(item.ident).to_string(),
|
name: get_ident(item.ident).to_string(),
|
||||||
qualname: qualname,
|
qualname: qualname,
|
||||||
span: sub_span.unwrap(),
|
span: sub_span.unwrap(),
|
||||||
scope: selfenclosing_scope(item.id),
|
scope: self.enclosing_scope(item.id),
|
||||||
value: self.span_utils.snippet(expr.span),
|
value: self.span_utils.snippet(expr.span),
|
||||||
type_value: ty_to_string(&typ),
|
type_value: ty_to_string(&typ),
|
||||||
})
|
})
|
||||||
|
@ -303,7 +305,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<Data> {
|
pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<VariableData> {
|
||||||
match field.node.kind {
|
match field.node.kind {
|
||||||
ast::NamedField(ident, _) => {
|
ast::NamedField(ident, _) => {
|
||||||
let name = get_ident(ident);
|
let name = get_ident(ident);
|
||||||
|
@ -313,7 +315,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||||
let typ = self.tcx.node_types().get(&field.node.id).unwrap()
|
let typ = self.tcx.node_types().get(&field.node.id).unwrap()
|
||||||
.to_string();
|
.to_string();
|
||||||
let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon);
|
let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon);
|
||||||
Some(Data::VariableData(VariableData {
|
Some(VariableData {
|
||||||
id: field.node.id,
|
id: field.node.id,
|
||||||
name: get_ident(ident).to_string(),
|
name: get_ident(ident).to_string(),
|
||||||
qualname: qualname,
|
qualname: qualname,
|
||||||
|
@ -321,12 +323,96 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||||
scope: scope,
|
scope: scope,
|
||||||
value: "".to_owned(),
|
value: "".to_owned(),
|
||||||
type_value: typ,
|
type_value: typ,
|
||||||
}))
|
})
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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,
|
pub fn get_trait_ref_data(&self,
|
||||||
trait_ref: &ast::TraitRef,
|
trait_ref: &ast::TraitRef,
|
||||||
parent: NodeId)
|
parent: NodeId)
|
||||||
|
|
Loading…
Reference in a new issue