Rollup merge of #152394 - GuillaumeGomez:macro-call, r=lolbinarycat
Correctly check if a macro call is actually a macro call in rustdoc highlighter Fixes rust-lang/rust#151904. Issues was that if there was a `!` following an ident, we would always assume it's a macro call... except it's very lacking. I'm actually surprised it went for so long unnoticed. To fix it, I added a check for the next (non-blank) token after the `!`, if it's a `{` or a `[` or a `(`, then only do we consider it to be a macro call. r? @lolbinarycat
This commit is contained in:
commit
4bc90240e1
3 changed files with 81 additions and 5 deletions
|
|
@ -1246,7 +1246,7 @@ impl<'src> Classifier<'src> {
|
|||
LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number,
|
||||
},
|
||||
TokenKind::GuardedStrPrefix => return no_highlight(sink),
|
||||
TokenKind::RawIdent if let Some((TokenKind::Bang, _)) = self.peek_non_trivia() => {
|
||||
TokenKind::RawIdent if self.check_if_macro_call("") => {
|
||||
self.new_macro_span(text, sink, before, file_span);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1268,9 +1268,7 @@ impl<'src> Classifier<'src> {
|
|||
// So if it's not a keyword which can be followed by a value (like `if` or
|
||||
// `return`) and the next non-whitespace token is a `!`, then we consider
|
||||
// it's a macro.
|
||||
if !NON_MACRO_KEYWORDS.contains(&text)
|
||||
&& matches!(self.peek_non_trivia(), Some((TokenKind::Bang, _)))
|
||||
{
|
||||
if !NON_MACRO_KEYWORDS.contains(&text) && self.check_if_macro_call(text) {
|
||||
self.new_macro_span(text, sink, before, file_span);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1278,7 +1276,7 @@ impl<'src> Classifier<'src> {
|
|||
}
|
||||
// If it's not a keyword and the next non whitespace token is a `!`, then
|
||||
// we consider it's a macro.
|
||||
_ if matches!(self.peek_non_trivia(), Some((TokenKind::Bang, _))) => {
|
||||
_ if self.check_if_macro_call(text) => {
|
||||
self.new_macro_span(text, sink, before, file_span);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1339,6 +1337,37 @@ impl<'src> Classifier<'src> {
|
|||
self.tokens.stop_peeking();
|
||||
None
|
||||
}
|
||||
|
||||
fn check_if_macro_call(&mut self, ident: &str) -> bool {
|
||||
let mut has_bang = false;
|
||||
let is_macro_rule_ident = ident == "macro_rules";
|
||||
|
||||
while let Some((kind, _)) = self.tokens.peek_next() {
|
||||
if let TokenKind::Whitespace
|
||||
| TokenKind::LineComment { doc_style: None }
|
||||
| TokenKind::BlockComment { doc_style: None, .. } = kind
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if !has_bang {
|
||||
if kind != TokenKind::Bang {
|
||||
break;
|
||||
}
|
||||
has_bang = true;
|
||||
continue;
|
||||
}
|
||||
self.tokens.stop_peeking();
|
||||
if is_macro_rule_ident {
|
||||
return matches!(kind, TokenKind::Ident | TokenKind::RawIdent);
|
||||
}
|
||||
return matches!(
|
||||
kind,
|
||||
TokenKind::OpenParen | TokenKind::OpenBracket | TokenKind::OpenBrace
|
||||
);
|
||||
}
|
||||
self.tokens.stop_peeking();
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_keyword(symbol: Symbol) -> bool {
|
||||
|
|
|
|||
18
tests/rustdoc-html/source-code-pages/macro-call-2.rs
Normal file
18
tests/rustdoc-html/source-code-pages/macro-call-2.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// This is yet another test to ensure that only macro calls are considered as such
|
||||
// by the rustdoc highlighter, in particular when named `macro_rules`.
|
||||
// This is a regression test for <https://github.com/rust-lang/rust/issues/151904>.
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has src/foo/macro-call-2.rs.html
|
||||
//@ count - '//code/span[@class="macro"]' 2
|
||||
//@ has - '//code/span[@class="macro"]' 'macro_rules!'
|
||||
//@ has - '//code/span[@class="macro"]' 'r#macro_rules!'
|
||||
|
||||
macro_rules! r#macro_rules {
|
||||
() => {
|
||||
fn main() {}
|
||||
}
|
||||
}
|
||||
|
||||
r#macro_rules!();
|
||||
29
tests/rustdoc-html/source-code-pages/macro-call.rs
Normal file
29
tests/rustdoc-html/source-code-pages/macro-call.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// This is yet another test to ensure that only macro calls are considered as such
|
||||
// by the rustdoc highlighter.
|
||||
// This is a regression test for <https://github.com/rust-lang/rust/issues/151904>.
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//@ has src/foo/macro-call.rs.html
|
||||
//@ count - '//code/span[@class="macro"]' 2
|
||||
//@ has - '//code/span[@class="macro"]' 'panic!'
|
||||
//@ has - '//code/span[@class="macro"]' 'macro_rules!'
|
||||
|
||||
pub struct Layout;
|
||||
|
||||
impl Layout {
|
||||
pub fn new<X: std::fmt::Debug>() {}
|
||||
}
|
||||
|
||||
pub fn bar() {
|
||||
let layout = Layout::new::<u32>();
|
||||
if layout != Layout::new::<u32>() {
|
||||
panic!();
|
||||
}
|
||||
let macro_rules = 3;
|
||||
if macro_rules != 3 {}
|
||||
}
|
||||
|
||||
macro_rules! blob {
|
||||
() => {}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue