Rollup merge of #36760 - nrc:input2, r=alexcrichton

Allow supplying an error destination via the compiler driver

Allows replacing stderr with a buffer from the client.

Also, some refactoring around run_compiler.
This commit is contained in:
Jonathan Turner 2016-09-28 20:21:51 -07:00 committed by GitHub
commit 45fd0626a4
6 changed files with 56 additions and 33 deletions

View File

@ -42,6 +42,7 @@ use std::cell::{self, Cell, RefCell};
use std::collections::HashMap;
use std::env;
use std::ffi::CString;
use std::io::Write;
use std::rc::Rc;
use std::fmt;
use std::time::Duration;
@ -449,7 +450,8 @@ pub fn build_session(sopts: config::Options,
local_crate_source_file,
registry,
cstore,
Rc::new(codemap::CodeMap::new()))
Rc::new(codemap::CodeMap::new()),
None)
}
pub fn build_session_with_codemap(sopts: config::Options,
@ -457,7 +459,8 @@ pub fn build_session_with_codemap(sopts: config::Options,
local_crate_source_file: Option<PathBuf>,
registry: errors::registry::Registry,
cstore: Rc<for<'a> CrateStore<'a>>,
codemap: Rc<codemap::CodeMap>)
codemap: Rc<codemap::CodeMap>,
emitter_dest: Option<Box<Write + Send>>)
-> Session {
// FIXME: This is not general enough to make the warning lint completely override
// normal diagnostic warnings, since the warning lint can also be denied and changed
@ -470,14 +473,21 @@ pub fn build_session_with_codemap(sopts: config::Options,
.unwrap_or(true);
let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;
let emitter: Box<Emitter> = match sopts.error_format {
config::ErrorOutputType::HumanReadable(color_config) => {
let emitter: Box<Emitter> = match (sopts.error_format, emitter_dest) {
(config::ErrorOutputType::HumanReadable(color_config), None) => {
Box::new(EmitterWriter::stderr(color_config,
Some(codemap.clone())))
}
config::ErrorOutputType::Json => {
(config::ErrorOutputType::HumanReadable(_), Some(dst)) => {
Box::new(EmitterWriter::new(dst,
Some(codemap.clone())))
}
(config::ErrorOutputType::Json, None) => {
Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
}
(config::ErrorOutputType::Json, Some(dst)) => {
Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone()))
}
};
let diagnostic_handler =

View File

@ -74,6 +74,7 @@ use rustc::dep_graph::DepGraph;
use rustc::session::{self, config, Session, build_session, CompileResult};
use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
use rustc::session::config::nightly_options;
use rustc::session::early_error;
use rustc::lint::Lint;
use rustc::lint;
use rustc_metadata::loader;
@ -93,8 +94,6 @@ use std::str;
use std::sync::{Arc, Mutex};
use std::thread;
use rustc::session::early_error;
use syntax::{ast, json};
use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
use syntax::feature_gate::{GatedCfg, UnstableFeatures};
@ -131,17 +130,18 @@ pub fn abort_on_err<T>(result: Result<T, usize>, sess: &Session) -> T {
}
}
pub fn run(args: Vec<String>) -> isize {
pub fn run<F>(run_compiler: F) -> isize
where F: FnOnce() -> (CompileResult, Option<Session>) + Send + 'static
{
monitor(move || {
let (result, session) = run_compiler(&args, &mut RustcDefaultCalls);
let (result, session) = run_compiler();
if let Err(err_count) = result {
if err_count > 0 {
match session {
Some(sess) => sess.fatal(&abort_msg(err_count)),
None => {
let emitter =
errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
None);
errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None);
let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
handler.emit(&MultiSpan::new(),
&abort_msg(err_count),
@ -155,20 +155,15 @@ pub fn run(args: Vec<String>) -> isize {
0
}
pub fn run_compiler<'a>(args: &[String],
callbacks: &mut CompilerCalls<'a>)
-> (CompileResult, Option<Session>) {
run_compiler_with_file_loader(args, callbacks, box RealFileLoader)
}
// Parse args and run the compiler. This is the primary entry point for rustc.
// See comments on CompilerCalls below for details about the callbacks argument.
// The FileLoader provides a way to load files from sources other than the file system.
pub fn run_compiler_with_file_loader<'a, L>(args: &[String],
callbacks: &mut CompilerCalls<'a>,
loader: Box<L>)
-> (CompileResult, Option<Session>)
where L: FileLoader + 'static {
pub fn run_compiler<'a>(args: &[String],
callbacks: &mut CompilerCalls<'a>,
file_loader: Option<Box<FileLoader + 'static>>,
emitter_dest: Option<Box<Write + Send>>)
-> (CompileResult, Option<Session>)
{
macro_rules! do_or_return {($expr: expr, $sess: expr) => {
match $expr {
Compilation::Stop => return (Ok(()), $sess),
@ -207,13 +202,16 @@ pub fn run_compiler_with_file_loader<'a, L>(args: &[String],
let dep_graph = DepGraph::new(sopts.build_dep_graph());
let cstore = Rc::new(CStore::new(&dep_graph));
let loader = file_loader.unwrap_or(box RealFileLoader);
let codemap = Rc::new(CodeMap::with_file_loader(loader));
let sess = session::build_session_with_codemap(sopts,
&dep_graph,
input_file_path,
descriptions,
cstore.clone(),
codemap);
codemap,
emitter_dest);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess, cfg);
target_features::add_configuration(&mut cfg, &sess);
@ -1144,6 +1142,9 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
}
pub fn main() {
let result = run(env::args().collect());
let result = run(|| run_compiler(&env::args().collect::<Vec<_>>(),
&mut RustcDefaultCalls,
None,
None));
process::exit(result as i32);
}

View File

@ -99,8 +99,10 @@ impl EmitterWriter {
pub fn new(dst: Box<Write + Send>,
code_map: Option<Rc<CodeMapper>>)
-> EmitterWriter {
EmitterWriter { dst: Raw(dst),
cm: code_map}
EmitterWriter {
dst: Raw(dst),
cm: code_map,
}
}
fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> {

View File

@ -38,10 +38,6 @@ pub struct JsonEmitter {
}
impl JsonEmitter {
pub fn basic() -> JsonEmitter {
JsonEmitter::stderr(None, Rc::new(CodeMap::new()))
}
pub fn stderr(registry: Option<Registry>,
code_map: Rc<CodeMap>) -> JsonEmitter {
JsonEmitter {
@ -50,6 +46,20 @@ impl JsonEmitter {
cm: code_map,
}
}
pub fn basic() -> JsonEmitter {
JsonEmitter::stderr(None, Rc::new(CodeMap::new()))
}
pub fn new(dst: Box<Write + Send>,
registry: Option<Registry>,
code_map: Rc<CodeMap>) -> JsonEmitter {
JsonEmitter {
dst: dst,
registry: registry,
cm: code_map,
}
}
}
impl Emitter for JsonEmitter {

View File

@ -79,8 +79,8 @@ fn main() {
format!("_ _ --sysroot {} --crate-type dylib", path.to_str().unwrap())
.split(' ').map(|s| s.to_string()).collect();
let (result, _) = rustc_driver::run_compiler_with_file_loader(
&args, &mut JitCalls, box JitLoader);
let (result, _) = rustc_driver::run_compiler(
&args, &mut JitCalls, Some(box JitLoader), None);
if let Err(n) = result {
panic!("Error {}", n);
}

View File

@ -86,6 +86,6 @@ fn main() {
let mut tc = TestCalls { count: 1 };
// we should never get use this filename, but lets make sure they are valid args.
let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
rustc_driver::run_compiler(&args, &mut tc);
rustc_driver::run_compiler(&args, &mut tc, None, None);
assert_eq!(tc.count, 30);
}