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::visit::{self, Visitor};
|
||||||
use syntax::print::pprust::ty_to_string;
|
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]
|
#[macro_use]
|
||||||
pub mod span_utils;
|
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> {
|
pub struct SaveContext<'l, 'tcx: 'l> {
|
||||||
tcx: &'l TyCtxt<'tcx>,
|
tcx: &'l TyCtxt<'tcx>,
|
||||||
@ -42,158 +61,10 @@ pub struct SaveContext<'l, 'tcx: 'l> {
|
|||||||
span_utils: SpanUtils<'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(
|
macro_rules! option_try(
|
||||||
($e:expr) => (match $e { Some(e) => e, None => return None })
|
($e:expr) => (match $e { Some(e) => e, None => return None })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||||
pub fn new(tcx: &'l TyCtxt<'tcx>,
|
pub fn new(tcx: &'l TyCtxt<'tcx>,
|
||||||
lcx: &'l lowering::LoweringContext<'l>)
|
lcx: &'l lowering::LoweringContext<'l>)
|
||||||
@ -325,7 +196,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||||||
TypeRefData {
|
TypeRefData {
|
||||||
span: sub_span.unwrap(),
|
span: sub_span.unwrap(),
|
||||||
scope: parent,
|
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));
|
.and_then(|tr| self.get_trait_ref_data(tr, parent));
|
||||||
|
|
||||||
filter!(self.span_utils, sub_span, typ.span, None);
|
filter!(self.span_utils, sub_span, typ.span, None);
|
||||||
Some(Data::ImplData(ImplData {
|
Some(Data::ImplData(ImplData2 {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
span: sub_span.unwrap(),
|
span: sub_span.unwrap(),
|
||||||
scope: parent,
|
scope: parent,
|
||||||
@ -477,7 +349,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||||||
Some(TypeRefData {
|
Some(TypeRefData {
|
||||||
span: sub_span.unwrap(),
|
span: sub_span.unwrap(),
|
||||||
scope: parent,
|
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 {
|
Some(Data::TypeRefData(TypeRefData {
|
||||||
span: sub_span.unwrap(),
|
span: sub_span.unwrap(),
|
||||||
scope: self.enclosing_scope(expr.id),
|
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, _) => {
|
Def::TyParam(_, _, def_id, _) => {
|
||||||
Some(Data::TypeRefData(TypeRefData {
|
Some(Data::TypeRefData(TypeRefData {
|
||||||
span: sub_span.unwrap(),
|
span: sub_span.unwrap(),
|
||||||
ref_id: def_id,
|
ref_id: Some(def_id),
|
||||||
scope: self.enclosing_scope(id),
|
scope: self.enclosing_scope(id),
|
||||||
|
qualname: String::new() // FIXME: generate the real qualname
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Def::Method(decl_id) => {
|
Def::Method(decl_id) => {
|
||||||
@ -635,9 +510,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||||||
}
|
}
|
||||||
Def::Mod(def_id) => {
|
Def::Mod(def_id) => {
|
||||||
Some(Data::ModRefData(ModRefData {
|
Some(Data::ModRefData(ModRefData {
|
||||||
ref_id: def_id,
|
ref_id: Some(def_id),
|
||||||
span: sub_span.unwrap(),
|
span: sub_span.unwrap(),
|
||||||
scope: self.enclosing_scope(id),
|
scope: self.enclosing_scope(id),
|
||||||
|
qualname: String::new() // FIXME: generate the real qualname
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -708,6 +584,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||||||
callee_span: mac_span,
|
callee_span: mac_span,
|
||||||
scope: self.enclosing_scope(id),
|
scope: self.enclosing_scope(id),
|
||||||
imported: true,
|
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,
|
callee_span: callee_span,
|
||||||
scope: self.enclosing_scope(id),
|
scope: self.enclosing_scope(id),
|
||||||
imported: false,
|
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(&tcx.sess.opts.cg.extra_filename);
|
||||||
out_name.push_str(".csv");
|
out_name.push_str(".csv");
|
||||||
root_path.push(&out_name);
|
root_path.push(&out_name);
|
||||||
let output_file = match File::create(&root_path) {
|
let mut output_file = File::create(&root_path).unwrap_or_else(|e| {
|
||||||
Ok(f) => box f,
|
let disp = root_path.display();
|
||||||
Err(e) => {
|
tcx.sess.fatal(&format!("Could not open {}: {}", disp, e));
|
||||||
let disp = root_path.display();
|
});
|
||||||
tcx.sess.fatal(&format!("Could not open {}: {}", disp, e));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
root_path.pop();
|
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);
|
visitor.dump_crate_info(cratename, krate);
|
||||||
visit::walk_crate(&mut visitor, 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