Rollup merge of #128806 - estebank:color-config, r=jieyouxu

Split `ColorConfig` off of `HumanReadableErrorType`

The previous setup tied two unrelated things together. Splitting these two is a better model.

Identified by https://github.com/rust-lang/rust/pull/126597/files#r1667800754
This commit is contained in:
Matthias Krüger 2024-08-09 00:03:36 +02:00 committed by GitHub
commit f106496b82
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 64 additions and 50 deletions

View file

@ -43,19 +43,14 @@ const DEFAULT_COLUMN_WIDTH: usize = 140;
/// Describes the way the content of the `rendered` field of the json output is generated /// Describes the way the content of the `rendered` field of the json output is generated
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HumanReadableErrorType { pub enum HumanReadableErrorType {
Default(ColorConfig), Default,
AnnotateSnippet(ColorConfig), AnnotateSnippet,
Short(ColorConfig), Short,
} }
impl HumanReadableErrorType { impl HumanReadableErrorType {
/// Returns a (`short`, `color`) tuple pub fn short(&self) -> bool {
pub fn unzip(self) -> (bool, ColorConfig) { *self == HumanReadableErrorType::Short
match self {
HumanReadableErrorType::Default(cc) => (false, cc),
HumanReadableErrorType::Short(cc) => (true, cc),
HumanReadableErrorType::AnnotateSnippet(cc) => (false, cc),
}
} }
} }

View file

@ -55,6 +55,7 @@ pub struct JsonEmitter {
ignored_directories_in_source_blocks: Vec<String>, ignored_directories_in_source_blocks: Vec<String>,
#[setters(skip)] #[setters(skip)]
json_rendered: HumanReadableErrorType, json_rendered: HumanReadableErrorType,
color_config: ColorConfig,
diagnostic_width: Option<usize>, diagnostic_width: Option<usize>,
macro_backtrace: bool, macro_backtrace: bool,
track_diagnostics: bool, track_diagnostics: bool,
@ -68,6 +69,7 @@ impl JsonEmitter {
fallback_bundle: LazyFallbackBundle, fallback_bundle: LazyFallbackBundle,
pretty: bool, pretty: bool,
json_rendered: HumanReadableErrorType, json_rendered: HumanReadableErrorType,
color_config: ColorConfig,
) -> JsonEmitter { ) -> JsonEmitter {
JsonEmitter { JsonEmitter {
dst: IntoDynSyncSend(dst), dst: IntoDynSyncSend(dst),
@ -79,6 +81,7 @@ impl JsonEmitter {
ui_testing: false, ui_testing: false,
ignored_directories_in_source_blocks: Vec::new(), ignored_directories_in_source_blocks: Vec::new(),
json_rendered, json_rendered,
color_config,
diagnostic_width: None, diagnostic_width: None,
macro_backtrace: false, macro_backtrace: false,
track_diagnostics: false, track_diagnostics: false,
@ -173,7 +176,7 @@ impl Emitter for JsonEmitter {
} }
fn should_show_explain(&self) -> bool { fn should_show_explain(&self) -> bool {
!matches!(self.json_rendered, HumanReadableErrorType::Short(_)) !self.json_rendered.short()
} }
} }
@ -353,8 +356,8 @@ impl Diagnostic {
let buf = BufWriter::default(); let buf = BufWriter::default();
let mut dst: Destination = Box::new(buf.clone()); let mut dst: Destination = Box::new(buf.clone());
let (short, color_config) = je.json_rendered.unzip(); let short = je.json_rendered.short();
match color_config { match je.color_config {
ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)), ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)),
ColorConfig::Never => {} ColorConfig::Never => {}
} }

View file

@ -50,7 +50,8 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
sm, sm,
fallback_bundle, fallback_bundle,
true, // pretty true, // pretty
HumanReadableErrorType::Short(ColorConfig::Never), HumanReadableErrorType::Short,
ColorConfig::Never,
); );
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1)); let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));

View file

