Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit f556184

Browse files
Add tests for custom_code_classes_in_docs feature
1 parent 5515fc8 commit f556184

9 files changed

+268
-27
lines changed

src/librustdoc/html/markdown/tests.rs

Lines changed: 104 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use super::{find_testable_code, plain_text_summary, short_markdown_summary};
2-
use super::{ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, Markdown, MarkdownItemInfo};
2+
use super::{
3+
ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, Markdown, MarkdownItemInfo, TagIterator,
4+
TokenKind,
5+
};
36
use rustc_span::edition::{Edition, DEFAULT_EDITION};
47

58
#[test]
@@ -51,10 +54,25 @@ fn test_lang_string_parse() {
5154

5255
t(Default::default());
5356
t(LangString { original: "rust".into(), ..Default::default() });
54-
t(LangString { original: ".rust".into(), ..Default::default() });
55-
t(LangString { original: "{rust}".into(), ..Default::default() });
56-
t(LangString { original: "{.rust}".into(), ..Default::default() });
57-
t(LangString { original: "sh".into(), rust: false, ..Default::default() });
57+
t(LangString {
58+
original: ".rust".into(),
59+
rust: false,
60+
unknown: vec![".rust".into()],
61+
..Default::default()
62+
});
63+
t(LangString { original: "{rust}".into(), rust: false, ..Default::default() });
64+
t(LangString {
65+
original: "{.rust}".into(),
66+
rust: false,
67+
added_classes: vec!["rust".into()],
68+
..Default::default()
69+
});
70+
t(LangString {
71+
original: "sh".into(),
72+
rust: false,
73+
unknown: vec!["sh".into()],
74+
..Default::default()
75+
});
5876
t(LangString { original: "ignore".into(), ignore: Ignore::All, ..Default::default() });
5977
t(LangString {
6078
original: "ignore-foo".into(),
@@ -70,41 +88,56 @@ fn test_lang_string_parse() {
7088
compile_fail: true,
7189
..Default::default()
7290
});
73-
t(LangString { original: "no_run,example".into(), no_run: true, ..Default::default() });
91+
t(LangString {
92+
original: "no_run,example".into(),
93+
no_run: true,
94+
unknown: vec!["example".into()],
95+
..Default::default()
96+
});
7497
t(LangString {
7598
original: "sh,should_panic".into(),
7699
should_panic: true,
77100
rust: false,
101+
unknown: vec!["sh".into()],
102+
..Default::default()
103+
});
104+
t(LangString {
105+
original: "example,rust".into(),
106+
unknown: vec!["example".into()],
78107
..Default::default()
79108
});
80-
t(LangString { original: "example,rust".into(), ..Default::default() });
81109
t(LangString {
82110
original: "test_harness,.rust".into(),
83111
test_harness: true,
112+
unknown: vec![".rust".into()],
84113
..Default::default()
85114
});
86115
t(LangString {
87116
original: "text, no_run".into(),
88117
no_run: true,
89118
rust: false,
119+
unknown: vec!["text".into()],
90120
..Default::default()
91121
});
92122
t(LangString {
93123
original: "text,no_run".into(),
94124
no_run: true,
95125
rust: false,
126+
unknown: vec!["text".into()],
96127
..Default::default()
97128
});
98129
t(LangString {
99130
original: "text,no_run, ".into(),
100131
no_run: true,
101132
rust: false,
133+
unknown: vec!["text".into()],
102134
..Default::default()
103135
});
104136
t(LangString {
105137
original: "text,no_run,".into(),
106138
no_run: true,
107139
rust: false,
140+
unknown: vec!["text".into()],
108141
..Default::default()
109142
});
110143
t(LangString {
@@ -118,52 +151,96 @@ fn test_lang_string_parse() {
118151
..Default::default()
119152
});
120153
t(LangString {
121-
original: "class:test".into(),
154+
original: "{class=test}".into(),
122155
added_classes: vec!["test".into()],
123156
rust: false,
124157
..Default::default()
125158
});
126159
t(LangString {
127-
original: "rust,class:test".into(),
160+
original: "{.test}".into(),
128161
added_classes: vec!["test".into()],
162+
rust: false,
163+
..Default::default()
164+
});
165+
t(LangString {
166+
original: "rust,{class=test,.test2}".into(),
167+
added_classes: vec!["test".into(), "test2".into()],
129168
rust: true,
130169
..Default::default()
131170
});
132171
t(LangString {
133-
original: "class:test:with:colon".into(),
134-
added_classes: vec!["test:with:colon".into()],
172+
original: "{class=test:with:colon .test1}".into(),
173+
added_classes: vec!["test:with:colon".into(), "test1".into()],
135174
rust: false,
136175
..Default::default()
137176
});
138177
t(LangString {
139-
original: "class:first,class:second".into(),
178+
original: "{class=first,class=second}".into(),
140179
added_classes: vec!["first".into(), "second".into()],
141180
rust: false,
142181
..Default::default()
143182
});
183+
t(LangString {
184+
original: "{class=first,.second},unknown".into(),
185+
added_classes: vec!["first".into(), "second".into()],
186+
rust: false,
187+
unknown: vec!["unknown".into()],
188+
..Default::default()
189+
});
190+
t(LangString {
191+
original: "{class=first .second} unknown".into(),
192+
added_classes: vec!["first".into(), "second".into()],
193+
rust: false,
194+
unknown: vec!["unknown".into()],
195+
..Default::default()
196+
});
197+
t(LangString {
198+
original: "{.first.second}".into(),
199+
added_classes: vec!["first.second".into()],
200+
rust: false,
201+
..Default::default()
202+
});
203+
t(LangString {
204+
original: "{class=first=second}".into(),
205+
added_classes: vec!["first=second".into()],
206+
rust: false,
207+
..Default::default()
208+
});
209+
t(LangString {
210+
original: "{class=first.second}".into(),
211+
added_classes: vec!["first.second".into()],
212+
rust: false,
213+
..Default::default()
214+
});
215+
t(LangString {
216+
original: "{class=.first}".into(),
217+
added_classes: vec![".first".into()],
218+
rust: false,
219+
..Default::default()
220+
});
144221
}
145222

146223
#[test]
147224
fn test_lang_string_tokenizer() {
148-
fn case(lang_string: &str, want: &[&str]) {
149-
let have = LangString::tokens(lang_string).collect::<Vec<&str>>();
225+
fn case(lang_string: &str, want: &[TokenKind<'_>]) {
226+
let have = TagIterator::new(lang_string, None).collect::<Vec<_>>();
150227
assert_eq!(have, want, "Unexpected lang string split for `{}`", lang_string);
151228
}
152229

153230
case("", &[]);
154-
case("foo", &["foo"]);
155-
case("foo,bar", &["foo", "bar"]);
156-
case(".foo,.bar", &["foo", "bar"]);
157-
case("{.foo,.bar}", &["foo", "bar"]);
158-
case(" {.foo,.bar} ", &["foo", "bar"]);
159-
case("foo bar", &["foo", "bar"]);
160-
case("foo\tbar", &["foo", "bar"]);
161-
case("foo\t, bar", &["foo", "bar"]);
162-
case(" foo , bar ", &["foo", "bar"]);
163-
case(",,foo,,bar,,", &["foo", "bar"]);
164-
case("foo=bar", &["foo=bar"]);
165-
case("a-b-c", &["a-b-c"]);
166-
case("a_b_c", &["a_b_c"]);
231+
case("foo", &[TokenKind::Token("foo")]);
232+
case("foo,bar", &[TokenKind::Token("foo"), TokenKind::Token("bar")]);
233+
case(".foo,.bar", &[TokenKind::Token(".foo"), TokenKind::Token(".bar")]);
234+
case("{.foo,.bar}", &[TokenKind::Attribute(".foo"), TokenKind::Attribute(".bar")]);
235+
case(" {.foo,.bar} ", &[TokenKind::Attribute(".foo"), TokenKind::Attribute(".bar")]);
236+
case("foo bar", &[TokenKind::Token("foo"), TokenKind::Token("bar")]);
237+
case("foo\tbar", &[TokenKind::Token("foo"), TokenKind::Token("bar")]);
238+
case("foo\t, bar", &[TokenKind::Token("foo"), TokenKind::Token("bar")]);
239+
case(" foo , bar ", &[TokenKind::Token("foo"), TokenKind::Token("bar")]);
240+
case(",,foo,,bar,,", &[TokenKind::Token("foo"), TokenKind::Token("bar")]);
241+
case("foo=bar", &[TokenKind::Token("foo=bar")]);
242+
case("a-b-c", &[TokenKind::Token("a-b-c")]);
243+
case("a_b_c", &[TokenKind::Token("a_b_c")]);
167244
}
168245

169246
#[test]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// This test ensures that warnings are working as expected for "custom_code_classes_in_docs"
2+
// feature.
3+
4+
#![feature(custom_code_classes_in_docs)]
5+
#![deny(warnings)]
6+
#![feature(no_core)]
7+
#![no_core]
8+
9+
/// ```{. class= whatever=hehe #id} } {{
10+
/// main;
11+
/// ```
12+
//~^^^ ERROR missing class name after `.`
13+
//~| ERROR missing class name after `class=`
14+
//~| ERROR unsupported attribute `whatever=hehe`
15+
//~| ERROR unsupported attribute `#id`
16+
//~| ERROR unexpected `}` outside attribute block (`{}`)
17+
//~| ERROR unclosed attribute block (`{}`): missing `}` at the end
18+
//~| ERROR unexpected `{` inside attribute block (`{}`)
19+
pub fn foo() {}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
error: missing class name after `.`
2+
--> $DIR/custom_code_classes_in_docs-warning.rs:9:1
3+
|
4+
LL | / /// ```{. class= whatever=hehe #id} } {{
5+
LL | | /// main;
6+
LL | | /// ```
7+
| |_______^
8+
|
9+
note: the lint level is defined here
10+
--> $DIR/custom_code_classes_in_docs-warning.rs:5:9
11+
|
12+
LL | #![deny(warnings)]
13+
| ^^^^^^^^
14+
= note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]`
15+
16+
error: missing class name after `class=`
17+
--> $DIR/custom_code_classes_in_docs-warning.rs:9:1
18+
|
19+
LL | / /// ```{. class= whatever=hehe #id} } {{
20+
LL | | /// main;
21+
LL | | /// ```
22+
| |_______^
23+
24+
error: unsupported attribute `whatever=hehe`
25+
--> $DIR/custom_code_classes_in_docs-warning.rs:9:1
26+
|
27+
LL | / /// ```{. class= whatever=hehe #id} } {{
28+
LL | | /// main;
29+
LL | | /// ```
30+
| |_______^
31+
32+
error: unsupported attribute `#id`
33+
--> $DIR/custom_code_classes_in_docs-warning.rs:9:1
34+
|
35+
LL | / /// ```{. class= whatever=hehe #id} } {{
36+
LL | | /// main;
37+
LL | | /// ```
38+
| |_______^
39+
40+
error: unexpected `}` outside attribute block (`{}`)
41+
--> $DIR/custom_code_classes_in_docs-warning.rs:9:1
42+
|
43+
LL | / /// ```{. class= whatever=hehe #id} } {{
44+
LL | | /// main;
45+
LL | | /// ```
46+
| |_______^
47+
48+
error: unexpected `{` inside attribute block (`{}`)
49+
--> $DIR/custom_code_classes_in_docs-warning.rs:9:1
50+
|
51+
LL | / /// ```{. class= whatever=hehe #id} } {{
52+
LL | | /// main;
53+
LL | | /// ```
54+
| |_______^
55+
56+
error: unclosed attribute block (`{}`): missing `}` at the end
57+
--> $DIR/custom_code_classes_in_docs-warning.rs:9:1
58+
|
59+
LL | / /// ```{. class= whatever=hehe #id} } {{
60+
LL | | /// main;
61+
LL | | /// ```
62+
| |_______^
63+
64+
error: aborting due to 7 previous errors
65+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// This test ensures that warnings are working as expected for "custom_code_classes_in_docs"
2+
// feature.
3+
4+
#![feature(custom_code_classes_in_docs)]
5+
#![deny(warnings)]
6+
#![feature(no_core)]
7+
#![no_core]
8+
9+
/// ```{class=}
10+
/// main;
11+
/// ```
12+
//~^^^ ERROR missing class name after `class=`
13+
pub fn foo() {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error: missing class name after `class=`
2+
--> $DIR/custom_code_classes_in_docs-warning2.rs:9:1
3+
|
4+
LL | / /// ```{class=}
5+
LL | | /// main;
6+
LL | | /// ```
7+
| |_______^
8+
|
9+
note: the lint level is defined here
10+
--> $DIR/custom_code_classes_in_docs-warning2.rs:5:9
11+
|
12+
LL | #![deny(warnings)]
13+
| ^^^^^^^^
14+
= note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]`
15+
16+
error: aborting due to previous error
17+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// ```{class=language-c}
2+
/// int main(void) { return 0; }
3+
/// ```
4+
//~^^^ ERROR 1:1: 3:8: custom classes in code blocks are unstable [E0658]
5+
pub struct Bar;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0658]: custom classes in code blocks are unstable
2+
--> $DIR/feature-gate-custom_code_classes_in_docs.rs:1:1
3+
|
4+
LL | / /// ```{class=language-c}
5+
LL | | /// int main(void) { return 0; }
6+
LL | | /// ```
7+
| |_______^
8+
|
9+
= note: see issue #79483 <https://github.com/rust-lang/rust/issues/79483> for more information
10+
= help: add `#![feature(custom_code_classes_in_docs)]` to the crate attributes to enable
11+
= note: found these custom classes: class=language-c
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0658`.

tests/rustdoc-ui/issues/issue-91713.stdout

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Available passes for running rustdoc:
2+
check-custom-code-classes - check for custom code classes without the feature-gate enabled
23
check_doc_test_visibility - run various visibility-related lints on doctests
34
strip-hidden - strips all `#[doc(hidden)]` items from the output
45
strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports
@@ -10,6 +11,7 @@ calculate-doc-coverage - counts the number of items with and without documentati
1011
run-lints - runs some of rustdoc's lints
1112

1213
Default passes for rustdoc:
14+
check-custom-code-classes
1315
collect-trait-impls
1416
check_doc_test_visibility
1517
strip-hidden (when not --document-hidden-items)

tests/rustdoc/custom_code_classes.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Test for `custom_code_classes_in_docs` feature.
2+
3+
#![feature(custom_code_classes_in_docs)]
4+
#![crate_name = "foo"]
5+
#![feature(no_core)]
6+
#![no_core]
7+
8+
// @has 'foo/struct.Bar.html'
9+
// @has - '//*[@id="main-content"]//pre[@class="language-whatever hoho-c"]' 'main;'
10+
// @has - '//*[@id="main-content"]//pre[@class="language-whatever2 haha-c"]' 'main;'
11+
// @has - '//*[@id="main-content"]//pre[@class="language-whatever4 huhu-c"]' 'main;'
12+
13+
/// ```{class=hoho-c},whatever
14+
/// main;
15+
/// ```
16+
///
17+
/// Testing multiple kinds of orders.
18+
///
19+
/// ```whatever2 {class=haha-c}
20+
/// main;
21+
/// ```
22+
///
23+
/// Testing with multiple "unknown". Only the first should be used.
24+
///
25+
/// ```whatever4{.huhu-c} whatever5
26+
/// main;
27+
/// ```
28+
pub struct Bar;

0 commit comments

Comments
 (0)