Skip to content

Commit 859f3fc

Browse files
committed
Auto merge of rust-lang#115914 - GuillaumeGomez:turn-custom_code_classes_in_docs-into-warning, r=Manishearth
Turn custom code classes in docs into warning By habit, since it was a new feature gate, I added a check which emitted an error in case the new syntax was used. However, since rustdoc tags parser was accepting *everything*, using the "new" syntax should never ever emit errors. It now emits a warning. Follow-up of rust-lang#110800. cc `@Manishearth` r? `@notriddle`
2 parents 203c57d + e1e1a02 commit 859f3fc

12 files changed

+158
-39
lines changed

src/librustdoc/doctest.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
12431243
def_id.to_def_id(),
12441244
span_of_fragments(&attrs.doc_strings).unwrap_or(sp),
12451245
)),
1246+
self.tcx.features().custom_code_classes_in_docs,
12461247
);
12471248
}
12481249

src/librustdoc/externalfiles.rs

+4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ impl ExternalHtml {
4646
edition,
4747
playground,
4848
heading_offset: HeadingOffset::H2,
49+
// For external files, it'll be disabled until the feature is enabled by default.
50+
custom_code_classes_in_docs: false,
4951
}
5052
.into_string()
5153
);
@@ -61,6 +63,8 @@ impl ExternalHtml {
6163
edition,
6264
playground,
6365
heading_offset: HeadingOffset::H2,
66+
// For external files, it'll be disabled until the feature is enabled by default.
67+
custom_code_classes_in_docs: false,
6468
}
6569
.into_string()
6670
);

src/librustdoc/html/markdown.rs

+79-16
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
//! edition: Edition::Edition2015,
2121
//! playground: &None,
2222
//! heading_offset: HeadingOffset::H2,
23+
//! custom_code_classes_in_docs: true,
2324
//! };
2425
//! let html = md.into_string();
2526
//! // ... something using html
@@ -95,6 +96,8 @@ pub struct Markdown<'a> {
9596
/// Offset at which we render headings.
9697
/// E.g. if `heading_offset: HeadingOffset::H2`, then `# something` renders an `<h2>`.
9798
pub heading_offset: HeadingOffset,
99+
/// `true` if the `custom_code_classes_in_docs` feature is enabled.
100+
pub custom_code_classes_in_docs: bool,
98101
}
99102
/// A struct like `Markdown` that renders the markdown with a table of contents.
100103
pub(crate) struct MarkdownWithToc<'a> {
@@ -103,6 +106,8 @@ pub(crate) struct MarkdownWithToc<'a> {
103106
pub(crate) error_codes: ErrorCodes,
104107
pub(crate) edition: Edition,
105108
pub(crate) playground: &'a Option<Playground>,
109+
/// `true` if the `custom_code_classes_in_docs` feature is enabled.
110+
pub(crate) custom_code_classes_in_docs: bool,
106111
}
107112
/// A tuple struct like `Markdown` that renders the markdown escaping HTML tags
108113
/// and includes no paragraph tags.
@@ -203,6 +208,7 @@ struct CodeBlocks<'p, 'a, I: Iterator<Item = Event<'a>>> {
203208
// Information about the playground if a URL has been specified, containing an
204209
// optional crate name and the URL.
205210
playground: &'p Option<Playground>,
211+
custom_code_classes_in_docs: bool,
206212
}
207213

208214
impl<'p, 'a, I: Iterator<Item = Event<'a>>> CodeBlocks<'p, 'a, I> {
@@ -211,8 +217,15 @@ impl<'p, 'a, I: Iterator<Item = Event<'a>>> CodeBlocks<'p, 'a, I> {
211217
error_codes: ErrorCodes,
212218
edition: Edition,
213219
playground: &'p Option<Playground>,
220+
custom_code_classes_in_docs: bool,
214221
) -> Self {
215-
CodeBlocks { inner: iter, check_error_codes: error_codes, edition, playground }
222+
CodeBlocks {
223+
inner: iter,
224+
check_error_codes: error_codes,
225+
edition,
226+
playground,
227+
custom_code_classes_in_docs,
228+
}
216229
}
217230
}
218231

@@ -242,8 +255,12 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
242255

