Skip to content

Commit 7b10746

Browse files
committed
Auto merge of #89277 - jyn514:codeblock-edition, r=GuillaumeGomez
Use the correct edition for syntax highlighting doctests Previously it would unconditionally use edition 2015, which was incorrect. Helps with #89135 in that you can now override the doctest to be 2018 edition instead of being forced to fix the error. This doesn't resolve any of the deeper problems that rustdoc disagrees with most rust users on what a code block is. cc `@Mark-Simulacrum`
2 parents 8a12be7 + 6f087ae commit 7b10746

File tree

4 files changed

+60
-19
lines changed

4 files changed

+60
-19
lines changed

src/librustdoc/html/markdown.rs

+8-15
Original file line numberDiff line numberDiff line change
@@ -1316,8 +1316,7 @@ crate struct RustCodeBlock {
13161316
/// The range in the markdown that the code within the code block occupies.
13171317
crate code: Range<usize>,
13181318
crate is_fenced: bool,
1319-
crate syntax: Option<String>,
1320-
crate is_ignore: bool,
1319+
crate lang_string: LangString,
13211320
}
13221321

13231322
/// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or
@@ -1333,7 +1332,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<RustCodeB
13331332

13341333
while let Some((event, offset)) = p.next() {
13351334
if let Event::Start(Tag::CodeBlock(syntax)) = event {
1336-
let (syntax, code_start, code_end, range, is_fenced, is_ignore) = match syntax {
1335+
let (lang_string, code_start, code_end, range, is_fenced) = match syntax {
13371336
CodeBlockKind::Fenced(syntax) => {
13381337
let syntax = syntax.as_ref();
13391338
let lang_string = if syntax.is_empty() {
@@ -1344,8 +1343,6 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<RustCodeB
13441343
if !lang_string.rust {
13451344
continue;
13461345
}
1347-
let is_ignore = lang_string.ignore != Ignore::None;
1348-
let syntax = if syntax.is_empty() { None } else { Some(syntax.to_owned()) };
13491346
let (code_start, mut code_end) = match p.next() {
13501347
Some((Event::Text(_), offset)) => (offset.start, offset.end),
13511348
Some((_, sub_offset)) => {
@@ -1354,8 +1351,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<RustCodeB
13541351
is_fenced: true,
13551352
range: offset,
13561353
code,
1357-
syntax,
1358-
is_ignore,
1354+
lang_string,
13591355
});
13601356
continue;
13611357
}
@@ -1365,31 +1361,29 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<RustCodeB
13651361
is_fenced: true,
13661362
range: offset,
13671363
code,
1368-
syntax,
1369-
is_ignore,
1364+
lang_string,
13701365
});
13711366
continue;
13721367
}
13731368
};
13741369
while let Some((Event::Text(_), offset)) = p.next() {
13751370
code_end = offset.end;
13761371
}
1377-
(syntax, code_start, code_end, offset, true, is_ignore)
1372+
(lang_string, code_start, code_end, offset, true)
13781373
}
13791374
CodeBlockKind::Indented => {
13801375
// The ending of the offset goes too far sometime so we reduce it by one in
13811376
// these cases.
13821377
if offset.end > offset.start && md.get(offset.end..=offset.end) == Some(&"\n") {
13831378
(
1384-
None,
1379+
LangString::default(),
13851380
offset.start,
13861381
offset.end,
13871382
Range { start: offset.start, end: offset.end - 1 },
13881383
false,
1389-
false,
13901384
)
13911385
} else {
1392-
(None, offset.start, offset.end, offset, false, false)
1386+
(LangString::default(), offset.start, offset.end, offset, false)
13931387
}
13941388
}
13951389
};
@@ -1398,8 +1392,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<RustCodeB
13981392
is_fenced,
13991393
range,
14001394
code: Range { start: code_start, end: code_end },
1401-
syntax,
1402-
is_ignore,
1395+
lang_string,
14031396
});
14041397
}
14051398
}

src/librustdoc/passes/check_code_block_syntax.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_middle::lint::LintDiagnosticBuilder;
44
use rustc_parse::parse_stream_from_source_str;
55
use rustc_session::parse::ParseSess;
66
use rustc_span::source_map::{FilePathMapping, SourceMap};
7-
use rustc_span::{FileName, InnerSpan};
7+
use rustc_span::{hygiene::AstPass, ExpnData, ExpnKind, FileName, InnerSpan, DUMMY_SP};
88

99
use crate::clean;
1010
use crate::core::DocContext;
@@ -36,12 +36,22 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
3636
let source = dox[code_block.code].to_owned();
3737
let sess = ParseSess::with_span_handler(handler, sm);
3838

39+
let edition = code_block.lang_string.edition.unwrap_or(self.cx.tcx.sess.edition());
40+
let expn_data = ExpnData::default(
41+
ExpnKind::AstPass(AstPass::TestHarness),
42+
DUMMY_SP,
43+
edition,
44+
None,
45+
None,
46+
);
47+
let span = DUMMY_SP.fresh_expansion(expn_data, self.cx.tcx.create_stable_hashing_context());
48+
3949
let is_empty = rustc_driver::catch_fatal_errors(|| {
4050
parse_stream_from_source_str(
4151
FileName::Custom(String::from("doctest")),
4252
source,
4353
&sess,
44-
None,
54+
Some(span),
4555
)
4656
.is_empty()
4757
})
@@ -61,8 +71,8 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
6171
};
6272

6373
let hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_id);
64-
let empty_block = code_block.syntax.is_none() && code_block.is_fenced;
65-
let is_ignore = code_block.is_ignore;
74+
let empty_block = code_block.lang_string == Default::default() && code_block.is_fenced;
75+
let is_ignore = code_block.lang_string.ignore != markdown::Ignore::None;
6676

6777
// The span and whether it is precise or not.
6878
let (sp, precise_span) = match super::source_span_for_markdown_range(
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// edition:2021
2+
3+
#![deny(rustdoc::invalid_rust_codeblocks)]
4+
//~^ NOTE lint level is defined here
5+
6+
// By default, rustdoc should use the edition of the crate.
7+
//! ```
8+
//! foo'b'
9+
//! ```
10+
//~^^^ ERROR could not parse
11+
//~| NOTE prefix `foo` is unknown
12+
13+
// Rustdoc should respect `edition2018` when highlighting syntax.
14+
//! ```edition2018
15+
//! foo'b'
16+
//! ```
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: could not parse code block as Rust code
2+
--> $DIR/doctest-edition.rs:7:5
3+
|
4+
LL | //! ```
5+
| _____^
6+
LL | | //! foo'b'
7+
LL | | //! ```
8+
| |_______^
9+
|
10+
note: the lint level is defined here
11+
--> $DIR/doctest-edition.rs:3:9
12+
|
13+
LL | #![deny(rustdoc::invalid_rust_codeblocks)]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
= note: error from rustc: prefix `foo` is unknown
16+
help: mark blocks that do not contain Rust code as text
17+
|
18+
LL | //! ```text
19+
| ++++
20+
21+
error: aborting due to previous error
22+

0 commit comments

Comments
 (0)