use syntax::parse;
use syntax::symbol::Symbol;
use syntax::feature_gate::UnstableFeatures;
+use errors::emitter::HumanReadableErrorType;
use errors::{ColorConfig, FatalError, Handler};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorOutputType {
- HumanReadable(ColorConfig),
+ HumanReadable(HumanReadableErrorType),
Json {
/// Render the json in a human readable way (with indents and newlines)
pretty: bool,
- /// The `rendered` field with the command line diagnostics include color codes
- colorful_rendered: bool,
+ /// The way the `rendered` field is created
+ json_rendered: HumanReadableErrorType,
},
- Short(ColorConfig),
}
impl Default for ErrorOutputType {
fn default() -> ErrorOutputType {
- ErrorOutputType::HumanReadable(ColorConfig::Auto)
+ ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto))
}
}
"print some statistics about AST and HIR"),
always_encode_mir: bool = (false, parse_bool, [TRACKED],
"encode MIR of all functions into the crate metadata"),
- colorful_json: bool = (false, parse_bool, [UNTRACKED],
- "encode color codes in the `rendered` field of json diagnostics"),
+ json_rendered: Option<String> = (None, parse_opt_string, [UNTRACKED],
+ "describes how to render the `rendered` field of json diagnostics"),
unleash_the_miri_inside_of_you: bool = (false, parse_bool, [TRACKED],
"take the breaks off const evaluation. NOTE: this is unsound"),
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
),
opt::opt(
"",
- "colorful-json",
- "Emit ansi color codes to the `rendered` field of json diagnostics",
- "TYPE",
+ "json-rendered",
+ "Choose `rendered` field of json diagnostics render scheme",
+ "plain|termcolor",
),
opt::opt_s(
"",
)
}
- let colorful_rendered = matches.opt_present("colorful-json");
+ let json_rendered = matches.opt_str("json-rendered").and_then(|s| match s.as_str() {
+ "plain" => None,
+ "termcolor" => Some(HumanReadableErrorType::Default(ColorConfig::Always)),
+ _ => early_error(
+ ErrorOutputType::default(),
+ &format!(
+ "argument for --json-rendered must be `plain` or `termcolor` (instead was `{}`)",
+ s,
+ ),
+ ),
+ }).unwrap_or(HumanReadableErrorType::Default(ColorConfig::Never));
// We need the opts_present check because the driver will send us Matches
// with only stable options if no unstable options are used. Since error-format
// opt_present because the latter will panic.
let error_format = if matches.opts_present(&["error-format".to_owned()]) {
match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
- Some("human") => ErrorOutputType::HumanReadable(color),
- Some("json") => ErrorOutputType::Json { pretty: false, colorful_rendered },
- Some("pretty-json") => ErrorOutputType::Json { pretty: true, colorful_rendered },
- Some("short") => ErrorOutputType::Short(color),
- None => ErrorOutputType::HumanReadable(color),
+ None |
+ Some("human") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
+ Some("json") => ErrorOutputType::Json { pretty: false, json_rendered },
+ Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered },
+ Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)),
Some(arg) => early_error(
- ErrorOutputType::HumanReadable(color),
+ ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
&format!(
"argument for --error-format must be `human`, `json` or \
`short` (instead was `{}`)",
),
}
} else {
- ErrorOutputType::HumanReadable(color)
+ ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
};
let unparsed_crate_types = matches.opt_strs("crate-type");
let mut debugging_opts = build_debugging_options(matches, error_format);
if !debugging_opts.unstable_options {
- if colorful_rendered {
- early_error(error_format, "--colorful-json=true is unstable");
+ if matches.opt_str("json-rendered").is_some() {
+ early_error(error_format, "`--json-rendered=x` is unstable");
}
- if let ErrorOutputType::Json { pretty: true, .. } = error_format {
+ if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
early_error(
- ErrorOutputType::Json { pretty: false, colorful_rendered: false },
+ ErrorOutputType::Json { pretty: false, json_rendered },
"--error-format=pretty-json is unstable",
);
}
const JSON: super::ErrorOutputType = super::ErrorOutputType::Json {
pretty: false,
- colorful_rendered: false,
+ json_rendered: super::HumanReadableErrorType::Default(super::ColorConfig::Never),
};
// Reference
emitter_dest: Option<Box<dyn Write + Send>>,
) -> Box<dyn Emitter + sync::Send> {
match (sopts.error_format, emitter_dest) {
- (config::ErrorOutputType::HumanReadable(color_config), None) => Box::new(
- EmitterWriter::stderr(
- color_config,
- Some(source_map.clone()),
- false,
- sopts.debugging_opts.teach,
- ).ui_testing(sopts.debugging_opts.ui_testing),
- ),
- (config::ErrorOutputType::HumanReadable(_), Some(dst)) => Box::new(
- EmitterWriter::new(
- dst, Some(source_map.clone()), false, false, sopts.debugging_opts.colorful_json,
- ).ui_testing(sopts.debugging_opts.ui_testing),
- ),
- (config::ErrorOutputType::Json { pretty, colorful_rendered }, None) => Box::new(
+ (config::ErrorOutputType::HumanReadable(kind), dst) => {
+ let (short, color_config) = kind.unzip();
+ let emitter = match dst {
+ None => EmitterWriter::stderr(
+ color_config,
+ Some(source_map.clone()),
+ short,
+ sopts.debugging_opts.teach,
+ ),
+ Some(dst) => EmitterWriter::new(
+ dst,
+ Some(source_map.clone()),
+ short,
+ false,
+ color_config.suggests_using_colors(),
+ ),
+ };
+ Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing))
+ },
+ (config::ErrorOutputType::Json { pretty, json_rendered }, None) => Box::new(
JsonEmitter::stderr(
Some(registry),
source_map.clone(),
pretty,
- colorful_rendered,
+ json_rendered,
).ui_testing(sopts.debugging_opts.ui_testing),
),
- (config::ErrorOutputType::Json { pretty, colorful_rendered }, Some(dst)) => Box::new(
+ (config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new(
JsonEmitter::new(
dst,
Some(registry),
source_map.clone(),
pretty,
- colorful_rendered,
+ json_rendered,
).ui_testing(sopts.debugging_opts.ui_testing),
),
- (config::ErrorOutputType::Short(color_config), None) => Box::new(
- EmitterWriter::stderr(color_config, Some(source_map.clone()), true, false),
- ),
- (config::ErrorOutputType::Short(_), Some(dst)) => {
- Box::new(EmitterWriter::new(
- dst, Some(source_map.clone()), true, false, sopts.debugging_opts.colorful_json,
- ))
- }
}
}
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
let emitter: Box<dyn Emitter + sync::Send> = match output {
- config::ErrorOutputType::HumanReadable(color_config) => {
- Box::new(EmitterWriter::stderr(color_config, None, false, false))
- }
- config::ErrorOutputType::Json { pretty, colorful_rendered } =>
- Box::new(JsonEmitter::basic(pretty, colorful_rendered)),
- config::ErrorOutputType::Short(color_config) => {
- Box::new(EmitterWriter::stderr(color_config, None, true, false))
+ config::ErrorOutputType::HumanReadable(kind) => {
+ let (short, color_config) = kind.unzip();
+ Box::new(EmitterWriter::stderr(color_config, None, short, false))
}
+ config::ErrorOutputType::Json { pretty, json_rendered } =>
+ Box::new(JsonEmitter::basic(pretty, json_rendered)),
};
let handler = errors::Handler::with_emitter(true, None, emitter);
handler.emit(&MultiSpan::new(), msg, errors::Level::Fatal);
pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
let emitter: Box<dyn Emitter + sync::Send> = match output {
- config::ErrorOutputType::HumanReadable(color_config) => {
- Box::new(EmitterWriter::stderr(color_config, None, false, false))
- }
- config::ErrorOutputType::Json { pretty, colorful_rendered } =>
- Box::new(JsonEmitter::basic(pretty, colorful_rendered)),
- config::ErrorOutputType::Short(color_config) => {
- Box::new(EmitterWriter::stderr(color_config, None, true, false))
+ config::ErrorOutputType::HumanReadable(kind) => {
+ let (short, color_config) = kind.unzip();
+ Box::new(EmitterWriter::stderr(color_config, None, short, false))
}
+ config::ErrorOutputType::Json { pretty, json_rendered } =>
+ Box::new(JsonEmitter::basic(pretty, json_rendered)),
};
let handler = errors::Handler::with_emitter(true, None, emitter);
handler.emit(&MultiSpan::new(), msg, errors::Level::Warning);
use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi};
use termcolor::{WriteColor, Color, Buffer};
+/// Describes the way the content of the `rendered` field of the json output is generated
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum HumanReadableErrorType {
+ Default(ColorConfig),
+ Short(ColorConfig),
+}
+
+impl HumanReadableErrorType {
+ /// Returns a (`short`, `color`) tuple
+ pub fn unzip(self) -> (bool, ColorConfig) {
+ match self {
+ HumanReadableErrorType::Default(cc) => (false, cc),
+ HumanReadableErrorType::Short(cc) => (true, cc),
+ }
+ }
+ pub fn new_emitter(
+ self,
+ dst: Box<dyn Write + Send>,
+ source_map: Option<Lrc<SourceMapperDyn>>,
+ teach: bool,
+ ) -> EmitterWriter {
+ let (short, color_config) = self.unzip();
+ EmitterWriter::new(dst, source_map, short, teach, color_config.suggests_using_colors())
+ }
+}
+
const ANONYMIZED_LINE_NUM: &str = "LL";
/// Emitter trait for emitting errors.
}
impl ColorConfig {
- fn to_color_choice(&self) -> ColorChoice {
- match *self {
+ fn to_color_choice(self) -> ColorChoice {
+ match self {
ColorConfig::Always => {
if atty::is(atty::Stream::Stderr) {
ColorChoice::Always
ColorConfig::Auto => ColorChoice::Never,
}
}
+ pub fn suggests_using_colors(self) -> bool {
+ match self {
+ | ColorConfig::Always
+ | ColorConfig::Auto
+ => true,
+ ColorConfig::Never => false,
+ }
+ }
}
pub struct EmitterWriter {
pub enum Destination {
Terminal(StandardStream),
Buffered(BufferWriter),
+ // The bool denotes whether we should be emitting ansi color codes or not
Raw(Box<(dyn Write + Send)>, bool),
}
use std::path::PathBuf;
use errors;
-use errors::emitter::ColorConfig;
+use errors::emitter::{ColorConfig, HumanReadableErrorType};
use getopts;
use rustc::lint::Level;
use rustc::session::early_error;
};
// FIXME: deduplicate this code from the identical code in librustc/session/config.rs
let error_format = match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
- Some("human") => ErrorOutputType::HumanReadable(color),
- Some("json") => ErrorOutputType::Json { pretty: false, colorful_rendered: false },
- Some("pretty-json") => ErrorOutputType::Json { pretty: true, colorful_rendered: false },
- Some("short") => ErrorOutputType::Short(color),
- None => ErrorOutputType::HumanReadable(color),
+ None |
+ Some("human") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
+ Some("json") => ErrorOutputType::Json {
+ pretty: false,
+ json_rendered: HumanReadableErrorType::Default(color),
+ },
+ Some("pretty-json") => ErrorOutputType::Json {
+ pretty: true,
+ json_rendered: HumanReadableErrorType::Default(color),
+ },
+ Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)),
Some(arg) => {
early_error(ErrorOutputType::default(),
&format!("argument for --error-format must be `human`, `json` or \
// stick to the defaults
let sessopts = Options::default();
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
- ErrorOutputType::HumanReadable(color_config) => Box::new(
- EmitterWriter::stderr(
- color_config,
- source_map.map(|cm| cm as _),
- false,
- sessopts.debugging_opts.teach,
- ).ui_testing(ui_testing)
- ),
- ErrorOutputType::Json { pretty, colorful_rendered } => {
+ ErrorOutputType::HumanReadable(kind) => {
+ let (short, color_config) = kind.unzip();
+ Box::new(
+ EmitterWriter::stderr(
+ color_config,
+ source_map.map(|cm| cm as _),
+ short,
+ sessopts.debugging_opts.teach,
+ ).ui_testing(ui_testing)
+ )
+ },
+ ErrorOutputType::Json { pretty, json_rendered } => {
let source_map = source_map.unwrap_or_else(
|| Lrc::new(source_map::SourceMap::new(sessopts.file_path_mapping())));
Box::new(
None,
source_map,
pretty,
- colorful_rendered,
+ json_rendered,
).ui_testing(ui_testing)
)
},
- ErrorOutputType::Short(color_config) => Box::new(
- EmitterWriter::stderr(
- color_config,
- source_map.map(|cm| cm as _),
- true,
- false)
- ),
};
errors::Handler::with_emitter_and_flags(
use errors::registry::Registry;
use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, SourceMapper};
use errors::{DiagnosticId, Applicability};
-use errors::emitter::{Emitter, EmitterWriter};
+use errors::emitter::{Emitter, HumanReadableErrorType};
use syntax_pos::{MacroBacktrace, Span, SpanLabel, MultiSpan};
use rustc_data_structures::sync::{self, Lrc};
sm: Lrc<dyn SourceMapper + sync::Send + sync::Sync>,
pretty: bool,
ui_testing: bool,
- colorful_rendered: bool,
+ json_rendered: HumanReadableErrorType,
}
impl JsonEmitter {
registry: Option<Registry>,
source_map: Lrc<SourceMap>,
pretty: bool,
- colorful_rendered: bool,
+ json_rendered: HumanReadableErrorType,
) -> JsonEmitter {
JsonEmitter {
dst: Box::new(io::stderr()),
sm: source_map,
pretty,
ui_testing: false,
- colorful_rendered,
+ json_rendered,
}
}
- pub fn basic(pretty: bool, colorful_rendered: bool) -> JsonEmitter {
+ pub fn basic(pretty: bool, json_rendered: HumanReadableErrorType) -> JsonEmitter {
let file_path_mapping = FilePathMapping::empty();
JsonEmitter::stderr(None, Lrc::new(SourceMap::new(file_path_mapping)),
- pretty, colorful_rendered)
+ pretty, json_rendered)
}
pub fn new(
registry: Option<Registry>,
source_map: Lrc<SourceMap>,
pretty: bool,
- colorful_rendered: bool,
+ json_rendered: HumanReadableErrorType,
) -> JsonEmitter {
JsonEmitter {
dst,
sm: source_map,
pretty,
ui_testing: false,
- colorful_rendered,
+ json_rendered,
}
}
}
let buf = BufWriter::default();
let output = buf.clone();
- EmitterWriter::new(Box::new(buf), Some(je.sm.clone()), false, false, je.colorful_rendered)
+ je.json_rendered.new_emitter(Box::new(buf), Some(je.sm.clone()), false)
.ui_testing(je.ui_testing).emit(db);
let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
let output = String::from_utf8(output).unwrap();
// ignore-cloudabi
-// compile-flags: --error-format pretty-json -Zunstable-options --colorful-json=true
+// compile-flags: --error-format pretty-json -Zunstable-options --json-rendered=termcolor
// The output for humans should just highlight the whole span without showing
// the suggested replacement, but we also want to test that suggested
"spans": [
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 461,
- "byte_end": 465,
+ "byte_start": 466,
+ "byte_end": 470,
"line_start": 11,
"line_end": 11,
"column_start": 12,
"spans": [
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,
},
{
"file_name": "$DIR/use_suggestion_json.rs",
- "byte_start": 438,
- "byte_end": 438,
+ "byte_start": 443,
+ "byte_end": 443,
"line_start": 10,
"line_end": 10,
"column_start": 1,