From 496c8ba1adabab5e06f87ba3c72984db4d4a7b5c Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 1 Mar 2015 02:21:47 +0200 Subject: [PATCH] rustc_driver: add env var RUSTC_PRETTY_DUMP=mode:dir which acts like --xpretty=mode -Z pretty-keep-going -Z pretty-dump-dir=dir. --- src/librustc_driver/lib.rs | 56 +++---------------- src/librustc_driver/pretty.rs | 102 +++++++++++++++++++++++++++------- 2 files changed, 91 insertions(+), 67 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 69c77be89af18..cbf5f5eccf83f 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -76,7 +76,6 @@ use std::cmp::Ordering::Equal; use std::old_io::{self, stdio}; use std::iter::repeat; use std::env; -use std::os; use std::sync::mpsc::channel; use std::thread; @@ -236,8 +235,7 @@ pub trait CompilerCalls<'a> { // CompilerCalls instance for a regular rustc build. pub struct RustcDefaultCalls { save_analysis: bool, - pretty_print: Option<(PpMode, Option)>, - pretty_dump_dir: Option + pretty_print: Option<(PpMode, Option)> } impl<'a> CompilerCalls<'a> for RustcDefaultCalls { @@ -305,19 +303,13 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { if sess.unstable_options() { self.pretty_print = matches.opt_default("pretty", "normal").map(|a| { // stable pretty-print variants only - pretty::parse_pretty(sess, &a, false) + pretty::parse_pretty(&a, false).unwrap_or_else(|e| sess.fatal(&e)) }).or_else(|| matches.opt_str("xpretty").map(|a| { // extended with unstable pretty-print variants - pretty::parse_pretty(sess, &a, true) + pretty::parse_pretty(&a, true).unwrap_or_else(|e| sess.fatal(&e)) })); } - if let Some(ref dir) = sess.opts.debugging_opts.pretty_dump_dir { - let pretty_dump_dir = os::getcwd().unwrap().join(dir); - assert!(pretty_dump_dir.is_absolute()); - self.pretty_dump_dir = Some(pretty_dump_dir); - } - RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile).and_then( || RustcDefaultCalls::list_metadata(sess, matches, input)) } @@ -343,40 +335,11 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_llvm.stop = Compilation::Stop; } - if let Some((ppm, opt_uii)) = self.pretty_print.take() { - let phase = pretty::printing_phase(&mut control, ppm, opt_uii.as_ref()); - - let dump_dir = self.pretty_dump_dir.take(); - phase.callback = box move |state| { - let pretty_output_path; - let output = if let Some(ref dir) = dump_dir { - let file_path = if let Some(outputs) = state.output_filenames { - outputs.with_extension("rs") - } else { - state.session.fatal( - "-Z pretty-dump-dir cannot be used with --pretty \ - options that print before expansion"); - }; - let file_path = os::getcwd().unwrap().join(&file_path); - assert!(file_path.is_absolute()); - - // Cheap isomorphism: /foo/bar--bar/baz <-> foo--bar----bar--baz. - let components: Vec<_> = file_path.components().map(|bytes| { - String::from_utf8_lossy(bytes).replace("--", "----") - }).collect(); - - pretty_output_path = dir.join(components.connect("--")); - Some(&pretty_output_path) - } else { - state.output - }; - pretty::print_from_phase(state, ppm, opt_uii.as_ref(), output).unwrap(); - }; - - if !sess.opts.debugging_opts.pretty_keep_going { - phase.stop = Compilation::Stop; - } - } + pretty::setup_controller(&mut control, + self.pretty_print.take(), + sess.opts.debugging_opts.pretty_dump_dir + .as_ref().map(|s| &s[..]), + sess.opts.debugging_opts.pretty_keep_going); if self.save_analysis { control.after_analysis.callback = box |state| { @@ -398,8 +361,7 @@ impl RustcDefaultCalls { pub fn new() -> RustcDefaultCalls { RustcDefaultCalls { save_analysis: false, - pretty_print: None, - pretty_dump_dir: None + pretty_print: None } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index ec4fb85e03a50..9bdb99d27f8c9 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -35,8 +35,10 @@ use syntax::ptr::P; use graphviz as dot; use std::borrow::{Cow, IntoCow}; +use std::env; use std::old_io::{self, BufReader}; use std::option; +use std::os; use std::str::FromStr; #[derive(Copy, PartialEq, Debug)] @@ -67,9 +69,8 @@ pub enum PpMode { PpmFlowGraph(PpFlowGraphMode), } -pub fn parse_pretty(sess: &Session, - name: &str, - extended: bool) -> (PpMode, Option) { +pub fn parse_pretty(name: &str, extended: bool) + -> Result<(PpMode, Option), String> { let mut split = name.splitn(1, '='); let first = split.next().unwrap(); let opt_second = split.next(); @@ -84,23 +85,23 @@ pub fn parse_pretty(sess: &Session, ("identified", _) => PpmSource(PpmIdentified), ("flowgraph", true) => PpmFlowGraph(PpFlowGraphMode::Default), ("flowgraph,unlabelled", true) => PpmFlowGraph(PpFlowGraphMode::UnlabelledEdges), - _ => { + _ => return Err({ if extended { - sess.fatal(&format!( + format!( "argument to `xpretty` must be one of `normal`, \ `expanded`, `flowgraph[,unlabelled]=`, `typed`, \ `typed,unsuffixed_literals`, `identified`, \ - `expanded,identified`, or `everybody_loops`; got {}", name)); + `expanded,identified`, or `everybody_loops`; got {}", name) } else { - sess.fatal(&format!( + format!( "argument to `pretty` must be one of `normal`, \ `expanded`, `typed`, `identified`, \ - or `expanded,identified`; got {}", name)); + or `expanded,identified`; got {}", name) } - } + }) }; let opt_second = opt_second.and_then(|s| s.parse::().ok()); - (first, opt_second) + Ok((first, opt_second)) } struct NoAnn; @@ -391,15 +392,46 @@ impl fold::Folder for ReplaceBodyWithLoop { } } -pub fn printing_phase<'a, 'b>(control: &'a mut driver::CompileController<'b>, - ppm: PpMode, - opt_uii: Option<&UserIdentifiedItem>) - -> &'a mut driver::PhaseController<'b> { +pub fn setup_controller(control: &mut driver::CompileController, + ppm_and_uui: Option<(PpMode, Option)>, + dump_dir: Option<&str>, + keep_going: bool) { + + fn mk_absolute(path: &str) -> Path { + let path = os::getcwd().unwrap().join(path); + assert!(path.is_absolute()); + path + } + + let (ppm, opt_uii, dump_dir, keep_going) = match ppm_and_uui { + Some((ppm, opt_uii)) => { + (ppm, opt_uii, dump_dir.map(mk_absolute), keep_going) + } + None => { + let decoded = env::var("RUSTC_PRETTY_DUMP").ok().and_then(|s| { + let mut s = s.split(":"); + + s.next().and_then(|mode| { + parse_pretty(mode, true).ok() + }).and_then(|(ppm, opt_uii)| { + s.next().map(|dump_dir| { + (ppm, opt_uii, Some(mk_absolute(dump_dir)), true) + }) + }) + }); + if let Some(parts) = decoded { + parts + } else { + return; + } + } + }; + if ppm == PpmSource(PpmEveryBodyLoops) { control.every_body_loops = true; } - match ppm { + let phase = match ppm { PpmSource(PpmNormal) | PpmSource(PpmEveryBodyLoops) | PpmSource(PpmIdentified) => { @@ -421,14 +453,44 @@ pub fn printing_phase<'a, 'b>(control: &'a mut driver::CompileController<'b>, PpmFlowGraph(_) => { &mut control.after_analysis } + }; + + phase.callback = box move |state| { + let pretty_output_path; + let output = if let Some(ref dir) = dump_dir { + let file_path = if let Some(outputs) = state.output_filenames { + outputs.with_extension("rs") + } else { + state.session.fatal( + "-Z pretty-dump-dir cannot be used with --pretty \ + options that print before expansion"); + }; + let file_path = os::getcwd().unwrap().join(&file_path); + assert!(file_path.is_absolute()); + + // Cheap isomorphism: /foo/bar--bar/baz <-> foo--bar----bar--baz. + let components: Vec<_> = file_path.components().map(|bytes| { + String::from_utf8_lossy(bytes).replace("--", "----") + }).collect(); + + pretty_output_path = dir.join(components.connect("--")); + Some(&pretty_output_path) + } else { + state.output + }; + print_from_phase(state, ppm, opt_uii.as_ref(), output).unwrap(); + }; + + if !keep_going { + phase.stop = ::Compilation::Stop; } } -pub fn print_from_phase(state: driver::CompileState, - ppm: PpMode, - opt_uii: Option<&UserIdentifiedItem>, - output: Option<&Path>) - -> old_io::IoResult<()> { +fn print_from_phase(state: driver::CompileState, + ppm: PpMode, + opt_uii: Option<&UserIdentifiedItem>, + output: Option<&Path>) + -> old_io::IoResult<()> { let sess = state.session; let krate = state.krate.or(state.expanded_crate) .expect("--pretty=typed missing crate");