mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-26 13:54:06 +00:00
Auto merge of #31838 - aochagavia:trans, r=nrc
Refactor rustc_trans::save to allow other backends than CSV r? @nrc Things done: * Moved `(.*)Data` structs to an own module, so they can be imported easily (`use data::*`). * Created a `Dump` trait with callbacks for dumping items. * Refactored `DumpCsvVisitor` to use an implementor of `Dump` instead of dumping as CSV. Renamed it to `DumpVisitor`. * Created a `DumpCsv` struct that implements `Dump` and serializes items as CSV. I tried to extract some of the logic contained in `FmtStr` and `Recorder`, such as normalization of ids (I put it in `DumpVisitor`). I think it makes sense to provide the same information to other implementors of `Dump`, instead of normalizing only for `DumpCsv`. However, there is still some logic related to spans implemented only for `DumpCsv`. I just thought it would be better to merge this as soon as possible, since there are so much changes, and fix this afterwards.
This commit is contained in:
commit
c66d2380a8
566
src/librustc_trans/save/csv_dumper.rs
Normal file
566
src/librustc_trans/save/csv_dumper.rs
Normal file
@ -0,0 +1,566 @@
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use middle::def_id::{DefId, DefIndex};
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use super::data::*;
|
||||
use super::dump::Dump;
|
||||
use super::span_utils::SpanUtils;
|
||||
|
||||
pub struct CsvDumper<'a, 'b, W: 'b> {
|
||||
output: &'b mut W,
|
||||
dump_spans: bool,
|
||||
span: SpanUtils<'a>
|
||||
}
|
||||
|
||||
impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> {
|
||||
pub fn new(writer: &'b mut W, span: SpanUtils<'a>) -> CsvDumper<'a, 'b, W> {
|
||||
CsvDumper { output: writer, dump_spans: false, span: span }
|
||||
}
|
||||
|
||||
fn record(&mut self, kind: &str, span: Span, values: String) {
|
||||
let span_str = self.span.extent_str(span);
|
||||
if let Err(_) = write!(self.output, "{},{}{}\n", kind, span_str, values) {
|
||||
error!("Error writing output");
|
||||
}
|
||||
}
|
||||
|
||||
fn record_raw(&mut self, info: &str) {
|
||||
if let Err(_) = write!(self.output, "{}", info) {
|
||||
error!("Error writing output '{}'", info);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump_span(&mut self, kind: &str, span: Span) {
|
||||
assert!(self.dump_spans);
|
||||
let result = format!("span,kind,{},{},text,\"{}\"\n",
|
||||
kind,
|
||||
self.span.extent_str(span),
|
||||
escape(self.span.snippet(span)));
|
||||
self.record_raw(&result);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> {
|
||||
fn crate_prelude(&mut self, span: Span, data: CratePreludeData) {
|
||||
let crate_root = data.crate_root.unwrap_or("<no source>".to_owned());
|
||||
|
||||
let values = make_values_str(&[
|
||||
("name", &data.crate_name),
|
||||
("crate_root", &crate_root)
|
||||
]);
|
||||
|
||||
self.record("crate", span, values);
|
||||
|
||||
for c in data.external_crates {
|
||||
let num = c.num.to_string();
|
||||
let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
|
||||
let file_name = SpanUtils::make_path_string(&lo_loc.file.name);
|
||||
let values = make_values_str(&[
|
||||
("name", &c.name),
|
||||
("crate", &num),
|
||||
("file_name", &file_name)
|
||||
]);
|
||||
|
||||
self.record_raw(&format!("external_crate{}\n", values));
|
||||
}
|
||||
|
||||
self.record_raw("end_external_crates\n");
|
||||
}
|
||||
|
||||
fn enum_data(&mut self, span: Span, data: EnumData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("enum", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("qualname", &data.qualname),
|
||||
("scopeid", &scope),
|
||||
("value", &data.value)
|
||||
]);
|
||||
|
||||
self.record("enum", data.span, values);
|
||||
}
|
||||
|
||||
fn extern_crate(&mut self, span: Span, data: ExternCrateData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("extern_crate", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let crate_num = data.crate_num.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("name", &data.name),
|
||||
("location", &data.location),
|
||||
("crate", &crate_num),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("extern_crate", data.span, values);
|
||||
}
|
||||
|
||||
fn impl_data(&mut self, span: Span, data: ImplData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("impl", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let self_ref = data.self_ref.unwrap_or(null_def_id());
|
||||
let trait_ref = data.trait_ref.unwrap_or(null_def_id());
|
||||
|
||||
let id = data.id.to_string();
|
||||
let ref_id = self_ref.index.as_usize().to_string();
|
||||
let ref_id_crate = self_ref.krate.to_string();
|
||||
let trait_id = trait_ref.index.as_usize().to_string();
|
||||
let trait_id_crate = trait_ref.krate.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("refid", &ref_id),
|
||||
("refidcrate", &ref_id_crate),
|
||||
("traitid", &trait_id),
|
||||
("traitidcrate", &trait_id_crate),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("impl", data.span, values);
|
||||
}
|
||||
|
||||
fn inheritance(&mut self, data: InheritanceData) {
|
||||
if self.dump_spans {
|
||||
return;
|
||||
}
|
||||
|
||||
let base_id = data.base_id.index.as_usize().to_string();
|
||||
let base_crate = data.base_id.krate.to_string();
|
||||
let deriv_id = data.deriv_id.to_string();
|
||||
let deriv_crate = 0.to_string();
|
||||
let values = make_values_str(&[
|
||||
("base", &base_id),
|
||||
("basecrate", &base_crate),
|
||||
("derived", &deriv_id),
|
||||
("derivedcrate", &deriv_crate)
|
||||
]);
|
||||
|
||||
self.record("inheritance", data.span, values);
|
||||
}
|
||||
|
||||
fn function(&mut self, span: Span, data: FunctionData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("function", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let (decl_id, decl_crate) = match data.declaration {
|
||||
Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()),
|
||||
None => (String::new(), String::new())
|
||||
};
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("qualname", &data.qualname),
|
||||
("declid", &decl_id),
|
||||
("declidcrate", &decl_crate),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("function", data.span, values);
|
||||
}
|
||||
|
||||
fn function_ref(&mut self, span: Span, data: FunctionRefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("fn_ref", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let ref_id = data.ref_id.index.as_usize().to_string();
|
||||
let ref_crate = data.ref_id.krate.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("refid", &ref_id),
|
||||
("refidcrate", &ref_crate),
|
||||
("qualname", ""),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("fn_ref", data.span, values);
|
||||
}
|
||||
|
||||
fn function_call(&mut self, span: Span, data: FunctionCallData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("fn_call", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let ref_id = data.ref_id.index.as_usize().to_string();
|
||||
let ref_crate = data.ref_id.krate.to_string();
|
||||
let qualname = String::new();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("refid", &ref_id),
|
||||
("refidcrate", &ref_crate),
|
||||
("qualname", &qualname),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("fn_call", data.span, values);
|
||||
}
|
||||
|
||||
fn method(&mut self, span: Span, data: MethodData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("method_decl", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("qualname", &data.qualname),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("method_decl", span, values);
|
||||
}
|
||||
|
||||
fn method_call(&mut self, span: Span, data: MethodCallData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("method_call", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let (dcn, dck) = match data.decl_id {
|
||||
Some(declid) => (declid.index.as_usize().to_string(), declid.krate.to_string()),
|
||||
None => (String::new(), String::new()),
|
||||
};
|
||||
|
||||
let ref_id = data.ref_id.unwrap_or(null_def_id());
|
||||
|
||||
let def_id = ref_id.index.as_usize().to_string();
|
||||
let def_crate = ref_id.krate.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("refid", &def_id),
|
||||
("refidcrate", &def_crate),
|
||||
("declid", &dcn),
|
||||
("declidcrate", &dck),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("method_call", data.span, values);
|
||||
}
|
||||
|
||||
fn macro_data(&mut self, span: Span, data: MacroData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("macro", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let values = make_values_str(&[
|
||||
("name", &data.name),
|
||||
("qualname", &data.qualname)
|
||||
]);
|
||||
|
||||
self.record("macro", data.span, values);
|
||||
}
|
||||
|
||||
fn macro_use(&mut self, span: Span, data: MacroUseData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("macro_use", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("callee_name", &data.name),
|
||||
("qualname", &data.qualname),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("macro_use", data.span, values);
|
||||
}
|
||||
|
||||
fn mod_data(&mut self, data: ModData) {
|
||||
if self.dump_spans {
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("qualname", &data.qualname),
|
||||
("scopeid", &scope),
|
||||
("def_file", &data.filename)
|
||||
]);
|
||||
|
||||
self.record("module", data.span, values);
|
||||
}
|
||||
|
||||
fn mod_ref(&mut self, span: Span, data: ModRefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("mod_ref", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let (ref_id, ref_crate) = match data.ref_id {
|
||||
Some(rid) => (rid.index.as_usize().to_string(), rid.krate.to_string()),
|
||||
None => (0.to_string(), 0.to_string())
|
||||
};
|
||||
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("refid", &ref_id),
|
||||
("refidcrate", &ref_crate),
|
||||
("qualname", &data.qualname),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("mod_ref", data.span, values);
|
||||
}
|
||||
|
||||
fn struct_data(&mut self, span: Span, data: StructData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("struct", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let ctor_id = data.ctor_id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("ctor_id", &ctor_id),
|
||||
("qualname", &data.qualname),
|
||||
("scopeid", &scope),
|
||||
("value", &data.value)
|
||||
]);
|
||||
|
||||
self.record("struct", data.span, values);
|
||||
}
|
||||
|
||||
fn struct_variant(&mut self, span: Span, data: StructVariantData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("variant_struct", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("ctor_id", &id),
|
||||
("qualname", &data.qualname),
|
||||
("type", &data.type_value),
|
||||
("value", &data.value),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("variant_struct", data.span, values);
|
||||
}
|
||||
|
||||
fn trait_data(&mut self, span: Span, data: TraitData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("trait", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("qualname", &data.qualname),
|
||||
("scopeid", &scope),
|
||||
("value", &data.value)
|
||||
]);
|
||||
|
||||
self.record("trait", data.span, values);
|
||||
}
|
||||
|
||||
fn tuple_variant(&mut self, span: Span, data: TupleVariantData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("variant", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("name", &data.name),
|
||||
("qualname", &data.qualname),
|
||||
("type", &data.type_value),
|
||||
("value", &data.value),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("variant", data.span, values);
|
||||
}
|
||||
|
||||
fn type_ref(&mut self, span: Span, data: TypeRefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("type_ref", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let (ref_id, ref_crate) = match data.ref_id {
|
||||
Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()),
|
||||
None => (0.to_string(), 0.to_string())
|
||||
};
|
||||
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("refid", &ref_id),
|
||||
("refidcrate", &ref_crate),
|
||||
("qualname", &data.qualname),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("type_ref", data.span, values);
|
||||
}
|
||||
|
||||
fn typedef(&mut self, span: Span, data: TypedefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("typedef", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("qualname", &data.qualname),
|
||||
("value", &data.value)
|
||||
]);
|
||||
|
||||
self.record("typedef", data.span, values);
|
||||
}
|
||||
|
||||
fn use_data(&mut self, span: Span, data: UseData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("use_alias", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let mod_id = data.mod_id.unwrap_or(null_def_id());
|
||||
|
||||
let id = data.id.to_string();
|
||||
let ref_id = mod_id.index.as_usize().to_string();
|
||||
let ref_crate = mod_id.krate.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("refid", &ref_id),
|
||||
("refidcrate", &ref_crate),
|
||||
("name", &data.name),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("use_alias", data.span, values);
|
||||
}
|
||||
|
||||
fn use_glob(&mut self, span: Span, data: UseGlobData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("use_glob", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let names = data.names.join(", ");
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("value", &names),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("use_glob", data.span, values);
|
||||
}
|
||||
|
||||
fn variable(&mut self, span: Span, data: VariableData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("variable", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let id = data.id.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("id", &id),
|
||||
("name", &data.name),
|
||||
("qualname", &data.qualname),
|
||||
("value", &data.value),
|
||||
("type", &data.type_value),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("variable", data.span, values);
|
||||
}
|
||||
|
||||
fn variable_ref(&mut self, span: Span, data: VariableRefData) {
|
||||
if self.dump_spans {
|
||||
self.dump_span("var_ref", span);
|
||||
return;
|
||||
}
|
||||
|
||||
let ref_id = data.ref_id.index.as_usize().to_string();
|
||||
let ref_crate = data.ref_id.krate.to_string();
|
||||
let scope = data.scope.to_string();
|
||||
let values = make_values_str(&[
|
||||
("refid", &ref_id),
|
||||
("refidcrate", &ref_crate),
|
||||
("qualname", ""),
|
||||
("scopeid", &scope)
|
||||
]);
|
||||
|
||||
self.record("var_ref", data.span, values)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to escape quotes in a string
|
||||
fn escape(s: String) -> String {
|
||||
s.replace("\"", "\"\"")
|
||||
}
|
||||
|
||||
fn make_values_str(pairs: &[(&'static str, &str)]) -> String {
|
||||
let pairs = pairs.into_iter().map(|&(f, v)| {
|
||||
// Never take more than 1020 chars
|
||||
if v.len() > 1020 {
|
||||
(f, &v[..1020])
|
||||
} else {
|
||||
(f, v)
|
||||
}
|
||||
});
|
||||
|
||||
let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v))));
|
||||
strs.fold(String::new(), |mut s, ss| {
|
||||
s.push_str(&ss[..]);
|
||||
s
|
||||
})
|
||||
}
|
||||
|
||||
fn null_def_id() -> DefId {
|
||||
DefId {
|
||||
krate: 0,
|
||||
index: DefIndex::new(0),
|
||||
}
|
||||
}
|
394
src/librustc_trans/save/data.rs
Normal file
394
src/librustc_trans/save/data.rs
Normal file
@ -0,0 +1,394 @@
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Structs representing the analysis data from a crate.
|
||||
//!
|
||||
//! The `Dump` trait can be used together with `DumpVisitor` in order to
|
||||
//! retrieve the data from a crate.
|
||||
|
||||
use std::hash::Hasher;
|
||||
|
||||
use middle::def_id::DefId;
|
||||
use middle::ty;
|
||||
use syntax::ast::{CrateNum, NodeId};
|
||||
use syntax::codemap::Span;
|
||||
|
||||
#[macro_export]
|
||||
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 CrateData {
|
||||
pub name: String,
|
||||
pub number: u32,
|
||||
}
|
||||
|
||||
/// Data for any entity in the Rust language. The actual data contained varies
|
||||
/// with the kind of entity being queried. See the nested structs for details.
|
||||
#[derive(Debug)]
|
||||
pub enum Data {
|
||||
/// Data for Enums.
|
||||
EnumData(EnumData),
|
||||
/// Data for extern crates.
|
||||
ExternCrateData(ExternCrateData),
|
||||
/// Data about a function call.
|
||||
FunctionCallData(FunctionCallData),
|
||||
/// Data for all kinds of functions and methods.
|
||||
FunctionData(FunctionData),
|
||||
/// Data about a function ref.
|
||||
FunctionRefData(FunctionRefData),
|
||||
/// Data for impls.
|
||||
ImplData(ImplData2),
|
||||
/// Data for trait inheritance.
|
||||
InheritanceData(InheritanceData),
|
||||
/// Data about a macro declaration.
|
||||
MacroData(MacroData),
|
||||
/// Data about a macro use.
|
||||
MacroUseData(MacroUseData),
|
||||
/// Data about a method call.
|
||||
MethodCallData(MethodCallData),
|
||||
/// Data for method declarations (methods with a body are treated as functions).
|
||||
MethodData(MethodData),
|
||||
/// Data for modules.
|
||||
ModData(ModData),
|
||||
/// Data for a reference to a module.
|
||||
ModRefData(ModRefData),
|
||||
/// Data for a struct declaration.
|
||||
StructData(StructData),
|
||||
/// Data for a struct variant.
|
||||
StructVariantDat(StructVariantData),
|
||||
/// Data for a trait declaration.
|
||||
TraitData(TraitData),
|
||||
/// Data for a tuple variant.
|
||||
TupleVariantData(TupleVariantData),
|
||||
/// Data for a typedef.
|
||||
TypeDefData(TypedefData),
|
||||
/// Data for a reference to a type or trait.
|
||||
TypeRefData(TypeRefData),
|
||||
/// Data for a use statement.
|
||||
UseData(UseData),
|
||||
/// Data for a global use statement.
|
||||
UseGlobData(UseGlobData),
|
||||
/// Data for local and global variables (consts and statics), and fields.
|
||||
VariableData(VariableData),
|
||||
/// 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 the prelude of a crate.
|
||||
#[derive(Debug)]
|
||||
pub struct CratePreludeData {
|
||||
pub crate_name: String,
|
||||
pub crate_root: Option<String>,
|
||||
pub external_crates: Vec<ExternalCrateData>
|
||||
}
|
||||
|
||||
/// Data for external crates in the prelude of a crate.
|
||||
#[derive(Debug)]
|
||||
pub struct ExternalCrateData {
|
||||
pub name: String,
|
||||
pub num: CrateNum
|
||||
}
|
||||
|
||||
/// Data for enum declarations.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EnumData {
|
||||
pub id: NodeId,
|
||||
pub value: String,
|
||||
pub qualname: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
}
|
||||
|
||||
/// Data for extern crates.
|
||||
#[derive(Debug)]
|
||||
pub struct ExternCrateData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
pub crate_num: CrateNum,
|
||||
pub location: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
}
|
||||
|
||||
/// Data about a function call.
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionCallData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub ref_id: DefId,
|
||||
}
|
||||
|
||||
/// Data for all kinds of functions and methods.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FunctionData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
pub qualname: String,
|
||||
pub declaration: Option<DefId>,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
}
|
||||
|
||||
/// Data about a function call.
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionRefData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub ref_id: DefId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImplData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub trait_ref: Option<DefId>,
|
||||
pub self_ref: Option<DefId>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
// FIXME: this struct should not exist. However, removing it requires heavy
|
||||
// refactoring of dump_visitor.rs. See PR 31838 for more info.
|
||||
pub struct ImplData2 {
|
||||
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>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InheritanceData {
|
||||
pub span: Span,
|
||||
pub base_id: DefId,
|
||||
pub deriv_id: NodeId
|
||||
}
|
||||
|
||||
/// Data about a macro declaration.
|
||||
#[derive(Debug)]
|
||||
pub struct MacroData {
|
||||
pub span: Span,
|
||||
pub name: String,
|
||||
pub qualname: String,
|
||||
}
|
||||
|
||||
/// Data about a macro use.
|
||||
#[derive(Debug)]
|
||||
pub struct MacroUseData {
|
||||
pub span: Span,
|
||||
pub name: String,
|
||||
pub qualname: String,
|
||||
// Because macro expansion happens before ref-ids are determined,
|
||||
// we use the callee span to reference the associated macro definition.
|
||||
pub callee_span: Span,
|
||||
pub scope: NodeId,
|
||||
pub imported: bool,
|
||||
}
|
||||
|
||||
/// 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>,
|
||||
}
|
||||
|
||||
/// Data for method declarations (methods with a body are treated as functions).
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MethodData {
|
||||
pub id: NodeId,
|
||||
pub qualname: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
}
|
||||
|
||||
/// Data for modules.
|
||||
#[derive(Debug)]
|
||||
pub struct ModData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
pub qualname: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub filename: String,
|
||||
}
|
||||
|
||||
/// Data for a reference to a module.
|
||||
#[derive(Debug)]
|
||||
pub struct ModRefData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub ref_id: Option<DefId>,
|
||||
pub qualname: String
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StructData {
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
pub ctor_id: NodeId,
|
||||
pub qualname: String,
|
||||
pub scope: NodeId,
|
||||
pub value: String
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StructVariantData {
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
pub qualname: String,
|
||||
pub type_value: String,
|
||||
pub value: String,
|
||||
pub scope: NodeId
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TraitData {
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
pub qualname: String,
|
||||
pub scope: NodeId,
|
||||
pub value: String
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TupleVariantData {
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
pub qualname: String,
|
||||
pub type_value: String,
|
||||
pub value: String,
|
||||
pub scope: NodeId
|
||||
}
|
||||
|
||||
/// Data for a typedef.
|
||||
#[derive(Debug)]
|
||||
pub struct TypedefData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub qualname: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
/// Data for a reference to a type or trait.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TypeRefData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub ref_id: Option<DefId>,
|
||||
pub qualname: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UseData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub name: String,
|
||||
pub mod_id: Option<DefId>,
|
||||
pub scope: NodeId
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UseGlobData {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub names: Vec<String>,
|
||||
pub scope: NodeId
|
||||
}
|
||||
|
||||
/// Data for local and global variables (consts and statics).
|
||||
#[derive(Debug)]
|
||||
pub struct VariableData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
pub qualname: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub value: String,
|
||||
pub type_value: String,
|
||||
}
|
||||
|
||||
/// Data for the use of some item (e.g., the use of a local variable, which
|
||||
/// will refer to that variables declaration (by ref_id)).
|
||||
#[derive(Debug)]
|
||||
pub struct VariableRefData {
|
||||
pub name: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub ref_id: DefId,
|
||||
}
|
||||
|
||||
// Emitted ids are used to cross-reference items across crates. DefIds and
|
||||
// NodeIds do not usually correspond in any way. The strategy is to use the
|
||||
// index from the DefId as a crate-local id. However, within a crate, DefId
|
||||
// indices and NodeIds can overlap. So, we must adjust the NodeIds. If an
|
||||
// item can be identified by a DefId as well as a NodeId, then we use the
|
||||
// DefId index as the id. If it can't, then we have to use the NodeId, but
|
||||
// need to adjust it so it will not clash with any possible DefId index.
|
||||
pub fn normalize_node_id<'a>(tcx: &ty::TyCtxt<'a>, id: NodeId) -> usize {
|
||||
match tcx.map.opt_local_def_id(id) {
|
||||
Some(id) => id.index.as_usize(),
|
||||
None => id as usize + tcx.map.num_local_def_ids()
|
||||
}
|
||||
}
|
||||
|
||||
// Macro to implement a normalize() function (see below for usage)
|
||||
macro_rules! impl_normalize {
|
||||
($($t:ty => $($field:ident),*);*) => {
|
||||
$(
|
||||
impl $t {
|
||||
pub fn normalize<'a>(mut self, tcx: &ty::TyCtxt<'a>) -> $t {
|
||||
$(
|
||||
self.$field = normalize_node_id(tcx, self.$field) as u32;
|
||||
)*
|
||||
self
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_normalize! {
|
||||
EnumData => id, scope;
|
||||
ExternCrateData => id, scope;
|
||||
FunctionCallData => scope;
|
||||
FunctionData => id, scope;
|
||||
FunctionRefData => scope;
|
||||
ImplData => id, scope;
|
||||
InheritanceData => deriv_id;
|
||||
MacroUseData => scope;
|
||||
MethodCallData => scope;
|
||||
MethodData => id, scope;
|
||||
ModData => id, scope;
|
||||
ModRefData => scope;
|
||||
StructData => ctor_id, id, scope;
|
||||
StructVariantData => id, scope;
|
||||
TupleVariantData => id, scope;
|
||||
TraitData => id, scope;
|
||||
TypedefData => id;
|
||||
TypeRefData => scope;
|
||||
UseData => id, scope;
|
||||
UseGlobData => id, scope;
|
||||
VariableData => id;
|
||||
VariableRefData => scope
|
||||
}
|
40
src/librustc_trans/save/dump.rs
Normal file
40
src/librustc_trans/save/dump.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use super::data::*;
|
||||
|
||||
pub trait Dump {
|
||||
fn crate_prelude(&mut self, _: Span, _: CratePreludeData) {}
|
||||
fn enum_data(&mut self, _: Span, _: EnumData) {}
|
||||
fn extern_crate(&mut self, _: Span, _: ExternCrateData) {}
|
||||
fn impl_data(&mut self, _: Span, _: ImplData) {}
|
||||
fn inheritance(&mut self, _: InheritanceData) {}
|
||||
fn function(&mut self, _: Span, _: FunctionData) {}
|
||||
fn function_ref(&mut self, _: Span, _: FunctionRefData) {}
|
||||
fn function_call(&mut self, _: Span, _: FunctionCallData) {}
|
||||
fn method(&mut self, _: Span, _: MethodData) {}
|
||||
fn method_call(&mut self, _: Span, _: MethodCallData) {}
|
||||
fn macro_data(&mut self, _: Span, _: MacroData) {}
|
||||
fn macro_use(&mut self, _: Span, _: MacroUseData) {}
|
||||
fn mod_data(&mut self, _: ModData) {}
|
||||
fn mod_ref(&mut self, _: Span, _: ModRefData) {}
|
||||
fn struct_data(&mut self, _: Span, _: StructData) {}
|
||||
fn struct_variant(&mut self, _: Span, _: StructVariantData) {}
|
||||
fn trait_data(&mut self, _: Span, _: TraitData) {}
|
||||
fn tuple_variant(&mut self, _: Span, _: TupleVariantData) {}
|
||||
fn type_ref(&mut self, _: Span, _: TypeRefData) {}
|
||||
fn typedef(&mut self, _: Span, _: TypedefData) {}
|
||||
fn use_data(&mut self, _: Span, _: UseData) {}
|
||||
fn use_glob(&mut self, _: Span, _: UseGlobData) {}
|
||||
fn variable(&mut self, _: Span, _: VariableData) {}
|
||||
fn variable_ref(&mut self, _: Span, _: VariableRefData) {}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -28,13 +28,32 @@ use syntax::parse::token::{self, keywords};
|
||||
use syntax::visit::{self, Visitor};
|
||||
use syntax::print::pprust::ty_to_string;
|
||||
|
||||
use self::span_utils::SpanUtils;
|
||||
|
||||
mod csv_dumper;
|
||||
#[macro_use]
|
||||
mod data;
|
||||
mod dump;
|
||||
mod dump_visitor;
|
||||
#[macro_use]
|
||||
pub mod span_utils;
|
||||
pub mod recorder;
|
||||
|
||||
mod dump_csv;
|
||||
pub use self::csv_dumper::CsvDumper;
|
||||
pub use self::data::*;
|
||||
pub use self::dump::Dump;
|
||||
pub use self::dump_visitor::DumpVisitor;
|
||||
use self::span_utils::SpanUtils;
|
||||
|
||||
// FIXME this is legacy code and should be removed
|
||||
pub mod recorder {
|
||||
pub use self::Row::*;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Row {
|
||||
TypeRef,
|
||||
ModRef,
|
||||
VarRef,
|
||||
FnRef,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SaveContext<'l, 'tcx: 'l> {
|
||||
tcx: &'l TyCtxt<'tcx>,
|
||||
@ -42,158 +61,10 @@ pub struct SaveContext<'l, 'tcx: 'l> {
|
||||
span_utils: SpanUtils<'l>,
|
||||
}
|
||||
|
||||
pub struct CrateData {
|
||||
pub name: String,
|
||||
pub number: u32,
|
||||
}
|
||||
|
||||
/// 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), 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 a reference to a module.
|
||||
ModRefData(ModRefData),
|
||||
/// Data about a function call.
|
||||
FunctionCallData(FunctionCallData),
|
||||
/// Data about a method call.
|
||||
MethodCallData(MethodCallData),
|
||||
/// Data about a macro use.
|
||||
MacroUseData(MacroUseData),
|
||||
}
|
||||
|
||||
/// Data for all kinds of functions and methods.
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
pub qualname: String,
|
||||
pub declaration: Option<DefId>,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
}
|
||||
|
||||
/// Data for local and global variables (consts and statics).
|
||||
#[derive(Debug)]
|
||||
pub struct VariableData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
pub qualname: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub value: String,
|
||||
pub type_value: String,
|
||||
}
|
||||
|
||||
/// Data for modules.
|
||||
#[derive(Debug)]
|
||||
pub struct ModData {
|
||||
pub id: NodeId,
|
||||
pub name: String,
|
||||
pub qualname: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
pub filename: String,
|
||||
}
|
||||
|
||||
/// 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 refer to that variables declaration (by ref_id)).
|
||||
#[derive(Debug)]
|
||||
pub struct VariableRefData {
|
||||
pub name: String,
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
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,
|
||||
}
|
||||
|
||||
/// Data for a reference to a module.
|
||||
#[derive(Debug)]
|
||||
pub struct ModRefData {
|
||||
pub span: Span,
|
||||
pub scope: NodeId,
|
||||
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>,
|
||||
}
|
||||
|
||||
/// Data about a macro use.
|
||||
#[derive(Debug)]
|
||||
pub struct MacroUseData {
|
||||
pub span: Span,
|
||||
pub name: String,
|
||||
// Because macro expansion happens before ref-ids are determined,
|
||||
// we use the callee span to reference the associated macro definition.
|
||||
pub callee_span: Span,
|
||||
pub scope: NodeId,
|
||||
pub imported: bool,
|
||||
}
|
||||
|
||||
macro_rules! option_try(
|
||||
($e:expr) => (match $e { Some(e) => e, None => return None })
|
||||
);
|
||||
|
||||
|
||||
|
||||
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
pub fn new(tcx: &'l TyCtxt<'tcx>,
|
||||
lcx: &'l lowering::LoweringContext<'l>)
|
||||
@ -325,7 +196,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
ref_id: id,
|
||||
ref_id: Some(id),
|
||||
qualname: String::new() // FIXME: generate the real qualname
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -340,7 +212,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
.and_then(|tr| self.get_trait_ref_data(tr, parent));
|
||||
|
||||
filter!(self.span_utils, sub_span, typ.span, None);
|
||||
Some(Data::ImplData(ImplData {
|
||||
Some(Data::ImplData(ImplData2 {
|
||||
id: item.id,
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
@ -477,7 +349,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
Some(TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
ref_id: def_id,
|
||||
ref_id: Some(def_id),
|
||||
qualname: String::new() // FIXME: generate the real qualname
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -518,7 +391,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
Some(Data::TypeRefData(TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.enclosing_scope(expr.id),
|
||||
ref_id: def.did,
|
||||
ref_id: Some(def.did),
|
||||
qualname: String::new() // FIXME: generate the real qualname
|
||||
}))
|
||||
}
|
||||
_ => {
|
||||
@ -586,8 +460,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
Def::TyParam(_, _, def_id, _) => {
|
||||
Some(Data::TypeRefData(TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
ref_id: def_id,
|
||||
ref_id: Some(def_id),
|
||||
scope: self.enclosing_scope(id),
|
||||
qualname: String::new() // FIXME: generate the real qualname
|
||||
}))
|
||||
}
|
||||
Def::Method(decl_id) => {
|
||||
@ -635,9 +510,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}
|
||||
Def::Mod(def_id) => {
|
||||
Some(Data::ModRefData(ModRefData {
|
||||
ref_id: def_id,
|
||||
ref_id: Some(def_id),
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.enclosing_scope(id),
|
||||
qualname: String::new() // FIXME: generate the real qualname
|
||||
}))
|
||||
}
|
||||
_ => None,
|
||||
@ -708,6 +584,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
callee_span: mac_span,
|
||||
scope: self.enclosing_scope(id),
|
||||
imported: true,
|
||||
qualname: String::new()// FIXME: generate the real qualname
|
||||
});
|
||||
}
|
||||
|
||||
@ -717,6 +594,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
callee_span: callee_span,
|
||||
scope: self.enclosing_scope(id),
|
||||
imported: false,
|
||||
qualname: String::new() // FIXME: generate the real qualname
|
||||
})
|
||||
}
|
||||
|
||||
@ -833,16 +711,16 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
|
||||
out_name.push_str(&tcx.sess.opts.cg.extra_filename);
|
||||
out_name.push_str(".csv");
|
||||
root_path.push(&out_name);
|
||||
let output_file = match File::create(&root_path) {
|
||||
Ok(f) => box f,
|
||||
Err(e) => {
|
||||
let disp = root_path.display();
|
||||
tcx.sess.fatal(&format!("Could not open {}: {}", disp, e));
|
||||
}
|
||||
};
|
||||
let mut output_file = File::create(&root_path).unwrap_or_else(|e| {
|
||||
let disp = root_path.display();
|
||||
tcx.sess.fatal(&format!("Could not open {}: {}", disp, e));
|
||||
});
|
||||
root_path.pop();
|
||||
|
||||
let mut visitor = dump_csv::DumpCsvVisitor::new(tcx, lcx, analysis, output_file);
|
||||
let utils = SpanUtils::new(&tcx.sess);
|
||||
let mut dumper = CsvDumper::new(&mut output_file, utils);
|
||||
let mut visitor = DumpVisitor::new(tcx, lcx, analysis, &mut dumper);
|
||||
// FIXME: we don't write anything!
|
||||
|
||||
visitor.dump_crate_info(cratename, krate);
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
|
@ -1,714 +0,0 @@
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub use self::Row::*;
|
||||
|
||||
use super::escape;
|
||||
use super::span_utils::SpanUtils;
|
||||
|
||||
use middle::cstore::LOCAL_CRATE;
|
||||
use middle::def_id::{CRATE_DEF_INDEX, DefId};
|
||||
use middle::ty::TyCtxt;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ast::NodeId;
|
||||
use syntax::codemap::*;
|
||||
|
||||
const CRATE_ROOT_DEF_ID: DefId = DefId {
|
||||
krate: LOCAL_CRATE,
|
||||
index: CRATE_DEF_INDEX,
|
||||
};
|
||||
|
||||
pub struct Recorder {
|
||||
// output file
|
||||
pub out: Box<Write + 'static>,
|
||||
pub dump_spans: bool,
|
||||
}
|
||||
|
||||
impl Recorder {
|
||||
pub fn record(&mut self, info: &str) {
|
||||
match write!(self.out, "{}", info) {
|
||||
Err(_) => error!("Error writing output '{}'", info),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump_span(&mut self, su: SpanUtils, kind: &str, span: Span, _sub_span: Option<Span>) {
|
||||
assert!(self.dump_spans);
|
||||
let result = format!("span,kind,{},{},text,\"{}\"\n",
|
||||
kind,
|
||||
su.extent_str(span),
|
||||
escape(su.snippet(span)));
|
||||
self.record(&result[..]);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FmtStrs<'a, 'tcx: 'a> {
|
||||
pub recorder: Box<Recorder>,
|
||||
span: SpanUtils<'a>,
|
||||
tcx: &'a TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
macro_rules! s { ($e:expr) => { format!("{}", $e) }}
|
||||
macro_rules! svec {
|
||||
($($e:expr),*) => ({
|
||||
// leading _ to allow empty construction without a warning.
|
||||
let mut _temp = ::std::vec::Vec::new();
|
||||
$(_temp.push(s!($e));)*
|
||||
_temp
|
||||
})
|
||||
}
|
||||
|
||||
// FIXME recorder should operate on super::Data, rather than lots of ad hoc
|
||||
// data.
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Row {
|
||||
Variable,
|
||||
Enum,
|
||||
Variant,
|
||||
VariantStruct,
|
||||
Function,
|
||||
MethodDecl,
|
||||
Struct,
|
||||
Trait,
|
||||
Impl,
|
||||
Module,
|
||||
UseAlias,
|
||||
UseGlob,
|
||||
ExternCrate,
|
||||
Inheritance,
|
||||
MethodCall,
|
||||
Typedef,
|
||||
ExternalCrate,
|
||||
Crate,
|
||||
FnCall,
|
||||
ModRef,
|
||||
VarRef,
|
||||
TypeRef,
|
||||
FnRef,
|
||||
Macro,
|
||||
MacroUse,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> {
|
||||
pub fn new(rec: Box<Recorder>,
|
||||
span: SpanUtils<'a>,
|
||||
tcx: &'a TyCtxt<'tcx>)
|
||||
-> FmtStrs<'a, 'tcx> {
|
||||
FmtStrs {
|
||||
recorder: rec,
|
||||
span: span,
|
||||
tcx: tcx,
|
||||
}
|
||||
}
|
||||
|
||||
// Emitted ids are used to cross-reference items across crates. DefIds and
|
||||
// NodeIds do not usually correspond in any way. The strategy is to use the
|
||||
// index from the DefId as a crate-local id. However, within a crate, DefId
|
||||
// indices and NodeIds can overlap. So, we must adjust the NodeIds. If an
|
||||
// item can be identified by a DefId as well as a NodeId, then we use the
|
||||
// DefId index as the id. If it can't, then we have to use the NodeId, but
|
||||
// need to adjust it so it will not clash with any possible DefId index.
|
||||
fn normalize_node_id(&self, id: NodeId) -> usize {
|
||||
match self.tcx.map.opt_local_def_id(id) {
|
||||
Some(id) => id.index.as_usize(),
|
||||
None => id as usize + self.tcx.map.num_local_def_ids()
|
||||
}
|
||||
}
|
||||
|
||||
// A map from kind of item to a tuple of
|
||||
// a string representation of the name
|
||||
// a vector of field names
|
||||
// whether this kind requires a span
|
||||
// whether dump_spans should dump for this kind
|
||||
fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
|
||||
match r {
|
||||
Variable => ("variable",
|
||||
vec!("id", "name", "qualname", "value", "type", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
Enum => ("enum",
|
||||
vec!("id", "qualname", "scopeid", "value"),
|
||||
true,
|
||||
true),
|
||||
Variant => ("variant",
|
||||
vec!("id", "name", "qualname", "type", "value", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
VariantStruct => ("variant_struct",
|
||||
vec!("id", "ctor_id", "qualname", "type", "value", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
Function => ("function",
|
||||
vec!("id", "qualname", "declid", "declidcrate", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
MethodDecl => ("method_decl",
|
||||
vec!("id", "qualname", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
Struct => ("struct",
|
||||
vec!("id", "ctor_id", "qualname", "scopeid", "value"),
|
||||
true,
|
||||
true),
|
||||
Trait => ("trait",
|
||||
vec!("id", "qualname", "scopeid", "value"),
|
||||
true,
|
||||
true),
|
||||
Impl => ("impl",
|
||||
vec!("id",
|
||||
"refid",
|
||||
"refidcrate",
|
||||
"traitid",
|
||||
"traitidcrate",
|
||||
"scopeid"),
|
||||
true,
|
||||
true),
|
||||
Module => ("module",
|
||||
vec!("id", "qualname", "scopeid", "def_file"),
|
||||
true,
|
||||
false),
|
||||
UseAlias => ("use_alias",
|
||||
vec!("id", "refid", "refidcrate", "name", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
UseGlob => ("use_glob", vec!("id", "value", "scopeid"), true, true),
|
||||
ExternCrate => ("extern_crate",
|
||||
vec!("id", "name", "location", "crate", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
Inheritance => ("inheritance",
|
||||
vec!("base", "basecrate", "derived", "derivedcrate"),
|
||||
true,
|
||||
false),
|
||||
MethodCall => ("method_call",
|
||||
vec!("refid", "refidcrate", "declid", "declidcrate", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
Typedef => ("typedef", vec!("id", "qualname", "value"), true, true),
|
||||
ExternalCrate => ("external_crate",
|
||||
vec!("name", "crate", "file_name"),
|
||||
false,
|
||||
false),
|
||||
Crate => ("crate", vec!("name", "crate_root"), true, false),
|
||||
FnCall => ("fn_call",
|
||||
vec!("refid", "refidcrate", "qualname", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
ModRef => ("mod_ref",
|
||||
vec!("refid", "refidcrate", "qualname", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
VarRef => ("var_ref",
|
||||
vec!("refid", "refidcrate", "qualname", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
TypeRef => ("type_ref",
|
||||
vec!("refid", "refidcrate", "qualname", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
FnRef => ("fn_ref",
|
||||
vec!("refid", "refidcrate", "qualname", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
Macro => ("macro",
|
||||
vec!("name", "qualname"),
|
||||
true,
|
||||
true),
|
||||
MacroUse => ("macro_use",
|
||||
vec!("callee_name", "qualname", "scopeid"),
|
||||
true,
|
||||
true),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_values_str(&self,
|
||||
kind: &'static str,
|
||||
fields: &Vec<&'static str>,
|
||||
values: Vec<String>,
|
||||
span: Span)
|
||||
-> Option<String> {
|
||||
if values.len() != fields.len() {
|
||||
self.span.sess.span_bug(span,
|
||||
&format!("Mismatch between length of fields for '{}', \
|
||||
expected '{}', found '{}'",
|
||||
kind,
|
||||
fields.len(),
|
||||
values.len()));
|
||||
}
|
||||
|
||||
let values = values.iter().map(|s| {
|
||||
// Never take more than 1020 chars
|
||||
if s.len() > 1020 {
|
||||
&s[..1020]
|
||||
} else {
|
||||
&s[..]
|
||||
}
|
||||
});
|
||||
|
||||
let pairs = fields.iter().zip(values);
|
||||
let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v))));
|
||||
Some(strs.fold(String::new(),
|
||||
|mut s, ss| {
|
||||
s.push_str(&ss[..]);
|
||||
s
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn record_without_span(&mut self, kind: Row, values: Vec<String>, span: Span) {
|
||||
let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
|
||||
|
||||
if needs_span {
|
||||
self.span.sess.span_bug(span,
|
||||
&format!("Called record_without_span for '{}' which does \
|
||||
requires a span",
|
||||
label));
|
||||
}
|
||||
assert!(!dump_spans);
|
||||
|
||||
if self.recorder.dump_spans {
|
||||
return;
|
||||
}
|
||||
|
||||
let values_str = match self.make_values_str(label, fields, values, span) {
|
||||
Some(vs) => vs,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let mut result = String::from(label);
|
||||
result.push_str(&values_str[..]);
|
||||
result.push_str("\n");
|
||||
self.recorder.record(&result[..]);
|
||||
}
|
||||
|
||||
pub fn record_with_span(&mut self,
|
||||
kind: Row,
|
||||
span: Span,
|
||||
sub_span: Span,
|
||||
values: Vec<String>) {
|
||||
let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
|
||||
|
||||
if self.recorder.dump_spans {
|
||||
if dump_spans {
|
||||
self.recorder.dump_span(self.span.clone(), label, span, Some(sub_span));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if !needs_span {
|
||||
self.span.sess.span_bug(span,
|
||||
&format!("Called record_with_span for '{}' which does not \
|
||||
require a span",
|
||||
label));
|
||||
}
|
||||
|
||||
let values_str = match self.make_values_str(label, fields, values, span) {
|
||||
Some(vs) => vs,
|
||||
None => return,
|
||||
};
|
||||
let result = format!("{},{}{}\n",
|
||||
label,
|
||||
self.span.extent_str(sub_span),
|
||||
values_str);
|
||||
self.recorder.record(&result[..]);
|
||||
}
|
||||
|
||||
pub fn check_and_record(&mut self,
|
||||
kind: Row,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
values: Vec<String>) {
|
||||
filter!(self.span, sub_span, span);
|
||||
match sub_span {
|
||||
Some(sub_span) => self.record_with_span(kind, span, sub_span, values),
|
||||
None => {
|
||||
let (label, _, _, _) = FmtStrs::lookup_row(kind);
|
||||
self.span.report_span_err(label, span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn variable_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
value: &str,
|
||||
typ: &str) {
|
||||
// Getting a fully qualified name for a variable is hard because in
|
||||
// the local case they can be overridden in one block and there is no nice way
|
||||
// to refer to such a scope in english, so we just hack it by appending the
|
||||
// variable def's node id
|
||||
let mut qualname = String::from(name);
|
||||
qualname.push_str("$");
|
||||
qualname.push_str(&id.to_string());
|
||||
let id = self.normalize_node_id(id);
|
||||
self.check_and_record(Variable,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, name, qualname, value, typ, 0));
|
||||
}
|
||||
|
||||
// formal parameters
|
||||
pub fn formal_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
fn_name: &str,
|
||||
name: &str,
|
||||
typ: &str) {
|
||||
let mut qualname = String::from(fn_name);
|
||||
qualname.push_str("::");
|
||||
qualname.push_str(name);
|
||||
let id = self.normalize_node_id(id);
|
||||
self.check_and_record(Variable,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, name, qualname, "", typ, 0));
|
||||
}
|
||||
|
||||
// value is the initialising expression of the static if it is not mut, otherwise "".
|
||||
pub fn static_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
qualname: &str,
|
||||
value: &str,
|
||||
typ: &str,
|
||||
scope_id: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(Variable,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, name, qualname, value, typ, scope_id));
|
||||
}
|
||||
|
||||
pub fn field_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
qualname: &str,
|
||||
typ: &str,
|
||||
scope_id: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(Variable,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, name, qualname, "", typ, scope_id));
|
||||
}
|
||||
|
||||
pub fn enum_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
scope_id: NodeId,
|
||||
value: &str) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(Enum, span, sub_span, svec!(id, name, scope_id, value));
|
||||
}
|
||||
|
||||
pub fn tuple_variant_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
qualname: &str,
|
||||
typ: &str,
|
||||
val: &str,
|
||||
scope_id: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(Variant,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, name, qualname, typ, val, scope_id));
|
||||
}
|
||||
|
||||
pub fn struct_variant_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
typ: &str,
|
||||
val: &str,
|
||||
scope_id: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let ctor_id = id;
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(VariantStruct,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, ctor_id, name, typ, val, scope_id));
|
||||
}
|
||||
|
||||
pub fn fn_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
scope_id: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(Function,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, name, "", "", scope_id));
|
||||
}
|
||||
|
||||
pub fn method_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
decl_id: Option<DefId>,
|
||||
scope_id: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
let values = match decl_id {
|
||||
Some(decl_id) => svec!(id,
|
||||
name,
|
||||
decl_id.index.as_usize(),
|
||||
decl_id.krate,
|
||||
scope_id),
|
||||
None => svec!(id, name, "", "", scope_id),
|
||||
};
|
||||
self.check_and_record(Function, span, sub_span, values);
|
||||
}
|
||||
|
||||
pub fn method_decl_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
scope_id: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(MethodDecl, span, sub_span, svec!(id, name, scope_id));
|
||||
}
|
||||
|
||||
pub fn struct_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
ctor_id: NodeId,
|
||||
name: &str,
|
||||
scope_id: NodeId,
|
||||
value: &str) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
let ctor_id = self.normalize_node_id(ctor_id);
|
||||
self.check_and_record(Struct,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, ctor_id, name, scope_id, value));
|
||||
}
|
||||
|
||||
pub fn trait_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
scope_id: NodeId,
|
||||
value: &str) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(Trait, span, sub_span, svec!(id, name, scope_id, value));
|
||||
}
|
||||
|
||||
pub fn impl_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
ref_id: Option<DefId>,
|
||||
trait_id: Option<DefId>,
|
||||
scope_id: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
let ref_id = ref_id.unwrap_or(CRATE_ROOT_DEF_ID);
|
||||
let trait_id = trait_id.unwrap_or(CRATE_ROOT_DEF_ID);
|
||||
self.check_and_record(Impl,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id,
|
||||
ref_id.index.as_usize(),
|
||||
ref_id.krate,
|
||||
trait_id.index.as_usize(),
|
||||
trait_id.krate,
|
||||
scope_id));
|
||||
}
|
||||
|
||||
pub fn mod_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
name: &str,
|
||||
parent: NodeId,
|
||||
filename: &str) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let parent = self.normalize_node_id(parent);
|
||||
self.check_and_record(Module,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, name, parent, filename));
|
||||
}
|
||||
|
||||
pub fn use_alias_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
mod_id: Option<DefId>,
|
||||
name: &str,
|
||||
parent: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let parent = self.normalize_node_id(parent);
|
||||
let mod_id = mod_id.unwrap_or(CRATE_ROOT_DEF_ID);
|
||||
self.check_and_record(UseAlias,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, mod_id.index.as_usize(), mod_id.krate, name, parent));
|
||||
}
|
||||
|
||||
pub fn use_glob_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
values: &str,
|
||||
parent: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let parent = self.normalize_node_id(parent);
|
||||
self.check_and_record(UseGlob, span, sub_span, svec!(id, values, parent));
|
||||
}
|
||||
|
||||
pub fn extern_crate_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
cnum: ast::CrateNum,
|
||||
name: &str,
|
||||
loc: &str,
|
||||
parent: NodeId) {
|
||||
let id = self.normalize_node_id(id);
|
||||
let parent = self.normalize_node_id(parent);
|
||||
self.check_and_record(ExternCrate,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id, name, loc, cnum, parent));
|
||||
}
|
||||
|
||||
pub fn inherit_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
base_id: DefId,
|
||||
deriv_id: NodeId) {
|
||||
let deriv_id = self.normalize_node_id(deriv_id);
|
||||
self.check_and_record(Inheritance,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(base_id.index.as_usize(), base_id.krate, deriv_id, 0));
|
||||
}
|
||||
|
||||
pub fn fn_call_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: DefId,
|
||||
scope_id: NodeId) {
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(FnCall,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id.index.as_usize(), id.krate, "", scope_id));
|
||||
}
|
||||
|
||||
pub fn meth_call_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
defid: Option<DefId>,
|
||||
declid: Option<DefId>,
|
||||
scope_id: NodeId) {
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
let defid = defid.unwrap_or(CRATE_ROOT_DEF_ID);
|
||||
let (dcn, dck) = match declid {
|
||||
Some(declid) => (s!(declid.index.as_usize()), s!(declid.krate)),
|
||||
None => ("".to_string(), "".to_string()),
|
||||
};
|
||||
self.check_and_record(MethodCall,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(defid.index.as_usize(), defid.krate, dcn, dck, scope_id));
|
||||
}
|
||||
|
||||
pub fn sub_mod_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str, parent: NodeId) {
|
||||
let parent = self.normalize_node_id(parent);
|
||||
self.record_with_span(ModRef, span, sub_span, svec!(0, 0, qualname, parent));
|
||||
}
|
||||
|
||||
pub fn typedef_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: NodeId,
|
||||
qualname: &str,
|
||||
value: &str) {
|
||||
let id = self.normalize_node_id(id);
|
||||
self.check_and_record(Typedef, span, sub_span, svec!(id, qualname, value));
|
||||
}
|
||||
|
||||
pub fn crate_str(&mut self, span: Span, name: &str, crate_root: &str) {
|
||||
self.record_with_span(Crate, span, span, svec!(name, crate_root));
|
||||
}
|
||||
|
||||
pub fn external_crate_str(&mut self, span: Span, name: &str, num: ast::CrateNum) {
|
||||
let lo_loc = self.span.sess.codemap().lookup_char_pos(span.lo);
|
||||
self.record_without_span(ExternalCrate,
|
||||
svec!(name, num, SpanUtils::make_path_string(&lo_loc.file.name)),
|
||||
span);
|
||||
}
|
||||
|
||||
pub fn sub_type_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str) {
|
||||
self.record_with_span(TypeRef, span, sub_span, svec!(0, 0, qualname, 0));
|
||||
}
|
||||
|
||||
// A slightly generic function for a reference to an item of any kind.
|
||||
pub fn ref_str(&mut self,
|
||||
kind: Row,
|
||||
span: Span,
|
||||
sub_span: Option<Span>,
|
||||
id: DefId,
|
||||
scope_id: NodeId) {
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.check_and_record(kind,
|
||||
span,
|
||||
sub_span,
|
||||
svec!(id.index.as_usize(), id.krate, "", scope_id));
|
||||
}
|
||||
|
||||
pub fn macro_str(&mut self, span: Span, sub_span: Span, name: String, qualname: String) {
|
||||
self.record_with_span(Macro, span, sub_span, svec!(name, qualname));
|
||||
}
|
||||
|
||||
pub fn macro_use_str(&mut self,
|
||||
span: Span,
|
||||
sub_span: Span,
|
||||
name: String,
|
||||
qualname: String,
|
||||
scope_id: NodeId) {
|
||||
let scope_id = self.normalize_node_id(scope_id);
|
||||
self.record_with_span(MacroUse, span, sub_span,
|
||||
svec!(name, qualname, scope_id));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user