@ -315,7 +315,8 @@ fn test_search_paths_tracking_hash_different_order() {
let early_dcx = EarlyDiagCtxt::new(JSON); let early_dcx = EarlyDiagCtxt::new(JSON);
const JSON: ErrorOutputType = ErrorOutputType::Json { const JSON: ErrorOutputType = ErrorOutputType::Json {
pretty: false, pretty: false,
json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), json_rendered: HumanReadableErrorType::Default,
color_config: ColorConfig::Never,
}; };
let push = |opts: &mut Options, search_path| { let push = |opts: &mut Options, search_path| {

View file

@ -602,7 +602,7 @@ impl OutputType {
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorOutputType { pub enum ErrorOutputType {
/// Output meant for the consumption of humans. /// Output meant for the consumption of humans.
HumanReadable(HumanReadableErrorType), HumanReadable(HumanReadableErrorType, ColorConfig),
/// Output that's consumed by other tools such as `rustfix` or the `RLS`. /// Output that's consumed by other tools such as `rustfix` or the `RLS`.
Json { Json {
/// Render the JSON in a human readable way (with indents and newlines). /// Render the JSON in a human readable way (with indents and newlines).
@ -610,12 +610,13 @@ pub enum ErrorOutputType {
/// The JSON output includes a `rendered` field that includes the rendered /// The JSON output includes a `rendered` field that includes the rendered
/// human output. /// human output.
json_rendered: HumanReadableErrorType, json_rendered: HumanReadableErrorType,
color_config: ColorConfig,
}, },
} }
impl Default for ErrorOutputType { impl Default for ErrorOutputType {
fn default() -> Self { fn default() -> Self {
Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) Self::HumanReadable(HumanReadableErrorType::Default, ColorConfig::Auto)
} }
} }
@ -1631,6 +1632,7 @@ pub fn parse_color(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Col
/// Possible json config files /// Possible json config files
pub struct JsonConfig { pub struct JsonConfig {
pub json_rendered: HumanReadableErrorType, pub json_rendered: HumanReadableErrorType,
pub json_color: ColorConfig,
json_artifact_notifications: bool, json_artifact_notifications: bool,
pub json_unused_externs: JsonUnusedExterns, pub json_unused_externs: JsonUnusedExterns,
json_future_incompat: bool, json_future_incompat: bool,
@ -1668,8 +1670,7 @@ impl JsonUnusedExterns {
/// The first value returned is how to render JSON diagnostics, and the second /// The first value returned is how to render JSON diagnostics, and the second
/// is whether or not artifact notifications are enabled. /// is whether or not artifact notifications are enabled.
pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> JsonConfig { pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> JsonConfig {
let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType = let mut json_rendered = HumanReadableErrorType::Default;
HumanReadableErrorType::Default;
let mut json_color = ColorConfig::Never; let mut json_color = ColorConfig::Never;
let mut json_artifact_notifications = false; let mut json_artifact_notifications = false;
let mut json_unused_externs = JsonUnusedExterns::No; let mut json_unused_externs = JsonUnusedExterns::No;
@ -1696,7 +1697,8 @@ pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Json
} }
JsonConfig { JsonConfig {
json_rendered: json_rendered(json_color), json_rendered,
json_color,
json_artifact_notifications, json_artifact_notifications,
json_unused_externs, json_unused_externs,
json_future_incompat, json_future_incompat,
@ -1708,6 +1710,7 @@ pub fn parse_error_format(
early_dcx: &mut EarlyDiagCtxt, early_dcx: &mut EarlyDiagCtxt,
matches: &getopts::Matches, matches: &getopts::Matches,
color: ColorConfig, color: ColorConfig,
json_color: ColorConfig,
json_rendered: HumanReadableErrorType, json_rendered: HumanReadableErrorType,
) -> ErrorOutputType { ) -> ErrorOutputType {
// We need the `opts_present` check because the driver will send us Matches // We need the `opts_present` check because the driver will send us Matches
@ -1717,18 +1720,22 @@ pub fn parse_error_format(
let error_format = if matches.opts_present(&["error-format".to_owned()]) { let error_format = if matches.opts_present(&["error-format".to_owned()]) {
match matches.opt_str("error-format").as_deref() { match matches.opt_str("error-format").as_deref() {
None | Some("human") => { None | Some("human") => {
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) ErrorOutputType::HumanReadable(HumanReadableErrorType::Default, color)
} }
Some("human-annotate-rs") => { Some("human-annotate-rs") => {
ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(color)) ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet, color)
} }
Some("json") => ErrorOutputType::Json { pretty: false, json_rendered }, Some("json") => {
Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered }, ErrorOutputType::Json { pretty: false, json_rendered, color_config: json_color }
Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)), }
Some("pretty-json") => {
ErrorOutputType::Json { pretty: true, json_rendered, color_config: json_color }
}
Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short, color),
Some(arg) => { Some(arg) => {
early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable( early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable(
HumanReadableErrorType::Default(color), HumanReadableErrorType::Default,
color,
)); ));
early_dcx.early_fatal(format!( early_dcx.early_fatal(format!(
"argument for `--error-format` must be `human`, `json` or \ "argument for `--error-format` must be `human`, `json` or \
@ -1737,7 +1744,7 @@ pub fn parse_error_format(
} }
} }
} else { } else {
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) ErrorOutputType::HumanReadable(HumanReadableErrorType::Default, color)
}; };
match error_format { match error_format {
@ -1791,7 +1798,7 @@ fn check_error_format_stability(
if let ErrorOutputType::Json { pretty: true, .. } = error_format { if let ErrorOutputType::Json { pretty: true, .. } = error_format {
early_dcx.early_fatal("`--error-format=pretty-json` is unstable"); early_dcx.early_fatal("`--error-format=pretty-json` is unstable");
} }
if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) = if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet, _) =
error_format error_format
{ {
early_dcx.early_fatal("`--error-format=human-annotate-rs` is unstable"); early_dcx.early_fatal("`--error-format=human-annotate-rs` is unstable");
@ -2392,12 +2399,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let JsonConfig { let JsonConfig {
json_rendered, json_rendered,
json_color,
json_artifact_notifications, json_artifact_notifications,
json_unused_externs, json_unused_externs,
json_future_incompat, json_future_incompat,
} = parse_json(early_dcx, matches); } = parse_json(early_dcx, matches);
let error_format = parse_error_format(early_dcx, matches, color, json_rendered); let error_format = parse_error_format(early_dcx, matches, color, json_color, json_rendered);
early_dcx.abort_if_error_and_set_error_format(error_format); early_dcx.abort_if_error_and_set_error_format(error_format);

View file

@ -950,10 +950,10 @@ fn default_emitter(
t => t, t => t,
}; };
match sopts.error_format { match sopts.error_format {
config::ErrorOutputType::HumanReadable(kind) => { config::ErrorOutputType::HumanReadable(kind, color_config) => {
let (short, color_config) = kind.unzip(); let short = kind.short();
if let HumanReadableErrorType::AnnotateSnippet(_) = kind { if let HumanReadableErrorType::AnnotateSnippet = kind {
let emitter = AnnotateSnippetEmitter::new( let emitter = AnnotateSnippetEmitter::new(
Some(source_map), Some(source_map),
bundle, bundle,
@ -978,13 +978,14 @@ fn default_emitter(
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing)) Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
} }
} }
config::ErrorOutputType::Json { pretty, json_rendered } => Box::new( config::ErrorOutputType::Json { pretty, json_rendered, color_config } => Box::new(
JsonEmitter::new( JsonEmitter::new(
Box::new(io::BufWriter::new(io::stderr())), Box::new(io::BufWriter::new(io::stderr())),
source_map, source_map,
fallback_bundle, fallback_bundle,
pretty, pretty,
json_rendered, json_rendered,
color_config,
) )
.registry(Some(registry)) .registry(Some(registry))
.fluent_bundle(bundle) .fluent_bundle(bundle)
@ -1425,20 +1426,23 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
let fallback_bundle = let fallback_bundle =
fallback_fluent_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false); fallback_fluent_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false);
let emitter: Box<DynEmitter> = match output { let emitter: Box<DynEmitter> = match output {
config::ErrorOutputType::HumanReadable(kind) => { config::ErrorOutputType::HumanReadable(kind, color_config) => {
let (short, color_config) = kind.unzip(); let short = kind.short();
Box::new( Box::new(
HumanEmitter::new(stderr_destination(color_config), fallback_bundle) HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
.short_message(short), .short_message(short),
) )
} }
config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::new( config::ErrorOutputType::Json { pretty, json_rendered, color_config } => {
Box::new(JsonEmitter::new(
Box::new(io::BufWriter::new(io::stderr())), Box::new(io::BufWriter::new(io::stderr())),
Lrc::new(SourceMap::new(FilePathMapping::empty())), Lrc::new(SourceMap::new(FilePathMapping::empty())),
fallback_bundle, fallback_bundle,
pretty, pretty,
json_rendered, json_rendered,
)), color_config,
))
}
}; };
emitter emitter
} }

View file

@ -362,9 +362,10 @@ impl Options {
} }
let color = config::parse_color(early_dcx, matches); let color = config::parse_color(early_dcx, matches);
let config::JsonConfig { json_rendered, json_unused_externs, .. } = let config::JsonConfig { json_rendered, json_unused_externs, json_color, .. } =
config::parse_json(early_dcx, matches); config::parse_json(early_dcx, matches);
let error_format = config::parse_error_format(early_dcx, matches, color, json_rendered); let error_format =
config::parse_error_format(early_dcx, matches, color, json_color, json_rendered);
let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_default(); let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_default();
let codegen_options = CodegenOptions::build(early_dcx, matches); let codegen_options = CodegenOptions::build(early_dcx, matches);

View file

@ -138,8 +138,8 @@ pub(crate) fn new_dcx(
false, false,
); );
let emitter: Box<DynEmitter> = match error_format { let emitter: Box<DynEmitter> = match error_format {
ErrorOutputType::HumanReadable(kind) => { ErrorOutputType::HumanReadable(kind, color_config) => {
let (short, color_config) = kind.unzip(); let short = kind.short();
Box::new( Box::new(
HumanEmitter::new(stderr_destination(color_config), fallback_bundle) HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
.sm(source_map.map(|sm| sm as _)) .sm(source_map.map(|sm| sm as _))
@ -150,7 +150,7 @@ pub(crate) fn new_dcx(
.ui_testing(unstable_opts.ui_testing), .ui_testing(unstable_opts.ui_testing),
) )
} }
ErrorOutputType::Json { pretty, json_rendered } => { ErrorOutputType::Json { pretty, json_rendered, color_config } => {
let source_map = source_map.unwrap_or_else(|| { let source_map = source_map.unwrap_or_else(|| {
Lrc::new(source_map::SourceMap::new(source_map::FilePathMapping::empty())) Lrc::new(source_map::SourceMap::new(source_map::FilePathMapping::empty()))
}); });
@ -161,6 +161,7 @@ pub(crate) fn new_dcx(
fallback_bundle, fallback_bundle,
pretty, pretty,
json_rendered, json_rendered,
color_config,
) )
.ui_testing(unstable_opts.ui_testing) .ui_testing(unstable_opts.ui_testing)
.diagnostic_width(diagnostic_width) .diagnostic_width(diagnostic_width)

View file

@ -422,8 +422,8 @@ fn run_test(
path_for_rustdoc.to_str().expect("target path must be valid unicode") path_for_rustdoc.to_str().expect("target path must be valid unicode")
} }
}); });
if let ErrorOutputType::HumanReadable(kind) = rustdoc_options.error_format { if let ErrorOutputType::HumanReadable(kind, color_config) = rustdoc_options.error_format {
let (short, color_config) = kind.unzip(); let short = kind.short();
if short { if short {
compiler.arg("--error-format").arg("short"); compiler.arg("--error-format").arg("short");