Rollup merge of #74293 - GuillaumeGomez:rustdoc-test-compiler-output-color, r=jyn514
Rustdoc test compiler output color Fixes #72915 We just need to be sure it doesn't break rustdoc doctests' compilation checks. Maybe some other unforeseen consequences too? r? `@ehuss` cc `@rust-lang/rustdoc`
This commit is contained in:
commit
81f9feba97
@ -200,6 +200,11 @@ pub trait Emitter {
|
||||
true
|
||||
}
|
||||
|
||||
/// Checks if we can use colors in the current output stream.
|
||||
fn supports_color(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>>;
|
||||
|
||||
/// Formats the substitutions of the primary_span
|
||||
@ -504,6 +509,10 @@ impl Emitter for EmitterWriter {
|
||||
fn should_show_explain(&self) -> bool {
|
||||
!self.short_message
|
||||
}
|
||||
|
||||
fn supports_color(&self) -> bool {
|
||||
self.dst.supports_color()
|
||||
}
|
||||
}
|
||||
|
||||
/// An emitter that does nothing when emitting a diagnostic.
|
||||
@ -2057,6 +2066,14 @@ impl Destination {
|
||||
Destination::Raw(ref mut t, true) => WritableDst::ColoredRaw(Ansi::new(t)),
|
||||
}
|
||||
}
|
||||
|
||||
fn supports_color(&self) -> bool {
|
||||
match *self {
|
||||
Self::Terminal(ref stream) => stream.supports_color(),
|
||||
Self::Buffered(ref buffer) => buffer.buffer().supports_color(),
|
||||
Self::Raw(_, supports_color) => supports_color,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> WritableDst<'a> {
|
||||
|
@ -1,13 +1,13 @@
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_errors::{ColorConfig, ErrorReported};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_hir::{HirId, CRATE_HIR_ID};
|
||||
use rustc_interface::interface;
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{self, CrateType};
|
||||
use rustc_session::config::{self, CrateType, ErrorOutputType};
|
||||
use rustc_session::{lint, DiagnosticOutput, Session};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
@ -248,7 +248,8 @@ fn run_test(
|
||||
outdir: DirState,
|
||||
path: PathBuf,
|
||||
) -> Result<(), TestFailure> {
|
||||
let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts, edition);
|
||||
let (test, line_offset, supports_color) =
|
||||
make_test(test, Some(cratename), as_test_harness, opts, edition);
|
||||
|
||||
let output_file = outdir.path().join("rust_out");
|
||||
|
||||
@ -293,6 +294,20 @@ fn run_test(
|
||||
path.to_str().expect("target path must be valid unicode").to_string()
|
||||
}
|
||||
});
|
||||
if let ErrorOutputType::HumanReadable(kind) = options.error_format {
|
||||
let (_, color_config) = kind.unzip();
|
||||
match color_config {
|
||||
ColorConfig::Never => {
|
||||
compiler.arg("--color").arg("never");
|
||||
}
|
||||
ColorConfig::Always => {
|
||||
compiler.arg("--color").arg("always");
|
||||
}
|
||||
ColorConfig::Auto => {
|
||||
compiler.arg("--color").arg(if supports_color { "always" } else { "never" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compiler.arg("-");
|
||||
compiler.stdin(Stdio::piped());
|
||||
@ -320,7 +335,10 @@ fn run_test(
|
||||
(true, false) => {}
|
||||
(false, true) => {
|
||||
if !error_codes.is_empty() {
|
||||
error_codes.retain(|err| !out.contains(&format!("error[{}]: ", err)));
|
||||
// We used to check if the output contained "error[{}]: " but since we added the
|
||||
// colored output, we can't anymore because of the color escape characters before
|
||||
// the ":".
|
||||
error_codes.retain(|err| !out.contains(&format!("error[{}]", err)));
|
||||
|
||||
if !error_codes.is_empty() {
|
||||
return Err(TestFailure::MissingErrorCodes(error_codes));
|
||||
@ -362,18 +380,19 @@ fn run_test(
|
||||
}
|
||||
|
||||
/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
|
||||
/// lines before the test code begins.
|
||||
/// lines before the test code begins as well as if the output stream supports colors or not.
|
||||
crate fn make_test(
|
||||
s: &str,
|
||||
cratename: Option<&str>,
|
||||
dont_insert_main: bool,
|
||||
opts: &TestOptions,
|
||||
edition: Edition,
|
||||
) -> (String, usize) {
|
||||
) -> (String, usize, bool) {
|
||||
let (crate_attrs, everything_else, crates) = partition_source(s);
|
||||
let everything_else = everything_else.trim();
|
||||
let mut line_offset = 0;
|
||||
let mut prog = String::new();
|
||||
let mut supports_color = false;
|
||||
|
||||
if opts.attrs.is_empty() && !opts.display_warnings {
|
||||
// If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
|
||||
@ -399,7 +418,7 @@ crate fn make_test(
|
||||
// crate already is included.
|
||||
let result = rustc_driver::catch_fatal_errors(|| {
|
||||
rustc_span::with_session_globals(edition, || {
|
||||
use rustc_errors::emitter::EmitterWriter;
|
||||
use rustc_errors::emitter::{Emitter, EmitterWriter};
|
||||
use rustc_errors::Handler;
|
||||
use rustc_parse::maybe_new_parser_from_source_str;
|
||||
use rustc_session::parse::ParseSess;
|
||||
@ -411,8 +430,13 @@ crate fn make_test(
|
||||
// Any errors in parsing should also appear when the doctest is compiled for real, so just
|
||||
// send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
|
||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
supports_color =
|
||||
EmitterWriter::stderr(ColorConfig::Auto, None, false, false, Some(80), false)
|
||||
.supports_color();
|
||||
|
||||
let emitter =
|
||||
EmitterWriter::new(box io::sink(), None, false, false, false, None, false);
|
||||
|
||||
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
|
||||
let handler = Handler::with_emitter(false, None, box emitter);
|
||||
let sess = ParseSess::with_span_handler(handler, sm);
|
||||
@ -482,7 +506,7 @@ crate fn make_test(
|
||||
Err(ErrorReported) => {
|
||||
// If the parser panicked due to a fatal error, pass the test code through unchanged.
|
||||
// The error will be reported during compilation.
|
||||
return (s.to_owned(), 0);
|
||||
return (s.to_owned(), 0, false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -532,7 +556,7 @@ crate fn make_test(
|
||||
|
||||
debug!("final doctest:\n{}", prog);
|
||||
|
||||
(prog, line_offset)
|
||||
(prog, line_offset, supports_color)
|
||||
}
|
||||
|
||||
// FIXME(aburka): use a real parser to deal with multiline attributes
|
||||
|
@ -11,8 +11,8 @@ fn main() {
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 2));
|
||||
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -26,8 +26,8 @@ fn main() {
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 2));
|
||||
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -44,8 +44,8 @@ use asdf::qwop;
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 3));
|
||||
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -61,8 +61,8 @@ use asdf::qwop;
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 2));
|
||||
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -79,8 +79,8 @@ use std::*;
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 2));
|
||||
let (output, len, _) = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -98,8 +98,8 @@ use asdf::qwop;
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 2));
|
||||
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -115,8 +115,8 @@ use asdf::qwop;
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 2));
|
||||
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -134,8 +134,8 @@ use asdf::qwop;
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 3));
|
||||
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 3));
|
||||
|
||||
// Adding more will also bump the returned line offset.
|
||||
opts.attrs.push("feature(hella_dope)".to_string());
|
||||
@ -147,8 +147,8 @@ use asdf::qwop;
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 4));
|
||||
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -164,8 +164,8 @@ fn main() {
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 2));
|
||||
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -180,8 +180,8 @@ fn main() {
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 1));
|
||||
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -196,8 +196,8 @@ fn main() {
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 2));
|
||||
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -210,8 +210,8 @@ assert_eq!(2+2, 4);";
|
||||
//Ceci n'est pas une `fn main`
|
||||
assert_eq!(2+2, 4);"
|
||||
.to_string();
|
||||
let output = make_test(input, None, true, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 1));
|
||||
let (output, len, _) = make_test(input, None, true, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -224,8 +224,8 @@ fn make_test_display_warnings() {
|
||||
assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 1));
|
||||
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -242,8 +242,8 @@ assert_eq!(2+2, 4);
|
||||
}"
|
||||
.to_string();
|
||||
|
||||
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 2));
|
||||
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 2));
|
||||
|
||||
let input = "extern crate hella_qwop;
|
||||
assert_eq!(asdf::foo, 4);";
|
||||
@ -256,8 +256,8 @@ assert_eq!(asdf::foo, 4);
|
||||
}"
|
||||
.to_string();
|
||||
|
||||
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 3));
|
||||
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -274,6 +274,6 @@ test_wrapper! {
|
||||
}"
|
||||
.to_string();
|
||||
|
||||
let output = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!(output, (expected, 1));
|
||||
let (output, len, _) = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION);
|
||||
assert_eq!((output, len), (expected, 1));
|
||||
}
|
||||
|
@ -243,7 +243,8 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||
.collect::<Vec<Cow<'_, str>>>()
|
||||
.join("\n");
|
||||
let krate = krate.as_ref().map(|s| &**s);
|
||||
let (test, _) = doctest::make_test(&test, krate, false, &Default::default(), edition);
|
||||
let (test, _, _) =
|
||||
doctest::make_test(&test, krate, false, &Default::default(), edition);
|
||||
let channel = if test.contains("#![feature(") { "&version=nightly" } else { "" };
|
||||
|
||||
let edition_string = format!("&edition={}", edition);
|
||||
|
Loading…
x
Reference in New Issue
Block a user