Skip to content

Commit 130dc8f

Browse files
committed
rustdoc: Recognize more weak keywords when highlighting Rust code
1 parent d8d9993 commit 130dc8f

File tree

1 file changed

+41
-33
lines changed

1 file changed

+41
-33
lines changed

src/librustdoc/html/highlight.rs

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,8 @@ fn get_real_ident_class(text: &str, allow_path_keywords: bool) -> Option<Class>
764764
Some(match text {
765765
"ref" | "mut" => Class::RefKeyWord,
766766
"false" | "true" => Class::Bool,
767-
_ if Symbol::intern(text).is_reserved(|| Edition::Edition2021) => Class::KeyWord,
767+
// FIXME(#148221): Don't hard-code the edition. The classifier should take it as an argument.
768+
_ if Symbol::intern(text).is_reserved(|| Edition::Edition2024) => Class::KeyWord,
768769
_ => return None,
769770
})
770771
}
@@ -1197,34 +1198,30 @@ impl<'src> Classifier<'src> {
11971198
},
11981199
TokenKind::GuardedStrPrefix => return no_highlight(sink),
11991200
TokenKind::Ident | TokenKind::RawIdent
1200-
if self.peek_non_whitespace() == Some(TokenKind::Bang) =>
1201+
if let Some((TokenKind::Bang, _)) = self.peek_non_trivia() =>
12011202
{
12021203
self.in_macro = true;
12031204
let span = new_span(before, text, file_span);
12041205
sink(DUMMY_SP, Highlight::EnterSpan { class: Class::Macro(span) });
12051206
sink(span, Highlight::Token { text, class: None });
12061207
return;
12071208
}
1208-
TokenKind::Ident => {
1209-
match get_real_ident_class(text, false) {
1210-
None => match text {
1211-
"Option" | "Result" => Class::PreludeTy(new_span(before, text, file_span)),
1212-
"Some" | "None" | "Ok" | "Err" => {
1213-
Class::PreludeVal(new_span(before, text, file_span))
1214-
}
1215-
// "union" is a weak keyword and is only considered as a keyword when declaring
1216-
// a union type.
1217-
"union" if self.check_if_is_union_keyword() => Class::KeyWord,
1218-
_ if self.in_macro_nonterminal => {
1219-
self.in_macro_nonterminal = false;
1220-
Class::MacroNonTerminal
1221-
}
1222-
"self" | "Self" => Class::Self_(new_span(before, text, file_span)),
1223-
_ => Class::Ident(new_span(before, text, file_span)),
1224-
},
1225-
Some(c) => c,
1226-
}
1227-
}
1209+
TokenKind::Ident => match get_real_ident_class(text, false) {
1210+
None => match text {
1211+
"Option" | "Result" => Class::PreludeTy(new_span(before, text, file_span)),
1212+
"Some" | "None" | "Ok" | "Err" => {
1213+
Class::PreludeVal(new_span(before, text, file_span))
1214+
}
1215+
_ if self.ident_is_weak_keyword(text) => Class::KeyWord,
1216+
_ if self.in_macro_nonterminal => {
1217+
self.in_macro_nonterminal = false;
1218+
Class::MacroNonTerminal
1219+
}
1220+
"self" | "Self" => Class::Self_(new_span(before, text, file_span)),
1221+
_ => Class::Ident(new_span(before, text, file_span)),
1222+
},
1223+
Some(c) => c,
1224+
},
12281225
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12291226
Class::Ident(new_span(before, text, file_span))
12301227
}
@@ -1245,25 +1242,36 @@ impl<'src> Classifier<'src> {
12451242
}
12461243
}
12471244

1245+
fn ident_is_weak_keyword(&mut self, text: &str) -> bool {
1246+
let matches = match text {
1247+
"auto" => |text| text == "trait", // `auto trait Trait {}` (`auto_traits`)
1248+
"pin" => |text| text == "const" || text == "mut", // `&pin mut Type` (`pin_ergonomics`)
1249+
"raw" => |text| text == "const" || text == "mut", // `&raw const local`
1250+
"safe" => |text| text == "fn" || text == "extern", // `unsafe extern { safe fn f(); }`
1251+
"union" => |_| true, // `union Untagged { field: () }`
1252+
_ => return false,
1253+
};
1254+
matches!(self.peek_non_trivia(), Some((TokenKind::Ident, text)) if matches(text))
1255+
}
1256+
12481257
fn peek(&mut self) -> Option<TokenKind> {
1249-
self.tokens.peek().map(|(token_kind, _text)| *token_kind)
1258+
self.tokens.peek().map(|&(kind, _)| kind)
12501259
}
12511260

1252-
fn peek_non_whitespace(&mut self) -> Option<TokenKind> {
1253-
while let Some((token_kind, _)) = self.tokens.peek_next() {
1254-
if *token_kind != TokenKind::Whitespace {
1255-
let token_kind = *token_kind;
1256-
self.tokens.stop_peeking();
1257-
return Some(token_kind);
1261+
fn peek_non_trivia(&mut self) -> Option<(TokenKind, &str)> {
1262+
while let Some(&token @ (kind, _)) = self.tokens.peek_next() {
1263+
if let TokenKind::Whitespace
1264+
| TokenKind::LineComment { doc_style: None }
1265+
| TokenKind::BlockComment { doc_style: None, .. } = kind
1266+
{
1267+
continue;
12581268
}
1269+
self.tokens.stop_peeking();
1270+
return Some(token);
12591271
}
12601272
self.tokens.stop_peeking();
12611273
None
12621274
}
1263-
1264-
fn check_if_is_union_keyword(&mut self) -> bool {
1265-
self.peek_non_whitespace().is_some_and(|kind| kind == TokenKind::Ident)
1266-
}
12671275
}
12681276

12691277
fn generate_link_to_def(

0 commit comments

Comments
 (0)