243256
let parse_result = match kind {
244257
CodeBlockKind::Fenced(ref lang) => {
245-
let parse_result =
246-
LangString::parse_without_check(lang, self.check_error_codes, false);
258+
let parse_result = LangString::parse_without_check(
259+
lang,
260+
self.check_error_codes,
261+
false,
262+
self.custom_code_classes_in_docs,
263+
);
247264
if !parse_result.rust {
248265
let added_classes = parse_result.added_classes;
249266
let lang_string = if let Some(lang) = parse_result.unknown.first() {
@@ -725,8 +742,17 @@ pub(crate) fn find_testable_code<T: doctest::Tester>(
725742
error_codes: ErrorCodes,
726743
enable_per_target_ignores: bool,
727744
extra_info: Option<&ExtraInfo<'_>>,
745+
custom_code_classes_in_docs: bool,
728746
) {
729-
find_codes(doc, tests, error_codes, enable_per_target_ignores, extra_info, false)
747+
find_codes(
748+
doc,
749+
tests,
750+
error_codes,
751+
enable_per_target_ignores,
752+
extra_info,
753+
false,
754+
custom_code_classes_in_docs,
755+
)
730756
}
731757

732758
pub(crate) fn find_codes<T: doctest::Tester>(
@@ -736,6 +762,7 @@ pub(crate) fn find_codes<T: doctest::Tester>(
736762
enable_per_target_ignores: bool,
737763
extra_info: Option<&ExtraInfo<'_>>,
738764
include_non_rust: bool,
765+
custom_code_classes_in_docs: bool,
739766
) {
740767
let mut parser = Parser::new(doc).into_offset_iter();
741768
let mut prev_offset = 0;
@@ -754,6 +781,7 @@ pub(crate) fn find_codes<T: doctest::Tester>(
754781
error_codes,
755782
enable_per_target_ignores,
756783
extra_info,
784+
custom_code_classes_in_docs,
757785
)
758786
}
759787
}
@@ -1153,15 +1181,23 @@ impl LangString {
11531181
string: &str,
11541182
allow_error_code_check: ErrorCodes,
11551183
enable_per_target_ignores: bool,
1184+
custom_code_classes_in_docs: bool,
11561185
) -> Self {
1157-
Self::parse(string, allow_error_code_check, enable_per_target_ignores, None)
1186+
Self::parse(
1187+
string,
1188+
allow_error_code_check,
1189+
enable_per_target_ignores,
1190+
None,
1191+
custom_code_classes_in_docs,
1192+
)
11581193
}
11591194

11601195
fn parse(
11611196
string: &str,
11621197
allow_error_code_check: ErrorCodes,
11631198
enable_per_target_ignores: bool,
11641199
extra: Option<&ExtraInfo<'_>>,
1200+
custom_code_classes_in_docs: bool,
11651201
) -> Self {
11661202
let allow_error_code_check = allow_error_code_check.as_bool();
11671203
let mut seen_rust_tags = false;
@@ -1197,7 +1233,11 @@ impl LangString {
11971233
seen_rust_tags = true;
11981234
}
11991235
LangStringToken::LangToken("custom") => {
1200-
seen_custom_tag = true;
1236+
if custom_code_classes_in_docs {
1237+
seen_custom_tag = true;
1238+
} else {
1239+
seen_other_tags = true;
1240+
}
12011241
}
12021242
LangStringToken::LangToken("test_harness") => {
12031243
data.test_harness = true;
@@ -1268,11 +1308,16 @@ impl LangString {
12681308
data.unknown.push(x.to_owned());
12691309
}
12701310
LangStringToken::KeyValueAttribute(key, value) => {
1271-
if key == "class" {
1272-
data.added_classes.push(value.to_owned());
1273-
} else if let Some(extra) = extra {
1274-
extra
1275-
.error_invalid_codeblock_attr(format!("unsupported attribute `{key}`"));
1311+
if custom_code_classes_in_docs {
1312+
if key == "class" {
1313+
data.added_classes.push(value.to_owned());
1314+
} else if let Some(extra) = extra {
1315+
extra.error_invalid_codeblock_attr(format!(
1316+
"unsupported attribute `{key}`"
1317+
));
1318+
}
1319+
} else {
1320+
seen_other_tags = true;
12761321
}
12771322
}
12781323
LangStringToken::ClassAttribute(class) => {
@@ -1302,6 +1347,7 @@ impl Markdown<'_> {
13021347
edition,
13031348
playground,
13041349
heading_offset,
1350+
custom_code_classes_in_docs,
13051351
} = self;
13061352

13071353
// This is actually common enough to special-case
@@ -1324,7 +1370,7 @@ impl Markdown<'_> {
13241370
let p = Footnotes::new(p);
13251371
let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
13261372
let p = TableWrapper::new(p);
1327-
let p = CodeBlocks::new(p, codes, edition, playground);
1373+
let p = CodeBlocks::new(p, codes, edition, playground, custom_code_classes_in_docs);
13281374
html::push_html(&mut s, p);
13291375

13301376
s
@@ -1333,7 +1379,14 @@ impl Markdown<'_> {
13331379

13341380
impl MarkdownWithToc<'_> {
13351381
pub(crate) fn into_string(self) -> String {
1336-
let MarkdownWithToc { content: md, ids, error_codes: codes, edition, playground } = self;
1382+
let MarkdownWithToc {
1383+
content: md,
1384+
ids,
1385+
error_codes: codes,
1386+
edition,
1387+
playground,
1388+
custom_code_classes_in_docs,
1389+
} = self;
13371390

13381391
let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
13391392

@@ -1345,7 +1398,7 @@ impl MarkdownWithToc<'_> {
13451398
let p = HeadingLinks::new(p, Some(&mut toc), ids, HeadingOffset::H1);
13461399
let p = Footnotes::new(p);
13471400
let p = TableWrapper::new(p.map(|(ev, _)| ev));
1348-
let p = CodeBlocks::new(p, codes, edition, playground);
1401+
let p = CodeBlocks::new(p, codes, edition, playground, custom_code_classes_in_docs);
13491402
html::push_html(&mut s, p);
13501403
}
13511404

@@ -1786,7 +1839,11 @@ pub(crate) struct RustCodeBlock {
17861839

17871840
/// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or
17881841
/// untagged (and assumed to be rust).
1789-
pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<RustCodeBlock> {
1842+
pub(crate) fn rust_code_blocks(
1843+
md: &str,
1844+
extra_info: &ExtraInfo<'_>,
1845+
custom_code_classes_in_docs: bool,
1846+
) -> Vec<RustCodeBlock> {
17901847
let mut code_blocks = vec![];
17911848

17921849
if md.is_empty() {
@@ -1803,7 +1860,13 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust
18031860
let lang_string = if syntax.is_empty() {
18041861
Default::default()
18051862
} else {
1806-
LangString::parse(&*syntax, ErrorCodes::Yes, false, Some(extra_info))
1863+
LangString::parse(
1864+
&*syntax,
1865+
ErrorCodes::Yes,
1866+
false,
1867+
Some(extra_info),
1868+
custom_code_classes_in_docs,
1869+
)
18071870
};
18081871
if !lang_string.rust {
18091872
continue;

src/librustdoc/html/markdown/tests.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fn test_unique_id() {
4949
fn test_lang_string_parse() {
5050
fn t(lg: LangString) {
5151
let s = &lg.original;
52-
assert_eq!(LangString::parse(s, ErrorCodes::Yes, true, None), lg)
52+
assert_eq!(LangString::parse(s, ErrorCodes::Yes, true, None, true), lg)
5353
}
5454

5555
t(Default::default());
@@ -290,6 +290,7 @@ fn test_header() {
290290
edition: DEFAULT_EDITION,
291291
playground: &None,
292292
heading_offset: HeadingOffset::H2,
293+
custom_code_classes_in_docs: true,
293294
}
294295
.into_string();
295296
assert_eq!(output, expect, "original: {}", input);
@@ -329,6 +330,7 @@ fn test_header_ids_multiple_blocks() {
329330
edition: DEFAULT_EDITION,
330331
playground: &None,
331332
heading_offset: HeadingOffset::H2,
333+
custom_code_classes_in_docs: true,
332334
}
333335
.into_string();
334336
assert_eq!(output, expect, "original: {}", input);
@@ -433,7 +435,7 @@ fn test_find_testable_code_line() {
433435
}
434436
}
435437
let mut lines = Vec::<usize>::new();
436-
find_testable_code(input, &mut lines, ErrorCodes::No, false, None);
438+
find_testable_code(input, &mut lines, ErrorCodes::No, false, None, true);
437439
assert_eq!(lines, expect);
438440
}
439441

@@ -458,6 +460,7 @@ fn test_ascii_with_prepending_hashtag() {
458460
edition: DEFAULT_EDITION,
459461
playground: &None,
460462
heading_offset: HeadingOffset::H2,
463+
custom_code_classes_in_docs: true,
461464
}
462465
.into_string();
463466
assert_eq!(output, expect, "original: {}", input);

src/librustdoc/html/render/mod.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,8 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
403403
error_codes: shared.codes,
404404
edition: shared.edition(),
405405
playground: &shared.playground,
406-
heading_offset: HeadingOffset::H1
406+
heading_offset: HeadingOffset::H1,
407+
custom_code_classes_in_docs: false,
407408
}
408409
.into_string()
409410
)
@@ -437,6 +438,7 @@ fn render_markdown<'a, 'cx: 'a>(
437438
heading_offset: HeadingOffset,
438439
) -> impl fmt::Display + 'a + Captures<'cx> {
439440
display_fn(move |f| {
441+
let custom_code_classes_in_docs = cx.tcx().features().custom_code_classes_in_docs;
440442
write!(
441443
f,
442444
"<div class=\"docblock\">{}</div>",
@@ -448,6 +450,7 @@ fn render_markdown<'a, 'cx: 'a>(
448450
edition: cx.shared.edition(),
449451
playground: &cx.shared.playground,
450452
heading_offset,
453+
custom_code_classes_in_docs,
451454
}
452455
.into_string()
453456
)
@@ -1778,6 +1781,7 @@ fn render_impl(
17781781
</div>",
17791782
);
17801783
}
1784+
let custom_code_classes_in_docs = cx.tcx().features().custom_code_classes_in_docs;
17811785
write!(
17821786
w,
17831787
"<div class=\"docblock\">{}</div>",
@@ -1788,7 +1792,8 @@ fn render_impl(
17881792
error_codes: cx.shared.codes,
17891793
edition: cx.shared.edition(),
17901794
playground: &cx.shared.playground,
1791-
heading_offset: HeadingOffset::H4
1795+
heading_offset: HeadingOffset::H4,
1796+
custom_code_classes_in_docs,
17921797
}
17931798
.into_string()
17941799
);

src/librustdoc/markdown.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ pub(crate) fn render<P: AsRef<Path>>(
8080
error_codes,
8181
edition,
8282
playground: &playground,
83+
// For markdown files, it'll be disabled until the feature is enabled by default.
84+
custom_code_classes_in_docs: false,
8385
}
8486
.into_string()
8587
} else {
@@ -91,6 +93,8 @@ pub(crate) fn render<P: AsRef<Path>>(
9193
edition,
9294
playground: &playground,
9395
heading_offset: HeadingOffset::H1,
96+
// For markdown files, it'll be disabled until the feature is enabled by default.
97+
custom_code_classes_in_docs: false,
9498
}
9599
.into_string()
96100
};
@@ -154,7 +158,15 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
154158
collector.set_position(DUMMY_SP);
155159
let codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
156160

157-
find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None);
161+
// For markdown files, custom code classes will be disabled until the feature is enabled by default.
162+
find_testable_code(
163+
&input_str,
164+
&mut collector,
165+
codes,
166+
options.enable_per_target_ignores,
167+
None,
168+
false,
169+
);
158170

159171
crate::doctest::run_tests(options.test_args, options.nocapture, collector.tests);
160172
Ok(())

src/librustdoc/passes/calculate_doc_coverage.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,14 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
208208
let has_docs = !i.attrs.doc_strings.is_empty();
209209
let mut tests = Tests { found_tests: 0 };
210210

211-
find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None);
211+
find_testable_code(
212+
&i.doc_value(),
213+
&mut tests,
214+
ErrorCodes::No,
215+
false,
216+
None,
217+
self.ctx.tcx.features().custom_code_classes_in_docs,
218+
);
212219

213220
let has_doc_example = tests.found_tests != 0;
214221
let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap();

0 commit comments

Comments
 (0)