]> git.lizzy.rs Git - rust.git/commitdiff
Respect `--color` when printing early errors
authorBarosl Lee <vcs@barosl.com>
Sat, 22 Aug 2015 14:51:53 +0000 (23:51 +0900)
committerBarosl Lee <vcs@barosl.com>
Tue, 25 Aug 2015 09:08:57 +0000 (18:08 +0900)
Currently, `early_error` and `early_warn` in `librustc::session` always
use `ColorConfig::Auto`. Modify them to follow the color configuration
set by the `--color` option.

As colored output is also printed during the early stage, parsing the
`--color` option should be done as early as possible. However, there are
still some cases when the output needs to be colored before knowing the
exact color settings. In these cases, it will be defaulted to
`ColorConfig::Auto`, which is the same as before.

Fixes #27879.

src/librustc/lint/context.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/session/search_paths.rs
src/librustc_driver/lib.rs
src/librustdoc/lib.rs
src/test/run-pass-fulldeps/compiler-calls.rs

index 40ee023b7e86110c0ce68ba2a3d3c391c20805ee..144dc15dd8aea408eac65d375f938440069d6f3b 100644 (file)
@@ -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.
index c5db7cd718b8ed931f6946d42fbb1cd05d253b82..f0f824a0218bb4dda91ca0c4bfb221b153c211f6 100644 (file)
@@ -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}=<value>)",
-                                                $outputname, key,
-                                                type_desc, $prefix))
+                            early_error(color, &format!("{0} option `{1}` requires \
+                                                         {2} ({3} {1}=<value>)",
+                                                        $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<String> ) -> 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::<Vec<_>>();
 
     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());
index 18982215f588f056416ba3bc15391ab755094e8f..ff732ee7b9d80c60099da78a70c3c65adec28c11 100644 (file)
@@ -473,13 +473,13 @@ pub fn expect<T, M>(sess: &Session, opt: Option<T>, 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);
 }
index 3dc31f9524effe1e5b32668c7c7d707bbf9ce1fb..caf776dad85e06ff28ebda7ee9a77b19dbb4b680 100644 (file)
@@ -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)));
     }
index 60eaffd71cbc6a91bd1ab5dfa341cdf787a8fe08..ed63b8153544e348308332a553f3f18d06429294 100644 (file)
@@ -117,11 +117,11 @@ macro_rules! do_or_return {($expr: expr) => {
         None => return
     };
 
-    let descriptions = diagnostics_registry();
+    let sopts = config::build_session_options(&matches);
 
-    do_or_return!(callbacks.early_callback(&matches, &descriptions));
+    let descriptions = diagnostics_registry();
 
-    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<String>) -> 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())
         }
     }
 
index 33902363e0a258a1bb89dfc3ba7f7c8407cd5c2a..933f9cab7f70640d4998e3b25a46dabfef7476ed 100644 (file)
@@ -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");
index 0805bc5dcb35955b1ca833d9c0cc62f5180d4cd5..8850f6e6d2a6e5863db91511efd4438bba2925d5 100644 (file)
@@ -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