diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 6bd4e775c0e..0a741f7815b 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -862,19 +862,34 @@ pub(crate) struct TagIterator<'a, 'tcx> { extra: Option<&'a ExtraInfo<'tcx>>, } -#[derive(Debug, PartialEq)] -pub(crate) enum TokenKind<'a> { - Token(&'a str), - Attribute(&'a str), +#[derive(Clone, Debug, Eq, PartialEq)] +pub(crate) enum LangStringToken<'a> { + LangToken(&'a str), + ClassAttribute(&'a str), + KeyValueAttribute(&'a str, &'a str), } +fn is_bareword_char(c: char) -> bool { + c == '_' || c == '-' || c == ':' || c.is_ascii_alphabetic() || c.is_ascii_digit() +} fn is_separator(c: char) -> bool { c == ' ' || c == ',' || c == '\t' } +struct Indices { + start: usize, + end: usize, +} + impl<'a, 'tcx> TagIterator<'a, 'tcx> { pub(crate) fn new(data: &'a str, extra: Option<&'a ExtraInfo<'tcx>>) -> Self { - Self { inner: data.char_indices().peekable(), data, extra, is_in_attribute_block: false } + Self { inner: data.char_indices().peekable(), data, is_in_attribute_block: false, extra } + } + + fn emit_error(&self, err: &str) { + if let Some(extra) = self.extra { + extra.error_invalid_codeblock_attr(err); + } } fn skip_separators(&mut self) -> Option { @@ -887,84 +902,183 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { None } - fn emit_error(&self, err: &str) { - if let Some(extra) = self.extra { - extra.error_invalid_codeblock_attr(err); + fn parse_string(&mut self, start: usize) -> Option { + while let Some((pos, c)) = self.inner.next() { + if c == '"' { + return Some(Indices { start: start + 1, end: pos }); + } + } + self.emit_error("unclosed quote string `\"`"); + None + } + + fn parse_class(&mut self, start: usize) -> Option> { + while let Some((pos, c)) = self.inner.peek().copied() { + if is_bareword_char(c) { + self.inner.next(); + } else { + let class = &self.data[start + 1..pos]; + if class.is_empty() { + self.emit_error(&format!("unexpected `{c}` character after `.`")); + return None; + } else if self.check_after_token() { + return Some(LangStringToken::ClassAttribute(class)); + } else { + return None; + } + } + } + let class = &self.data[start + 1..]; + if class.is_empty() { + self.emit_error("missing character after `.`"); + None + } else if self.check_after_token() { + Some(LangStringToken::ClassAttribute(class)) + } else { + None } } - /// Returns false if the string is unfinished. - fn skip_string(&mut self) -> bool { + fn parse_token(&mut self, start: usize) -> Option { + while let Some((pos, c)) = self.inner.peek() { + if !is_bareword_char(*c) { + return Some(Indices { start, end: *pos }); + } + self.inner.next(); + } + self.emit_error("unexpected end"); + None + } + + fn parse_key_value(&mut self, c: char, start: usize) -> Option> { + let key_indices = + if c == '"' { self.parse_string(start)? } else { self.parse_token(start)? }; + if key_indices.start == key_indices.end { + self.emit_error("unexpected empty string as key"); + return None; + } + + if let Some((_, c)) = self.inner.next() { + if c != '=' { + self.emit_error(&format!("expected `=`, found `{}`", c)); + return None; + } + } else { + self.emit_error("unexpected end"); + return None; + } + let value_indices = match self.inner.next() { + Some((pos, '"')) => self.parse_string(pos)?, + Some((pos, c)) if is_bareword_char(c) => self.parse_token(pos)?, + Some((_, c)) => { + self.emit_error(&format!("unexpected `{c}` character after `=`")); + return None; + } + None => { + self.emit_error("expected value after `=`"); + return None; + } + }; + if value_indices.start == value_indices.end { + self.emit_error("unexpected empty string as value"); + None + } else if self.check_after_token() { + Some(LangStringToken::KeyValueAttribute( + &self.data[key_indices.start..key_indices.end], + &self.data[value_indices.start..value_indices.end], + )) + } else { + None + } + } + + /// Returns `false` if an error was emitted. + fn check_after_token(&mut self) -> bool { + if let Some((_, c)) = self.inner.peek().copied() { + if c == '}' || is_separator(c) || c == '(' { + true + } else { + self.emit_error(&format!("unexpected `{c}` character")); + false + } + } else { + // The error will be caught on the next iteration. + true + } + } + + fn parse_in_attribute_block(&mut self) -> Option> { + while let Some((pos, c)) = self.inner.next() { + if c == '}' { + self.is_in_attribute_block = false; + return self.next(); + } else if c == '.' { + return self.parse_class(pos); + } else if c == '"' || is_bareword_char(c) { + return self.parse_key_value(c, pos); + } else { + self.emit_error(&format!("unexpected character `{c}`")); + return None; + } + } + self.emit_error("unclosed attribute block (`{}`): missing `}` at the end"); + None + } + + /// Returns `false` if an error was emitted. + fn skip_paren_block(&mut self) -> bool { while let Some((_, c)) = self.inner.next() { - if c == '"' { + if c == ')' { return true; } } - self.emit_error("unclosed quote string: missing `\"` at the end"); + self.emit_error("unclosed comment: missing `)` at the end"); false } - fn parse_in_attribute_block(&mut self, start: usize) -> Option> { + fn parse_outside_attribute_block(&mut self, start: usize) -> Option> { while let Some((pos, c)) = self.inner.next() { - if is_separator(c) { - return Some(TokenKind::Attribute(&self.data[start..pos])); - } else if c == '{' { - // There shouldn't be a nested block! - self.emit_error("unexpected `{` inside attribute block (`{}`)"); - let attr = &self.data[start..pos]; - if attr.is_empty() { - return self.next(); + if c == '"' { + if pos != start { + self.emit_error("expected ` `, `{` or `,` found `\"`"); + return None; } - self.inner.next(); - return Some(TokenKind::Attribute(attr)); - } else if c == '}' { - self.is_in_attribute_block = false; - let attr = &self.data[start..pos]; - if attr.is_empty() { - return self.next(); + let indices = self.parse_string(pos)?; + if let Some((_, c)) = self.inner.peek().copied() && c != '{' && !is_separator(c) && c != '(' { + self.emit_error(&format!("expected ` `, `{{` or `,` after `\"`, found `{c}`")); + return None; } - return Some(TokenKind::Attribute(attr)); - } else if c == '"' && !self.skip_string() { - return None; - } - } - // Unclosed attribute block! - self.emit_error("unclosed attribute block (`{}`): missing `}` at the end"); - let token = &self.data[start..]; - if token.is_empty() { None } else { Some(TokenKind::Attribute(token)) } - } - - fn parse_outside_attribute_block(&mut self, start: usize) -> Option> { - while let Some((pos, c)) = self.inner.next() { - if is_separator(c) { - return Some(TokenKind::Token(&self.data[start..pos])); + return Some(LangStringToken::LangToken(&self.data[indices.start..indices.end])); } else if c == '{' { self.is_in_attribute_block = true; - let token = &self.data[start..pos]; - if token.is_empty() { - return self.next(); + return self.next(); + } else if is_bareword_char(c) { + continue; + } else if is_separator(c) { + if pos != start { + return Some(LangStringToken::LangToken(&self.data[start..pos])); } - return Some(TokenKind::Token(token)); - } else if c == '}' { - // We're not in a block so it shouldn't be there! - self.emit_error("unexpected `}` outside attribute block (`{}`)"); - let token = &self.data[start..pos]; - if token.is_empty() { - return self.next(); + return self.next(); + } else if c == '(' { + if !self.skip_paren_block() { + return None; } - self.inner.next(); - return Some(TokenKind::Attribute(token)); - } else if c == '"' && !self.skip_string() { + if pos != start { + return Some(LangStringToken::LangToken(&self.data[start..pos])); + } + return self.next(); + } else { + self.emit_error(&format!("unexpected character `{c}`")); return None; } } let token = &self.data[start..]; - if token.is_empty() { None } else { Some(TokenKind::Token(token)) } + if token.is_empty() { None } else { Some(LangStringToken::LangToken(&self.data[start..])) } } } impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> { - type Item = TokenKind<'a>; + type Item = LangStringToken<'a>; fn next(&mut self) -> Option { let Some(start) = self.skip_separators() else { @@ -974,7 +1088,7 @@ impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> { return None; }; if self.is_in_attribute_block { - self.parse_in_attribute_block(start) + self.parse_in_attribute_block() } else { self.parse_outside_attribute_block(start) } @@ -999,16 +1113,6 @@ impl Default for LangString { } } -fn handle_class(class: &str, after: &str, data: &mut LangString, extra: Option<&ExtraInfo<'_>>) { - if class.is_empty() { - if let Some(extra) = extra { - extra.error_invalid_codeblock_attr(&format!("missing class name after `{after}`")); - } - } else { - data.added_classes.push(class.replace('"', "")); - } -} - impl LangString { fn parse_without_check( string: &str, @@ -1034,41 +1138,41 @@ impl LangString { for token in TagIterator::new(string, extra) { match token { - TokenKind::Token("should_panic") => { + LangStringToken::LangToken("should_panic") => { data.should_panic = true; seen_rust_tags = !seen_other_tags; } - TokenKind::Token("no_run") => { + LangStringToken::LangToken("no_run") => { data.no_run = true; seen_rust_tags = !seen_other_tags; } - TokenKind::Token("ignore") => { + LangStringToken::LangToken("ignore") => { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; } - TokenKind::Token(x) if x.starts_with("ignore-") => { + LangStringToken::LangToken(x) if x.starts_with("ignore-") => { if enable_per_target_ignores { ignores.push(x.trim_start_matches("ignore-").to_owned()); seen_rust_tags = !seen_other_tags; } } - TokenKind::Token("rust") => { + LangStringToken::LangToken("rust") => { data.rust = true; seen_rust_tags = true; } - TokenKind::Token("test_harness") => { + LangStringToken::LangToken("test_harness") => { data.test_harness = true; seen_rust_tags = !seen_other_tags || seen_rust_tags; } - TokenKind::Token("compile_fail") => { + LangStringToken::LangToken("compile_fail") => { data.compile_fail = true; seen_rust_tags = !seen_other_tags || seen_rust_tags; data.no_run = true; } - TokenKind::Token(x) if x.starts_with("edition") => { + LangStringToken::LangToken(x) if x.starts_with("edition") => { data.edition = x[7..].parse::().ok(); } - TokenKind::Token(x) + LangStringToken::LangToken(x) if allow_error_code_check && x.starts_with('E') && x.len() == 5 => { if x[1..].parse::().is_ok() { @@ -1078,7 +1182,7 @@ impl LangString { seen_other_tags = true; } } - TokenKind::Token(x) if extra.is_some() => { + LangStringToken::LangToken(x) if extra.is_some() => { let s = x.to_lowercase(); if let Some((flag, help)) = if s == "compile-fail" || s == "compile_fail" @@ -1120,22 +1224,24 @@ impl LangString { seen_other_tags = true; data.unknown.push(x.to_owned()); } - TokenKind::Token(x) => { + LangStringToken::LangToken(x) => { seen_other_tags = true; data.unknown.push(x.to_owned()); } - TokenKind::Attribute(attr) => { + LangStringToken::KeyValueAttribute(key, value) => { seen_other_tags = true; - if let Some(class) = attr.strip_prefix('.') { - handle_class(class, ".", &mut data, extra); - } else if let Some(class) = attr.strip_prefix("class=") { - handle_class(class, "class=", &mut data, extra); + if key == "class" { + data.added_classes.push(value.to_owned()); } else if let Some(extra) = extra { extra.error_invalid_codeblock_attr(&format!( - "unsupported attribute `{attr}`" + "unsupported attribute `{key}`" )); } } + LangStringToken::ClassAttribute(class) => { + seen_other_tags = true; + data.added_classes.push(class.to_owned()); + } } } diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index b0b4de65cca..35b243d3d29 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -1,7 +1,7 @@ use super::{find_testable_code, plain_text_summary, short_markdown_summary}; use super::{ - ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, Markdown, MarkdownItemInfo, TagIterator, - TokenKind, + ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, LangStringToken, Markdown, + MarkdownItemInfo, TagIterator, }; use rustc_span::edition::{Edition, DEFAULT_EDITION}; @@ -55,12 +55,13 @@ fn test_lang_string_parse() { t(Default::default()); t(LangString { original: "rust".into(), ..Default::default() }); t(LangString { - original: ".rust".into(), + original: "rusta".into(), rust: false, - unknown: vec![".rust".into()], + unknown: vec!["rusta".into()], ..Default::default() }); - t(LangString { original: "{rust}".into(), rust: false, ..Default::default() }); + // error + t(LangString { original: "{rust}".into(), rust: true, ..Default::default() }); t(LangString { original: "{.rust}".into(), rust: false, @@ -107,9 +108,9 @@ fn test_lang_string_parse() { ..Default::default() }); t(LangString { - original: "test_harness,.rust".into(), + original: "test_harness,rusta".into(), test_harness: true, - unknown: vec![".rust".into()], + unknown: vec!["rusta".into()], ..Default::default() }); t(LangString { @@ -194,65 +195,51 @@ fn test_lang_string_parse() { unknown: vec!["unknown".into()], ..Default::default() }); - t(LangString { - original: "{.first.second}".into(), - added_classes: vec!["first.second".into()], - rust: false, - ..Default::default() - }); - t(LangString { - original: "{class=first=second}".into(), - added_classes: vec!["first=second".into()], - rust: false, - ..Default::default() - }); - t(LangString { - original: "{class=first.second}".into(), - added_classes: vec!["first.second".into()], - rust: false, - ..Default::default() - }); - t(LangString { - original: "{class=.first}".into(), - added_classes: vec![".first".into()], - rust: false, - ..Default::default() - }); + // error + t(LangString { original: "{.first.second}".into(), rust: true, ..Default::default() }); + // error + t(LangString { original: "{class=first=second}".into(), rust: true, ..Default::default() }); + // error + t(LangString { original: "{class=first.second}".into(), rust: true, ..Default::default() }); + // error + t(LangString { original: "{class=.first}".into(), rust: true, ..Default::default() }); t(LangString { original: r#"{class="first"}"#.into(), added_classes: vec!["first".into()], rust: false, ..Default::default() }); - t(LangString { - original: r#"{class=f"irst"}"#.into(), - added_classes: vec!["first".into()], - rust: false, - ..Default::default() - }); + // error + t(LangString { original: r#"{class=f"irst"}"#.into(), rust: true, ..Default::default() }); } #[test] fn test_lang_string_tokenizer() { - fn case(lang_string: &str, want: &[TokenKind<'_>]) { + fn case(lang_string: &str, want: &[LangStringToken<'_>]) { let have = TagIterator::new(lang_string, None).collect::>(); assert_eq!(have, want, "Unexpected lang string split for `{}`", lang_string); } case("", &[]); - case("foo", &[TokenKind::Token("foo")]); - case("foo,bar", &[TokenKind::Token("foo"), TokenKind::Token("bar")]); - case(".foo,.bar", &[TokenKind::Token(".foo"), TokenKind::Token(".bar")]); - case("{.foo,.bar}", &[TokenKind::Attribute(".foo"), TokenKind::Attribute(".bar")]); - case(" {.foo,.bar} ", &[TokenKind::Attribute(".foo"), TokenKind::Attribute(".bar")]); - case("foo bar", &[TokenKind::Token("foo"), TokenKind::Token("bar")]); - case("foo\tbar", &[TokenKind::Token("foo"), TokenKind::Token("bar")]); - case("foo\t, bar", &[TokenKind::Token("foo"), TokenKind::Token("bar")]); - case(" foo , bar ", &[TokenKind::Token("foo"), TokenKind::Token("bar")]); - case(",,foo,,bar,,", &[TokenKind::Token("foo"), TokenKind::Token("bar")]); - case("foo=bar", &[TokenKind::Token("foo=bar")]); - case("a-b-c", &[TokenKind::Token("a-b-c")]); - case("a_b_c", &[TokenKind::Token("a_b_c")]); + case("foo", &[LangStringToken::LangToken("foo")]); + case("foo,bar", &[LangStringToken::LangToken("foo"), LangStringToken::LangToken("bar")]); + case(".foo,.bar", &[]); + case( + "{.foo,.bar}", + &[LangStringToken::ClassAttribute("foo"), LangStringToken::ClassAttribute("bar")], + ); + case( + " {.foo,.bar} ", + &[LangStringToken::ClassAttribute("foo"), LangStringToken::ClassAttribute("bar")], + ); + case("foo bar", &[LangStringToken::LangToken("foo"), LangStringToken::LangToken("bar")]); + case("foo\tbar", &[LangStringToken::LangToken("foo"), LangStringToken::LangToken("bar")]); + case("foo\t, bar", &[LangStringToken::LangToken("foo"), LangStringToken::LangToken("bar")]); + case(" foo , bar ", &[LangStringToken::LangToken("foo"), LangStringToken::LangToken("bar")]); + case(",,foo,,bar,,", &[LangStringToken::LangToken("foo"), LangStringToken::LangToken("bar")]); + case("foo=bar", &[]); + case("a-b-c", &[LangStringToken::LangToken("a-b-c")]); + case("a_b_c", &[LangStringToken::LangToken("a_b_c")]); } #[test] diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs index c28921b01f1..dd8759b7e37 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs @@ -6,14 +6,80 @@ #![feature(no_core)] #![no_core] -/// ```{. class= whatever=hehe #id} } {{ +/// ```{. } /// main; /// ``` -//~^^^ ERROR missing class name after `.` -//~| ERROR missing class name after `class=` -//~| ERROR unsupported attribute `whatever=hehe` -//~| ERROR unsupported attribute `#id` -//~| ERROR unexpected `}` outside attribute block (`{}`) -//~| ERROR unclosed attribute block (`{}`): missing `}` at the end -//~| ERROR unexpected `{` inside attribute block (`{}`) +//~^^^ ERROR unexpected ` ` character after `.` pub fn foo() {} + +/// ```{class= a} +/// main; +/// ``` +//~^^^ ERROR unexpected ` ` character after `=` +pub fn foo2() {} + +/// ```{#id} +/// main; +/// ``` +//~^^^ ERROR unexpected character `#` +pub fn foo3() {} + +/// ```{{ +/// main; +/// ``` +//~^^^ ERROR unexpected character `{` +pub fn foo4() {} + +/// ```} +/// main; +/// ``` +//~^^^ ERROR unexpected character `}` +pub fn foo5() {} + +/// ```) +/// main; +/// ``` +//~^^^ ERROR unexpected character `)` +pub fn foo6() {} + +/// ```{class=} +/// main; +/// ``` +//~^^^ ERROR unexpected `}` character after `=` +pub fn foo7() {} + +/// ```( +/// main; +/// ``` +//~^^^ ERROR unclosed comment: missing `)` at the end +pub fn foo8() {} + +/// ```{class=one=two} +/// main; +/// ``` +//~^^^ ERROR unexpected `=` +pub fn foo9() {} + +/// ```{.one.two} +/// main; +/// ``` +//~^^^ ERROR unexpected `.` character +pub fn foo10() {} + +/// ```{class=.one} +/// main; +/// ``` +//~^^^ ERROR unexpected `.` character after `=` +pub fn foo11() {} + +/// ```{class=one.two} +/// main; +/// ``` +//~^^^ ERROR unexpected `.` character +pub fn foo12() {} + +/// ```{(comment)} +/// main; +/// ``` +//~^^^ ERROR unexpected character `(` +pub fn foo13() {} diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr index f19b62914db..3e0dc4b2f7a 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr @@ -1,7 +1,7 @@ -error: missing class name after `.` +error: unexpected ` ` character after `.` --> $DIR/custom_code_classes_in_docs-warning.rs:9:1 | -LL | / /// ```{. class= whatever=hehe #id} } {{ +LL | / /// ```{. } LL | | /// main; LL | | /// ``` | |_______^ @@ -13,53 +13,101 @@ LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]` -error: missing class name after `class=` - --> $DIR/custom_code_classes_in_docs-warning.rs:9:1 +error: unexpected ` ` character after `=` + --> $DIR/custom_code_classes_in_docs-warning.rs:15:1 | -LL | / /// ```{. class= whatever=hehe #id} } {{ +LL | / /// ```{class= a} LL | | /// main; LL | | /// ``` | |_______^ -error: unsupported attribute `whatever=hehe` - --> $DIR/custom_code_classes_in_docs-warning.rs:9:1 +error: unexpected character `#` + --> $DIR/custom_code_classes_in_docs-warning.rs:21:1 | -LL | / /// ```{. class= whatever=hehe #id} } {{ +LL | / /// ```{#id} LL | | /// main; LL | | /// ``` | |_______^ -error: unsupported attribute `#id` - --> $DIR/custom_code_classes_in_docs-warning.rs:9:1 +error: unexpected character `{` + --> $DIR/custom_code_classes_in_docs-warning.rs:27:1 | -LL | / /// ```{. class= whatever=hehe #id} } {{ +LL | / /// ```{{ LL | | /// main; LL | | /// ``` | |_______^ -error: unexpected `}` outside attribute block (`{}`) - --> $DIR/custom_code_classes_in_docs-warning.rs:9:1 +error: unexpected character `}` + --> $DIR/custom_code_classes_in_docs-warning.rs:33:1 | -LL | / /// ```{. class= whatever=hehe #id} } {{ +LL | / /// ```} LL | | /// main; LL | | /// ``` | |_______^ -error: unexpected `{` inside attribute block (`{}`) - --> $DIR/custom_code_classes_in_docs-warning.rs:9:1 +error: unexpected character `)` + --> $DIR/custom_code_classes_in_docs-warning.rs:39:1 | -LL | / /// ```{. class= whatever=hehe #id} } {{ +LL | / /// ```) LL | | /// main; LL | | /// ``` | |_______^ -error: unclosed attribute block (`{}`): missing `}` at the end - --> $DIR/custom_code_classes_in_docs-warning.rs:9:1 +error: unexpected `}` character after `=` + --> $DIR/custom_code_classes_in_docs-warning.rs:45:1 | -LL | / /// ```{. class= whatever=hehe #id} } {{ +LL | / /// ```{class=} LL | | /// main; LL | | /// ``` | |_______^ -error: aborting due to 7 previous errors +error: unclosed comment: missing `)` at the end + --> $DIR/custom_code_classes_in_docs-warning.rs:51:1 + | +LL | / /// ```( +LL | | /// main; +LL | | /// ``` + | |_______^ + +error: unexpected `=` character + --> $DIR/custom_code_classes_in_docs-warning.rs:57:1 + | +LL | / /// ```{class=one=two} +LL | | /// main; +LL | | /// ``` + | |_______^ + +error: unexpected `.` character + --> $DIR/custom_code_classes_in_docs-warning.rs:63:1 + | +LL | / /// ```{.one.two} +LL | | /// main; +LL | | /// ``` + | |_______^ + +error: unexpected `.` character after `=` + --> $DIR/custom_code_classes_in_docs-warning.rs:69:1 + | +LL | / /// ```{class=.one} +LL | | /// main; +LL | | /// ``` + | |_______^ + +error: unexpected `.` character + --> $DIR/custom_code_classes_in_docs-warning.rs:75:1 + | +LL | / /// ```{class=one.two} +LL | | /// main; +LL | | /// ``` + | |_______^ + +error: unexpected character `(` + --> $DIR/custom_code_classes_in_docs-warning.rs:81:1 + | +LL | / /// ```{(comment)} +LL | | /// main; +LL | | /// ``` + | |_______^ + +error: aborting due to 13 previous errors diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning2.rs b/tests/rustdoc-ui/custom_code_classes_in_docs-warning2.rs deleted file mode 100644 index b2ce7407ec6..00000000000 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning2.rs +++ /dev/null @@ -1,13 +0,0 @@ -// This test ensures that warnings are working as expected for "custom_code_classes_in_docs" -// feature. - -#![feature(custom_code_classes_in_docs)] -#![deny(warnings)] -#![feature(no_core)] -#![no_core] - -/// ```{class=} -/// main; -/// ``` -//~^^^ ERROR missing class name after `class=` -pub fn foo() {} diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning2.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning2.stderr deleted file mode 100644 index 52bb1dae9f6..00000000000 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning2.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: missing class name after `class=` - --> $DIR/custom_code_classes_in_docs-warning2.rs:9:1 - | -LL | / /// ```{class=} -LL | | /// main; -LL | | /// ``` - | |_______^ - | -note: the lint level is defined here - --> $DIR/custom_code_classes_in_docs-warning2.rs:5:9 - | -LL | #![deny(warnings)] - | ^^^^^^^^ - = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]` - -error: aborting due to previous error - diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr index 7432af19360..4f2ded78c29 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr @@ -1,4 +1,4 @@ -error: unclosed quote string: missing `"` at the end +error: unclosed quote string `"` --> $DIR/custom_code_classes_in_docs-warning3.rs:9:1 | LL | / /// ```{class="} @@ -17,7 +17,7 @@ LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]` -error: unclosed quote string: missing `"` at the end +error: unclosed quote string `"` --> $DIR/custom_code_classes_in_docs-warning3.rs:9:1 | LL | / /// ```{class="} diff --git a/tests/rustdoc/custom_code_classes.rs b/tests/rustdoc/custom_code_classes.rs index f110721c5a7..cd20d8b7d6c 100644 --- a/tests/rustdoc/custom_code_classes.rs +++ b/tests/rustdoc/custom_code_classes.rs @@ -22,7 +22,7 @@ /// /// Testing with multiple "unknown". Only the first should be used. /// -/// ```whatever4{.huhu-c} whatever5 +/// ```whatever4,{.huhu-c} whatever5 /// main; /// ``` pub struct Bar;