diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 40ee023b7e8..144dc15dd8a 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -43,6 +43,7 @@ use syntax::visit::{Visitor, FnKind}; use syntax::parse::token::InternedString; use syntax::{ast, ast_util, visit}; +use syntax::diagnostic; /// Information about the registered lints. /// @@ -141,7 +142,7 @@ pub fn register_pass(&mut self, sess: Option<&Session>, match (sess, from_plugin) { // We load builtin lints first, so a duplicate is a compiler bug. // Use early_error when handling -W help with no crate. - (None, _) => early_error(&msg[..]), + (None, _) => early_error(diagnostic::Auto, &msg[..]), (Some(sess), false) => sess.bug(&msg[..]), // A duplicate name from a plugin is a user error. @@ -166,7 +167,7 @@ pub fn register_group(&mut self, sess: Option<&Session>, match (sess, from_plugin) { // We load builtin lints first, so a duplicate is a compiler bug. // Use early_error when handling -W help with no crate. - (None, _) => early_error(&msg[..]), + (None, _) => early_error(diagnostic::Auto, &msg[..]), (Some(sess), false) => sess.bug(&msg[..]), // A duplicate name from a plugin is a user error. diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index c5db7cd718b..f0f824a0218 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -288,7 +288,7 @@ pub fn $defaultfn() -> $struct_name { $struct_name { $($opt: $init),* } } - pub fn $buildfn(matches: &getopts::Matches) -> $struct_name + pub fn $buildfn(matches: &getopts::Matches, color: ColorConfig) -> $struct_name { let mut op = $defaultfn(); for option in matches.opt_strs($prefix) { @@ -302,20 +302,20 @@ pub fn $buildfn(matches: &getopts::Matches) -> $struct_name if !setter(&mut op, value) { match (value, opt_type_desc) { (Some(..), None) => { - early_error(&format!("{} option `{}` takes no \ - value", $outputname, key)) + early_error(color, &format!("{} option `{}` takes no \ + value", $outputname, key)) } (None, Some(type_desc)) => { - early_error(&format!("{0} option `{1}` requires \ - {2} ({3} {1}=)", - $outputname, key, - type_desc, $prefix)) + early_error(color, &format!("{0} option `{1}` requires \ + {2} ({3} {1}=)", + $outputname, key, + type_desc, $prefix)) } (Some(value), Some(type_desc)) => { - early_error(&format!("incorrect value `{}` for {} \ - option `{}` - {} was expected", - value, $outputname, - key, type_desc)) + early_error(color, &format!("incorrect value `{}` for {} \ + option `{}` - {} was expected", + value, $outputname, + key, type_desc)) } (None, None) => unreachable!() } @@ -324,8 +324,8 @@ pub fn $buildfn(matches: &getopts::Matches) -> $struct_name break; } if !found { - early_error(&format!("unknown {} option: `{}`", - $outputname, key)); + early_error(color, &format!("unknown {} option: `{}`", + $outputname, key)); } } return op; @@ -850,9 +850,23 @@ pub fn parse_cfgspecs(cfgspecs: Vec ) -> ast::CrateConfig { } pub fn build_session_options(matches: &getopts::Matches) -> Options { + let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) { + Some("auto") => Auto, + Some("always") => Always, + Some("never") => Never, + + None => Auto, + + Some(arg) => { + early_error(Auto, &format!("argument for --color must be auto, always \ + or never (instead was `{}`)", + arg)) + } + }; + let unparsed_crate_types = matches.opt_strs("crate-type"); let crate_types = parse_crate_types_from_list(unparsed_crate_types) - .unwrap_or_else(|e| early_error(&e[..])); + .unwrap_or_else(|e| early_error(color, &e[..])); let mut lint_opts = vec!(); let mut describe_lints = false; @@ -869,11 +883,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let lint_cap = matches.opt_str("cap-lints").map(|cap| { lint::Level::from_str(&cap).unwrap_or_else(|| { - early_error(&format!("unknown lint level: `{}`", cap)) + early_error(color, &format!("unknown lint level: `{}`", cap)) }) }); - let debugging_opts = build_debugging_options(matches); + let debugging_opts = build_debugging_options(matches, color); let parse_only = debugging_opts.parse_only; let no_trans = debugging_opts.no_trans; @@ -897,8 +911,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { "link" => OutputTypeExe, "dep-info" => OutputTypeDepInfo, _ => { - early_error(&format!("unknown emission type: `{}`", - part)) + early_error(color, &format!("unknown emission type: `{}`", + part)) } }; output_types.push(output_type) @@ -911,7 +925,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { output_types.push(OutputTypeExe); } - let cg = build_codegen_options(matches); + let cg = build_codegen_options(matches, color); let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); let target = matches.opt_str("target").unwrap_or( @@ -919,7 +933,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let opt_level = { if matches.opt_present("O") { if cg.opt_level.is_some() { - early_error("-O and -C opt-level both provided"); + early_error(color, "-O and -C opt-level both provided"); } Default } else { @@ -930,9 +944,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { Some(2) => Default, Some(3) => Aggressive, Some(arg) => { - early_error(&format!("optimization level needs to be \ - between 0-3 (instead was `{}`)", - arg)); + early_error(color, &format!("optimization level needs to be \ + between 0-3 (instead was `{}`)", + arg)); } } } @@ -941,7 +955,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let gc = debugging_opts.gc; let debuginfo = if matches.opt_present("g") { if cg.debuginfo.is_some() { - early_error("-g and -C debuginfo both provided"); + early_error(color, "-g and -C debuginfo both provided"); } FullDebugInfo } else { @@ -950,16 +964,16 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { Some(1) => LimitedDebugInfo, Some(2) => FullDebugInfo, Some(arg) => { - early_error(&format!("debug info level needs to be between \ - 0-2 (instead was `{}`)", - arg)); + early_error(color, &format!("debug info level needs to be between \ + 0-2 (instead was `{}`)", + arg)); } } }; let mut search_paths = SearchPaths::new(); for s in &matches.opt_strs("L") { - search_paths.add_path(&s[..]); + search_paths.add_path(&s[..], color); } let libs = matches.opt_strs("l").into_iter().map(|s| { @@ -971,9 +985,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { (Some(name), "framework") => (name, cstore::NativeFramework), (Some(name), "static") => (name, cstore::NativeStatic), (_, s) => { - early_error(&format!("unknown library kind `{}`, expected \ - one of dylib, framework, or static", - s)); + early_error(color, &format!("unknown library kind `{}`, expected \ + one of dylib, framework, or static", + s)); } }; (name.to_string(), kind) @@ -989,40 +1003,26 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { "file-names" => PrintRequest::FileNames, "sysroot" => PrintRequest::Sysroot, req => { - early_error(&format!("unknown print request `{}`", req)) + early_error(color, &format!("unknown print request `{}`", req)) } } }).collect::>(); if !cg.remark.is_empty() && debuginfo == NoDebugInfo { - early_warn("-C remark will not show source locations without \ - --debuginfo"); + early_warn(color, "-C remark will not show source locations without \ + --debuginfo"); } - let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) { - Some("auto") => Auto, - Some("always") => Always, - Some("never") => Never, - - None => Auto, - - Some(arg) => { - early_error(&format!("argument for --color must be auto, always \ - or never (instead was `{}`)", - arg)) - } - }; - let mut externs = HashMap::new(); for arg in &matches.opt_strs("extern") { let mut parts = arg.splitn(2, '='); let name = match parts.next() { Some(s) => s, - None => early_error("--extern value must not be empty"), + None => early_error(color, "--extern value must not be empty"), }; let location = match parts.next() { Some(s) => s, - None => early_error("--extern value must be of the format `foo=bar`"), + None => early_error(color, "--extern value must be of the format `foo=bar`"), }; externs.entry(name.to_string()).or_insert(vec![]).push(location.to_string()); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 18982215f58..ff732ee7b9d 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -473,13 +473,13 @@ pub fn expect(sess: &Session, opt: Option, msg: M) -> T where diagnostic::expect(sess.diagnostic(), opt, msg) } -pub fn early_error(msg: &str) -> ! { - let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None); +pub fn early_error(color: diagnostic::ColorConfig, msg: &str) -> ! { + let mut emitter = diagnostic::EmitterWriter::stderr(color, None); emitter.emit(None, msg, None, diagnostic::Fatal); panic!(diagnostic::FatalError); } -pub fn early_warn(msg: &str) { - let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None); +pub fn early_warn(color: diagnostic::ColorConfig, msg: &str) { + let mut emitter = diagnostic::EmitterWriter::stderr(color, None); emitter.emit(None, msg, None, diagnostic::Warning); } diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index 3dc31f9524e..caf776dad85 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -11,6 +11,7 @@ use std::slice; use std::path::{Path, PathBuf}; use session::early_error; +use syntax::diagnostic; #[derive(Clone, Debug)] pub struct SearchPaths { @@ -37,7 +38,7 @@ pub fn new() -> SearchPaths { SearchPaths { paths: Vec::new() } } - pub fn add_path(&mut self, path: &str) { + pub fn add_path(&mut self, path: &str, color: diagnostic::ColorConfig) { let (kind, path) = if path.starts_with("native=") { (PathKind::Native, &path["native=".len()..]) } else if path.starts_with("crate=") { @@ -52,7 +53,7 @@ pub fn add_path(&mut self, path: &str) { (PathKind::All, path) }; if path.is_empty() { - early_error("empty search path given via `-L`"); + early_error(color, "empty search path given via `-L`"); } self.paths.push((kind, PathBuf::from(path))); } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 60eaffd71cb..ed63b815354 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -117,11 +117,11 @@ macro_rules! do_or_return {($expr: expr) => { None => return }; + let sopts = config::build_session_options(&matches); + let descriptions = diagnostics_registry(); - do_or_return!(callbacks.early_callback(&matches, &descriptions)); - - let sopts = config::build_session_options(&matches); + do_or_return!(callbacks.early_callback(&matches, &descriptions, sopts.color)); let (odir, ofile) = make_output(&matches); let (input, input_file_path) = match make_input(&matches.free) { @@ -205,7 +205,8 @@ pub trait CompilerCalls<'a> { // else (e.g., selecting input and output). fn early_callback(&mut self, _: &getopts::Matches, - _: &diagnostics::registry::Registry) + _: &diagnostics::registry::Registry, + _: diagnostic::ColorConfig) -> Compilation { Compilation::Continue } @@ -277,7 +278,8 @@ fn parse_pretty(&mut self, impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn early_callback(&mut self, matches: &getopts::Matches, - descriptions: &diagnostics::registry::Registry) + descriptions: &diagnostics::registry::Registry, + color: diagnostic::ColorConfig) -> Compilation { match matches.opt_str("explain") { Some(ref code) => { @@ -287,7 +289,7 @@ fn early_callback(&mut self, print!("{}", &description[1..]); } None => { - early_error(&format!("no extended information for {}", code)); + early_error(color, &format!("no extended information for {}", code)); } } return Compilation::Stop; @@ -319,10 +321,10 @@ fn no_input(&mut self, if should_stop == Compilation::Stop { return None; } - early_error("no input filename given"); + early_error(sopts.color, "no input filename given"); } 1 => panic!("make_input should have provided valid inputs"), - _ => early_error("multiple input filenames provided") + _ => early_error(sopts.color, "multiple input filenames provided") } None @@ -414,7 +416,7 @@ pub fn list_metadata(sess: &Session, println!("{}", String::from_utf8(v).unwrap()); } &Input::Str(_) => { - early_error("cannot list metadata for stdin"); + early_error(sess.opts.color, "cannot list metadata for stdin"); } } return Compilation::Stop; @@ -441,7 +443,7 @@ fn print_crate_info(sess: &Session, PrintRequest::CrateName => { let input = match input { Some(input) => input, - None => early_error("no input file provided"), + None => early_error(sess.opts.color, "no input file provided"), }; let attrs = attrs.as_ref().unwrap(); let t_outputs = driver::build_output_filenames(input, @@ -701,14 +703,15 @@ fn parse_all_options(args: &Vec) -> getopts::Matches { &opt.opt_group.short_name }; if m.opt_present(opt_name) { - early_error(&format!("use of unstable option '{}' requires \ - -Z unstable-options", opt_name)); + early_error(diagnostic::Auto, &format!("use of unstable option '{}' \ + requires -Z unstable-options", + opt_name)); } } } m } - Err(f) => early_error(&f.to_string()) + Err(f) => early_error(diagnostic::Auto, &f.to_string()) } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 33902363e0a..933f9cab7f7 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -65,6 +65,7 @@ use serialize::Decodable; use serialize::json::{self, Json}; use rustc::session::search_paths::SearchPaths; +use syntax::diagnostic; // reexported from `clean` so it can be easily updated with the mod itself pub use clean::SCHEMA_VERSION; @@ -227,7 +228,7 @@ pub fn main_args(args: &[String]) -> isize { let mut libs = SearchPaths::new(); for s in &matches.opt_strs("L") { - libs.add_path(s); + libs.add_path(s, diagnostic::Auto); } let externs = match parse_externs(&matches) { Ok(ex) => ex, @@ -362,7 +363,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche // First, parse the crate and extract all relevant information. let mut paths = SearchPaths::new(); for s in &matches.opt_strs("L") { - paths.add_path(s); + paths.add_path(s, diagnostic::Auto); } let cfgs = matches.opt_strs("cfg"); let triple = matches.opt_str("target"); diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index 0805bc5dcb3..8850f6e6d2a 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -23,7 +23,7 @@ use rustc::session::Session; use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; -use syntax::diagnostics; +use syntax::{diagnostics, diagnostic}; use std::path::PathBuf; @@ -34,7 +34,8 @@ struct TestCalls { impl<'a> CompilerCalls<'a> for TestCalls { fn early_callback(&mut self, _: &getopts::Matches, - _: &diagnostics::registry::Registry) + _: &diagnostics::registry::Registry, + _: diagnostic::ColorConfig) -> Compilation { self.count *= 2; Compilation::Continue