Skip to content

Commit 81f9feb

Browse files
authored
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`
2 parents e0ef0fc + ec10824 commit 81f9feb

File tree

4 files changed

+86
-44
lines changed

4 files changed

+86
-44
lines changed

compiler/rustc_errors/src/emitter.rs

+17
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ pub trait Emitter {
200200
true
201201
}
202202

203+
/// Checks if we can use colors in the current output stream.
204+
fn supports_color(&self) -> bool {
205+
false
206+
}
207+
203208
fn source_map(&self) -> Option<&Lrc<SourceMap>>;
204209

205210
/// Formats the substitutions of the primary_span
@@ -504,6 +509,10 @@ impl Emitter for EmitterWriter {
504509
fn should_show_explain(&self) -> bool {
505510
!self.short_message
506511
}
512+
513+
fn supports_color(&self) -> bool {
514+
self.dst.supports_color()
515+
}
507516
}
508517

509518
/// An emitter that does nothing when emitting a diagnostic.
@@ -2057,6 +2066,14 @@ impl Destination {
20572066
Destination::Raw(ref mut t, true) => WritableDst::ColoredRaw(Ansi::new(t)),
20582067
}
20592068
}
2069+
2070+
fn supports_color(&self) -> bool {
2071+
match *self {
2072+
Self::Terminal(ref stream) => stream.supports_color(),
2073+
Self::Buffered(ref buffer) => buffer.buffer().supports_color(),
2074+
Self::Raw(_, supports_color) => supports_color,
2075+
}
2076+
}
20602077
}
20612078

20622079
impl<'a> WritableDst<'a> {

src/librustdoc/doctest.rs

+33-9
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use rustc_ast as ast;
22
use rustc_data_structures::sync::Lrc;
3-
use rustc_errors::ErrorReported;
3+
use rustc_errors::{ColorConfig, ErrorReported};
44
use rustc_hir as hir;
55
use rustc_hir::intravisit;
66
use rustc_hir::{HirId, CRATE_HIR_ID};
77
use rustc_interface::interface;
88
use rustc_middle::hir::map::Map;
99
use rustc_middle::ty::TyCtxt;
10-
use rustc_session::config::{self, CrateType};
10+
use rustc_session::config::{self, CrateType, ErrorOutputType};
1111
use rustc_session::{lint, DiagnosticOutput, Session};
1212
use rustc_span::edition::Edition;
1313
use rustc_span::source_map::SourceMap;
@@ -248,7 +248,8 @@ fn run_test(
248248
outdir: DirState,
249249
path: PathBuf,
250250
) -> Result<(), TestFailure> {
251-
let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts, edition);
251+
let (test, line_offset, supports_color) =
252+
make_test(test, Some(cratename), as_test_harness, opts, edition);
252253

253254
let output_file = outdir.path().join("rust_out");
254255

@@ -293,6 +294,20 @@ fn run_test(
293294
path.to_str().expect("target path must be valid unicode").to_string()
294295
}
295296
});
297+
if let ErrorOutputType::HumanReadable(kind) = options.error_format {
298+
let (_, color_config) = kind.unzip();
299+
match color_config {
300+
ColorConfig::Never => {
301+
compiler.arg("--color").arg("never");
302+
}
303+
ColorConfig::Always => {
304+
compiler.arg("--color").arg("always");
305+
}
306+
ColorConfig::Auto => {
307+
compiler.arg("--color").arg(if supports_color { "always" } else { "never" });
308+
}
309+
}
310+
}
296311

297312
compiler.arg("-");
298313
compiler.stdin(Stdio::piped());
@@ -320,7 +335,10 @@ fn run_test(
320335
(true, false) => {}
321336
(false, true) => {
322337
if !error_codes.is_empty() {
323-
error_codes.retain(|err| !out.contains(&format!("error[{}]: ", err)));
338+
// We used to check if the output contained "error[{}]: " but since we added the
339+
// colored output, we can't anymore because of the color escape characters before
340+
// the ":".
341+
error_codes.retain(|err| !out.contains(&format!("error[{}]", err)));
324342

325343
if !error_codes.is_empty() {
326344
return Err(TestFailure::MissingErrorCodes(error_codes));
@@ -362,18 +380,19 @@ fn run_test(
362380
}
363381

364382
/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
365-
/// lines before the test code begins.
383+
/// lines before the test code begins as well as if the output stream supports colors or not.
366384
crate fn make_test(
367385
s: &str,
368386
cratename: Option<&str>,
369387
dont_insert_main: bool,
370388
opts: &TestOptions,
371389
edition: Edition,
372-
) -> (String, usize) {
390+
) -> (String, usize, bool) {
373391
let (crate_attrs, everything_else, crates) = partition_source(s);
374392
let everything_else = everything_else.trim();
375393
let mut line_offset = 0;
376394
let mut prog = String::new();
395+
let mut supports_color = false;
377396

378397
if opts.attrs.is_empty() && !opts.display_warnings {
379398
// If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
@@ -399,7 +418,7 @@ crate fn make_test(
399418
// crate already is included.
400419
let result = rustc_driver::catch_fatal_errors(|| {
401420
rustc_span::with_session_globals(edition, || {
402-
use rustc_errors::emitter::EmitterWriter;
421+
use rustc_errors::emitter::{Emitter, EmitterWriter};
403422
use rustc_errors::Handler;
404423
use rustc_parse::maybe_new_parser_from_source_str;
405424
use rustc_session::parse::ParseSess;
@@ -411,8 +430,13 @@ crate fn make_test(
411430
// Any errors in parsing should also appear when the doctest is compiled for real, so just
412431
// send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
413432
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
433+
supports_color =
434+
EmitterWriter::stderr(ColorConfig::Auto, None, false, false, Some(80), false)
435+
.supports_color();
436+
414437
let emitter =
415438
EmitterWriter::new(box io::sink(), None, false, false, false, None, false);
439+
416440
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
417441
let handler = Handler::with_emitter(false, None, box emitter);
418442
let sess = ParseSess::with_span_handler(handler, sm);
@@ -482,7 +506,7 @@ crate fn make_test(
482506
Err(ErrorReported) => {
483507
// If the parser panicked due to a fatal error, pass the test code through unchanged.
484508
// The error will be reported during compilation.
485-
return (s.to_owned(), 0);
509+
return (s.to_owned(), 0, false);
486510
}
487511
};
488512

@@ -532,7 +556,7 @@ crate fn make_test(
532556

533557
debug!("final doctest:\n{}", prog);
534558

535-
(prog, line_offset)
559+
(prog, line_offset, supports_color)
536560
}
537561

538562
// FIXME(aburka): use a real parser to deal with multiline attributes

src/librustdoc/doctest/tests.rs

+34-34
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ fn main() {
1111
assert_eq!(2+2, 4);
1212
}"
1313
.to_string();
14-
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
15-
assert_eq!(output, (expected, 2));
14+
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
15+
assert_eq!((output, len), (expected, 2));
1616
}
1717

1818
#[test]
@@ -26,8 +26,8 @@ fn main() {
2626
assert_eq!(2+2, 4);
2727
}"
2828
.to_string();
29-
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
30-
assert_eq!(output, (expected, 2));
29+
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
30+
assert_eq!((output, len), (expected, 2));
3131
}
3232

3333
#[test]
@@ -44,8 +44,8 @@ use asdf::qwop;
4444
assert_eq!(2+2, 4);
4545
}"
4646
.to_string();
47-
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
48-
assert_eq!(output, (expected, 3));
47+
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
48+
assert_eq!((output, len), (expected, 3));
4949
}
5050

5151
#[test]
@@ -61,8 +61,8 @@ use asdf::qwop;
6161
assert_eq!(2+2, 4);
6262
}"
6363
.to_string();
64-
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
65-
assert_eq!(output, (expected, 2));
64+
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
65+
assert_eq!((output, len), (expected, 2));
6666
}
6767

6868
#[test]
@@ -79,8 +79,8 @@ use std::*;
7979
assert_eq!(2+2, 4);
8080
}"
8181
.to_string();
82-
let output = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION);
83-
assert_eq!(output, (expected, 2));
82+
let (output, len, _) = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION);
83+
assert_eq!((output, len), (expected, 2));
8484
}
8585

8686
#[test]
@@ -98,8 +98,8 @@ use asdf::qwop;
9898
assert_eq!(2+2, 4);
9999
}"
100100
.to_string();
101-
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
102-
assert_eq!(output, (expected, 2));
101+
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
102+
assert_eq!((output, len), (expected, 2));
103103
}
104104

105105
#[test]
@@ -115,8 +115,8 @@ use asdf::qwop;
115115
assert_eq!(2+2, 4);
116116
}"
117117
.to_string();
118-
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
119-
assert_eq!(output, (expected, 2));
118+
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
119+
assert_eq!((output, len), (expected, 2));
120120
}
121121

122122
#[test]
@@ -134,8 +134,8 @@ use asdf::qwop;
134134
assert_eq!(2+2, 4);
135135
}"
136136
.to_string();
137-
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
138-
assert_eq!(output, (expected, 3));
137+
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
138+
assert_eq!((output, len), (expected, 3));
139139

140140
// Adding more will also bump the returned line offset.
141141
opts.attrs.push("feature(hella_dope)".to_string());
@@ -147,8 +147,8 @@ use asdf::qwop;
147147
assert_eq!(2+2, 4);
148148
}"
149149
.to_string();
150-
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
151-
assert_eq!(output, (expected, 4));
150+
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
151+
assert_eq!((output, len), (expected, 4));
152152
}
153153

154154
#[test]
@@ -164,8 +164,8 @@ fn main() {
164164
assert_eq!(2+2, 4);
165165
}"
166166
.to_string();
167-
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
168-
assert_eq!(output, (expected, 2));
167+
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
168+
assert_eq!((output, len), (expected, 2));
169169
}
170170

171171
#[test]
@@ -180,8 +180,8 @@ fn main() {
180180
assert_eq!(2+2, 4);
181181
}"
182182
.to_string();
183-
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
184-
assert_eq!(output, (expected, 1));
183+
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
184+
assert_eq!((output, len), (expected, 1));
185185
}
186186

187187
#[test]
@@ -196,8 +196,8 @@ fn main() {
196196
assert_eq!(2+2, 4);
197197
}"
198198
.to_string();
199-
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
200-
assert_eq!(output, (expected, 2));
199+
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
200+
assert_eq!((output, len), (expected, 2));
201201
}
202202

203203
#[test]
@@ -210,8 +210,8 @@ assert_eq!(2+2, 4);";
210210
//Ceci n'est pas une `fn main`
211211
assert_eq!(2+2, 4);"
212212
.to_string();
213-
let output = make_test(input, None, true, &opts, DEFAULT_EDITION);
214-
assert_eq!(output, (expected, 1));
213+
let (output, len, _) = make_test(input, None, true, &opts, DEFAULT_EDITION);
214+
assert_eq!((output, len), (expected, 1));
215215
}
216216

217217
#[test]
@@ -224,8 +224,8 @@ fn make_test_display_warnings() {
224224
assert_eq!(2+2, 4);
225225
}"
226226
.to_string();
227-
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
228-
assert_eq!(output, (expected, 1));
227+
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
228+
assert_eq!((output, len), (expected, 1));
229229
}
230230

231231
#[test]
@@ -242,8 +242,8 @@ assert_eq!(2+2, 4);
242242
}"
243243
.to_string();
244244

245-
let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
246-
assert_eq!(output, (expected, 2));
245+
let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
246+
assert_eq!((output, len), (expected, 2));
247247

248248
let input = "extern crate hella_qwop;
249249
assert_eq!(asdf::foo, 4);";
@@ -256,8 +256,8 @@ assert_eq!(asdf::foo, 4);
256256
}"
257257
.to_string();
258258

259-
let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
260-
assert_eq!(output, (expected, 3));
259+
let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
260+
assert_eq!((output, len), (expected, 3));
261261
}
262262

263263
#[test]
@@ -274,6 +274,6 @@ test_wrapper! {
274274
}"
275275
.to_string();
276276

277-
let output = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION);
278-
assert_eq!(output, (expected, 1));
277+
let (output, len, _) = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION);
278+
assert_eq!((output, len), (expected, 1));
279279
}

src/librustdoc/html/markdown.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
243243
.collect::<Vec<Cow<'_, str>>>()
244244
.join("\n");
245245
let krate = krate.as_ref().map(|s| &**s);
246-
let (test, _) = doctest::make_test(&test, krate, false, &Default::default(), edition);
246+
let (test, _, _) =
247+
doctest::make_test(&test, krate, false, &Default::default(), edition);
247248
let channel = if test.contains("#![feature(") { "&amp;version=nightly" } else { "" };
248249

249250
let edition_string = format!("&amp;edition={}", edition);

0 commit comments

Comments
 (0)