From e8a4db25acde9d2d23a4ebfb464d283d495b5b8d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 27 Sep 2016 11:45:50 +1300 Subject: [PATCH] Allow supplying an error destination via the compiler driver Allows replacing stderr with a buffer from the client. Also, some refactoring around run_compiler. --- src/librustc/session/mod.rs | 20 +++++++--- src/librustc_driver/lib.rs | 39 ++++++++++---------- src/librustc_errors/emitter.rs | 6 ++- src/libsyntax/json.rs | 18 +++++++-- src/test/run-make/llvm-phase/test.rs | 4 +- src/test/run-pass-fulldeps/compiler-calls.rs | 2 +- 6 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 268dbd70bb5..53e1dcc5533 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -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, registry: errors::registry::Registry, cstore: Rc CrateStore<'a>>, - codemap: Rc) + codemap: Rc, + emitter_dest: Option>) -> 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 = match sopts.error_format { - config::ErrorOutputType::HumanReadable(color_config) => { + let emitter: Box = 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 = diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 5089af89285..5ac4512fe39 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -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(result: Result, sess: &Session) -> T { } } -pub fn run(args: Vec) -> isize { +pub fn run(run_compiler: F) -> isize + where F: FnOnce() -> (CompileResult, Option) + 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) -> isize { 0 } -pub fn run_compiler<'a>(args: &[String], - callbacks: &mut CompilerCalls<'a>) - -> (CompileResult, Option) { - 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) - -> (CompileResult, Option) - where L: FileLoader + 'static { +pub fn run_compiler<'a>(args: &[String], + callbacks: &mut CompilerCalls<'a>, + file_loader: Option>, + emitter_dest: Option>) + -> (CompileResult, Option) +{ 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::>(), + &mut RustcDefaultCalls, + None, + None)); process::exit(result as i32); } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 6456b72dfb5..1d7ff45b3b8 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -99,8 +99,10 @@ impl EmitterWriter { pub fn new(dst: Box, code_map: Option>) -> EmitterWriter { - EmitterWriter { dst: Raw(dst), - cm: code_map} + EmitterWriter { + dst: Raw(dst), + cm: code_map, + } } fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec { diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index a40c30b3e33..a1c273baeea 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -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, code_map: Rc) -> 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, + registry: Option, + code_map: Rc) -> JsonEmitter { + JsonEmitter { + dst: dst, + registry: registry, + cm: code_map, + } + } } impl Emitter for JsonEmitter { diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs index 19e410fef53..05c1713561a 100644 --- a/src/test/run-make/llvm-phase/test.rs +++ b/src/test/run-make/llvm-phase/test.rs @@ -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); } diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index 775ba38004e..35e9f3f5c8d 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -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); }