In fact, we make JSOn the default and add an option for save-analysis-csv for the legacy behaviour.
We also rename some bits and pieces `dxr` -> `save-analysis`
ls: bool = (false, parse_bool,
"list the symbols defined by a library crate"),
save_analysis: bool = (false, parse_bool,
- "write syntax and type analysis information in addition to normal output"),
+ "write syntax and type analysis (in JSON format) information in addition to normal output"),
+ save_analysis_csv: bool = (false, parse_bool,
+ "write syntax and type analysis (in CSV format) information in addition to normal output"),
print_move_fragments: bool = (false, parse_bool,
"print out move-fragment data for every fn"),
flowgraph_print_loans: bool = (false, parse_bool,
dep_graph));
// Discard MTWT tables that aren't required past lowering to HIR.
- if !sess.opts.debugging_opts.keep_mtwt_tables &&
- !sess.opts.debugging_opts.save_analysis {
+ if !keep_mtwt_tables(sess) {
syntax::ext::mtwt::clear_tables();
}
"early lint checks",
|| lint::check_ast_crate(sess, &expanded_crate));
- let opt_crate = if sess.opts.debugging_opts.keep_ast ||
- sess.opts.debugging_opts.save_analysis {
+ let opt_crate = if keep_ast(sess) {
Some(&expanded_crate)
} else {
drop(expanded_crate);
Ok(())
}
+fn keep_mtwt_tables(sess: &Session) -> bool {
+ sess.opts.debugging_opts.keep_mtwt_tables ||
+ sess.opts.debugging_opts.save_analysis ||
+ sess.opts.debugging_opts.save_analysis_csv
+}
+
+fn keep_ast(sess: &Session) -> bool {
+ sess.opts.debugging_opts.keep_ast ||
+ sess.opts.debugging_opts.save_analysis ||
+ sess.opts.debugging_opts.save_analysis_csv
+}
+
/// The name used for source code that doesn't originate in a file
/// (e.g. source from stdin or a string)
pub fn anon_src() -> String {
control.after_llvm.stop = Compilation::Stop;
}
- if sess.opts.debugging_opts.save_analysis {
+ if save_analysis(sess) {
control.after_analysis.callback = box |state| {
time(state.session.time_passes(), "save analysis", || {
save::process_crate(state.tcx.unwrap(),
state.krate.unwrap(),
state.analysis.unwrap(),
state.crate_name.unwrap(),
- state.out_dir)
+ state.out_dir,
+ save_analysis_format(state.session))
});
};
control.after_analysis.run_callback_on_error = true;
}
}
+fn save_analysis(sess: &Session) -> bool {
+ sess.opts.debugging_opts.save_analysis ||
+ sess.opts.debugging_opts.save_analysis_csv
+}
+
+fn save_analysis_format(sess: &Session) -> save::Format {
+ if sess.opts.debugging_opts.save_analysis {
+ save::Format::Json
+ } else if sess.opts.debugging_opts.save_analysis_csv {
+ save::Format::Csv
+ } else {
+ unreachable!();
+ }
+}
+
impl RustcDefaultCalls {
pub fn list_metadata(sess: &Session, matches: &getopts::Matches, input: &Input) -> Compilation {
let r = matches.opt_strs("Z");
use super::data::{self, SpanData};
use super::dump::Dump;
-pub struct JsonDumper<'a, 'b, W: 'b> {
+pub struct JsonDumper<'a, 'b, W: Write + 'b> {
output: &'b mut W,
codemap: &'a CodeMap,
+ first: bool,
}
impl<'a, 'b, W: Write> JsonDumper<'a, 'b, W> {
pub fn new(writer: &'b mut W, codemap: &'a CodeMap) -> JsonDumper<'a, 'b, W> {
- JsonDumper { output: writer, codemap:codemap }
+ if let Err(_) = write!(writer, "[") {
+ error!("Error writing output");
+ }
+ JsonDumper { output: writer, codemap:codemap, first: true }
+ }
+}
+
+impl<'a, 'b, W: Write> Drop for JsonDumper<'a, 'b, W> {
+ fn drop(&mut self) {
+ if let Err(_) = write!(self.output, "]") {
+ error!("Error writing output");
+ }
}
}
macro_rules! impl_fn {
($fn_name: ident, $data_type: ident) => {
fn $fn_name(&mut self, data: data::$data_type) {
+ if self.first {
+ self.first = false;
+ } else {
+ if let Err(_) = write!(self.output, ",") {
+ error!("Error writing output");
+ }
+ }
let data = data.lower(self.codemap);
if let Err(_) = write!(self.output, "{}", as_json(&data)) {
error!("Error writing output '{}'", as_json(&data));
}
}
+#[derive(Clone, Copy, Debug)]
+pub enum Format {
+ Csv,
+ Json,
+}
+
+impl Format {
+ fn extension(&self) -> &'static str {
+ match *self {
+ Format::Csv => ".csv",
+ Format::Json => ".json",
+ }
+ }
+}
+
pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
lcx: &'l lowering::LoweringContext<'l>,
krate: &ast::Crate,
analysis: &'l ty::CrateAnalysis<'l>,
cratename: &str,
- odir: Option<&Path>) {
+ odir: Option<&Path>,
+ format: Format) {
let _ignore = tcx.dep_graph.in_ignore();
assert!(analysis.glob_map.is_some());
info!("Dumping crate {}", cratename);
// find a path to dump our data to
- let mut root_path = match env::var_os("DXR_RUST_TEMP_FOLDER") {
+ let mut root_path = match env::var_os("RUST_SAVE_ANALYSIS_FOLDER") {
Some(val) => PathBuf::from(val),
None => match odir {
- Some(val) => val.join("dxr"),
- None => PathBuf::from("dxr-temp"),
+ Some(val) => val.join("save-analysis"),
+ None => PathBuf::from("save-analysis-temp"),
},
};
};
out_name.push_str(&cratename);
out_name.push_str(&tcx.sess.opts.cg.extra_filename);
- out_name.push_str(".csv");
+ out_name.push_str(format.extension());
root_path.push(&out_name);
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 output = &mut output_file;
let utils: SpanUtils<'tcx> = SpanUtils::new(&tcx.sess);
let save_ctxt = SaveContext::new(tcx, lcx);
- let mut dumper = CsvDumper::new(&mut output_file, utils);
- let mut visitor = DumpVisitor::new(tcx, save_ctxt, analysis, &mut dumper);
- // FIXME: we don't write anything!
- visitor.dump_crate_info(cratename, krate);
- visit::walk_crate(&mut visitor, krate);
+ macro_rules! dump {
+ ($new_dumper: expr) => {{
+ let mut dumper = $new_dumper;
+ let mut visitor = DumpVisitor::new(tcx, save_ctxt, analysis, &mut dumper);
+
+ visitor.dump_crate_info(cratename, krate);
+ visit::walk_crate(&mut visitor, krate);
+ }}
+ }
+
+ match format {
+ Format::Csv => dump!(CsvDumper::new(output, utils)),
+ Format::Json => dump!(JsonDumper::new(output, utils.sess.codemap())),
+ }
}
// Utility functions for the module.